feat: Edit on preview

This commit is contained in:
Artemy 2023-04-03 15:23:41 +03:00
parent 68aa1527cb
commit b250d27093
9 changed files with 441 additions and 64 deletions

View file

@ -17,10 +17,6 @@ if (!fs.existsSync("./notes")) {
fs.mkdirSync("./notes"); fs.mkdirSync("./notes");
} }
setInterval(() => {
io.emit("foo", "bar");
}, 1000);
app.use(bodyParser.json()); app.use(bodyParser.json());
app.post("/publish", function (req, res) { app.post("/publish", function (req, res) {

346
package-lock.json generated
View file

@ -17,15 +17,20 @@
"express": "^4.18.2", "express": "^4.18.2",
"js-sha3": "^0.8.0", "js-sha3": "^0.8.0",
"react": "^18.2.0", "react": "^18.2.0",
"react-contenteditable": "^3.3.7",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-markdown": "^8.0.3", "react-markdown": "^8.0.3",
"react-router-dom": "^6.4.2", "react-router-dom": "^6.4.2",
"react-syntax-highlighter": "^15.5.0", "react-syntax-highlighter": "^15.5.0",
"rehype-mathjax": "^4.0.2", "rehype-mathjax": "^4.0.2",
"rehype-parse": "^8.0.4",
"rehype-remark": "^9.1.2",
"remark-gfm": "^3.0.1", "remark-gfm": "^3.0.1",
"remark-math": "^5.1.1", "remark-math": "^5.1.1",
"remark-stringify": "^10.0.2",
"socket.io": "^4.6.1", "socket.io": "^4.6.1",
"socket.io-client": "^4.6.1" "socket.io-client": "^4.6.1",
"unified": "^10.1.2"
}, },
"devDependencies": { "devDependencies": {
"@types/react": "^18.0.17", "@types/react": "^18.0.17",
@ -627,6 +632,11 @@
"@types/ms": "*" "@types/ms": "*"
} }
}, },
"node_modules/@types/extend": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/@types/extend/-/extend-3.0.1.tgz",
"integrity": "sha512-R1g/VyKFFI2HLC1QGAeTtCBWCo6n75l41OnsVYNbmKG+kempOESaodf6BeJyUM3Q0rKa/NQcTHbB2+66lNnxLw=="
},
"node_modules/@types/hast": { "node_modules/@types/hast": {
"version": "2.3.4", "version": "2.3.4",
"resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.4.tgz", "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.4.tgz",
@ -2335,6 +2345,18 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/hast-util-embedded": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/hast-util-embedded/-/hast-util-embedded-2.0.1.tgz",
"integrity": "sha512-QUdSOP1/o+/TxXtpPFXR2mUg2P+ySrmlX7QjwHZCXqMFyYk7YmcGSvqRW+4XgXAoHifdE1t2PwFaQK33TqVjSw==",
"dependencies": {
"hast-util-is-element": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/hast-util-from-dom": { "node_modules/hast-util-from-dom": {
"version": "4.2.0", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-4.2.0.tgz", "resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-4.2.0.tgz",
@ -2348,6 +2370,47 @@
"url": "https://opencollective.com/unified" "url": "https://opencollective.com/unified"
} }
}, },
"node_modules/hast-util-from-parse5": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-7.1.2.tgz",
"integrity": "sha512-Nz7FfPBuljzsN3tCQ4kCBKqdNhQE2l0Tn+X1ubgKBPRoiDIu1mL08Cfw4k7q71+Duyaw7DXDN+VTAp4Vh3oCOw==",
"dependencies": {
"@types/hast": "^2.0.0",
"@types/unist": "^2.0.0",
"hastscript": "^7.0.0",
"property-information": "^6.0.0",
"vfile": "^5.0.0",
"vfile-location": "^4.0.0",
"web-namespaces": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/hast-util-has-property": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/hast-util-has-property/-/hast-util-has-property-2.0.1.tgz",
"integrity": "sha512-X2+RwZIMTMKpXUzlotatPzWj8bspCymtXH3cfG3iQKV+wPF53Vgaqxi/eLqGck0wKq1kS9nvoB1wchbCPEL8sg==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/hast-util-is-body-ok-link": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/hast-util-is-body-ok-link/-/hast-util-is-body-ok-link-2.0.0.tgz",
"integrity": "sha512-S58hCexyKdD31vMsErvgLfflW6vYWo/ixRLPJTtkOvLld24vyI8vmYmkgLA5LG3la2ME7nm7dLGdm48gfLRBfw==",
"dependencies": {
"@types/hast": "^2.0.0",
"hast-util-has-property": "^2.0.0",
"hast-util-is-element": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/hast-util-is-element": { "node_modules/hast-util-is-element": {
"version": "2.1.3", "version": "2.1.3",
"resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-2.1.3.tgz", "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-2.1.3.tgz",
@ -2373,6 +2436,48 @@
"url": "https://opencollective.com/unified" "url": "https://opencollective.com/unified"
} }
}, },
"node_modules/hast-util-phrasing": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hast-util-phrasing/-/hast-util-phrasing-2.0.2.tgz",
"integrity": "sha512-yGkCfPkkfCyiLfK6KEl/orMDr/zgCnq/NaO9HfULx6/Zga5fso5eqQA5Ov/JZVqACygvw9shRYWgXNcG2ilo7w==",
"dependencies": {
"@types/hast": "^2.0.0",
"hast-util-embedded": "^2.0.0",
"hast-util-has-property": "^2.0.0",
"hast-util-is-body-ok-link": "^2.0.0",
"hast-util-is-element": "^2.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/hast-util-to-mdast": {
"version": "8.4.1",
"resolved": "https://registry.npmjs.org/hast-util-to-mdast/-/hast-util-to-mdast-8.4.1.tgz",
"integrity": "sha512-tfmBLASuCgyhCzpkTXM5kU8xeuS5jkMZ17BYm2YftGT5wvgc7uHXTZ/X8WfNd6F5NV/IGmrLsuahZ+jXQir4zQ==",
"dependencies": {
"@types/extend": "^3.0.0",
"@types/hast": "^2.0.0",
"@types/mdast": "^3.0.0",
"@types/unist": "^2.0.0",
"extend": "^3.0.0",
"hast-util-has-property": "^2.0.0",
"hast-util-is-element": "^2.0.0",
"hast-util-phrasing": "^2.0.0",
"hast-util-to-text": "^3.0.0",
"mdast-util-phrasing": "^3.0.0",
"mdast-util-to-string": "^3.0.0",
"rehype-minify-whitespace": "^5.0.0",
"trim-trailing-lines": "^2.0.0",
"unist-util-is": "^5.0.0",
"unist-util-visit": "^4.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/hast-util-to-text": { "node_modules/hast-util-to-text": {
"version": "3.1.2", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-3.1.2.tgz", "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-3.1.2.tgz",
@ -4188,6 +4293,18 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/react-contenteditable": {
"version": "3.3.7",
"resolved": "https://registry.npmjs.org/react-contenteditable/-/react-contenteditable-3.3.7.tgz",
"integrity": "sha512-GA9NbC0DkDdpN3iGvib/OMHWTJzDX2cfkgy5Tt98JJAbA3kLnyrNbBIpsSpPpq7T8d3scD39DHP+j8mAM7BIfQ==",
"dependencies": {
"fast-deep-equal": "^3.1.3",
"prop-types": "^15.7.1"
},
"peerDependencies": {
"react": ">=16.3"
}
},
"node_modules/react-dom": { "node_modules/react-dom": {
"version": "18.2.0", "version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
@ -4412,6 +4529,53 @@
"url": "https://opencollective.com/unified" "url": "https://opencollective.com/unified"
} }
}, },
"node_modules/rehype-minify-whitespace": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/rehype-minify-whitespace/-/rehype-minify-whitespace-5.0.1.tgz",
"integrity": "sha512-PPp4lWJiBPlePI/dv1BeYktbwkfgXkrK59MUa+tYbMPgleod+4DvFK2PLU0O0O60/xuhHfiR9GUIUlXTU8sRIQ==",
"dependencies": {
"@types/hast": "^2.0.0",
"hast-util-embedded": "^2.0.0",
"hast-util-is-element": "^2.0.0",
"hast-util-whitespace": "^2.0.0",
"unified": "^10.0.0",
"unist-util-is": "^5.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/rehype-parse": {
"version": "8.0.4",
"resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-8.0.4.tgz",
"integrity": "sha512-MJJKONunHjoTh4kc3dsM1v3C9kGrrxvA3U8PxZlP2SjH8RNUSrb+lF7Y0KVaUDnGH2QZ5vAn7ulkiajM9ifuqg==",
"dependencies": {
"@types/hast": "^2.0.0",
"hast-util-from-parse5": "^7.0.0",
"parse5": "^6.0.0",
"unified": "^10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/rehype-remark": {
"version": "9.1.2",
"resolved": "https://registry.npmjs.org/rehype-remark/-/rehype-remark-9.1.2.tgz",
"integrity": "sha512-c0fG3/CrJ95zAQ07xqHSkdpZybwdsY7X5dNWvgL2XqLKZuqmG3+vk6kP/4miCnp+R+x/0uKKRSpfXb9aGR8Z5w==",
"dependencies": {
"@types/hast": "^2.0.0",
"@types/mdast": "^3.0.0",
"hast-util-to-mdast": "^8.3.0",
"unified": "^10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/remark-gfm": { "node_modules/remark-gfm": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-3.0.1.tgz", "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-3.0.1.tgz",
@ -4471,6 +4635,20 @@
"url": "https://opencollective.com/unified" "url": "https://opencollective.com/unified"
} }
}, },
"node_modules/remark-stringify": {
"version": "10.0.2",
"resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-10.0.2.tgz",
"integrity": "sha512-6wV3pvbPvHkbNnWB0wdDvVFHOe1hBRAx1Q/5g/EpH4RppAII6J8Gnwe7VbHuXaoKIF6LAg6ExTel/+kNqSQ7lw==",
"dependencies": {
"@types/mdast": "^3.0.0",
"mdast-util-to-markdown": "^1.0.0",
"unified": "^10.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/require-from-string": { "node_modules/require-from-string": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
@ -4963,6 +5141,15 @@
"url": "https://github.com/sponsors/wooorm" "url": "https://github.com/sponsors/wooorm"
} }
}, },
"node_modules/trim-trailing-lines": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-2.1.0.tgz",
"integrity": "sha512-5UR5Biq4VlVOtzqkm2AZlgvSlDJtME46uV0br0gENbwN4l5+mMKT4b9gJKqWtuL2zAIqajGJGuvbCbcAJUZqBg==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/trough": { "node_modules/trough": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/trough/-/trough-2.1.0.tgz", "resolved": "https://registry.npmjs.org/trough/-/trough-2.1.0.tgz",
@ -5220,6 +5407,19 @@
"url": "https://opencollective.com/unified" "url": "https://opencollective.com/unified"
} }
}, },
"node_modules/vfile-location": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-4.1.0.tgz",
"integrity": "sha512-YF23YMyASIIJXpktBa4vIGLJ5Gs88UB/XePgqPmTa7cDA+JeO3yclbpheQYCHjVHBn/yePzrXuygIL+xbvRYHw==",
"dependencies": {
"@types/unist": "^2.0.0",
"vfile": "^5.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/unified"
}
},
"node_modules/vfile-message": { "node_modules/vfile-message": {
"version": "3.1.2", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.2.tgz", "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.2.tgz",
@ -5862,6 +6062,11 @@
"@types/ms": "*" "@types/ms": "*"
} }
}, },
"@types/extend": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/@types/extend/-/extend-3.0.1.tgz",
"integrity": "sha512-R1g/VyKFFI2HLC1QGAeTtCBWCo6n75l41OnsVYNbmKG+kempOESaodf6BeJyUM3Q0rKa/NQcTHbB2+66lNnxLw=="
},
"@types/hast": { "@types/hast": {
"version": "2.3.4", "version": "2.3.4",
"resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.4.tgz", "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.4.tgz",
@ -7026,6 +7231,14 @@
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="
}, },
"hast-util-embedded": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/hast-util-embedded/-/hast-util-embedded-2.0.1.tgz",
"integrity": "sha512-QUdSOP1/o+/TxXtpPFXR2mUg2P+ySrmlX7QjwHZCXqMFyYk7YmcGSvqRW+4XgXAoHifdE1t2PwFaQK33TqVjSw==",
"requires": {
"hast-util-is-element": "^2.0.0"
}
},
"hast-util-from-dom": { "hast-util-from-dom": {
"version": "4.2.0", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-4.2.0.tgz", "resolved": "https://registry.npmjs.org/hast-util-from-dom/-/hast-util-from-dom-4.2.0.tgz",
@ -7035,6 +7248,35 @@
"web-namespaces": "^2.0.0" "web-namespaces": "^2.0.0"
} }
}, },
"hast-util-from-parse5": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-7.1.2.tgz",
"integrity": "sha512-Nz7FfPBuljzsN3tCQ4kCBKqdNhQE2l0Tn+X1ubgKBPRoiDIu1mL08Cfw4k7q71+Duyaw7DXDN+VTAp4Vh3oCOw==",
"requires": {
"@types/hast": "^2.0.0",
"@types/unist": "^2.0.0",
"hastscript": "^7.0.0",
"property-information": "^6.0.0",
"vfile": "^5.0.0",
"vfile-location": "^4.0.0",
"web-namespaces": "^2.0.0"
}
},
"hast-util-has-property": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/hast-util-has-property/-/hast-util-has-property-2.0.1.tgz",
"integrity": "sha512-X2+RwZIMTMKpXUzlotatPzWj8bspCymtXH3cfG3iQKV+wPF53Vgaqxi/eLqGck0wKq1kS9nvoB1wchbCPEL8sg=="
},
"hast-util-is-body-ok-link": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/hast-util-is-body-ok-link/-/hast-util-is-body-ok-link-2.0.0.tgz",
"integrity": "sha512-S58hCexyKdD31vMsErvgLfflW6vYWo/ixRLPJTtkOvLld24vyI8vmYmkgLA5LG3la2ME7nm7dLGdm48gfLRBfw==",
"requires": {
"@types/hast": "^2.0.0",
"hast-util-has-property": "^2.0.0",
"hast-util-is-element": "^2.0.0"
}
},
"hast-util-is-element": { "hast-util-is-element": {
"version": "2.1.3", "version": "2.1.3",
"resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-2.1.3.tgz", "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-2.1.3.tgz",
@ -7052,6 +7294,40 @@
"@types/hast": "^2.0.0" "@types/hast": "^2.0.0"
} }
}, },
"hast-util-phrasing": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hast-util-phrasing/-/hast-util-phrasing-2.0.2.tgz",
"integrity": "sha512-yGkCfPkkfCyiLfK6KEl/orMDr/zgCnq/NaO9HfULx6/Zga5fso5eqQA5Ov/JZVqACygvw9shRYWgXNcG2ilo7w==",
"requires": {
"@types/hast": "^2.0.0",
"hast-util-embedded": "^2.0.0",
"hast-util-has-property": "^2.0.0",
"hast-util-is-body-ok-link": "^2.0.0",
"hast-util-is-element": "^2.0.0"
}
},
"hast-util-to-mdast": {
"version": "8.4.1",
"resolved": "https://registry.npmjs.org/hast-util-to-mdast/-/hast-util-to-mdast-8.4.1.tgz",
"integrity": "sha512-tfmBLASuCgyhCzpkTXM5kU8xeuS5jkMZ17BYm2YftGT5wvgc7uHXTZ/X8WfNd6F5NV/IGmrLsuahZ+jXQir4zQ==",
"requires": {
"@types/extend": "^3.0.0",
"@types/hast": "^2.0.0",
"@types/mdast": "^3.0.0",
"@types/unist": "^2.0.0",
"extend": "^3.0.0",
"hast-util-has-property": "^2.0.0",
"hast-util-is-element": "^2.0.0",
"hast-util-phrasing": "^2.0.0",
"hast-util-to-text": "^3.0.0",
"mdast-util-phrasing": "^3.0.0",
"mdast-util-to-string": "^3.0.0",
"rehype-minify-whitespace": "^5.0.0",
"trim-trailing-lines": "^2.0.0",
"unist-util-is": "^5.0.0",
"unist-util-visit": "^4.0.0"
}
},
"hast-util-to-text": { "hast-util-to-text": {
"version": "3.1.2", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-3.1.2.tgz", "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-3.1.2.tgz",
@ -8228,6 +8504,15 @@
"loose-envify": "^1.1.0" "loose-envify": "^1.1.0"
} }
}, },
"react-contenteditable": {
"version": "3.3.7",
"resolved": "https://registry.npmjs.org/react-contenteditable/-/react-contenteditable-3.3.7.tgz",
"integrity": "sha512-GA9NbC0DkDdpN3iGvib/OMHWTJzDX2cfkgy5Tt98JJAbA3kLnyrNbBIpsSpPpq7T8d3scD39DHP+j8mAM7BIfQ==",
"requires": {
"fast-deep-equal": "^3.1.3",
"prop-types": "^15.7.1"
}
},
"react-dom": { "react-dom": {
"version": "18.2.0", "version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
@ -8390,6 +8675,41 @@
"unist-util-visit": "^4.0.0" "unist-util-visit": "^4.0.0"
} }
}, },
"rehype-minify-whitespace": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/rehype-minify-whitespace/-/rehype-minify-whitespace-5.0.1.tgz",
"integrity": "sha512-PPp4lWJiBPlePI/dv1BeYktbwkfgXkrK59MUa+tYbMPgleod+4DvFK2PLU0O0O60/xuhHfiR9GUIUlXTU8sRIQ==",
"requires": {
"@types/hast": "^2.0.0",
"hast-util-embedded": "^2.0.0",
"hast-util-is-element": "^2.0.0",
"hast-util-whitespace": "^2.0.0",
"unified": "^10.0.0",
"unist-util-is": "^5.0.0"
}
},
"rehype-parse": {
"version": "8.0.4",
"resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-8.0.4.tgz",
"integrity": "sha512-MJJKONunHjoTh4kc3dsM1v3C9kGrrxvA3U8PxZlP2SjH8RNUSrb+lF7Y0KVaUDnGH2QZ5vAn7ulkiajM9ifuqg==",
"requires": {
"@types/hast": "^2.0.0",
"hast-util-from-parse5": "^7.0.0",
"parse5": "^6.0.0",
"unified": "^10.0.0"
}
},
"rehype-remark": {
"version": "9.1.2",
"resolved": "https://registry.npmjs.org/rehype-remark/-/rehype-remark-9.1.2.tgz",
"integrity": "sha512-c0fG3/CrJ95zAQ07xqHSkdpZybwdsY7X5dNWvgL2XqLKZuqmG3+vk6kP/4miCnp+R+x/0uKKRSpfXb9aGR8Z5w==",
"requires": {
"@types/hast": "^2.0.0",
"@types/mdast": "^3.0.0",
"hast-util-to-mdast": "^8.3.0",
"unified": "^10.0.0"
}
},
"remark-gfm": { "remark-gfm": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-3.0.1.tgz", "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-3.0.1.tgz",
@ -8433,6 +8753,16 @@
"unified": "^10.0.0" "unified": "^10.0.0"
} }
}, },
"remark-stringify": {
"version": "10.0.2",
"resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-10.0.2.tgz",
"integrity": "sha512-6wV3pvbPvHkbNnWB0wdDvVFHOe1hBRAx1Q/5g/EpH4RppAII6J8Gnwe7VbHuXaoKIF6LAg6ExTel/+kNqSQ7lw==",
"requires": {
"@types/mdast": "^3.0.0",
"mdast-util-to-markdown": "^1.0.0",
"unified": "^10.0.0"
}
},
"require-from-string": { "require-from-string": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
@ -8790,6 +9120,11 @@
"resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz",
"integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==" "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="
}, },
"trim-trailing-lines": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/trim-trailing-lines/-/trim-trailing-lines-2.1.0.tgz",
"integrity": "sha512-5UR5Biq4VlVOtzqkm2AZlgvSlDJtME46uV0br0gENbwN4l5+mMKT4b9gJKqWtuL2zAIqajGJGuvbCbcAJUZqBg=="
},
"trough": { "trough": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/trough/-/trough-2.1.0.tgz", "resolved": "https://registry.npmjs.org/trough/-/trough-2.1.0.tgz",
@ -8963,6 +9298,15 @@
"vfile-message": "^3.0.0" "vfile-message": "^3.0.0"
} }
}, },
"vfile-location": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-4.1.0.tgz",
"integrity": "sha512-YF23YMyASIIJXpktBa4vIGLJ5Gs88UB/XePgqPmTa7cDA+JeO3yclbpheQYCHjVHBn/yePzrXuygIL+xbvRYHw==",
"requires": {
"@types/unist": "^2.0.0",
"vfile": "^5.0.0"
}
},
"vfile-message": { "vfile-message": {
"version": "3.1.2", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.2.tgz", "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.2.tgz",

View file

@ -20,15 +20,20 @@
"express": "^4.18.2", "express": "^4.18.2",
"js-sha3": "^0.8.0", "js-sha3": "^0.8.0",
"react": "^18.2.0", "react": "^18.2.0",
"react-contenteditable": "^3.3.7",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-markdown": "^8.0.3", "react-markdown": "^8.0.3",
"react-router-dom": "^6.4.2", "react-router-dom": "^6.4.2",
"react-syntax-highlighter": "^15.5.0", "react-syntax-highlighter": "^15.5.0",
"rehype-mathjax": "^4.0.2", "rehype-mathjax": "^4.0.2",
"rehype-parse": "^8.0.4",
"rehype-remark": "^9.1.2",
"remark-gfm": "^3.0.1", "remark-gfm": "^3.0.1",
"remark-math": "^5.1.1", "remark-math": "^5.1.1",
"remark-stringify": "^10.0.2",
"socket.io": "^4.6.1", "socket.io": "^4.6.1",
"socket.io-client": "^4.6.1" "socket.io-client": "^4.6.1",
"unified": "^10.1.2"
}, },
"devDependencies": { "devDependencies": {
"@types/react": "^18.0.17", "@types/react": "^18.0.17",

View file

@ -4,13 +4,13 @@ import Menu from "./components/menu";
import CreateNote from "./pages/create"; import CreateNote from "./pages/create";
import Save from "./pages/save-local"; import Save from "./pages/save-local";
import Publish from "./pages/publish"; import Publish from "./pages/publish";
import Note from "./pages/note"; import NotePage from "./pages/note";
import Notes from "./pages/notes"; import Notes from "./pages/notes";
import PubNote from "./pages/pubNote"; import PubNote from "./pages/pubNote";
import PubError from "./pages/pubError"; import PubError from "./pages/pubError";
import PubNoteSafe from "./pages/pubNoteSafe"; import PubNoteSafe from "./pages/pubNoteSafe";
import RenderMarkdown from "./components/markdown"; import RenderMarkdown from "./components/markdown";
import { io } from "socket.io-client"; import socket from "./components/socket";
function App() { function App() {
Storage.prototype.setObj = function (key, obj) { Storage.prototype.setObj = function (key, obj) {
@ -20,24 +20,6 @@ function App() {
return JSON.parse(this.getItem(key)) || {}; return JSON.parse(this.getItem(key)) || {};
}; };
const socket = io();
function onConnect() {
console.log("connect");
}
function onDisconnect() {
console.log("disconnect");
}
function onFooEvent(value) {
console.log("foo event", value);
}
socket.on("connect", onConnect);
socket.on("disconnect", onDisconnect);
socket.on("foo", onFooEvent);
return ( return (
<div className="grid grid-cols-4 lg:grid-cols-5 gap-10 text-black dark:text-white"> <div className="grid grid-cols-4 lg:grid-cols-5 gap-10 text-black dark:text-white">
<Menu /> <Menu />
@ -46,7 +28,7 @@ function App() {
<Route path="/" element={<CreateNote />} /> <Route path="/" element={<CreateNote />} />
<Route path="/notes/save-local" element={<Save />} /> <Route path="/notes/save-local" element={<Save />} />
<Route path="/notes/publish" element={<Publish />} /> <Route path="/notes/publish" element={<Publish />} />
<Route path="/notes/:id" element={<Note />} /> <Route path="/notes/:id" element={<NotePage />} />
<Route path="/pubNotes/:id" element={<PubNote />} /> <Route path="/pubNotes/:id" element={<PubNote />} />
<Route path="/pubNotesSafe/:id" element={<PubNoteSafe />} /> <Route path="/pubNotesSafe/:id" element={<PubNoteSafe />} />
<Route path="/pubError" element={<PubError />} /> <Route path="/pubError" element={<PubError />} />

22
src/components/note.jsx Normal file
View file

@ -0,0 +1,22 @@
import RenderMarkdown from "../components/markdown";
import printDate from "./utils";
function Note({ note }) {
return (
<div className="border border-blue-300 rounded-lg p-4">
<div className="grid grid-cols-1 lg:grid-cols-2">
<h2 className="font-medium text-center lg:text-left leading-tight text-4xl mt-0 mb-2">
{note.name}
</h2>
<div className="justify-self-center lg:justify-self-end">
{printDate(note.time)}
</div>
</div>
<div className="w-full md break-words">
<RenderMarkdown>{note.text}</RenderMarkdown>
</div>
</div>
);
}
export default Note;

21
src/components/socket.js Normal file
View file

@ -0,0 +1,21 @@
import { io } from "socket.io-client";
const socket = io();
function onConnect() {
console.log("Socket connected");
}
function onDisconnect() {
console.log("Socket disconnected, local mode only");
}
function onFooEvent() {
console.log("bar");
}
socket.on("connect", onConnect);
socket.on("disconnect", onDisconnect);
socket.on("foo", onFooEvent);
export default socket;

View file

@ -4,6 +4,14 @@ import { CheckBox } from "../components/checkbox";
import { useState } from "react"; import { useState } from "react";
import RenderMarkdown from "../components/markdown"; import RenderMarkdown from "../components/markdown";
import printDate from "../components/utils"; import printDate from "../components/utils";
import rehypeRemark from "rehype-remark/lib";
import ContentEditable from "react-contenteditable";
import ReactDOMServer from "react-dom/server";
import { unified } from "unified";
import rehypeParse from "rehype-parse";
import remarkStringify from "remark-stringify";
import remarkGfm from "remark-gfm";
import remarkMath from "remark-math";
function CreateNote() { function CreateNote() {
const [preview, setPreview] = useState(false); const [preview, setPreview] = useState(false);
@ -13,11 +21,25 @@ function CreateNote() {
const [date, setDate] = useState(Date.now()); const [date, setDate] = useState(Date.now());
setInterval(() => { // setInterval(() => {
if (preview) { // if (preview) {
setDate(Date.now()); // setDate(Date.now());
} // }
}, 1000); // }, 1000);
async function previewChange(val) {
let md = await unified()
.use(remarkGfm)
.use(remarkMath)
.use(rehypeParse)
.use(rehypeRemark)
.use(remarkStringify)
.process(val.target.value);
md = md.value.trim();
localStorage.setItem("NoteText", md);
}
let inputStyle = `form-control block px-3 py-1.5 text-base font-normal text-gray-700 dark:text-white bg-white dark:bg-zinc-900 bg-clip-padding border border-solid border-gray-300 rounded-lg transition ease-in-out focus:border-blue-600 focus:outline-none`; let inputStyle = `form-control block px-3 py-1.5 text-base font-normal text-gray-700 dark:text-white bg-white dark:bg-zinc-900 bg-clip-padding border border-solid border-gray-300 rounded-lg transition ease-in-out focus:border-blue-600 focus:outline-none`;
return ( return (
@ -30,7 +52,10 @@ function CreateNote() {
className="justify-self-center lg:justify-self-end" className="justify-self-center lg:justify-self-end"
label="Предпросмотр" label="Предпросмотр"
id="preview" id="preview"
onClick={() => setPreview(!preview)} onClick={() => {
setText(localStorage.getItem("NoteText"));
setPreview(!preview);
}}
/> />
</div> </div>
@ -75,7 +100,13 @@ function CreateNote() {
)} )}
{preview && ( {preview && (
<div className="w-full md break-words"> <div className="w-full md break-words">
<RenderMarkdown>{text}</RenderMarkdown> <ContentEditable
disabled={false}
onChange={previewChange}
html={ReactDOMServer.renderToString(
<RenderMarkdown>{text}</RenderMarkdown>
)}
/>
</div> </div>
)} )}

View file

@ -1,10 +1,9 @@
import RenderMarkdown from "../components/markdown";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import printDate from "../components/utils";
import { ChevronDoubleLeftIcon, TrashIcon } from "@heroicons/react/24/outline"; import { ChevronDoubleLeftIcon, TrashIcon } from "@heroicons/react/24/outline";
import { Button, IconWithText } from "../components/button"; import { Button, IconWithText } from "../components/button";
import Note from "../components/note";
function Note() { function NotePage() {
let params = useParams(); let params = useParams();
let note = localStorage.getObj("Notes")[params.id]; let note = localStorage.getObj("Notes")[params.id];
@ -22,19 +21,7 @@ function Note() {
</IconWithText> </IconWithText>
</Button> </Button>
<div className="border border-blue-300 rounded-lg p-4"> <Note note={note} />
<div className="grid grid-cols-1 lg:grid-cols-2">
<h2 className="font-medium text-center lg:text-left leading-tight text-4xl mt-0 mb-2">
{note.name}
</h2>
<div className="justify-self-center lg:justify-self-end">
{printDate(note.time)}
</div>
</div>
<div className="w-full md break-words">
<RenderMarkdown>{note.text}</RenderMarkdown>
</div>
</div>
<div className="grid grid-cols-1"> <div className="grid grid-cols-1">
<div className="justify-self-center lg:justify-self-end"> <div className="justify-self-center lg:justify-self-end">
<Button <Button
@ -76,4 +63,4 @@ function Note() {
} }
} }
export default Note; export default NotePage;

View file

@ -5,6 +5,7 @@ import printDate from "../components/utils";
import { ChevronDoubleLeftIcon } from "@heroicons/react/24/outline"; import { ChevronDoubleLeftIcon } from "@heroicons/react/24/outline";
import { Button, IconWithText } from "../components/button"; import { Button, IconWithText } from "../components/button";
import { CopyToClipboard } from "../components/copytocb"; import { CopyToClipboard } from "../components/copytocb";
import Note from "../components/note";
function PubNoteSafe() { function PubNoteSafe() {
let params = useParams(); let params = useParams();
@ -64,19 +65,7 @@ function PubNoteSafe() {
</div> </div>
)} )}
<div className="border border-blue-300 rounded-lg p-4"> <Note note={note} />
<div className="grid grid-cols-1 lg:grid-cols-2">
<h2 className="font-medium text-center lg:text-left leading-tight text-4xl mt-0 mb-2">
{note?.name || "Загрузка..."}
</h2>
<div className="justify-self-center lg:justify-self-end">
{printDate(note?.time || Date.now())}
</div>
</div>
<div className="w-full md break-words">
<RenderMarkdown>{note?.text || "Загрузка..."}</RenderMarkdown>
</div>
</div>
</div> </div>
); );
} }