| A consistent experience is A better experience. – Mark Eberman | consistent experience is A better experience. — Mark Eberman, 16 Quotes from Designers

background

1.UI consistency project

The Tangram Sketch plug-in is originated from the CONSISTENCY project of MEituan Takeout UI, which was proposed in May 2019. It is a joint project of UI design team and R&D team, aiming to improve the consistency of user experience, enhance the versatility and reuse rate of components among multi-technical solutions, and reduce the overall r&d cost of visual revision.

All along, the takeout business has been in the stage of rapid development, with the expansion of personnel scale and the continuous increase of project complexity. At present, the platform carries meituan catering, supermarket, flash shopping, errands, medicine and other business categories. The user entrance also covers meituan App takeout channel, takeout App, Dianping and other independent apps. Because the client has been focusing on business development, in order to meet the needs of fast online business, UI components are not unified, but scattered to various business scenarios. In the development process, due to the lack of the same UI standard, the following problems are constantly highlighted:

The UI/UE level

① The UI lacks standardized design specifications, and the design styles are not unified in different apps and different language platforms, and the user experience is inconsistent.

② The design resources and codes are lack of unified management means, unable to achieve accumulation and precipitation, unable to adapt to the development needs of new business.

RD level

(1) Component code fragmentation, there are many times of development, quality is difficult to guarantee.

(2) The API of each end is not unified, the cost of maintenance and expansion is high, and it is difficult to achieve the requirements of changing the theme and adapting Dark Mode.

QA level

Repeat walk check, frequent regression, and verify component quality for each release.

The PM levels

The version iteration efficiency is low and the throughput of version requirements is low, which cannot meet the rapid expansion capability of services.

Based on the practical pain points in the above development work, and the foreseeable development needs for client capabilities in the future, we urgently need a unified SET of UI design specifications to precipitate the design style and establish a unified UI design standard, so as to separate the mature business scenarios. Provide high quality, extensible, unified configuration can be based on Android/iOS/MRN/Mach components of the development of the code base, and support multi-business high-level code reuse ability, improve the UI business capabilities, so that the project has a high degree of consistency.

We through building blocks the Sketch design code plug-in to be born, can ensure that the design elements are obtained from the given design criteria, design language output in line with the business of design draft, and the platform also has a corresponding implementation in the UI component library, which makes blocks plug-in UI consistency of gripper, finally can reduce development costs, improving the quality of delivery, Provide good service to our multiple business teams.

2. Sketch & Sketch Plugin

To maintain UI consistency, rules must not be broken. From color selection, font specification and control style in design stage to unified code management, API formulation and multi-terminal implementation mode in RD development stage, a set of rules must be observed. The construction of Sketch Plugin is a solution to implement the specification.

Before discussing its importance, a quick introduction to Sketch: Sketch is a design toolkit developed by BohemianCoding, based in the Hague, the Netherlands. Currently, the BohemianCoding team has less than 100 members working remotely and collaboratively over the Internet in multiple countries around the world, and is typically a highly effective development team.

Sketch is easy to understand and use; Can create, update and share all Symbol components with everyone in the team, to achieve the sharing and version management of design resources, farewell to “final-final-final-1”; Its version iteration speed is very fast, and can constantly add new functions to meet the needs of users, more in line with the Internet era; Sketch can be designed with real data. At present, our design team has fully used Sketch for design.

Design languages include Iconfont, color swatch, text specification, language, illustration, animation, components, etc. In fact, it is not an abstract concept. For example, when people mention “Meituan”, they will think of “Meituan Huang”, the lovely “kangaroo”, and those young riders on motorcycles wearing bright yellow clothes printed with “Meituan Takeout”. Through design language, we can better communicate brand propositions and design concepts. The UI team gradually precipitates the design language into the design specification and quantifies it into the building block Sketch Plugin, which makes the produced design draft correspond to components in the RD code base one by one, thus forming a complete closed loop and accelerating the delivery process of the whole business.

3. Building Block Sketch plug-in project

There are plug-ins like this already on the market, so why do we need to develop them ourselves? Because the UI design language has a strong correlation with its own business, different business color system, graphics, grid system, projection system, graphic relations are very different, the loss of any one of them will lead to the destruction of consistency. The general design elements provided by existing plug-ins cannot meet the needs of the takeout design team, so it is important to develop a plug-in that is strongly relevant to the business and has customizable functions.

In addition, unified brand symbols and brand features can also help deepen the impression of the product in the mind of users. Unified colors and interactive forms can help users deepen the sense of familiarity and trust of the product. A good design language itself can add points to the product experience and create a more consistent experience.

After a period of construction, the building Block Sketch plug-in has been equipped with Iconfont, standard color palette, component library, data filling, text template and other functions.

