免费下载!由 O’Reilly 出版的《NGINX 完全指南》中文版已正式上线 了解详情
写点什么

携程机票 Sketch 插件开发实践

  • 2020-02-15
  • 本文字数:5361 字

    阅读完需:约 18 分钟

携程机票Sketch插件开发实践

Sketch 是伴随移动应用程序崛起而流行的 UI 设计工具。2014 年 Sketch V3 增加 Symbols 功能,在 UI 设计工具领域的优势越来越大。它持续改进和增强功能,不断加强对插件社区的建设,吸引越来越多的开发者进入。




随着 Design System 的普及和流行,许多大公司都在设计插件领域有所投入,如 Google,Airbnb 等,同时诞生了一系列提供设计管理的初创企业,如 Abstract,UXPIN 等。中国很多大中型互联网企业也开始研制自己的设计系统和插件工具,例如 Dapllo,Kitchen,Fusion,Anto。


2016 年,携程机票 UED 团队主力生产工具完全切换到 Sketch。与此同时,机票前端研发技术团队也关注到设计系统和插件工具规范化自动化对业务交付工作流程的加速作用。于是设计团队与前端技术团队开始携手探索设计语言升级,从业务需求项目实践中提炼通用规范,落地插件工具系统,并输出一整套设计资源管理规范和流程。

一、设计资源管理

产品的设计语言是一家公司留给消费者最直观的形象,通常包含品牌 Logo,颜色,文字,符号,插画,动画和文案话术等。而 Design System 是为了让设计语言落地执行而构建的解决方案,包括设计指导文档,设计资源,组件代码和工具等。


设计资源的共享和版本管理一直困扰着设计师们。Sketch 通过引入 Symbols,Library 等功能解决了共享组件问题,但在颜色,文字排版,图标管理等问题上依然缺少足够好的解决方案,需要各家公司针对自身的特点开发插件和服务去解决这些问题。


二、Kirby - Sketch Plugin

Kirby 是携程机票前端团队的 Sketch Plugin 系统代号,故事源于一次 Sketch 版本升级引起的标注导出功能失效问题。


Sketch 社区著名插件 Sketch Measure,它将设计稿和数据参数导出 HTML 网页,供技术人员查看,节省从设计到开发过程的沟通成本。但 Sketch 的版本升级经常致其无法正常使用,维护者也无暇快速修复问题,设计师们若继续使用,将被迫使用一个低版本 Sketch。


为了让设计师能够使用 Sketch 最新版本,并修复 Sketch Measure 缺陷功能,Kirby 诞生。


之后我们陆续添加更多功能,从 Design Token,到 Icon System,再到 Component,以及 Template,一步步接近成熟和完整。


Kirby 目前已交付若干重要特性:

2.1 设计语言规范约束

Color Pallete



Typography



Shadow


2.2 设计稿静态扫描检查

方便设计师查找和修正问题。



字体与图标系统



在线版设计资源模版库


三、Sketch Plugin 开发技术

在插件开发实现过程中,我们遇到许多交叉技术领域的问题,也因此进行了多次技术重构。

3.1 基础知识

Sketch 官方技术文档提供了简单介绍:


1)Sketch 插件是按照特定方式管理的一个文件夹,包含一个或多个 scripts,每个 script 含有若干扩展 Sketch 用途的命令。


2)插件主要使用 Javascript 语言编写,支持 ES6 语法,但运行环境既不是浏览器也不是 Nodejs,而是 Hybrid SketchAPI for macOS Native 运行环境。


从最简单的部分看起:


打开一个 Sketch 文件,control + shift + k 快捷键开启 Run Script 面板,输入:


const sketch = require('sketch')sketch.UI.message('Hello, world!')
复制代码


运行以上代码,将在 Sketch 文件下方区域显示 Toast:Hello, world,该 Script 面板常用于快速测试脚本 API。

3.2 API 概述

The plugin system in Sketch gives you full access to the app’s internals and the core frameworks in macOS. So you have an immense power to build almost anything.


Sketch 插件系统开放了几乎所有权限,让许多天马行空的想法可以实现。但是插件开发者需要及时关注 Sketch 版本升级,其向下兼容性较差,或者说官方团队并不重视这部分。典型案例例如,著名插件 Paddy,在开发 V2.0 版本过程中,因 Sktech API 大量变更,原插件无法兼容,作者最终无力修复而放弃开发,非常可惜。


官方 API 有两个: Actions API, Javascript API。

3.3 Actions API

