diff --git a/package-lock.json b/package-lock.json index 58c9bad98..5c054f7de 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1896,9 +1896,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001265", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001265.tgz", - "integrity": "sha512-YzBnspggWV5hep1m9Z6sZVLOt7vrju8xWooFAgN6BA5qvy98qPAPb7vNUzypFaoh2pb3vlfzbDO8tB57UPGbtw==", + "version": "1.0.30001269", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001269.tgz", + "integrity": "sha512-UOy8okEVs48MyHYgV+RdW1Oiudl1H6KolybD6ZquD0VcrPSgj25omXO1S7rDydjpqaISCwA8Pyx+jUQKZwWO5w==", "dev": true }, "caseless": { @@ -2188,6 +2188,12 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, + "colorette": { + "version": "2.0.16", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", + "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==", + "dev": true + }, "colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", @@ -3546,9 +3552,9 @@ } }, "electron-to-chromium": { - "version": "1.3.867", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.867.tgz", - "integrity": "sha512-WbTXOv7hsLhjJyl7jBfDkioaY++iVVZomZ4dU6TMe/SzucV6mUAs2VZn/AehBwuZMiNEQDaPuTGn22YK5o+aDw==", + "version": "1.3.872", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.872.tgz", + "integrity": "sha512-qG96atLFY0agKyEETiBFNhpRLSXGSXOBuhXWpbkYqrLKKASpRyRBUtfkn0ZjIf/yXfA7FA4nScVOMpXSHFlUCQ==", "dev": true }, "electron-window-state": { @@ -4955,9 +4961,9 @@ "dev": true }, "jest-worker": { - "version": "27.2.5", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.2.5.tgz", - "integrity": "sha512-HTjEPZtcNKZ4LnhSp02NEH4vE+5OpJ0EsOWYvGQpHgUMLngydESAAMH5Wd/asPf29+XUDQZszxpLg1BkIIA2aw==", + "version": "27.3.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.3.1.tgz", + "integrity": "sha512-ks3WCzsiZaOPJl/oMsDjaf0TRiSv7ctNgs0FqRr2nARsovz6AWWy4oLElwcquGSz692DzgZQrCLScPNs5YlC4g==", "dev": true, "requires": { "@types/node": "*", @@ -7960,12 +7966,6 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" }, - "v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -8032,9 +8032,9 @@ "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==" }, "webpack": { - "version": "5.58.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.58.2.tgz", - "integrity": "sha512-3S6e9Vo1W2ijk4F4PPWRIu6D/uGgqaPmqw+av3W3jLDujuNkdxX5h5c+RQ6GkjVR+WwIPOfgY8av+j5j4tMqJw==", + "version": "5.59.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.59.0.tgz", + "integrity": "sha512-2HiFHKnWIb/cBfOfgssQn8XIRvntISXiz//F1q1+hKMs+uzC1zlVCJZEP7XqI1wzrDyc/ZdB4G+MYtz5biJxCA==", "dev": true, "requires": { "@types/eslint-scope": "^3.7.0", @@ -8064,9 +8064,9 @@ } }, "webpack-cli": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.9.0.tgz", - "integrity": "sha512-n/jZZBMzVEl4PYIBs+auy2WI0WTQ74EnJDiyD98O2JZY6IVIHJNitkYp/uTXOviIOMfgzrNvC9foKv/8o8KSZw==", + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.9.1.tgz", + "integrity": "sha512-JYRFVuyFpzDxMDB+v/nanUdQYcZtqFPGzmlW4s+UkPMFhSpfRNmf1z4AwYcHJVdvEFAM7FFCQdNTpsBYhDLusQ==", "dev": true, "requires": { "@discoveryjs/json-ext": "^0.5.0", @@ -8080,16 +8080,9 @@ "import-local": "^3.0.2", "interpret": "^2.2.0", "rechoir": "^0.7.0", - "v8-compile-cache": "^2.2.0", "webpack-merge": "^5.7.3" }, "dependencies": { - "colorette": { - "version": "2.0.16", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz", - "integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==", - "dev": true - }, "commander": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", diff --git a/package.json b/package.json index 0f8416fb2..71474aaed 100644 --- a/package.json +++ b/package.json @@ -90,8 +90,8 @@ "jsdoc": "3.6.7", "lorem-ipsum": "2.0.4", "rcedit": "3.0.1", - "webpack": "5.58.2", - "webpack-cli": "4.9.0" + "webpack": "5.59.0", + "webpack-cli": "4.9.1" }, "optionalDependencies": { "electron-installer-debian": "3.1.0" diff --git a/src/public/stylesheets/share.css b/src/public/stylesheets/share.css new file mode 100644 index 000000000..8320b90ce --- /dev/null +++ b/src/public/stylesheets/share.css @@ -0,0 +1,81 @@ +html { + box-sizing: border-box; + font-size: 16px; +} + +*, *:before, *:after { + box-sizing: inherit; +} + +body, h1, h2, h3, h4, h5, h6, p, ol, ul { + margin: 0; + padding: 0; + font-weight: normal; +} + +ul { + padding-left: 20px; +} + +#layout { + max-width: 1200px; + margin: 0 auto; + display: flex; + flex-direction: row; +} + +#menu { + padding: 20px; + flex-basis: 0; + flex-grow: 1; + background-color: #ccc; + overflow: auto; +} + +#main { + flex-basis: 0; + flex-grow: 3; + background-color:#eee; +} + +#title, #content { + padding: 20px; +} + +#menuLink { + position: fixed; + display: block; + top: 0; + left: 0; + width: 1.4em; + background: #000; + background: rgba(0,0,0,0.7); + font-size: 2rem; + z-index: 10; + height: auto; + color: white; + border: none; + cursor: pointer; +} + +@media (max-width: 48em) { + #layout.active #menu { + display: block; + } + + #layout.active #main { + display: none; + } + + #layout.active #menuLink::after { + content: "«"; + } + + #menu { + display: none; + } + + #menuLink::after { + content: "»"; + } +} diff --git a/src/share/routes.js b/src/share/routes.js index 525821b4e..250639295 100644 --- a/src/share/routes.js +++ b/src/share/routes.js @@ -1,5 +1,20 @@ const shaca = require("./shaca/shaca"); const shacaLoader = require("./shaca/shaca_loader"); +const shareRoot = require("./share_root"); + +function getSubRoot(note) { + if (note.noteId === shareRoot.SHARE_ROOT_NOTE_ID) { + return null; + } + + const parentNote = note.getParentNotes()[0]; + + if (parentNote.noteId === shareRoot.SHARE_ROOT_NOTE_ID) { + return note; + } + + return getSubRoot(parentNote); +} function register(router) { router.get('/share/:noteId', (req, res, next) => { @@ -8,12 +23,34 @@ function register(router) { shacaLoader.ensureLoad(); if (noteId in shaca.notes) { - res.send(shaca.notes[noteId].title); + const note = shaca.notes[noteId]; + + const subRoot = getSubRoot(note); + + res.render("share", { + note, + subRoot + }); } else { res.send("FFF"); } }); + + router.get('/share/api/images/:noteId/:filename', (req, res, next) => { + const image = shaca.getNote(req.params.noteId); + + if (!image) { + return res.sendStatus(404); + } + else if (image.type !== 'image') { + return res.sendStatus(400); + } + + res.set('Content-Type', image.mime); + + res.send(image.getContent()); + }); } module.exports = { diff --git a/src/share/shaca/entities/attribute.js b/src/share/shaca/entities/attribute.js index 986a3dad5..8aeba46c5 100644 --- a/src/share/shaca/entities/attribute.js +++ b/src/share/shaca/entities/attribute.js @@ -29,6 +29,16 @@ class Attribute extends AbstractEntity { if (targetNote) { targetNote.targetRelations.push(this); } + + if (this.type === 'relation' && this.name === 'imageLink') { + const linkedChildNote = this.note.getChildNotes().find(childNote => childNote.noteId === this.value); + + if (linkedChildNote) { + this.note.children = this.note.children.filter(childNote => childNote.noteId !== this.value); + + linkedChildNote.parents = linkedChildNote.parents.filter(parentNote => parentNote.noteId !== this.noteId); + } + } } get isAffectingSubtree() { diff --git a/src/share/share_root.js b/src/share/share_root.js index 9b4684681..712646572 100644 --- a/src/share/share_root.js +++ b/src/share/share_root.js @@ -1,3 +1,3 @@ module.exports = { - SHARE_ROOT_NOTE_ID: 'HX6aiJr1yjK4' + SHARE_ROOT_NOTE_ID: 'root' } diff --git a/src/views/share-tree-item.ejs b/src/views/share-tree-item.ejs new file mode 100644 index 000000000..a1285746d --- /dev/null +++ b/src/views/share-tree-item.ejs @@ -0,0 +1,17 @@ +
+ <% if (activeNote.noteId === note.noteId) { %> + <%= note.title %> + <% } else { %> + <%= note.title %> + <% } %> +
+ +<% if (note.hasChildren()) { %> +