We can use Iconfont to pull SVG ICONS uploaded by the design team from the icon library of Meituan and directly apply them to the design draft. Standard color palette can limit the range of colors used by designers to ensure that the colors in the design draft conform to the design specifications; The component library contains the basic controls and general components extracted from the takeout business, which are reusable and standardized, and correspond to the code in the component library of different language platforms. The design efficiency, development efficiency and walkthrough efficiency of UI can be improved by using components in the component library. The data filling library can realize picture filling and text filling. The picture contains goods and business materials, and the text contains dishes, shop names and other information. Through data filling, designers can use real data to fill, making the design more intuitive and closer to the online environment. There are built-in specifications for the use of Head, SubTitle, Body and Caption in the text template. Click on the text layer according to the position of the text in the design, you can directly apply properties such as font, line height and spacing.

In addition, we continue to add new features based on the feedback of design students. At the same time, it is also expanding the use scenarios of plug-ins, adding the function of switching between business lines, so that the building blocks plug-in can serve more teams, and it is expected that it can become the “intimate partner” of more designers.

4. Why write this article?

After reading the above, you must be eager to check out the Sketch plugin to quickly improve your team’s development efficiency.

Actually, before we get started, let’s look at some of the downsides. Firstly, due to the rapid update speed of Sketch, the official documentation is very simple and outdated. Therefore, many well-known Sketch Plugins give up maintenance due to the large change of API each time. Secondly, due to the confusion of the development technology stack, mature projects are generally not open source yet, and open source projects are basically of no reference value, most of which are “update 3 years ago”. Last but not least, macOS development data is scarce.

We read a lot of documentation and don’t get it all figured out. It seems like a lot of wikis don’t make sense when they explain key points, such as how a much-anticipated feature is implemented. In the last popular science article about Sketch Plugin on Zhihu, many netizens commented that “I can buy teaching videos with money”. After stepping on the pit step by step, we summed up some development experience. In order to avoid people “stepping on the pit”, we decided to write an article to record the development process. There are still a lot of gaps compared to mature projects that have been updated many times, but at least there is less confusion.

Of course, even if you think of yourself as a “sketchless” developer, we think this article is worth reading because it will expose you to front-end, mobile, desktop, and server-side development. As we all know, more and more companies are starting to hire full-stack engineers, like Facebook, which basically only hires full-stack engineers. Are you thinking to yourself, “Is this funny? Just a plugin?” Don’t jump to conclusions yet.

Are you ready? Offer it!

Before I go Coding

Okay, don’t hit the keyboard yet. After all, we didn’t even decide which language to use for development, which had been a problem for a long time. Currently, there are two ways to develop Sketch Plugin:

Using a hybrid development mode of JavaScript and CocoaScript, the Sketch team maintains an official JS API and writes a very encouraging quote on the developer website: “Take advantage of ES6, access macOS frameworks and use the Sketch APIs without learning Objective-C or Swift.”

Ideal is very happy, but the reality is very skinny. The API is not yet complete and many features are not available, so we need to use CocoaScript to access the richer internal API.

(2) Directly using Objective-C or Swift, and with macOS UI framework AppKit for development, simple and crude, and can use OC runtime directly call Sketch internal API. One caveat, however, is that you run the risk that as Sketch gets updated, the naming and usage of the internal API will change so much that many well-known plug-ins will not update.

This article uses the “hybrid development model” to explain, hoping to give you some inspiration.

1. School of Sketch Plugin

2. Configure the environment

Skpm (Sketch Plugin Manager) is an official tool provided by Sketch for Plugin creation, Build, and release. Skpm uses Webpack as a packaging tool, although Rollup or Roadhog can also be used if you are familiar with the front end. However, in case you encounter various errors, this is not recommended.

Skpm provides a number of templates to help you get started quickly. The most useful is Skpm/with-webView, which can help you create a Demo based on a WebView presentation, and Skpm will, after the build is complete, Automatically creating a Symbolic Link adds the plug-in to Sketch’s installation directory, making the Plugin immediately available.

SKPM NPM install -g SKPM create my-plugin --template= SKPM /with-webview // install NPM install NPM run buildCopy the code

3. Project structure

Plugin Bundle After following the steps above, we will have the following Plugin directory, which stores the source files in a standardized hierarchical structure and builds the generated Sketch plug-in installation package. Instead of using the simplest Demo in official documents, the most commonly used with-webview template in current development is used for analysis, so as to avoid the problem of “calculus” after learning “1+1”, and most plug-ins are expanded on this basis.

