oipage 1.4.1 → 1.5.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/CHANGELOG +11 -1
  2. package/bin/WebSocket/decodeWsFrame.js +43 -0
  3. package/bin/WebSocket/encodeWsFrame.js +28 -0
  4. package/bin/WebSocket/headersToJSON.js +26 -0
  5. package/bin/WebSocket/index.js +80 -0
  6. package/bin/intercept.js +2 -2
  7. package/bin/serve.js +14 -10
  8. package/bin/template/404.html +5 -2
  9. package/bin/website-htmls/dialogs/imageSize/index.html +55 -0
  10. package/bin/website-htmls/dialogs/imageSize/index.js +53 -0
  11. package/bin/website-htmls/dialogs/imageSize/index.scss +139 -0
  12. package/bin/website-htmls/dialogs/index.js +29 -19
  13. package/bin/website-htmls/images/chart.png +0 -0
  14. package/bin/website-htmls/images/image-editor.png +0 -0
  15. package/bin/website-htmls/images/lock.png +0 -0
  16. package/bin/website-htmls/images/mosaic.png +0 -0
  17. package/bin/website-htmls/images/size.png +0 -0
  18. package/bin/website-htmls/index.html +1 -1
  19. package/bin/website-htmls/main.js +2 -0
  20. package/bin/website-htmls/pages/App/index.html +4 -1
  21. package/bin/website-htmls/pages/App/index.scss +6 -5
  22. package/bin/website-htmls/pages/appStore/index.html +19 -6
  23. package/bin/website-htmls/pages/appStore/index.js +3 -1
  24. package/bin/website-htmls/pages/appStore/index.scss +38 -23
  25. package/bin/website-htmls/pages/chart/index.html +9 -0
  26. package/bin/website-htmls/pages/chart/index.js +73 -0
  27. package/bin/website-htmls/pages/chart/index.scss +73 -0
  28. package/bin/website-htmls/pages/image-editor/index.html +28 -0
  29. package/bin/website-htmls/pages/image-editor/index.js +107 -0
  30. package/bin/website-htmls/pages/image-editor/index.scss +46 -0
  31. package/bin/website-htmls/router.config.js +6 -0
  32. package/bin/website-htmls/styles/common.css +0 -3
  33. package/bin/website-plugins/intercept/chart.js +34 -0
  34. package/bin/website-plugins/intercept/head.js +1 -1
  35. package/bin/website-plugins/intercept/index.js +5 -1
  36. package/bin/website-plugins/intercept/oipage-vislite-intercept.js +34 -0
  37. package/bin/website-plugins/intercept/oipage-zipaper-intercept.js +2 -2
  38. package/nodejs/animation/index.js +1 -1
  39. package/nodejs/cmdlog/index.js +1 -1
  40. package/nodejs/disk/index.js +1 -1
  41. package/nodejs/format/index.js +1 -1
  42. package/nodejs/json/index.js +1 -1
  43. package/nodejs/logform/index.js +1 -1
  44. package/nodejs/reader/index.js +1 -1
  45. package/nodejs/throttle/index.js +1 -1
  46. package/package.json +2 -2
  47. package/web/XMLHttpRequest/index.js +1 -1
  48. package/web/animation/index.js +1 -1
  49. package/web/format/index.js +1 -1
  50. package/web/json/index.js +1 -1
  51. package/web/onReady/index.js +1 -1
  52. package/web/performChunk/index.js +1 -1
  53. package/web/reader/index.js +1 -1
  54. package/web/style/index.js +1 -1
  55. package/web/throttle/index.js +1 -1
  56. /package/bin/website-htmls/{logo.png → images/logo.png} +0 -0
@@ -32,12 +32,13 @@
32
32
  .fork {
33
33
  line-height: 30px;
34
34
  position: fixed;
35
- background-color: #9E9E9E;
35
+ background-color: #607D8B;
36
36
  text-align: center;
37
37
  color: white;
38
- outline: 2px dashed #9E9E9E;
38
+ outline: 2px dashed #607D8B;
39
39
  width: 200px;
40
- transform: rotate(-45deg);
41
- right: -40px;
42
- bottom: 44px;
40
+ transform: rotate(45deg);
41
+ right: -45px;
42
+ top: 45px;
43
+ z-index: 1;
43
44
  }