用于监听用户操作行为和触发的事件。据社区消息,该 API 未来会被新的 Events API 替代。它代表了 Sketch App 内部触发的事件,例如 CloseDocument, TogglePresentationMode 等, 细节详见官网:


https://developer.sketch.com/reference/action/


1)订阅 Actions


manifest.json 文件,配置相应 handlers。


示例:当 OpenDocument 事件被触发时调用 onOpenDocument handler 。


"commands" : [  ...  {    "script" : "my-action-listener.js",    "name" : "My Action Listener",    "handlers" : {      "actions": {        "OpenDocument": "onOpenDocument"      }    },    "identifier" : "my-action-listener-identifier"  }  ...],
复制代码


my-action-listener.js


export function onOpenDocument(context) {  context.actionContext.document.showMessage('Document Opened')}
复制代码


2)Action Context


Action 事件会将 context.actionContext 传递给 handler。有些 Action 包含两个状态,begin 和 finished,例如 SelectionChanged 。需分别订阅 SelectionChanged.begin 和 SelectionChanged.finished,否则会触发两次事件。


当我们不知道应该订阅哪个 Action 时,可以使用通配符。但运行时性能开销很大,建议仅在开发阶段使用。


示例:Terminal 打开通配符支持。


defaults write com.bohemiancoding.sketch3 actionWildcardsAllowed -bool YES
复制代码


manifest.json 文件配置通配符。


{  ...  "handlers": {    "actions": {      "*": "onActionHandler"    }  }  ...}
复制代码

3.4 Javascript API

它是针对 Native API 的封装,目前还未涵盖所有场景,官方承诺未来将覆盖 90%。细节详见官网和 GitHub:


https://developer.sketch.com/reference/api/


https://github.com/BohemianCoding/SketchAPI/blob/develop/CHANGELOG.json


3.5 开发环境

官方提供了一个打包工具 skpm, 用于快速上手插件开发。它基于 webpack,项目根目录下存放 webpack.skpm.config.js, 用于工程配置修改。


安装示例


npm install -g skpmskpm create my-plugincd my-pluginnpm run build# 然后在 Plugins -> my-plugin -> MyCommand 中运行插件命令
复制代码


典型的插件开发工程的目录结构示例


├── .gitignore├── README.md├── src                         // sources│   ├── manifest.json           // plugin's manifest│   └── my-command.js           // source code of the command├── node_modules│   └── skpm                    // the sketch plugin developer toolchain├── my-plugin.sketchplugin      // compilation output, the actual plugin│   └── Contents│       ├── Resources│       └── Sketch│           ├── manifest.json│           └── my-command.js└── package.json
复制代码

3.6 崩溃保护

当 Sketch 运行发生崩溃,它会停用所有插件以避免循环崩溃。对于使用者,每次崩溃重启后手动在菜单栏启用所需插件非常繁琐。因此可以通过如下命令禁用该特性。


defaults write com.bohemiancoding.sketch3 disableAutomaticSafeMode true
复制代码

3.7 插件缓存

通过配置启用或禁用缓存机制:


defaults write com.bohemiancoding.sketch3 AlwaysReloadScript -bool YES
复制代码


但是该方法对于某些场景不适用。例如当正在使用一个 long-running 脚本时,即 Javascript Context 不变,并存储在内存中,那么则需要重启 Sketch 或通过 coscript.setShouldKeepAround(false) 使改动生效。

3.8 WebView 调试

如果插件实现方案使用 WebView 做界面,可通过以下配置开启调试功能。


defaults write com.bohemiancoding.sketch3 WebKitDeveloperExtras -bool true
复制代码

3.9 打印输出日志

Sketch 运行环境 JavascriptCore 的日志输出方式:


1)macOS console.app 中搜索 与 sketch 相关的 Filter。


2)查看 ~/Library/Logs/com.bohemiancoding.sketch3/Plugin Output.log。


3)运行 skpm log 查看上述文件,-f 参数使用 stream 方式查看。


4)使用 skpm 开发的插件,可以使用 console.log 语法,需安装 sketch-dev-tools。

3.10 代码调试

Safari 浏览器开发工具可用于插件的 Javascript 代码调试。


Developer > name of your machine > Automatically Show Web Inspector for JSContexts

同时启用选项 Automatically Pause Connecting to JSContext

3.11 Objective-C Classes

Sketch 对外暴露了全部内部方法的调用权限,其 Objective-C 类 通过 Bridge 提供 Javascript API 调用。

3.12 插件 GUI 的实现