Parameters in the directory, which I’m sure you’ll understand as soon as you read the comments. However, if you have no front-end development experience, you may not know that the file name of the script file will change after being packaged by Webpack. For example, webView.js in Resources will be stored in the resources folder of the plug-in after being packaged. The file name is changed to resources_webview.js. Therefore, if you need to reference this file in HTML during code writing, use the packaged file name, that is:. Here’s a tip: if you don’t know the filename and path of the packed script file, it is recommended to compile it using Webpack first, then check its location and name in the packed Plugin, and then reference it.

├─ Exercises ─ Assets // As needs to be changed to be in the package. The json SKPM) assets set ├ ─ ─ my - plugin. Sketchplugin / / SKPM build process generated plug-in package │ └ ─ ─ Contents │ ├ ─ ─ Resources │ │ └ ─ ─ │ ├─ ├─ ├─ manifest.json │ ├─ __my -command. Js │ └ ─ ─ __my -command. Js. Map ├ ─ ─ package. The json ├ ─ ─ webpack. SKPM. Config. Js ├ ─ ─ the resources / / resource file │ ├ ─ ─ Style. CSS │ ├─ ├─ manifest.txt │ ├─ manifest.txt │ ├─ manifest.txt my-command.jsCopy the code

Manifest

You read that right! Manifest.json is also available in plugin, which has the same meaning as manifest files in other platforms such as Android development. The manifest file records author information, description, icon, how to get updates, and so on. When you think about staying up all night writing code, you have to write your name down somewhere. But the most important thing manifest does is tell Sketch how to run plug-ins and how to integrate them into Sketch’s menu bar.

Commands uses an array that records all commands provided by the plug-in. In the following example, function showPlugin() in script.js is executed when the user clicks on the “Show toolbar” item from the menu bar. Menu provides the layout of the plug-in in the Sketch menu bar, which is initialized when the plug-in is loaded.

{
  "commands": [{"name": "Show toolbar"."identifier": "roo-sketch-plugin.toolbar"."script": "./script.js"."handlers": {
        "run": "showPlugin"}}]."menu": {
    "title": "🦘 Takeout Building Blocks SketchPlugin Toolbar"."items": ["roo-sketch-plugin.toolbar"]}}Copy the code

package.json

Simply put, as long as your project uses NPM, the package.json file is automatically generated in the root directory. The Node.js project follows a modular architecture, and package.json defines the various modules and configuration information needed for the project. Using the NPM install command automatically downloads the required modules from this configuration file, that is, the runtime and development environment required to configure the project.

It is very commendable that Plugin development can use Node.js-compatible Polyfill for network requests, I/O operations and other functions. Many of the commonly used modules are already pre-installed in Sketch. Console, Fetch, Process, QueryString, Stream, util, etc.

