Pure node rendering (#443)
This commit is contained in:
parent
5ce5e5ac1e
commit
7f6e1f420e
438
package-lock.json
generated
438
package-lock.json
generated
@ -3607,6 +3607,12 @@
|
||||
"safe-buffer": "^5.0.1"
|
||||
}
|
||||
},
|
||||
"circular-json": {
|
||||
"version": "0.3.3",
|
||||
"resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz",
|
||||
"integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==",
|
||||
"dev": true
|
||||
},
|
||||
"class-utils": {
|
||||
"version": "0.3.6",
|
||||
"resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
|
||||
@ -10903,6 +10909,12 @@
|
||||
"semver-compare": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"pluralize": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz",
|
||||
"integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==",
|
||||
"dev": true
|
||||
},
|
||||
"pn": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz",
|
||||
@ -12744,6 +12756,39 @@
|
||||
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
|
||||
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
|
||||
},
|
||||
"require-uncached": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz",
|
||||
"integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"caller-path": "^0.1.0",
|
||||
"resolve-from": "^1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"caller-path": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz",
|
||||
"integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"callsites": "^0.2.0"
|
||||
}
|
||||
},
|
||||
"callsites": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz",
|
||||
"integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=",
|
||||
"dev": true
|
||||
},
|
||||
"resolve-from": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz",
|
||||
"integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"requires-port": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
|
||||
@ -12842,6 +12887,384 @@
|
||||
"integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
|
||||
"dev": true
|
||||
},
|
||||
"rewire": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/rewire/-/rewire-4.0.1.tgz",
|
||||
"integrity": "sha512-+7RQ/BYwTieHVXetpKhT11UbfF6v1kGhKFrtZN7UDL2PybMsSt/rpLWeEUGF5Ndsl1D5BxiCB14VDJyoX+noYw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"eslint": "^4.19.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"acorn": {
|
||||
"version": "5.7.3",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz",
|
||||
"integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==",
|
||||
"dev": true
|
||||
},
|
||||
"acorn-jsx": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz",
|
||||
"integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"acorn": "^3.0.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"acorn": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
|
||||
"integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"ajv": {
|
||||
"version": "5.5.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
|
||||
"integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"co": "^4.6.0",
|
||||
"fast-deep-equal": "^1.0.0",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.3.0"
|
||||
}
|
||||
},
|
||||
"ajv-keywords": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz",
|
||||
"integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=",
|
||||
"dev": true
|
||||
},
|
||||
"ansi-escapes": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz",
|
||||
"integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==",
|
||||
"dev": true
|
||||
},
|
||||
"ansi-regex": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
|
||||
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
|
||||
"dev": true
|
||||
},
|
||||
"chardet": {
|
||||
"version": "0.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz",
|
||||
"integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=",
|
||||
"dev": true
|
||||
},
|
||||
"cli-cursor": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
|
||||
"integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"restore-cursor": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"cross-spawn": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
|
||||
"integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"lru-cache": "^4.0.1",
|
||||
"shebang-command": "^1.2.0",
|
||||
"which": "^1.2.9"
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
"version": "3.2.6",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
|
||||
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ms": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"doctrine": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
|
||||
"integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"esutils": "^2.0.2"
|
||||
}
|
||||
},
|
||||
"eslint": {
|
||||
"version": "4.19.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz",
|
||||
"integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ajv": "^5.3.0",
|
||||
"babel-code-frame": "^6.22.0",
|
||||
"chalk": "^2.1.0",
|
||||
"concat-stream": "^1.6.0",
|
||||
"cross-spawn": "^5.1.0",
|
||||
"debug": "^3.1.0",
|
||||
"doctrine": "^2.1.0",
|
||||
"eslint-scope": "^3.7.1",
|
||||
"eslint-visitor-keys": "^1.0.0",
|
||||
"espree": "^3.5.4",
|
||||
"esquery": "^1.0.0",
|
||||
"esutils": "^2.0.2",
|
||||
"file-entry-cache": "^2.0.0",
|
||||
"functional-red-black-tree": "^1.0.1",
|
||||
"glob": "^7.1.2",
|
||||
"globals": "^11.0.1",
|
||||
"ignore": "^3.3.3",
|
||||
"imurmurhash": "^0.1.4",
|
||||
"inquirer": "^3.0.6",
|
||||
"is-resolvable": "^1.0.0",
|
||||
"js-yaml": "^3.9.1",
|
||||
"json-stable-stringify-without-jsonify": "^1.0.1",
|
||||
"levn": "^0.3.0",
|
||||
"lodash": "^4.17.4",
|
||||
"minimatch": "^3.0.2",
|
||||
"mkdirp": "^0.5.1",
|
||||
"natural-compare": "^1.4.0",
|
||||
"optionator": "^0.8.2",
|
||||
"path-is-inside": "^1.0.2",
|
||||
"pluralize": "^7.0.0",
|
||||
"progress": "^2.0.0",
|
||||
"regexpp": "^1.0.1",
|
||||
"require-uncached": "^1.0.3",
|
||||
"semver": "^5.3.0",
|
||||
"strip-ansi": "^4.0.0",
|
||||
"strip-json-comments": "~2.0.1",
|
||||
"table": "4.0.2",
|
||||
"text-table": "~0.2.0"
|
||||
}
|
||||
},
|
||||
"eslint-scope": {
|
||||
"version": "3.7.3",
|
||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz",
|
||||
"integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"esrecurse": "^4.1.0",
|
||||
"estraverse": "^4.1.1"
|
||||
}
|
||||
},
|
||||
"espree": {
|
||||
"version": "3.5.4",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz",
|
||||
"integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"acorn": "^5.5.0",
|
||||
"acorn-jsx": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"external-editor": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz",
|
||||
"integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chardet": "^0.4.0",
|
||||
"iconv-lite": "^0.4.17",
|
||||
"tmp": "^0.0.33"
|
||||
}
|
||||
},
|
||||
"fast-deep-equal": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
|
||||
"integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=",
|
||||
"dev": true
|
||||
},
|
||||
"figures": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
|
||||
"integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"escape-string-regexp": "^1.0.5"
|
||||
}
|
||||
},
|
||||
"file-entry-cache": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz",
|
||||
"integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"flat-cache": "^1.2.1",
|
||||
"object-assign": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"flat-cache": {
|
||||
"version": "1.3.4",
|
||||
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz",
|
||||
"integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"circular-json": "^0.3.1",
|
||||
"graceful-fs": "^4.1.2",
|
||||
"rimraf": "~2.6.2",
|
||||
"write": "^0.2.1"
|
||||
}
|
||||
},
|
||||
"ignore": {
|
||||
"version": "3.3.10",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz",
|
||||
"integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==",
|
||||
"dev": true
|
||||
},
|
||||
"inquirer": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz",
|
||||
"integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-escapes": "^3.0.0",
|
||||
"chalk": "^2.0.0",
|
||||
"cli-cursor": "^2.1.0",
|
||||
"cli-width": "^2.0.0",
|
||||
"external-editor": "^2.0.4",
|
||||
"figures": "^2.0.0",
|
||||
"lodash": "^4.3.0",
|
||||
"mute-stream": "0.0.7",
|
||||
"run-async": "^2.2.0",
|
||||
"rx-lite": "^4.0.8",
|
||||
"rx-lite-aggregates": "^4.0.8",
|
||||
"string-width": "^2.1.0",
|
||||
"strip-ansi": "^4.0.0",
|
||||
"through": "^2.3.6"
|
||||
}
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
|
||||
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
|
||||
"dev": true
|
||||
},
|
||||
"json-schema-traverse": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
|
||||
"integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=",
|
||||
"dev": true
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "4.1.5",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
|
||||
"integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"pseudomap": "^1.0.2",
|
||||
"yallist": "^2.1.2"
|
||||
}
|
||||
},
|
||||
"mimic-fn": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
|
||||
"integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
|
||||
"dev": true
|
||||
},
|
||||
"mute-stream": {
|
||||
"version": "0.0.7",
|
||||
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz",
|
||||
"integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
|
||||
"dev": true
|
||||
},
|
||||
"onetime": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
|
||||
"integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"mimic-fn": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"regexpp": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz",
|
||||
"integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==",
|
||||
"dev": true
|
||||
},
|
||||
"restore-cursor": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
|
||||
"integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"onetime": "^2.0.0",
|
||||
"signal-exit": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
|
||||
"dev": true
|
||||
},
|
||||
"slice-ansi": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz",
|
||||
"integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-fullwidth-code-point": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"string-width": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
|
||||
"integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-fullwidth-code-point": "^2.0.0",
|
||||
"strip-ansi": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
|
||||
"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"strip-json-comments": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
|
||||
"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
|
||||
"dev": true
|
||||
},
|
||||
"table": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz",
|
||||
"integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ajv": "^5.2.3",
|
||||
"ajv-keywords": "^2.1.0",
|
||||
"chalk": "^2.1.0",
|
||||
"lodash": "^4.17.4",
|
||||
"slice-ansi": "1.0.0",
|
||||
"string-width": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"write": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz",
|
||||
"integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"mkdirp": "^0.5.1"
|
||||
}
|
||||
},
|
||||
"yallist": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
|
||||
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"rework": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/rework/-/rework-1.0.1.tgz",
|
||||
@ -12922,6 +13345,21 @@
|
||||
"aproba": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"rx-lite": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz",
|
||||
"integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=",
|
||||
"dev": true
|
||||
},
|
||||
"rx-lite-aggregates": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz",
|
||||
"integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"rx-lite": "*"
|
||||
}
|
||||
},
|
||||
"rxjs": {
|
||||
"version": "6.5.4",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz",
|
||||
|
@ -23,6 +23,7 @@
|
||||
"lint-staged": "9.5.0",
|
||||
"node-sass": "4.13.1",
|
||||
"prettier": "1.19.1",
|
||||
"rewire": "^4.0.1",
|
||||
"typescript": "3.7.5"
|
||||
},
|
||||
"eslintConfig": {
|
||||
@ -47,6 +48,7 @@
|
||||
"name": "excalidraw",
|
||||
"scripts": {
|
||||
"build": "react-scripts build",
|
||||
"build-node": "./scripts/build-node.js",
|
||||
"eject": "react-scripts eject",
|
||||
"fix": "npm run prettier -- --write",
|
||||
"prettier": "prettier \"**/*.{js,css,scss,json,md,ts,tsx,html,yml}\"",
|
||||
|
40
scripts/build-node.js
Executable file
40
scripts/build-node.js
Executable file
@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// In order to use this, you need to install Cairo on your machine. See
|
||||
// instructions here: https://github.com/Automattic/node-canvas#compiling
|
||||
|
||||
// In order to run:
|
||||
// npm install canvas # please do not check it in
|
||||
// npm run build-node
|
||||
// node build/static/js/build-node.js
|
||||
// open test.png
|
||||
|
||||
var rewire = require("rewire");
|
||||
var defaults = rewire("react-scripts/scripts/build.js");
|
||||
var config = defaults.__get__("config");
|
||||
|
||||
// Disable multiple chunks
|
||||
config.optimization.runtimeChunk = false;
|
||||
config.optimization.splitChunks = {
|
||||
cacheGroups: {
|
||||
default: false
|
||||
}
|
||||
};
|
||||
// Set the filename to be deterministic
|
||||
config.output.filename = "static/js/build-node.js";
|
||||
// Don't choke on node-specific requires
|
||||
config.target = "node";
|
||||
// Set the node entrypoint
|
||||
config.entry = "./src/index-node";
|
||||
// By default, webpack is going to replace the require of the canvas.node file
|
||||
// to just a string with the path of the canvas.node file. We need to tell
|
||||
// webpack to avoid rewriting that dependency.
|
||||
config.externals = function(context, request, callback) {
|
||||
if (/\.node$/.test(request)) {
|
||||
return callback(
|
||||
null,
|
||||
"commonjs ../../../node_modules/canvas/build/Release/canvas.node"
|
||||
);
|
||||
}
|
||||
callback();
|
||||
};
|
@ -1,5 +1,5 @@
|
||||
import { Action } from "./types";
|
||||
import { META_KEY } from "../keys";
|
||||
import { KEYS } from "../keys";
|
||||
|
||||
export const actionSelectAll: Action = {
|
||||
name: "selectAll",
|
||||
@ -9,5 +9,5 @@ export const actionSelectAll: Action = {
|
||||
};
|
||||
},
|
||||
contextItemLabel: "Select All",
|
||||
keyTest: event => event[META_KEY] && event.code === "KeyA"
|
||||
keyTest: event => event[KEYS.META] && event.code === "KeyA"
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Action } from "./types";
|
||||
import { isTextElement, redrawTextBoundingBox } from "../element";
|
||||
import { META_KEY } from "../keys";
|
||||
import { KEYS } from "../keys";
|
||||
|
||||
let copiedStyles: string = "{}";
|
||||
|
||||
@ -14,7 +14,7 @@ export const actionCopyStyles: Action = {
|
||||
return {};
|
||||
},
|
||||
contextItemLabel: "Copy Styles",
|
||||
keyTest: event => event[META_KEY] && event.shiftKey && event.code === "KeyC",
|
||||
keyTest: event => event[KEYS.META] && event.shiftKey && event.code === "KeyC",
|
||||
contextMenuOrder: 0
|
||||
};
|
||||
|
||||
@ -46,6 +46,6 @@ export const actionPasteStyles: Action = {
|
||||
};
|
||||
},
|
||||
contextItemLabel: "Paste Styles",
|
||||
keyTest: event => event[META_KEY] && event.shiftKey && event.code === "KeyV",
|
||||
keyTest: event => event[KEYS.META] && event.shiftKey && event.code === "KeyV",
|
||||
contextMenuOrder: 1
|
||||
};
|
||||
|
@ -6,7 +6,7 @@ import {
|
||||
moveAllRight
|
||||
} from "../zindex";
|
||||
import { getSelectedIndices } from "../scene";
|
||||
import { META_KEY } from "../keys";
|
||||
import { KEYS } from "../keys";
|
||||
|
||||
export const actionSendBackward: Action = {
|
||||
name: "sendBackward",
|
||||
@ -19,7 +19,7 @@ export const actionSendBackward: Action = {
|
||||
contextItemLabel: "Send Backward",
|
||||
keyPriority: 40,
|
||||
keyTest: event =>
|
||||
event[META_KEY] && event.shiftKey && event.altKey && event.code === "KeyB"
|
||||
event[KEYS.META] && event.shiftKey && event.altKey && event.code === "KeyB"
|
||||
};
|
||||
|
||||
export const actionBringForward: Action = {
|
||||
@ -33,7 +33,7 @@ export const actionBringForward: Action = {
|
||||
contextItemLabel: "Bring Forward",
|
||||
keyPriority: 40,
|
||||
keyTest: event =>
|
||||
event[META_KEY] && event.shiftKey && event.altKey && event.code === "KeyF"
|
||||
event[KEYS.META] && event.shiftKey && event.altKey && event.code === "KeyF"
|
||||
};
|
||||
|
||||
export const actionSendToBack: Action = {
|
||||
@ -45,7 +45,7 @@ export const actionSendToBack: Action = {
|
||||
};
|
||||
},
|
||||
contextItemLabel: "Send to Back",
|
||||
keyTest: event => event[META_KEY] && event.shiftKey && event.code === "KeyB"
|
||||
keyTest: event => event[KEYS.META] && event.shiftKey && event.code === "KeyB"
|
||||
};
|
||||
|
||||
export const actionBringToFront: Action = {
|
||||
@ -57,5 +57,5 @@ export const actionBringToFront: Action = {
|
||||
};
|
||||
},
|
||||
contextItemLabel: "Bring to Front",
|
||||
keyTest: event => event[META_KEY] && event.shiftKey && event.code === "KeyF"
|
||||
keyTest: event => event[KEYS.META] && event.shiftKey && event.code === "KeyF"
|
||||
};
|
||||
|
@ -8,7 +8,7 @@ import { clipboard, exportFile, downloadFile } from "./icons";
|
||||
import { Island } from "./Island";
|
||||
import { ExcalidrawElement } from "../element/types";
|
||||
import { AppState } from "../types";
|
||||
import { getExportCanvasPreview } from "../scene/data";
|
||||
import { getExportCanvasPreview } from "../scene/getExportCanvasPreview";
|
||||
import { ActionsManagerInterface, UpdaterFn } from "../actions/types";
|
||||
import Stack from "./Stack";
|
||||
|
||||
|
74
src/index-node.ts
Normal file
74
src/index-node.ts
Normal file
@ -0,0 +1,74 @@
|
||||
import { getExportCanvasPreview } from "../src/scene/getExportCanvasPreview";
|
||||
|
||||
const { registerFont, createCanvas } = require("canvas");
|
||||
|
||||
const elements = [
|
||||
{
|
||||
id: "eVzaxG3YnHhqjEmD7NdYo",
|
||||
type: "diamond",
|
||||
x: 519,
|
||||
y: 199,
|
||||
width: 113,
|
||||
height: 115,
|
||||
strokeColor: "#000000",
|
||||
backgroundColor: "transparent",
|
||||
fillStyle: "hachure",
|
||||
strokeWidth: 1,
|
||||
roughness: 1,
|
||||
opacity: 100,
|
||||
isSelected: false,
|
||||
seed: 749612521
|
||||
},
|
||||
{
|
||||
id: "7W-iw5pEBPTU3eaCaLtFo",
|
||||
type: "ellipse",
|
||||
x: 552,
|
||||
y: 238,
|
||||
width: 49,
|
||||
height: 44,
|
||||
strokeColor: "#000000",
|
||||
backgroundColor: "transparent",
|
||||
fillStyle: "hachure",
|
||||
strokeWidth: 1,
|
||||
roughness: 1,
|
||||
opacity: 100,
|
||||
isSelected: false,
|
||||
seed: 952056308
|
||||
},
|
||||
{
|
||||
id: "kqKI231mvTrcsYo2DkUsR",
|
||||
type: "text",
|
||||
x: 557.5,
|
||||
y: 317.5,
|
||||
width: 43,
|
||||
height: 31,
|
||||
strokeColor: "#000000",
|
||||
backgroundColor: "transparent",
|
||||
fillStyle: "hachure",
|
||||
strokeWidth: 1,
|
||||
roughness: 1,
|
||||
opacity: 100,
|
||||
isSelected: false,
|
||||
seed: 1683771448,
|
||||
text: "test",
|
||||
font: "20px Virgil",
|
||||
baseline: 22
|
||||
}
|
||||
];
|
||||
|
||||
registerFont("./public/FG_Virgil.ttf", { family: "Virgil" });
|
||||
const canvas = getExportCanvasPreview(
|
||||
elements as any,
|
||||
{
|
||||
exportBackground: true,
|
||||
viewBackgroundColor: "#ffffff",
|
||||
scale: 1
|
||||
},
|
||||
createCanvas
|
||||
);
|
||||
|
||||
const fs = require("fs");
|
||||
const out = fs.createWriteStream("test.png");
|
||||
const stream = canvas.createPNGStream();
|
||||
stream.pipe(out);
|
||||
out.on("finish", () => console.log("test.png was created."));
|
@ -35,7 +35,7 @@ import { AppState } from "./types";
|
||||
import { ExcalidrawElement, ExcalidrawTextElement } from "./element/types";
|
||||
|
||||
import { isInputLike, measureText, debounce, capitalizeString } from "./utils";
|
||||
import { KEYS, META_KEY, isArrowKey } from "./keys";
|
||||
import { KEYS, isArrowKey } from "./keys";
|
||||
|
||||
import { findShapeByKey, shapesShortcutKeys, SHAPES } from "./shapes";
|
||||
import { createHistory } from "./history";
|
||||
@ -303,7 +303,7 @@ export class App extends React.Component<{}, AppState> {
|
||||
this.state.elementType !== "selection")
|
||||
) {
|
||||
this.setState({ elementType: findShapeByKey(event.key) });
|
||||
} else if (event[META_KEY] && event.code === "KeyZ") {
|
||||
} else if (event[KEYS.META] && event.code === "KeyZ") {
|
||||
if (event.shiftKey) {
|
||||
// Redo action
|
||||
const data = history.redoOnce();
|
||||
|
11
src/keys.ts
11
src/keys.ts
@ -6,13 +6,14 @@ export const KEYS = {
|
||||
ENTER: "Enter",
|
||||
ESCAPE: "Escape",
|
||||
DELETE: "Delete",
|
||||
BACKSPACE: "Backspace"
|
||||
BACKSPACE: "Backspace",
|
||||
get META() {
|
||||
return /Mac|iPod|iPhone|iPad/.test(window.navigator.platform)
|
||||
? "metaKey"
|
||||
: "ctrlKey";
|
||||
}
|
||||
};
|
||||
|
||||
export const META_KEY = /Mac|iPod|iPhone|iPad/.test(window.navigator.platform)
|
||||
? "metaKey"
|
||||
: "ctrlKey";
|
||||
|
||||
export function isArrowKey(keyCode: string) {
|
||||
return (
|
||||
keyCode === KEYS.ARROW_LEFT ||
|
||||
|
@ -1,13 +1,10 @@
|
||||
import rough from "roughjs/bin/rough";
|
||||
|
||||
import { ExcalidrawElement } from "../element/types";
|
||||
|
||||
import { getElementAbsoluteCoords } from "../element";
|
||||
import { getDefaultAppState } from "../appState";
|
||||
|
||||
import { renderScene } from "../renderer";
|
||||
import { AppState } from "../types";
|
||||
import { ExportType } from "./types";
|
||||
import { getExportCanvasPreview } from "./getExportCanvasPreview";
|
||||
import nanoid from "nanoid";
|
||||
|
||||
const LOCAL_STORAGE_KEY = "excalidraw";
|
||||
@ -169,66 +166,6 @@ export async function loadFromJSON() {
|
||||
}
|
||||
}
|
||||
|
||||
export function getExportCanvasPreview(
|
||||
elements: readonly ExcalidrawElement[],
|
||||
{
|
||||
exportBackground,
|
||||
exportPadding = 10,
|
||||
viewBackgroundColor,
|
||||
scale = 1
|
||||
}: {
|
||||
exportBackground: boolean;
|
||||
exportPadding?: number;
|
||||
scale?: number;
|
||||
viewBackgroundColor: string;
|
||||
}
|
||||
) {
|
||||
// calculate smallest area to fit the contents in
|
||||
let subCanvasX1 = Infinity;
|
||||
let subCanvasX2 = 0;
|
||||
let subCanvasY1 = Infinity;
|
||||
let subCanvasY2 = 0;
|
||||
|
||||
elements.forEach(element => {
|
||||
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element);
|
||||
subCanvasX1 = Math.min(subCanvasX1, x1);
|
||||
subCanvasY1 = Math.min(subCanvasY1, y1);
|
||||
subCanvasX2 = Math.max(subCanvasX2, x2);
|
||||
subCanvasY2 = Math.max(subCanvasY2, y2);
|
||||
});
|
||||
|
||||
function distance(x: number, y: number) {
|
||||
return Math.abs(x > y ? x - y : y - x);
|
||||
}
|
||||
|
||||
const tempCanvas = document.createElement("canvas");
|
||||
const width = distance(subCanvasX1, subCanvasX2) + exportPadding * 2;
|
||||
const height = distance(subCanvasY1, subCanvasY2) + exportPadding * 2;
|
||||
tempCanvas.style.width = width + "px";
|
||||
tempCanvas.style.height = height + "px";
|
||||
tempCanvas.width = width * scale;
|
||||
tempCanvas.height = height * scale;
|
||||
tempCanvas.getContext("2d")?.scale(scale, scale);
|
||||
|
||||
renderScene(
|
||||
elements,
|
||||
rough.canvas(tempCanvas),
|
||||
tempCanvas,
|
||||
{
|
||||
viewBackgroundColor: exportBackground ? viewBackgroundColor : null,
|
||||
scrollX: 0,
|
||||
scrollY: 0
|
||||
},
|
||||
{
|
||||
offsetX: -subCanvasX1 + exportPadding,
|
||||
offsetY: -subCanvasY1 + exportPadding,
|
||||
renderScrollbars: false,
|
||||
renderSelection: false
|
||||
}
|
||||
);
|
||||
return tempCanvas;
|
||||
}
|
||||
|
||||
export async function exportCanvas(
|
||||
type: ExportType,
|
||||
elements: readonly ExcalidrawElement[],
|
||||
@ -262,7 +199,7 @@ export async function exportCanvas(
|
||||
if (type === "png") {
|
||||
const fileName = `${name}.png`;
|
||||
if ("chooseFileSystemEntries" in window) {
|
||||
tempCanvas.toBlob(async blob => {
|
||||
tempCanvas.toBlob(async (blob: any) => {
|
||||
if (blob) {
|
||||
await saveFileNative(fileName, blob);
|
||||
}
|
||||
@ -272,7 +209,7 @@ export async function exportCanvas(
|
||||
}
|
||||
} else if (type === "clipboard") {
|
||||
try {
|
||||
tempCanvas.toBlob(async function(blob) {
|
||||
tempCanvas.toBlob(async function(blob: any) {
|
||||
try {
|
||||
await navigator.clipboard.write([
|
||||
new window.ClipboardItem({ "image/png": blob })
|
||||
|
71
src/scene/getExportCanvasPreview.ts
Normal file
71
src/scene/getExportCanvasPreview.ts
Normal file
@ -0,0 +1,71 @@
|
||||
import rough from "roughjs/bin/rough";
|
||||
import { ExcalidrawElement } from "../element/types";
|
||||
import { getElementAbsoluteCoords } from "../element/bounds";
|
||||
import { renderScene } from "../renderer/renderScene";
|
||||
|
||||
export function getExportCanvasPreview(
|
||||
elements: readonly ExcalidrawElement[],
|
||||
{
|
||||
exportBackground,
|
||||
exportPadding = 10,
|
||||
viewBackgroundColor,
|
||||
scale = 1
|
||||
}: {
|
||||
exportBackground: boolean;
|
||||
exportPadding?: number;
|
||||
scale?: number;
|
||||
viewBackgroundColor: string;
|
||||
},
|
||||
createCanvas: (width: number, height: number) => any = function(
|
||||
width,
|
||||
height
|
||||
) {
|
||||
const tempCanvas = document.createElement("canvas");
|
||||
tempCanvas.style.width = width + "px";
|
||||
tempCanvas.style.height = height + "px";
|
||||
tempCanvas.width = width * scale;
|
||||
tempCanvas.height = height * scale;
|
||||
return tempCanvas;
|
||||
}
|
||||
) {
|
||||
// calculate smallest area to fit the contents in
|
||||
let subCanvasX1 = Infinity;
|
||||
let subCanvasX2 = 0;
|
||||
let subCanvasY1 = Infinity;
|
||||
let subCanvasY2 = 0;
|
||||
|
||||
elements.forEach(element => {
|
||||
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element);
|
||||
subCanvasX1 = Math.min(subCanvasX1, x1);
|
||||
subCanvasY1 = Math.min(subCanvasY1, y1);
|
||||
subCanvasX2 = Math.max(subCanvasX2, x2);
|
||||
subCanvasY2 = Math.max(subCanvasY2, y2);
|
||||
});
|
||||
|
||||
function distance(x: number, y: number) {
|
||||
return Math.abs(x > y ? x - y : y - x);
|
||||
}
|
||||
|
||||
const width = distance(subCanvasX1, subCanvasX2) + exportPadding * 2;
|
||||
const height = distance(subCanvasY1, subCanvasY2) + exportPadding * 2;
|
||||
const tempCanvas: any = createCanvas(width, height);
|
||||
tempCanvas.getContext("2d")?.scale(scale, scale);
|
||||
|
||||
renderScene(
|
||||
elements,
|
||||
rough.canvas(tempCanvas),
|
||||
tempCanvas,
|
||||
{
|
||||
viewBackgroundColor: exportBackground ? viewBackgroundColor : null,
|
||||
scrollX: 0,
|
||||
scrollY: 0
|
||||
},
|
||||
{
|
||||
offsetX: -subCanvasX1 + exportPadding,
|
||||
offsetY: -subCanvasY1 + exportPadding,
|
||||
renderScrollbars: false,
|
||||
renderSelection: false
|
||||
}
|
||||
);
|
||||
return tempCanvas;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user