Recently, WHEN I was doing h5 page reconstruction, I encountered several uncomfortable problems:

  1. For configuration purposes, h5 usually uses rem units. Almost all size units need to be written manually: px2REM ($pixel);
  2. For colors and shadows, you have to manually add # or RGBA every time;
  3. For some unusual attributes, check the documentation manually, such as box-shadow Linear-gradient.
  4. For styles that are not obvious, errors often occur, such as text-shadow;

These are small problems, but every time H5 development will encounter, affect time, affect efficiency, affect mood. Is there a way to optimize it? Around these problems, I began to try Sketch plug-in development.

The development environment

The development process requires frequent log debugging, which can be directly allowed in the Sketch page through document.showMessage. You can also view the log printing by setting the process and library as Sketch through Console software. And then in your code you write log or print

Sketch does not automatically update script code by default, if you want it to be automatically updated every time you save Sketch, you can execute the following code.

defaults write ~/Library/Preferences/com.bohemiancoding.sketch3.plist AlwaysReloadScript -bool YESCopy the code

Plug-in profile

The Sketch plugin is in the form of *. Sketchplugin, which is basically a folder. By right-clicking the contents of the package, you can see that the most common internal structure looks like this:

Manifest.json is used to declare plug-in configuration information. Commands define all executable commands. Each command has a unique identifier and menu defines the plug-in menu. You can configure events that you want to listen for, and Sketch executes the corresponding event method when the event is triggered. You can see all the actions in the Action List or install an Action-Logger plugin to see when the event fires.

{"name" : "first-plugin", "identifier" : "com.w3ctrain", "version" : "1.0", "description" : "first plugin", "author" : "w3ctrain", "commands" : [ { "script" : "plugin.js", "handlers": { "run": "onRun", "actions": { "SelectionChanged.finish": "onSelectionChanged" } }, "name": "Say Hello World", "identifier" : "com.w3ctrain.HelloWorld" } ], "menu" : { "items" : [ "com.w3ctrain.HelloWorld" ], "title" : "first plugin" } }Copy the code

Plugin.js corresponds to the manifest.json script field execution script, such scripts can be many, can be arbitrarily named.

var onRun = function (context) {
  context.document.showMessage("Hello World")
}
var onSelectionChanged = function (context) {
  var selection = context.actionContext.document.selectedLayers().layers();
  if (selection.length >= 1) {
    context.actionContext.document.showMessage(`${selection.length} layers selected`)
  } else {
    context.actionContext.document.showMessage("nothing selected")
  }
}Copy the code

Put the plug-in in ~ / Library/Application Support/com bohemiancoding. Sketch3 / Plugins/directory, you can perform in the Plugins menu.

The Sketch plugin is written in CocoaScript and is not a new language. It is a JavaScript + ObjectC host environment, which means you can write JS to call ObjectC methods and objects.

Such as

[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString: @"https://baidu.com"]]]Copy the code

It looks like this when written in CocoaScript:

webView.loadRequest(NSURLRequest.requestWithURL(NSURL. URLWithString("https://baidu.com"))Copy the code

I don’t really care about the ObjectC code, I’m just a front end, as long as I can finish creating a Panel to load my page. The next problem to solve is how to notify the WebView of updates when the Sketch event is triggered. This is actually quite simple, as we saw in the previous article. ObjectC can call JS code directly.

The Sketch inform webview

Webview.js exposes global methods

Function updatePreview () {// Get CSS attributes}Copy the code

Plugin.js, using evaluateWebScript to invoke global methods

function onSelectionChanged { var windowObject = webView.windowScriptObject(); var selection = context.actionContext.document.selectedLayers().layers(); if (selection.length >= 1) { windowObject.evaluateWebScript(`updatePreview(${ayer.CSSAttributes().join('')})`); } else { windowObject.evaluateWebScript("updatePreview(' ')"); }}Copy the code

Since the cssAttributes provided by Sketch were not what we ultimately wanted, we needed to intercept the stack of content with a complementary substitution.

Other processing

Add text alignment and sizing

let layer = selection[0]; var frame = layer.frame(); var attributes = layer.CSSAttributes(); if (layer.class() == "MSTextLayer") { if (! Layer. The lineHeight ()) {attributes. The addObject (` line - height: 1.4; `); } for (const key in TEXT_ALIGNMENT) { if (layer.textAlignment() === TEXT_ALIGNMENT[key]) { attributes.addObject(`text-align: ${TEXT_ALIGNMENT_MAP[key]}; `); } } } attributes.addObject('\n'); attributes.addObject('/* Size: */'); attributes.addObject(`width: ${frame.width()}px; `); attributes.addObject(`height: ${frame.height()}px; `);Copy the code

Filter out attributes that are not commonly used.

function removeBlackListAttributes (codeString) {
  var blackList = ['font-family', 'letter-spacing']
  for (let i = 0; i < blackList.length; i ++) {
    codeString = codeString.replace(new RegExp(`${blackList[i]}(.*)\n`, 'ig', ''), '');
  }
  return codeString
}Copy the code

Make a unit substitution

  var unitsFunc = (match, val) => {
    let unit = unitInput.value
    let miniPixel = miniPixelInput.value
    if (val <= parseInt(miniPixel)) {
      return `${val}px`
    }
    return `${unit}(${val})`
  }
  let result = codeString.replace(/([0-9]+)px/ig, unitsFunc)
}Copy the code

After a meal, the result looks like this:

It takes much less time to realize than expected, because many things do not need to deal with themselves, but the overall effect is very significant, the general points mentioned at the beginning of the article are solved, just copy and paste, move and write a few lines of code can solve their own needs, happy.

The code can be seen here.

Related articles

  • How to create floating Sketch plugins
  • github – sketch-plugin-boilerplate

If reproduced, please indicate the source:
W3ctrain.com/2017/12/07/…

My name is Zhou Xiaokai

I am a front-end development engineer now, and I am still a rookie in the way of programming. W3ctrain is the place where I record my learning and growth.