Fixes #154
parent
cff343a66b
commit
3ca132e16a
|
@ -9,6 +9,7 @@ import { listFilesCached } from "../federation/federation.ts";
|
||||||
import { queryObjects } from "../index/plug_api.ts";
|
import { queryObjects } from "../index/plug_api.ts";
|
||||||
import { folderName } from "$sb/lib/resolve.ts";
|
import { folderName } from "$sb/lib/resolve.ts";
|
||||||
import { decoration } from "$sb/syscalls.ts";
|
import { decoration } from "$sb/syscalls.ts";
|
||||||
|
import type { LinkObject } from "../index/page_links.ts";
|
||||||
|
|
||||||
// A meta page is a page tagged with either #template or #meta
|
// A meta page is a page tagged with either #template or #meta
|
||||||
const isMetaPageFilter: QueryExpression = ["or", ["=", ["attr", "tags"], [
|
const isMetaPageFilter: QueryExpression = ["or", ["=", ["attr", "tags"], [
|
||||||
|
@ -66,14 +67,34 @@ export async function pageComplete(completeEvent: CompleteEvent) {
|
||||||
// Include both pages and meta in page completion in ```include and ```template blocks
|
// Include both pages and meta in page completion in ```include and ```template blocks
|
||||||
allPages = await queryObjects<PageMeta>("page", {}, 5);
|
allPages = await queryObjects<PageMeta>("page", {}, 5);
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, just complete non-meta pages
|
// This is the most common case, we're combining three types of completions here:
|
||||||
allPages = await queryObjects<PageMeta>("page", {
|
allPages = (await Promise.all([
|
||||||
filter: ["not", isMetaPageFilter],
|
// All non-meta pages
|
||||||
}, 5);
|
queryObjects<PageMeta>("page", {
|
||||||
// and attachments
|
filter: ["not", isMetaPageFilter],
|
||||||
allPages = allPages.concat(
|
}, 5),
|
||||||
await queryObjects<AttachmentMeta>("attachment", {}, 5),
|
// All attachments
|
||||||
);
|
queryObjects<AttachmentMeta>("attachment", {}, 5),
|
||||||
|
// And all links to non-existing pages (to augment the existing ones)
|
||||||
|
queryObjects<LinkObject>("link", {
|
||||||
|
filter: ["and", ["attr", "toPage"], ["not", ["call", "pageExists", [[
|
||||||
|
"attr",
|
||||||
|
"toPage",
|
||||||
|
]]]]],
|
||||||
|
select: [{ name: "toPage" }],
|
||||||
|
}, 5).then((brokenLinks) =>
|
||||||
|
// Rewrite them to PageMeta shaped objects
|
||||||
|
brokenLinks.map((link): PageMeta => ({
|
||||||
|
ref: link.toPage!,
|
||||||
|
tag: "page",
|
||||||
|
tags: ["non-existing"], // Picked up later in completion
|
||||||
|
name: link.toPage!,
|
||||||
|
created: "",
|
||||||
|
lastModified: "",
|
||||||
|
perm: "rw",
|
||||||
|
}))
|
||||||
|
),
|
||||||
|
])).flat();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't complete hidden pages
|
// Don't complete hidden pages
|
||||||
|
@ -143,6 +164,9 @@ export async function pageComplete(completeEvent: CompleteEvent) {
|
||||||
label: pageMeta.name,
|
label: pageMeta.name,
|
||||||
displayLabel: decoratedName,
|
displayLabel: decoratedName,
|
||||||
boost: new Date(pageMeta.lastModified).getTime(),
|
boost: new Date(pageMeta.lastModified).getTime(),
|
||||||
|
detail: pageMeta.tags?.includes("non-existing")
|
||||||
|
? "Linked but not created"
|
||||||
|
: undefined,
|
||||||
type: "page",
|
type: "page",
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -62,6 +62,7 @@ import { LimitedMap } from "$lib/limited_map.ts";
|
||||||
import { plugPrefix } from "$common/spaces/constants.ts";
|
import { plugPrefix } from "$common/spaces/constants.ts";
|
||||||
import { lezerToParseTree } from "$common/markdown_parser/parse_tree.ts";
|
import { lezerToParseTree } from "$common/markdown_parser/parse_tree.ts";
|
||||||
import { findNodeMatching } from "$sb/lib/tree.ts";
|
import { findNodeMatching } from "$sb/lib/tree.ts";
|
||||||
|
import type { LinkObject } from "../plugs/index/page_links.ts";
|
||||||
|
|
||||||
const frontMatterRegex = /^---\n(([^\n]|\n)*?)---\n/;
|
const frontMatterRegex = /^---\n(([^\n]|\n)*?)---\n/;
|
||||||
|
|
||||||
|
@ -787,9 +788,27 @@ export class Client {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const allPages = await this.clientSystem.queryObjects<PageMeta>("page", {});
|
const allPages = await this.clientSystem.queryObjects<PageMeta>("page", {});
|
||||||
|
const allBrokenLinkPages = (await this.clientSystem.queryObjects<
|
||||||
|
LinkObject
|
||||||
|
>("link", {
|
||||||
|
filter: ["and", ["attr", "toPage"], ["not", ["call", "pageExists", [[
|
||||||
|
"attr",
|
||||||
|
"toPage",
|
||||||
|
]]]]],
|
||||||
|
select: [{ name: "toPage" }],
|
||||||
|
})).map((link): PageMeta => ({
|
||||||
|
ref: link.toPage!,
|
||||||
|
tag: "page",
|
||||||
|
_isBrokenLink: true,
|
||||||
|
name: link.toPage!,
|
||||||
|
created: "",
|
||||||
|
lastModified: "",
|
||||||
|
perm: "rw",
|
||||||
|
}));
|
||||||
|
|
||||||
this.ui.viewDispatch({
|
this.ui.viewDispatch({
|
||||||
type: "update-page-list",
|
type: "update-page-list",
|
||||||
allPages,
|
allPages: allPages.concat(allBrokenLinkPages),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,7 @@ export function PageNavigator({
|
||||||
name: (pageMeta.pageDecoration?.prefix ?? "") + pageMeta.name,
|
name: (pageMeta.pageDecoration?.prefix ?? "") + pageMeta.name,
|
||||||
description,
|
description,
|
||||||
orderId: orderId,
|
orderId: orderId,
|
||||||
|
hint: pageMeta._isBrokenLink ? "Create page" : undefined,
|
||||||
});
|
});
|
||||||
} else if (mode === "meta") {
|
} else if (mode === "meta") {
|
||||||
// Special behavior for #template and #meta pages
|
// Special behavior for #template and #meta pages
|
||||||
|
@ -99,11 +100,15 @@ export function PageNavigator({
|
||||||
} else if (currentPage && currentPage.includes(" ")) {
|
} else if (currentPage && currentPage.includes(" ")) {
|
||||||
completePrefix = currentPage.split(" ")[0] + " ";
|
completePrefix = currentPage.split(" ")[0] + " ";
|
||||||
}
|
}
|
||||||
|
|
||||||
const pageNoun = mode === "meta" ? mode : "page";
|
const pageNoun = mode === "meta" ? mode : "page";
|
||||||
return (
|
return (
|
||||||
<FilterList
|
<FilterList
|
||||||
placeholder={mode === "page" ? "Page" : (mode === "meta" ? "#template or #meta page" : "Any page, also hidden")}
|
placeholder={mode === "page"
|
||||||
|
? "Page"
|
||||||
|
: (mode === "meta"
|
||||||
|
? "#template or #meta page"
|
||||||
|
: "Any page, also hidden")}
|
||||||
label="Open"
|
label="Open"
|
||||||
options={options}
|
options={options}
|
||||||
vimMode={vimMode}
|
vimMode={vimMode}
|
||||||
|
@ -116,7 +121,7 @@ export function PageNavigator({
|
||||||
onKeyPress={(key, text) => {
|
onKeyPress={(key, text) => {
|
||||||
// Pages cannot start with ^, as documented in Page Name Rules
|
// Pages cannot start with ^, as documented in Page Name Rules
|
||||||
if (key === "^" && text === "^") {
|
if (key === "^" && text === "^") {
|
||||||
switch(mode) {
|
switch (mode) {
|
||||||
case "page":
|
case "page":
|
||||||
onModeSwitch("meta");
|
onModeSwitch("meta");
|
||||||
break;
|
break;
|
||||||
|
@ -159,7 +164,9 @@ export function PageNavigator({
|
||||||
|
|
||||||
if (mode !== "all") {
|
if (mode !== "all") {
|
||||||
// Filter out hidden pages
|
// Filter out hidden pages
|
||||||
options = options.filter((page) => !(page.pageDecoration?.hide === true));
|
options = options.filter((page) =>
|
||||||
|
!(page.pageDecoration?.hide === true)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return options;
|
return options;
|
||||||
}}
|
}}
|
||||||
|
|
Loading…
Reference in New Issue