Here’s what you need to know:

  • Scripts that need to participate in Webpack packaging must be declared in the Resources directory, otherwise they will not participate in compilation (important! Take the exam! .
  • The assets directory must be configured under skpm.assets.
  • Common commands can be defined in scripts for direct invocation.
  • The Dependencies field specifies the modules on which the project runs, and devDependencies specifies the modules needed to develop the project.
{
  "name": "roo-sketch-plugin"."author": "hanyang"."description": "Takeout building blocks Sketch Plugin, UI students love ~"."version": "0.1.0 from"."skpm": {
    "manifest": "src/manifest.json"."main": "roo-sketch-plugin.sketchplugin"."assets": ["assets/**/*"]},"resources": [
    "src/webview/template/webview.js"]."scripts": {
    "build": "rm -rf roo-sketch-plugin.sketchplugin && NODE_ENV=development skpm-build",},"dependencies": {},
  "devDependencies": {}}Copy the code

4. API Reference

Javascript API

Plugin scripts are fully supported by ES6 because they use the same JS engine as Safari. The official JavaScript API is maintained by the Sketch team and allows access to and modification of Sketch documents, providing data to Sketch users and some basic user interface integration.

// Access, modify, and create documents from color to layer to symbol
var sketchDom = require('sketch/dom')
// For asynchronous operations, the JavaScript API provides fibers to extend contex lifeTime
var async = require('sketch/async')
// To provide image or text data directly in Sketch, DataSupplier integrates directly with the Sketch user interface.
var DataSupplier = require('sketch/data-supplier')
// Display notifications and get user input without rebuilding
var UI = require('sketch/ui')
// Save custom data for layers or documents and store user Settings for the plugin.
var Settings = require('sketch/settings')
Copy the code

CocoaScript Syntax

By giving JavaScript the ability to call the internal apis of Sketch and macOS Cocoa frameworks, CocoaScript means that many cool classes and functions are available in addition to standard JavaScript libraries. CocoaScript is built on top of Apple’s JavaScriptCore, the JavaScript engine that supports Safari.

Therefore, when you write code in CocoaScript, you are writing JavaScript. Mocha in CocoaScript implements JS to Objective-C Bridges. Although Mocha is included in CocoaScript, the documentation remains in the original Github. As a result, you won’t see any syntax tutorials in CocoaScript’s Readme. The trick here is that if you want to see the attributes, classes, or instance methods that Mocha passes native Sketch Objects to the JavaScript layer via bridge from Objective-C, you can print them out via console:

let mocha = context.document.class().mocha()
console.log(mocha.properties())
//OC
[executeOperation:withObject:error:]
//CocoaScript
executeOperation_withObject_error()
Copy the code

The basic syntax for calling Objective-C using JavaScript via the CocoaScript Bridge is as follows:

  • Objective-c’s square bracket syntax “[]” is converted to the dot “. “syntax in JavaScript.
  • Objective-c properties are exported to JavaScript with getters of Object.name () and setters of Object.name = ‘Sketch’.
  • Objective-c selectors are exposed as JavaScript proxy methods.
  • The colon “:” is converted to the underscore “_”, and the last underscore is optional.
  • Calling a method with an underscore needs to be doubled to two underscores: sketch_method becomes sketch__method.
  • Each component of the selector is concatenated into a single undelimited string.

5. Actions

defining

Actions refer to events that occur in the application as a result of user interaction, such as “open document,” “close document,” “Save,” and so on. Sketch provides an Action API that allows plug-ins to react to events in an application, similar to BroadCast or Job Scheduler in Android development. The official documentation lists hundreds of actions that you can listen to, but the most commonly used are the following:

Listen to the callback

We simply add a handler to the manifest.json file of the plug-in. For example, the following example adds a listener for “OpenDocument”, which tells the plugin to execute the onOpenDocument function when a new document is opened.

 {
      "script": "action.js"."identifier": "my-action-listener-identifier"."handlers": {
        "actions": {
          "OpenDocument": "onOpenDocument"}}}Copy the code

When an Action is triggered, it calls back the listening method in the JS, and Sketch can send the Action Context to the target function, which contains some information about the Action itself. In the following example, a Toast pops up every time a document is opened.

function onOpenDocument(context) {
    context.actionContext.document.showMessage('Document Opened')}Copy the code

6. Bridge two-way communication

In general plug-in development, the UI layer is implemented using Webview, so you can use various front-end frameworks such as React or Vue. The logical layer of the plug-in (responsible for calling the Skecth API) is obviously not in the WebView, so it needs to communicate through the Bridge. The logical layer will pass the data obtained from the server to the UI layer for presentation, while the UI layer will pass the user’s operation feedback to the logical layer and make it call the Sketch API to update Layers.

The plug-in sends a message to the WebView

//On the plugin:
browserWindow.webContents
  .executeJavaScript('someGlobalFunctionDefinedInTheWebview("hello")')
  .then(res= > {
    // do something with the result
  })
​
//On the WebView:
window.someGlobalFunctionDefinedInTheWebview = function(arg) {
  console.log(arg)
}
Copy the code

The WebView sends a message to the plug-in

//On the webview:
window.postMessage('nativeLog'.'Called from the webview')
//On the plugin:
var sketch = require('sketch')
browserWindow.webContents.on('nativeLog'.function(s) {
  sketch.UI.message(s)
})
Copy the code

After the above steps, we have a basic plug-in that uses WebView as the content carrier and has two-way communication. When the plug-in is opened, the Webview will pass the event that the page is loaded to the logical layer. The logical layer calls the Sketch API to pop up Toast. Click Get a random number to retrieve a random number from the logical layer.

Come and officially join the development team

After reading the above section, you should be able to create a simple plug-in. But at this point, the question arises: why is the UI of Demo so different from that of plugins?

Yes, the official documentation only teaches the basics of the plug-in development process, and a mature commercial project is much more than that. A fully functional plug-in should have three parts: the toolbar, the WebView container, and the business data. Below, we will show you step by step how to develop a commercial plug-in UI, as well as how to implement the “fill function” of Meituan Takeout (note: only the key code is reserved in the document for reasons of length).

1. Create the adsorption toolbar

The so-called adsorbed toolbar is displayed next to the Inspector Panel on the right side of Skecth. It absorbs into the Sketch interface in a adsorbed way, which is also the visual representation of most plug-ins. The toolbar shows most of the functions that the current plug-in can provide, making it easy for us to quickly select and use the Document when working with it.

The development toolbar mainly uses NSStackView, NSButton, NSImage and NSFont classes. These classes may be unfamiliar to those who have not developed macOS applications. They can be compared to the control classes prefixed with UI in iOS development. NS prefixes are mainly related classes of AppKit and Foundation, MS prefixes are related classes of Skecth, CA and CF prefixes are core animation library and core Foundation classes.

The following code documents the key steps to create a toolbar. For more details, refer to Github repositories such as Sketch-plugin-BoilerPlate.

const contentView = context.document.documentWindow().contentView();
const stageView = contentView.subviews().objectAtIndex(0);
​
/ / 1. Create the toolbar
const toolbar = NSStackView.alloc().initWithFrame(NSMakeRect(0.0.27.420));
toolbar.setBackgroundColor(NSColor.windowBackgroundColor());
toolbar.orientation = 1;
​
/ / 2. Create a Button
const button =  NSButton.alloc().initWithFrame(rect)
const Image = NSImage.alloc().initWithContentsOfURL(imageURL)
button.setImage(image)
button.setTitle("Data filling")
button.setFont(NSFont.fontWithName_size('Arial'.11))
​
//3. Add Button to toolbar
toolbar.addView_inGravity(button, gravityType);
​
//4. Add toolbar to SketchWindow
const views = stageView.subviews()
const finalViews = []
for (let i = 0; i < views.count(); i++) {
 finalViews.push(view)
 if(view[i].identifier() === 'view_canvas'){
   finalViews.push(toolbar)
}
 stageView.subviews = finalViews
 stageView.adjustSubviews()
Copy the code

2. Create a WebView container

In addition to creating native NSPanel via CocoaScript, it is recommended to quickly create WebView containers using the official Sketch-module-web-view, which provides rich apis to customize the presentation style and behavior of Windows. Including Frameless Window, Drag, etc., but also encapsulates the WebView and plug-in layer communication Bridge, This allows you to easily send messages between “frontend” (the WebView) and “Backend” (the plugin running in Sketch).

//(1) Method 1: Join webView natively
const panel = NSPanel.alloc().init();
panel.setFrame_display(NSMakeRect(0.0, panelWidth, panelHeight), true);
const wkwebviewConfig = WKWebViewConfiguration.alloc().init()
const webView = WKWebView.alloc().initWithFrame_configuration(
  CGRectMake(0.0, panelWidth, panelWidth),
  wkwebviewConfig
)
panel.contentView().addSubview(webView);
webview.loadFileURL_allowingReadAccessToURL(
  NSURL.URLWithString(url),
  NSURL.URLWithString('file:///'))//(2) Use the official BrowserWindow
import BrowserWindow from "sketch-module-web-view";
const browserWindow = new BrowserWindow(options);
const webViewContents = browserWindow.webContents;
​
 webViewContents
    .executeJavaScript(`someGlobalFunctionDefinedInTheWebview(The ${JSON.stringify(someObject)}) `)
    .then(res= > {
      // do something with the result
    })
 browserWindow.loadURL(require('./webview.html'))
Copy the code

3. Create a content page

After a lot of hard work, we finally got the WebView, and now you can let your imagination run wild. React, Vue, or simply static pages should be easy for you. After completing the interface development, simply send instructions to the plug-in through the Window. The following example demonstrates the “data fill” functionality of the Building blocks plug-in.

The UI side

import React from 'react';
import ReactDOM from 'react-dom';
​
// Use react to build the user page
ReactDOM.render(<Provider store={store}><App /></Provider>.document.getElementById('root'));
​
// Pass the user click on the fill category to the plugin layer, using the fill text as an example
export const PostMessage = (name, fillData) = > {
  try {
    window.postMessage("fill-text-layer", fillData);
  } catch (e) {
    console.error(name, "An exception!!"+ fillData); }};Copy the code

The plug-in side

  browserWindow.webContents.on('fill-text-layer'.function(s) {
   // Find the current page document
  const document = context.document;
   // Get the layers selected by the user
     const selection = Document.fromNative(document).selectedLayers;
        layers.forEach(item= > {
          // Check whether the layer type is literal
          if (item.type === 'Text') {
            / / update the textlayeritem.text = value; }}); })Copy the code

4. Also want to add some fancy features

If you are not satisfied with this, it means that you really love learning and have the potential to develop students. A good plug-in requires an interaction layer, an API layer, a business layer, a debug layer, and a release layer, each of which is doing its job in silence.

The previous steps, through the component menu bar, creating a Webiew completed the development of the interaction layer; Pass user actions to plug-in side code via Webview Bridge, and then call Sketch API to operate the layer. This is the job of API layer. It is the job of the business layer to write business code according to its own needs and rely on the implementation of the interaction layer and API layer. At this point, you should have a working plug-in.

In addition, Lint components are also required to assist development during code writing, and various Dev tools are used to debug problems. After passing QA verification, Cli tools are required to package and release plug-in updates. In this section, we will briefly cover some basic debugging and release layers.

Webpack configuration

Skpm uses Webpack as its packaging tool by default. Webpack is a static Module Bundler for modern JavaScript applications. When Webpack processes an application, it recursively builds a Dependency Graph containing each module needed by the application, and then bundles all these modules into one or more bundles that need to be configured in webpack.config.js. Similar to Gradle in Android, it also supports various plug-ins.

Since the developer of the plugin may not be a front-end student and may not have been exposed to Webpack before, we’ll cover some of its common configurations to give you more time to focus on your business code. My first contact with Webpack was in an internal technical training of the company last year (Meituan Institute of Technology provides many technical training courses, so we can enjoy swimming in the ocean of knowledge). Webpack is the package scheme of MEituan MRN project.

There are various packaging tools in the front circle, such as Webpack, Rollup, Gulp, Grunt, and so on. RN packaging uses a set of tools called Metro implemented by Facebook, while The selection of MEituan MRN packaging tool is Webpack, because Webpack has a powerful plug-in mechanism and rich community ecology, which can complete the complex assembly line packaging work. Webpack also plays an important role in Plugin development. Webpack has five core concepts:

In plug-in development, various files such as HTML, CSS, Sass, JPG and style need to be processed. These files can only be processed after the corresponding Loader is configured in Webpack. It is also likely that some files will require a specific plug-in, while others will not. The following examples illustrate three common basic operations: adding plug-ins, processing files individually, and configuring parameters.

module.exports = function (config, entry) { 
  // Common function 1: add plug-ins
    config.module.rules.push({
    test: /\.(svg)([\?] ? $/. *).use: [{loader: "file-loader".options: {
          outputPath: url= > path.join(WEBPACK_DIRECTORY, url),
          publicPath: url= > {returnurl; }}}}); }// The file is processed separately
if (entry.script === "src/script.js") {
    config.plugins.push(
      new htmlWebpackPlugin({ })
    );
}
​
// Create a custom JS process
  config.module.rules.push({
    test: /\.jsx? $/.use: [{loader: "babel-loader".options: {
          presets: [
            "@babel/preset-react"."@babel/preset-env"].plugins: [
            // Introduce the ANTD component library
            ["import", {libraryName: "antd".libraryDirectory: "es".style: "css"}}}}]]]);Copy the code

ESLint configuration

JavaScript is a very flexible language, many errors are often exposed at runtime. By configuring the front-end code check scheme, error feedback can be directly obtained during code writing and code style check can be carried out, which not only improves the development efficiency, but also corrects bad code writing habits. You need to configure basic syntax rules, React rules, and JSX rules in ESLint. Due to the special CocoaScript syntax of Sketch, you need to configure global variables to ignore classes that cannot be identified in AppKit.

Although we have been “amley” ESLint’s power many times in departmental group meetings (here is a technical article on ESLint’s application practices in large and mid-size teams), those of you who are not front-end or RN developers may not be familiar with the complex configuration of ESLint. You can directly use the ESlint Config provided by Skpm, which contains global variables containing header files for Sketch and macOS, while Prettier is recommended for code formatting.

NPM install --save-dev eslint-config-sketch // Or use the SKPM template project $SKPM create my-plugin with prettier in esLint --template=skpm/with-prettierCopy the code

Content server-side

The Library features of Sketch play a very important role in maintaining a design system or style guide. They can create an efficient working experience for the team and even change the way the design team works and processes. The Component Library allows us to share symbols across the design team. The Library makes it possible to “change one place, work everywhere”. Even design drafts associated with a remote component Library history are notified of updates, ensuring that we are working with the latest components.

Library functions play a crucial role in the consistency of MEituan takeout UI, which is mainly reflected in two aspects: First is to realize the design style of precipitation, the kangaroo UI has formed its own unique style, take-out design team, according to the design specifications to meet the UI consistency take-away business scenarios the components of the abstraction and construction unceasingly, precipitation out more and more common business components, these components require timely expansion to the Library, for the use of team members; Another function is to keep the team using the latest components. Due to various reasons, the design elements of components (colors, fonts, rounded corners, etc.) may change, so team members need to be reminded to update the components in time to keep all pages consistent.

The automatic update of library components is actually the association of “library list” – “library ID” – “external component original ID”. Object identification in Sketch is done by UUID. According to the library ID of the library component, all undisabled and well-linked libraries are retrieved from the list of the library panel according to the added time, from the new to the old, until the LIBRARY ID is matched, and then the library file is searched to see if there is a component that matches the SymbolID of the library component. If the content is included and the content is different, the update process is actually content replacement.

We used RSS technology to share the Library for use by the entire UI design team through the following steps:

  • Host the Library Document on the corporate Intranet server.
  • Create an XML file to record version information and update addresses.
  • Finally, use a tool like the Meyerweb URL encoder (or direct encodeURIComponent) to encode the XML feed URL and add it to the following: sketch://add-library? Url = https:// * * *. The XML.
  • Just open the URI in a browser.
<? xml version="1.0" encoding="UTF-8"? ><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle">
  <channel>
    <title>My Sketch Library</title>
    <description>My Sketch Library</description>
    <image>
      <url></url>
    </image>
    <item>
      <title>My Sketch Library</title>
      <pubDate>Wed, 23 Jun 2019 11:19:04 +0000</pubDate>
      <enclosure url="mysketchlibrary.sketch" type="application/octet-stream" sparkle:version="1"/>
    </item>
  </channel>
</rss>
Copy the code

5. Summary of development process

Here’s a quick summary of the plug-in development process:

  • Start by developing the action panel using JavaScript or CocoaScript.
  • Install the required dependencies using NPM.
  • The user action is passed to the plug-in logic through the Bridge, and the document is processed by calling the Skecth API.
  • Use Webpack for packaging.
  • Release plug-in updates after testing.

Things people may not tell you

This part mainly records the experience of stepping on holes in the development process of building block Sketch Plugin. However, we did not paste a large section of code here, and did not directly tell you the answer. Instead, we recorded the process of analyzing problems. “It is better to teach a man to fish than to give him a fish.” I believe that as long as you understand these analytical skills, even if you meet more problems later, you can solve them easily.

1. Mix compilation with Xcode projects

First, we need to clarify the question, why use XCode project?

Although the OFFICIAL JS API is provided and the promise of continuous maintenance is made, the work is always in Doing state, and the official documentation is updated slowly with no clear timeline. Therefore, for some features, such as building a plug-in with a Native Inspector Panel, we have to use XCode for development. Developing with Xcode is also more friendly for iOS developers, eliminating the need to learn about front-end interface development.

Invison developer James Tang shared a blog post called Sketch Plugin Xcode Template, which describes in detail the steps to build the Plugin Xcode project, which has become a model for many Plugin developers to follow. Of course, with the continuous upgrading of Sketch, some apis are no longer supported, but the development process and ideas described by the author remain unchanged, which is of great learning value.

Var Mocha = mocha.sharedrunTime (); [mocha loadFrameworkWithName:frameworkNameinDirectory:pluginRootPath]
Copy the code

In addition, @skpm/ XcodeProj-loader has been built into Skpm, and the Framework can also be directly loaded in JS.

JavaScript // load framework const framework = require('.. /xcode-project-name/project-name.xcodeproj/project.pbxproj');
const nativeClass = framework.getClass('NativeClassName'); // getNib file const UI = framework.getnib ('NativeNibFile'); // XiB file const NibUI = require('.. /xcode-project-name/view-name.xib')
var nib = NibUI()
let dialog = NSAlert.alloc().init()
dialog.setAccessoryView(nib.getRoot())
dialog.runModal()
Copy the code

You can also use some of Github’s well-known open source projects directly, some of which provide the Framework for you to use, such as changing the native toolbar:

2. Understand the Electron

Why is Electron suddenly mentioned in the Sketch Plugin? Here is a small story, one day at work to open the elephant (Meituan internal communication software).

The company has established the Electron technology Club (many technology clubs have been set up spontaneously within meituan technology team). After learning about it, it is found that Electron can build desktop applications using HTML, CSS and JavaScript based on Chromium and Node.js. Electron takes care of the more complex parts of this, and developers only need to focus on the core requirements of the application. The Mac terminal of Elephant uses Electron technology extensively to develop desktop applications with Web framework, which can directly reuse the existing development results of Web and obtain excellent operation efficiency.

After a brief learning, we did not pay attention to this technology for a period of time, until one day in the process of plug-in development, we suddenly encountered a problem: when the plug-in WebView was displayed, the Sketch software lost its focus by clicking on the blank part of the desktop, and the whole App would be hidden. I tried several popular plug-ins and found that most of them had this problem, which caused a lot of inconvenience to the designer’s work. Imagine, I’m just going to open Finder to find a file, why would you minimize my software? After leaving a comment on Github and getting an official reply from project developer Mathieu Dutour, it turns out that all you need to do is set up a hidesOnDeactivate attribute.

Wait a minute! Isn’t that a property in Electron? “The API is mimicking The BrowserWindow API of Electron.” That’s a lot easier! If you want to customize the appearance of the window, just follow the Electron API Settings. Does Electron work in the same way as the Sketch Plugin?

3. Update the native properties panel

In order to better improve the experience of using the building block Sketch Plugin, UI set up a public Wiki to record the feedback suggestions of our design team in the process of using the Plugin, among which there is a strange one: “After the Layer attribute is updated through the Plugin panel, the right panel is not refreshed.” As with the previous problem, most of the other plug-ins tested have this problem, but how do I update the right properties panel? Browsing through the API documentation of Sketch, I still have no idea. The Interface Inspector, a powerful tool developed by macOS, analyzes the Interface structure and properties of running Mac applications at runtime.

After downloading it happily, I found that the last update time of this software was 6 years ago, and suddenly I had a kind of foreboding. Sure enough, when you Attach any App, a message will be displayed indicating that you cannot Attach, and the macOS Catalina version will no longer work. But how is this supposed to baffle the “almighty” programmer? Mach_inject_bundle_stub = mach_INJect_bundle_stub = mach_inject_bundle_stub = mach_inject_bundle_stub = mach_inject_bundle_stub = mach_inject_bundle_stub = mach_inject_bundle_stub = mach_inject_bundle_stub = mach_inject_bundle_stub = mach_inject_bundle_stub

After Attach is successful, attribute analysis can be carried out on the panel of Sketch. Does it suddenly feel like opening the door of a new world? The right panel is in ms SpectorController after checking. As shown below:

Next you need to use the class-dump tool to extract the Sketch header file and see all the ways you can manipulate the Inspector panel:

As expected, we found Reload (), guessing that calling this method would refresh the panel and test that the problem was fixed. If you’re using the JavaScript API of Sketch, the names don’t necessarily correspond exactly, but they’re pretty much the same and can be found with a bit of analysis. This is just an idea so that even if you encounter other problems, try the steps above and you may be able to solve them.

JavaScript
// reload the inspector to see the changes 
var sketch = require('sketch')
var document = sketch.getSelectedDocument()
document.sketchObject.inspectorController().reload()
Copy the code

You will join us in the future.

As you can see, the Building block Sketch Plugin helps design teams improve design efficiency, deposit design language, and reduce the burden of walk-through. RD students can focus on business requirements without spending time on component writing when facing new projects; Reduce QA workload and ensure control quality without frequent regression testing; Help PM to improve version iteration efficiency and version requirement throughput, and provide rapid business expansion capability.

Of course, in addition to making first-class products, we also want building blocks to give you a break from your busy work schedule. We will continue to build UI consistency based on design language and Skecth Plugin to improve client UI business capability.

React, Webpack, etc., might be handy for a front-end engineer. For an iOS engineer, XCode debugging, Objective-C syntax is the foundation before development; Electron and Hook analysis are familiar to a desktop engineer. The Development of Sketch Plugin is so interesting. Although it is only a small plug-in, it will let you contact various technologies and improve your technical horizon. However, it will also make you encounter many difficulties in the development process. Colleagues in the department helped us contact a front-end girl with rich development experience to consult, who solved the problem with a line of code. Do what you’re afraid to do, and you’ll find that’s all.

At present, the development of building blocks plug-in is still in a relatively preliminary stage, including Mach (Takeaway development dynamic framework) real-time preview, template code automatic generation, self-built illustration library and other functions are on the way. In addition, we also planned a lot of exciting features, need to make more beautiful front-end pages, need more perfect background management.

Add an AD here! No matter you are FE, Android, iOS or backend, you are welcome to join our delivery technology team as long as you are not soft on bugs and keep improving. We will work with you to improve the Sketch plugin ecosystem, so that building blocks plugin can provide services for more business scenarios and provide excellent experience for users. Let’s use “building blocks” to create a thousand worlds together!

Well, that’s it for now! The UI team said that our implementation was one pixel off from the design draft, and we had to go back and fix the Bug.

Thank you

Special thanks to excellent designers Yu Han, Peidong, Miaolin and Xue Mei for their help in the plug-in development process.

Special thanks to yunpeng and Xiaofei from the technical team for their technical guidance.

“One generation plants trees, and another enjoys the shade.” We salute the great open source project developers.

reference

  • Official documentation for the Development of the Sketch Plugin
  • In-depth understanding of the Sketch library
  • Bump Lab High Master Sketch plug-in development practice
  • Sketch Plugin Xcode Template
  • Beginning Sketch Plugins Development in Xcode
  • Ctrip Flight Ticket Sketch plug-in development practice

Recruitment information

Meituan takeout is looking for senior/senior engineers and technical experts on Android, iOS and FE. Welcome to join the family of takeout apps. Please send your resume to [email protected] (subject: Meituan Takeout Technical team)

To read more technical articles, please scan the code to follow the wechat public number – Meituan technical team!