@@ -1,6 +1,19 @@
1
- <header>
2
- 应用市场
3
- <a class="fork" href="https://github.com/oi-contrib/OIPage" target="_blank">
4
- Fork me on Github
5
- </a>
6
- </header>
1
+ <div class="appstore-view">
2
+ <header>
3
+ 应用市场
4
+ </header>
5
+ <ul>
6
+ <li z-on:click.prevent="goto" tag="chart">
7
+ <img src="./images/chart.png" />
8
+ <h2>
9
+ 群聊贴
10
+ </h2>
11
+ </li>
12
+ <li z-on:click="goto" tag="image-editor">
13
+ <img src="./images/image-editor.png" />
14
+ <h2>
15
+ 图片编辑器
16
+ </h2>
17
+ </li>
18
+ </ul>
19
+ </div>
@@ -10,7 +10,9 @@ export default defineElement({
10
10
  }
11
11
  },
12
12
  methods: {
13
-
13
+ goto(event, target) {
14
+ this.$goto("/" + target.getAttribute("tag"))
15
+ }
14
16
  },
15
17
  style: {
16
18
  content: style
@@ -1,27 +1,42 @@
1
- header {
2
- height: 50px;
3
- line-height: 50px;
4
- background-color: white;
5
- box-shadow: rgba(0, 0, 0, 0.1) 0px 2px 4px;
6
- background-image: url("./logo.png");
7
- background-size: auto 90%;
8
- background-repeat: no-repeat;
9
- background-position-x: 5px;
10
- padding-left: 50px;
11
- font-size: 20px;
12
- font-weight: 800;
1
+ .appstore-view {
13
2
 
14
- .fork {
15
- line-height: 30px;
16
- position: fixed;
17
- background-color: #9E9E9E;
3
+ header {
4
+ height: 50px;
5
+ line-height: 50px;
6
+ background-color: white;
7
+ box-shadow: rgba(0, 0, 0, 0.1) 0px 2px 4px;
8
+ background-image: url("./images/logo.png");
9
+ background-size: auto 90%;
10
+ background-repeat: no-repeat;
11
+ background-position-x: 5px;
12
+ padding-left: 50px;
13
+ font-size: 18px;
14
+ font-weight: 800;
15
+ }
16
+
17
+ ul {
18
18
  text-align: center;
19
- color: white;
20
- outline: 2px dashed #9E9E9E;
21
- width: 200px;
22
- transform: rotate(-45deg);
23
- right: -40px;
24
- bottom: 44px;
25
- font-weight: 400;
19
+ padding: 50px 0;
20
+
21
+ &>li {
22
+ display: inline-block;
23
+ margin: 0 10px;
24
+
25
+ &:hover {
26
+ text-decoration: underline;
27
+ cursor: pointer;
28
+ }
29
+
30
+ &>img {
31
+ border-radius: 10px;
32
+ width: 70px;
33
+ }
34
+
35
+ &>h2 {
36
+ font-size: 14px;
37
+ line-height: 2em;
38
+ }
39
+ }
26
40
  }
41
+
27
42
  }
@@ -0,0 +1,9 @@
1
+ <form z-on:submit.prevent="doSubmit">
2
+ <div class="chart-view">
3
+ <div class="content" id="chart-content-id"></div>
4
+ <div class="input">
5
+ <input placeholder="请输入内容......" z-model="msg" spellcheck="false" autocomplete="off" />
6
+ <button type="submit">发送</button>
7
+ </div>
8
+ </div>
9
+ </form>
@@ -0,0 +1,73 @@
1
+ import { defineElement, ref } from "zipaper"
2
+ import template from "./index.html"
3
+ import style from "./index.scss"
4
+
5
+ export default defineElement({
6
+ template,
7
+ data() {
8
+ return {
9
+ uniqueid: new Date().valueOf() + "#" + (Math.random() * 10000).toFixed(0),
10
+ msg: ref("")
11
+ }
12
+ },
13
+ created() {
14
+
15
+ let ws = new WebSocket('ws://' + window.location.hostname + ':' + (+window.location.port + 1) + '/');
16
+
17
+ // 连接成功
18
+ ws.addEventListener('open', () => {
19
+ ws.send('客户端和服务器建立连接成功!(' + this.uniqueid + ')');
20
+ });
21
+
22
+ // 监听来自服务器的数据
23
+ ws.addEventListener('message', (event) => {
24
+ let data = JSON.parse(event.data);
25
+
26
+ let contentEl = document.getElementById("chart-content-id");
27
+
28
+ let itemEl = document.createElement("div");
29
+ contentEl.appendChild(itemEl);
30
+
31
+ itemEl.setAttribute("class", "item");
32
+
33
+ if (data.uniqueid === this.uniqueid) {
34
+ itemEl.setAttribute("tag", "sender");
35
+ } else {
36
+ itemEl.setAttribute("tag", "receiver");
37
+ }
38
+
39
+ let textEl = document.createElement("div");
40
+ textEl.innerText = data.msg;
41
+ itemEl.appendChild(textEl);
42
+ textEl.setAttribute("class", "text");
43
+
44
+ itemEl.scrollIntoView({
45
+ behavior: 'smooth',
46
+ block: 'end',
47
+ inline: 'nearest'
48
+ });
49
+ });
50
+
51
+ },
52
+ methods: {
53
+ doSubmit() {
54
+ fetch("./chart/sendMsg", {
55
+ method: "POST",
56
+ headers: {
57
+ "Content-Type": "application/json;charset=utf-8"
58
+ },
59
+ body: JSON.stringify({
60
+ msg: this.msg,
61
+ uniqueid: this.uniqueid
62
+ })
63
+ }).then(() => {
64
+ this.msg = "";
65
+ }).catch(() => {
66
+ alert("发送失败!");
67
+ });
68
+ }
69
+ },
70
+ style: {
71
+ content: style
72
+ }
73
+ })
@@ -0,0 +1,73 @@
1
+ .chart-view {
2
+ &>.content {
3
+ position: fixed;
4
+ width: 350px;
5
+ height: calc(100% - 130px);
6
+ border: 2px solid #000000;
7
+ left: 50%;
8
+ top: 50px;
9
+ transform: translateX(-50%);
10
+ padding: 5px;
11
+ overflow: auto;
12
+
13
+ &::-webkit-scrollbar {
14
+ width: 0;
15
+ height: 0;
16
+ }
17
+
18
+ &>.item {
19
+ display: flex;
20
+ padding: 5px;
21
+
22
+ &[tag="sender"] {
23
+ flex-direction: row-reverse;
24
+ padding-left: 50px;
25
+ }
26
+
27
+ &[tag="receiver"] {
28
+ flex-direction: row;
29
+ padding-right: 50px;
30
+ }
31
+
32
+ &>.text {
33
+ background-color: #dfdbdb;
34
+ padding: 5px;
35
+ width: fit-content;
36
+ border-radius: 5px;
37
+ font-size: 12px;
38
+ }
39
+ }
40
+ }
41
+
42
+ &>.input {
43
+ position: fixed;
44
+ width: 350px;
45
+ height: 30px;
46
+ left: 50%;
47
+ bottom: 50px;
48
+ transform: translateX(-50%);
49
+ display: flex;
50
+
51
+ &>input {
52
+ flex-grow: 1;
53
+ resize: none;
54
+ outline: none;
55
+ border: 2px solid #000000;
56
+ border-top-width: 0;
57
+ border-radius: 0;
58
+ }
59
+
60
+ &>button {
61
+ width: 70px;
62
+ cursor: pointer;
63
+ background-color: #000000;
64
+ color: white;
65
+ outline: none;
66
+ border: none;
67
+
68
+ &:hover {
69
+ text-decoration: underline;
70
+ }
71
+ }
72
+ }
73
+ }
@@ -0,0 +1,28 @@
1
+ <div class="image-editor-view">
2
+ <ul class="menu">
3
+ <li>
4
+ <label for="openImage">打开</label>
5
+ </li>
6
+ <li>
7
+ <label z-on:click="changeSize">画布大小</label>
8
+ </li>
9
+ <li>
10
+ <label z-on:click="changeSize">图像大小</label>
11
+ </li>
12
+ <li>
13
+ <label z-on:click="download" type="jpeg">下载JPEG</label>
14
+ </li>
15
+ <li>
16
+ <label z-on:click="download" type="png">下载PNG</label>
17
+ </li>
18
+ </ul>
19
+ <div class="content">
20
+ <div id="drawId"></div>
21
+ </div>
22
+ <div class="no-view">
23
+
24
+ <!-- 选择图片 -->
25
+ <input type="file" id="openImage" z-on:change="openImage" accept="image/*" />
26
+
27
+ </div>
28
+ </div>
@@ -0,0 +1,107 @@
1
+ import { defineElement } from "zipaper";
2
+ import template from "./index.html";
3
+ import style from "./index.scss";
4
+ import { Canvas } from "vislite";
5
+
6
+ export default defineElement({
7
+ template,
8
+ data() {
9
+ return {
10
+ painter: null,
11
+ drawEl: null
12
+ }
13
+ },
14
+ created() {
15
+ this.drawEl = document.getElementById("drawId");
16
+ this.painter = new Canvas(this.drawEl, {
17
+ scale: 1
18
+ }, 700, 400);
19
+ },
20
+ methods: {
21
+ openImage(event, target) {
22
+ let file = target.files[0];
23
+ if (file) {
24
+ let reader = new FileReader();
25
+
26
+ reader.onload = () => {
27
+ let image = new Image();
28
+
29
+ image.onload = () => {
30
+
31
+ // 调整画布大小
32
+ this.painter = new Canvas(this.drawEl, {
33
+ scale: 1
34
+ }, image.width, image.height);
35
+
36
+ // 绘制图片
37
+ this.painter.clearRect(0, 0, image.width, image.height).drawImage(image, 0, 0, image.width, image.height);
38
+ }
39
+
40
+ image.src = reader.result;
41
+ }
42
+ reader.readAsDataURL(file);
43
+ }
44
+ },
45
+ download(event, target) {
46
+ let btn = document.createElement('a');
47
+ btn.href = this.painter.__canvas.toDataURL("image/" + target.getAttribute("type"));
48
+ btn.download = "图片." + target.getAttribute("type");
49
+ btn.click();
50
+ },
51
+ changeSize(event, target) {
52
+ let canvasInfo = this.painter.getInfo();
53
+ this.$openDialog("imageSize", {
54
+ title: target.innerText.trim(),
55
+ width: canvasInfo.width,
56
+ height: canvasInfo.height
57
+ }).then(data => {
58
+ if (data) {
59
+ let base64 = this.painter.__canvas.toDataURL();
60
+
61
+ // 调整画布大小
62
+ this.painter = new Canvas(this.drawEl, {
63
+ scale: 1
64
+ }, data.width, data.height).clearRect(0, 0, data.width, data.height);
65
+
66
+ if (target.innerText.trim() === "画布大小") {
67
+
68
+ // 计算图片的对齐方式
69
+
70
+ let _left, _top;
71
+ let changeType = data.changeType.split('-');
72
+
73
+ // 水平方向
74
+ if (changeType[0] == 'left') {
75
+ _left = 0;
76
+ } else if (changeType[0] == 'right') {
77
+ _left = data.width - canvasInfo.width;
78
+ } else {
79
+ _left = (data.width - canvasInfo.width) * 0.5;
80
+ }
81
+
82
+ // 垂直方向
83
+ if (changeType[1] == 'top') {
84
+ _top = 0;
85
+ } else if (changeType[1] == 'bottom') {
86
+ _top = data.height - canvasInfo.height;
87
+ } else {
88
+ _top = (data.height - canvasInfo.height) * 0.5;
89
+ }
90
+
91
+ const img = new Image();
92
+ img.onload = () => {
93
+ this.painter.getContext().drawImage(img, 0, 0, canvasInfo.width, canvasInfo.height, _left, _top, canvasInfo.width, canvasInfo.height);
94
+ };
95
+ img.src = base64;
96
+
97
+ } else {
98
+ this.painter.drawImage(base64, 0, 0, data.width, data.height);
99
+ }
100
+ }
101
+ });
102
+ }
103
+ },
104
+ style: {
105
+ content: style
106
+ }
107
+ })
@@ -0,0 +1,46 @@
1
+ .image-editor-view {
2
+ &>.menu {
3
+ position: fixed;
4
+ left: 50%;
5
+ top: 5px;
6
+ transform: translateX(-50%);
7
+ white-space: nowrap;
8
+
9
+ &>li {
10
+ display: inline-block;
11
+ background-color: #FF5722;
12
+ color: white;
13
+ margin: 0 5px;
14
+ border-radius: 5px;
15
+
16
+ &>label {
17
+ line-height: 30px;
18
+ padding: 0 5px;
19
+ display: inline-block;
20
+ cursor: pointer;
21
+ }
22
+
23
+ &:hover {
24
+ text-decoration: underline;
25
+ }
26
+ }
27
+ }
28
+
29
+ &>.content {
30
+ text-align: center;
31
+ margin-top: 100px;
32
+
33
+ #drawId {
34
+ display: inline-block;
35
+
36
+ &>canvas {
37
+ background-image: url("./images/mosaic.png");
38
+ outline: 2px solid #CDDC39;
39
+ }
40
+ }
41
+ }
42
+
43
+ &>.no-view {
44
+ display: none;
45
+ }
46
+ }
@@ -7,5 +7,11 @@ export default defineRouter({
7
7
  }, {
8
8
  path: "/appStore",
9
9
  component: () => import("./pages/appStore/index.js"),
10
+ }, {
11
+ path: "/chart",
12
+ component: () => import("./pages/chart/index.js"),
13
+ }, {
14
+ path: "/image-editor",
15
+ component: () => import("./pages/image-editor/index.js"),
10
16
  }]
11
17
  })
