开发一个基于uni-app的imgcook DSL

最近看到了阿里的前端智能化的实践:imgcook 由设计稿一键智能生成代码的大厨,由设计稿直接生成前端代码,试用了一下,比zeplin和蓝湖做的更进一步,可以直接集成到项目开发的过程中。但发现一个问题,imgcook官方支持的DSL并不多,我们团队是使用Uni-app做跨端开发的,希望能将设计稿直接生成符合uni-app的代码,但官方没有,找了一个其他开发者贡献的,也没有找到合适的,于是自己动手写(组装)了一个。

什么是DSL

imgcook最后解析出来的是一个个schema,大约长这样:

export default {
  "componentName": "Block",
  "id": "49111ab0-7bef-11eb-8fa6-15a5d2c3ef39",
  "props": {
    "style": {
      "display": "flex",
      "alignItems": "center",
      "flexDirection": "row",
      "justifyContent": "center",
      "width": "252px",
      "height": "19px"
    },
    "className": "mod"
  },
  "artboardImg": "https://ai-sample.oss-cn-hangzhou.aliyuncs.com/test/40d1bee07bef11eb999b6fe08011a65f.png",
  "rect": {
    "x": 0,
    "y": 0,
    "width": 252,
    "height": 19
  },
  "pluginVersion": "4.0.0",
  "name": "编组 7",
  "reference": "sketch",
  "restore_id": "11d65847-f8d2-48ce-b1a3-50e60f9a42a8",
  "children": [{
    "componentName": "Div",
    "id": "49111ab2-7bef-11eb-8fa6-15a5d2c3ef39",
    "props": {
      "style": {
        "display": "flex",
        "alignItems": "center",
        "flexDirection": "row",
        "marginTop": "1px",
        "borderRadius": "8.333333333333314px",
        "backgroundColor": "#016F48",
        "width": "250px"
      },
      "className": "wrap"
    },
    "rect": {
      "x": 1,
      "y": 2,
      "width": 250,
      "height": 16
    },
    "selfId": "0F85A572-20CC-4D31-A409-A140BDFF9466",
    "children": [{
      "componentName": "Div",
      "id": "49111ab1-7bef-11eb-8fa6-15a5d2c3ef39",
      "props": {
        "style": {
          "borderRadius": "8.333333333333314px",
          "backgroundColor": "#D4A351",
          "width": "186px",
          "height": "16px"
        },
        "className": "color"
      },
      "rect": {
        "x": 1,
        "y": 2,
        "width": 186,
        "height": 16
      },
      "selfId": "CB7B56F7-4631-49F3-86AA-B36EE62E70EC",
      "smart": {
        "nodeIdentification": {
          "baseComponent": ["sliderbar", "sliderbar"]
        },
        "nodeCustom": {
          "baseComponent": {
            "isConfident": true,
            "label": "sliderbar",
            "score": 0.9860943555831909,
            "type": "baseComponent",
            "meta": {
              "threshold": 0.9
            },
            "rect": {
              "x": 1,
              "y": 2,
              "width": 186,
              "height": 16
            },
            "selfId": "CB7B56F7-4631-49F3-86AA-B36EE62E70EC"
          }
        },
        "layerProtocol": {
          "component": {
            "type": "sliderbar"
          }
        }
      }
    }],
    "smart": {
      "nodeIdentification": {
        "baseComponent": ["sliderbar_low_confident"]
      },
      "nodeCustom": {
        "baseComponent": {
          "isConfident": true,
          "label": "sliderbar_low_confident",
          "score": 0.9999985694885254,
          "type": "baseComponent",
          "meta": {
            "threshold": 0.9
          },
          "rect": {
            "x": 1,
            "y": 2,
            "width": 250,
            "height": 16
          },
          "selfId": "0F85A572-20CC-4D31-A409-A140BDFF9466"
        }
      },
      "layerProtocol": {
        "component": {
          "type": "sliderbar_low_confident"
        }
      }
    }
  }],
  "smart": {
    "nodeIdentification": {
      "bizModule": ["smartModule"]
    },
    "nodeCustom": {
      "bizModule": {
        "isConfident": true,
        "label": "smartModule",
        "score": 0.9998334646224976,
        "type": "bizModule",
        "meta": {
          "threshold": 0.9,
          "props": {
            "labels": ["module_label_A", "module_label_B"]
          }
        },
        "rect": {
          "x": 0,
          "y": 0,
          "width": 252,
          "height": 19
        },
        "selfId": null
      }
    },
    "layerProtocol": {
      "module": {
        "type": "smartModule",
        "param": {
          "labels": ["module_label_A", "module_label_B"]
        }
      }
    }
  },
  "imgcook": {
    "restore_id": "11d65847-f8d2-48ce-b1a3-50e60f9a42a8"
  }
}

上述代码描述的是一个进度条组件,DSL要做的就是把这个描述转化成实际的Code,比如React、Flutter、Android等等。目前官方已有的DSL如下:

思路

目前DSL的市场里已经有uni-app的实现了,比如这个:xiashui-uni-app,但这个有问题,图片使用的是img,块使用的是div,估计作者是使用uni-app做H5相关开发。

在进行开发之前,我们可以先看下uni-app的官网及官方的组件,一个有趣的规律是:它的组件名和微信小程序的几乎一致,API也一致;但它又是使用了Vue的语法进行开发。所以我们的开发思路就有了。

  1. 借鉴官方的小程序DSL来解析标签
  2. 借鉴官方的小程序DSL来控制响应式
  3. 借鉴官方的Vue组件来控制语法

过程

按照官方的流程,自定义 DSL | imgcook docs,填写了基本信息后,会自动生成一个repo,然后代码在这个Repo里提交就可以了。

小技巧:可以使用自带的test来本地测试哦。

实现

具体的细节就不多说了,直接放地址:uni-app-pointspike

要使用的话,必须官方审核,审核通过就可以在项目中使用了。下面这个是我写的:

注意

一个问题是,这个玩意你是没有办法私有,按照imgcook官方的规范,只要开发了,就会在github上自动生成一个repo,也就是必须开源。所以注意一些公司私有内部的逻辑不要放在DSL上面哦。

PS:当然,imgcook的插件、组件库也一样有这个问题。