用户(设计师)可以通过以下几种方式使用插件:


1)菜单 -> 插件 -> 选择插件已定义的 Handler


2)Handler 预定义的快捷键


3)插件提供的其他 GUI 方案


其他 GUI 方案有 Native(Appkit) 和 WebView ,以 Kirby 为例,目前大部分 UI 由 WebView 实现。这种方案对于 Web 前端技术人员上手学习成本较低。 skpm 提供了已封装好的基于 WKWebView 的 sketch-module-web-view,其 API 设计接近 Electron,细节详见 GitHub。


https://github.com/skpm/sketch-module-web-view/blob/master/docs/browser-window.md


除此之外,skpm 还提供了一些供 JavaScript 调用的 Native 控件,例如 Dialog:


import dialog from '@skpm/dialog'console.log(  dialog.showOpenDialog({    properties: ['openFile', 'openDirectory', 'multiSelections']  }))
复制代码

3.13 CocoaScript GUI

CocoaScript is built on top of Apple’s JavaScriptCore, the same JavaScript engine that powers Safari. So when you write in CocoaScript, you are really writing JavaScript.

CocoaScript also includes a bridge which lets you access Apple’s Cocoa frameworks from JavaScript. This means you have a ton wonderful classes and functions you can use in addition to the standard JavaScript library.


Sketch 插件通过 Mohca / CocoaScript 连接到 Objective-C / Cocoa。Javascript 调用 Objective-C 方法,需要将方法名的冒号改为下划线(最后一个可选),所有 selector 连接成一个连续的字符串。例如 executeOperation:withObject:error: 将转为 executeOperation_withObject_error()。


示例:


/*打开文件对话框,使用 Appkit NSOpenPanel。https://developer.apple.com/documentation/appkit/nsopenpanel?language=objc*/var openPanel = NSOpenPanel.openPanel()openPanel.setCanChooseDirectories(false)openPanel.setCanChooseFiles(true)openPanel.setCanCreateDirectories(false)openPanel.setDirectoryURL(NSURL.fileURLWithPath('~/Documents/'))openPanel.setTitle('Choose a file')openPanel.setPrompt('Choose')openPanel.runModal()

//设置异步操作不被 Sketch GC回收COScript.currentCOScript().shouldKeepAround = true//异步执行完成后,释放COScript.currentCOScript().shouldKeepAround = false
复制代码

3.14 Native GUI

实现 Native GUI 的难点在于“合适的时机”找到“正确的实例”。Actions API 用于解决“合适的时机”问题。而寻找“正确的实例”相对复杂一些。首先从 Sketch-Headers 入手,搜索与事件有关的方法。


例如,当我们需要扩展 “创建组件“ 对话框,该对话框在 “创建组件” 事件发生时才会出现,因此在 Actions API 中搜索与 symbol 有关的事件,找到名为 Create Symbol 的 Action。然后继续搜索关键字 CreateSymbol,可找到如下结果。



code 能够以黑盒方式分析系统当前运行的应用程序界面,提取对于插件开发有用的信息。使用 Xcode 分析 Sketch 可知,MSCreateSymbolNamingSheet 继承自 NSWindowController,如下示例代码可获取其调用对象。


const doc = context.actionContext.document;const docData = doc.documentData();const window = doc.window();const sheetWindow = window.attachedSheet();const createSymbolNameingSheet = sheetWindow.windowController();
复制代码


3.15 Webview GUI

Webview 与 Plugin 之间需要实现双向通讯互操作。Webview 可通过 WKWebView delegates 向 Plugin 发送消息,Plugin 则通过 webView.evaluateJavaScript_completionHandler() 触发 Webview 执行 Javascript 代码。


export function createPopoverWKHandler () {    return new MochaJSDelegate({        'userContentController:didReceiveScriptMessage:': (function (controller, message) {            let body = Utils.toJSON(message.body()),                { key, value } = body            switch (key) {                case 'setTypography':                    Utils.setTextStyle(value)                    break            }        })    })}
复制代码

四、Milestone One

一个功能完整易用性佳的 Sketch 插件系统,除了上述技术实现细节,还有很多需要思考兼顾的方面。例如,设计文件版本管理,Sketch 版本兼容性,用户配置文件,云同步协作,用户(企业内网)鉴权认证接入。


Kirby 每一个新增功能都是围绕着从设计到研发再到交付的一致性和复用性,这也正是设计系统所要解决的核心问题。


我们 hack 的不仅是一个软件,而是完整的 DesignOps 工作流程。


