diff --git a/src/public/app/widgets/attribute_widgets/attribute_detail.js b/src/public/app/widgets/attribute_widgets/attribute_detail.js
index 9f85945fb..01c6b80a2 100644
--- a/src/public/app/widgets/attribute_widgets/attribute_detail.js
+++ b/src/public/app/widgets/attribute_widgets/attribute_detail.js
@@ -216,6 +216,7 @@ const ATTR_HELP = {
"shareOmitDefaultCss": "default share page CSS will be omitted. Use when you make extensive styling changes.",
"shareRoot": "marks note which is served on /share root.",
"shareRaw": "note will be served in its raw format, without HTML wrapper",
+ "shareDisallowRobotIndexing": `will forbid robot indexing of this note via X-Robots-Tag: noindex
header`,
"displayRelations": "comma delimited names of relations which should be displayed. All other ones will be hidden.",
"hideRelations": "comma delimited names of relations which should be hidden. All other ones will be displayed.",
},
diff --git a/src/services/attributes.js b/src/services/attributes.js
index 3ddd41223..5c6d309a0 100644
--- a/src/services/attributes.js
+++ b/src/services/attributes.js
@@ -128,10 +128,6 @@ function isAttributeDangerous(type, name) {
);
}
-function getBuiltinAttributeNames() {
- return BUILTIN_ATTRIBUTES;
-}
-
function sanitizeAttributeName(origName) {
let fixedName;
@@ -156,6 +152,5 @@ module.exports = {
getAttributeNames,
isAttributeType,
isAttributeDangerous,
- getBuiltinAttributeNames,
sanitizeAttributeName
};
diff --git a/src/services/builtin_attributes.js b/src/services/builtin_attributes.js
index ed8a61a27..51243aa0b 100644
--- a/src/services/builtin_attributes.js
+++ b/src/services/builtin_attributes.js
@@ -47,6 +47,7 @@ module.exports = [
{ type: 'label', name: 'shareOmitDefaultCss' },
{ type: 'label', name: 'shareRoot' },
{ type: 'label', name: 'shareRaw' },
+ { type: 'label', name: 'shareDisallowRobotIndexing' },
{ type: 'label', name: 'displayRelations' },
{ type: 'label', name: 'hideRelations' },
diff --git a/src/share/routes.js b/src/share/routes.js
index 27ec655f7..609028597 100644
--- a/src/share/routes.js
+++ b/src/share/routes.js
@@ -20,30 +20,39 @@ function getSharedSubTreeRoot(note) {
return getSharedSubTreeRoot(parentNote);
}
+function addNoIndexHeader(note, res) {
+ if (note.hasLabel('shareDisallowRobotIndexing')) {
+ res.setHeader('X-Robots-Tag', 'noindex');
+ }
+}
+
function register(router) {
function renderNote(note, res) {
- if (note) {
- if (note.hasLabel('shareRaw')) {
- res.setHeader('Content-Type', note.mime);
-
- res.send(note.getContent());
- return;
- }
-
- const {header, content, isEmpty} = contentRenderer.getContent(note);
-
- const subRoot = getSharedSubTreeRoot(note);
-
- res.render("share/page", {
- note,
- header,
- content,
- isEmpty,
- subRoot
- });
- } else {
+ if (!note) {
res.status(404).render("share/404");
+ return;
}
+
+ addNoIndexHeader(note, res);
+
+ if (note.hasLabel('shareRaw') || ['image', 'file'].includes(note.type)) {
+ res.setHeader('Content-Type', note.mime);
+
+ res.send(note.getContent());
+ return;
+ }
+
+ const {header, content, isEmpty} = contentRenderer.getContent(note);
+
+ const subRoot = getSharedSubTreeRoot(note);
+
+ res.render("share/page", {
+ note,
+ header,
+ content,
+ isEmpty,
+ subRoot
+ });
}
router.get(['/share', '/share/'], (req, res, next) => {
@@ -70,6 +79,8 @@ function register(router) {
return res.status(404).send(`Note ${noteId} not found`);
}
+ addNoIndexHeader(note, res);
+
res.json(note.getPojoWithAttributes());
});
@@ -81,6 +92,8 @@ function register(router) {
return res.status(404).send(`Note ${noteId} not found`);
}
+ addNoIndexHeader(note, res);
+
const utils = require("../services/utils");
const filename = utils.formatDownloadTitle(note.title, note.type, note.mime);
@@ -103,6 +116,8 @@ function register(router) {
return res.status(400).send("Requested note is not an image");
}
+ addNoIndexHeader(image, res);
+
res.set('Content-Type', image.mime);
res.send(image.getContent());
@@ -117,6 +132,8 @@ function register(router) {
return res.status(404).send(`Note ${noteId} not found`);
}
+ addNoIndexHeader(note, res);
+
res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
res.setHeader('Content-Type', note.mime);
diff --git a/src/share/shaca/entities/attribute.js b/src/share/shaca/entities/attribute.js
index 471a3793e..ac87c4ddc 100644
--- a/src/share/shaca/entities/attribute.js
+++ b/src/share/shaca/entities/attribute.js
@@ -34,9 +34,9 @@ class Attribute extends AbstractEntity {
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);
+ const branch = this.shaca.getBranchFromChildAndParent(this.noteId, linkedChildNote.noteId);
- linkedChildNote.parents = linkedChildNote.parents.filter(parentNote => parentNote.noteId !== this.noteId);
+ branch.isHidden = true;
}
}
diff --git a/src/share/shaca/entities/branch.js b/src/share/shaca/entities/branch.js
index 1f84d83a9..a1b55538e 100644
--- a/src/share/shaca/entities/branch.js
+++ b/src/share/shaca/entities/branch.js
@@ -16,6 +16,8 @@ class Branch extends AbstractEntity {
this.prefix = prefix;
/** @param {boolean} */
this.isExpanded = !!isExpanded;
+ /** @param {boolean} */
+ this.isHidden = false;
const childNote = this.childNote;
const parentNote = this.parentNote;
diff --git a/src/share/shaca/entities/note.js b/src/share/shaca/entities/note.js
index 95b3d1f83..d19548760 100644
--- a/src/share/shaca/entities/note.js
+++ b/src/share/shaca/entities/note.js
@@ -59,7 +59,10 @@ class Note extends AbstractEntity {
}
getVisibleChildNotes() {
- return this.children.filter(childNote => !childNote.hasLabel('shareHiddenFromTree') && !childNote.isProtected);
+ return this.getChildBranches()
+ .filter(branch => !branch.isHidden)
+ .map(branch => branch.getNote())
+ .filter(childNote => !childNote.hasLabel('shareHiddenFromTree') && !childNote.isProtected);
}
hasChildren() {
@@ -67,7 +70,7 @@ class Note extends AbstractEntity {
}
hasVisibleChildren() {
- return this.children && !!this.children.find(childNote => !childNote.hasLabel('shareHiddenFromTree') && !childNote.isProtected);
+ return this.getVisibleChildNotes().length > 0;
}
getChildBranches() {
diff --git a/src/views/share/page.ejs b/src/views/share/page.ejs
index ed52d218b..38b4955c9 100644
--- a/src/views/share/page.ejs
+++ b/src/views/share/page.ejs
@@ -21,6 +21,9 @@
<% for (const jsRelation of note.getRelations("shareJs")) { %>
<% } %>
+ <% if (note.hasLabel('shareDisallowRobotIndexing')) { %>
+
+ <% } %>
<%- header %>