@@ -1,3 +0,0 @@
1
- body {
2
- font-family: cursive;
3
- }
@@ -0,0 +1,34 @@
1
+ const headFactory = require("./head.js");
2
+
3
+ const head = headFactory();
4
+
5
+ // 聊天
6
+ module.exports = {
7
+ test: /^\/chart\//,
8
+ handler(request, response, wsHandler) {
9
+ let url = decodeURIComponent(request.url);
10
+
11
+ let requestData = "";
12
+
13
+ request.on('data', (chunk) => {
14
+ requestData += chunk;
15
+ });
16
+
17
+ request.on('end', () => {
18
+
19
+ if (/sendMsg$/.test(url)) {
20
+ wsHandler.notifyBrowser({
21
+ payloadData: requestData
22
+ });
23
+ }
24
+
25
+ head["Content-Type"] = "application/json;charset=utf-8";
26
+ response.writeHead(200, head);
27
+ response.write(JSON.stringify({
28
+ code: "000000"
29
+ }));
30
+ response.end();
31
+
32
+ });
33
+ }
34
+ };
@@ -4,6 +4,6 @@ module.exports = function () {
4
4
  return {
5
5
  'Access-Control-Allow-Origin': '*',
6
6
  'Server': 'Powered by OIPage:website@' + pkg.version,
7
- 'Content-type': 'text/plain;charset=utf-8'
7
+ 'Content-Type': 'text/plain;charset=utf-8'
8
8
  };
9
9
  };