作者介绍


尹正波,携程机票研发部前端工程师,专注设计和开发的交叉领域,用系统和工具改进设计体验和交付。


本文转载自公众号携程技术(ID:ctriptech)。


原文链接


https://mp.weixin.qq.com/s/b0jPTft4nKhVFraJl6H3_A


2020-02-15 17:46800

评论 1 条评论

发布
用户头像
模版库这边,插件展示模板是怎么个方案实现的呢?去读了Sketch文件的JSON数据解析出来后去渲染的?
2020-06-30 11:36
回复
没有更多了
发现更多内容

AI数据采集——数字世界的智能伙伴

来自四九城儿

[杂谈]大型JSON数据切分(Java Jackson)

alexgaoyh

json elasticsearch Jackson 分割

盘古云课堂加入 PolarDB 开源数据库社区

阿里云数据库开源

polarDB PolarDB-X PolarDB-PG PolarDB for PostgreSQL 阿里云瑶池数据库

腾讯云和ScaleFlux联合推出可计算存储与大容量QLC NAND解决方案

ScaleFlux

腾讯云 数据中心 降本增效 企业级SSD SSD寿命

通过自定义域名 + SSL 的方式访问 Amazon MQ for RabbitMQ

亚马逊云科技 (Amazon Web Services)

Redis Operator在中原银行实践落地及能力创新

中原银行

redis 云原生 operator redis operator

来了!昇腾MindStudio全流程工具链分论坛精彩回顾,助力高效开发和迁移效率提升

Geek_2d6073

可计算存储是否真的与众不同?

ScaleFlux

压缩数据 计算与存储 固态硬盘

从IDC数据库安全报告,看OceanBase安全能力

OceanBase 数据库

数据库 oceanbase

浅谈如何做好知乎内容营销:需要注意哪些细节

石头IT视角

云原生应用交付流程安全规范

穿过生命散发芬芳

安全规范 三周年连更

HTTPS 的加密过程及其工作原理

wljslmz

https 三周年连更

AE/PR插件-去朦胧除雾霾增强色彩调色插件ClearPlus

真大的脸盆

Mac AE插件 AE

软件测试/测试开发丨Python学习笔记之封装、继承、多态、模块

测试人

Python 软件测试 自动化测试 测试开发

AntDB数据库体验室上线啦!一站式培训+实操,带您感受“电信级”国产数据库的魅力

亚信AntDB数据库

AntDB AntDB数据库 企业号 5 月 PK 榜

2023 开源之夏|和 Milvus & Towhee 一起玩转 AI、享开源、得奖金

Zilliz

Milvus Zilliz 向量数据库 Towhee 开源之下

软件测试丨Pytest-运行用例、常用参数、执行pytest、异常处理

测试人

软件测试 自动化测试 测试开发 pytest

类似Redmine,但更好的7款项目管理工具

PingCode

项目管理 项目管理软件 Redmine

麻了,一个操作把MySQL主从复制整崩了

JAVA旭阳

Java MySQL

澳鹏与 Reka AI 强强联合,构建高质量的多模态 LLM 应用

澳鹏Appen

人工智能 数据标注 生成式AI

Flink中的时间及窗口类型

阿泽🧸

flink 三周年连更

被AI端掉饭碗之前,提升自己的硬核实力

这我可不懂

人工智能 AI ChatGPT

AI别来搅局,chatGPT的世界不懂低代码

引迈信息

人工智能 低代码 ChatGPT JNPF

专访惠众科技|元宇宙应用如何借助3DCAT实时云渲染实现流畅大并发呈现?

3DCAT实时渲染

元宇宙 实时渲染云

2023-05-10:给你一棵以 root 为根的二叉树和一个 head 为第一个节点的链表 如果在二叉树中,存在一条一直向下的路径 且每个点的数值恰好一一对应以 head 为首的链表中每个节点的值,

福大大架构师每日一题

Go 算法 rust 福大大

挑战与机遇,全面预算管理的执行计划

智达方通

如何通过appuploader把ipa文件上传到App Store教程步骤​

雪奈椰子

AI数据采集的挑战和解决方案

来自四九城儿

大数据如何助力营销(1)市场调研

MobTech袤博科技

用LeangooScrum敏捷工具做缺陷管理和迭代规划和迭代执行

顿顿顿

Scrum 敏捷开发 敏捷项目管理 敏捷工具 scrum敏捷工具

携程机票Sketch插件开发实践_技术管理_尹正波_InfoQ精选文章