@@ -1,5 +1,9 @@
1
1
  const OIPageZipaperIntercept = require("./oipage-zipaper-intercept.js");
2
+ const OIPageVISLiteIntercept = require("./oipage-vislite-intercept.js");
3
+ const ChartIntercept = require("./chart.js");
2
4
 
3
5
  module.exports = [
4
- OIPageZipaperIntercept
6
+ OIPageZipaperIntercept,
7
+ OIPageVISLiteIntercept,
8
+ ChartIntercept
5
9
  ];
@@ -0,0 +1,34 @@
1
+ const { readFileSync } = require("fs");
2
+ const { join } = require("path");
3
+ const headFactory = require("./head.js");
4
+
5
+ const head = headFactory();
6
+
7
+ // VISLite库
8
+ module.exports = {
9
+ test: /^vislite$/,
10
+ handler(request, response) {
11
+ head["Content-Type"] = "application/javascript;charset=utf-8";
12
+ head["ETag"] = "VISLite@v" + require("vislite/package.json").version;
13
+
14
+ if (request.headers["if-none-match"] === head["ETag"]) {
15
+ response.writeHead('304', head);
16
+ response.end();
17
+ console.log("<i> \x1b[1m\x1b[32m[OIPage-dev-server] Cache File: VISLite\x1b[0m " + new Date().toLocaleString() + "\x1b[33m\x1b[1m 304\x1b[0m");;
18
+ return;
19
+ }
20
+
21
+ response.writeHead(200, head);
22
+
23
+ let source = readFileSync(join(__dirname, "../../../node_modules/vislite/lib/index.umd.min.js"), {
24
+ encoding: "utf8"
25
+ });
26
+
27
+ response.write(`let module = { exports: {} };
28
+ let exports = module.exports;
29
+ ${source}
30
+ export let Canvas = module.exports.Canvas;
31
+ `);
32
+ response.end();
33
+ }
34
+ };
@@ -8,7 +8,7 @@ const head = headFactory();
8
8
  module.exports = {
9
9
  test: /^zipaper$/,
10
10
  handler(request, response) {
11
- head["Content-type"] = "application/javascript;charset=utf-8";
11
+ head["Content-Type"] = "application/javascript;charset=utf-8";
12
12
  head["ETag"] = "Zipaper@v" + require("zipaper/package.json").version;
13
13
 
14
14
  if (request.headers["if-none-match"] === head["ETag"]) {
@@ -24,7 +24,7 @@ module.exports = {
24
24
  encoding: "utf8"
25
25
  });
26
26
 
27
- response.write(`let module = { exports: {}};
27
+ response.write(`let module = { exports: {} };
28
28
  let exports = module.exports;
29
29
  ${source}
30
30
  export let createApp = exports.createApp;
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * animation of OIPage v1.4.1
2
+ * animation of OIPage v1.5.0-alpha.1
3
3
  * git+https://github.com/oi-contrib/OIPage.git
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * cmdlog of OIPage v1.4.1
2
+ * cmdlog of OIPage v1.5.0-alpha.1
3
3
  * git+https://github.com/oi-contrib/OIPage.git
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * disk of OIPage v1.4.1
2
+ * disk of OIPage v1.5.0-alpha.1
3
3
  * git+https://github.com/oi-contrib/OIPage.git
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * format of OIPage v1.4.1
2
+ * format of OIPage v1.5.0-alpha.1
3
3
  * git+https://github.com/oi-contrib/OIPage.git
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * json of OIPage v1.4.1
2
+ * json of OIPage v1.5.0-alpha.1
3
3
  * git+https://github.com/oi-contrib/OIPage.git
4
4
  */
5
5
  const {reader} = require("../reader/index.js");
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * logform of OIPage v1.4.1
2
+ * logform of OIPage v1.5.0-alpha.1
3
3
  * git+https://github.com/oi-contrib/OIPage.git
4
4
  */
5
5
  const {linelog} = require("../cmdlog/index.js");
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * reader of OIPage v1.4.1
2
+ * reader of OIPage v1.5.0-alpha.1
3
3
  * git+https://github.com/oi-contrib/OIPage.git
4
4
  */
5
5
 
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * throttle of OIPage v1.4.1
2
+ * throttle of OIPage v1.5.0-alpha.1
3
3
  * git+https://github.com/oi-contrib/OIPage.git
4
4
  */
5
5
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oipage",
3
- "version": "1.4.1",
3
+ "version": "1.5.0-alpha.1",
4
4
  "description": "前端网页或应用快速开发助手,包括开发服务器、辅助命令、实用API等",
5
5
  "sideEffects": false,
6
6
  "scripts": {
@@ -35,7 +35,7 @@
35
35
  },
36
36
  "homepage": "https://oi-contrib.github.io/OIPage",
37
37
  "dependencies": {
38
- "vislite": "^1.4.0",
38
+ "vislite": "^1.5.0",
39
39
  "xhtml-to-json": "^0.1.0",
40
40
  "zipaper": "^0.2.0"
41
41
  }