Linked mentions improvements and other fixes
This commit is contained in:
parent
ae3e5f375e
commit
17ba536801
@ -60,9 +60,15 @@ export class EventHook implements Hook<EventHookT> {
|
|||||||
) {
|
) {
|
||||||
// Only dispatch functions that can run in this environment
|
// Only dispatch functions that can run in this environment
|
||||||
if (await plug.canInvoke(name)) {
|
if (await plug.canInvoke(name)) {
|
||||||
const result = await plug.invoke(name, args);
|
try {
|
||||||
if (result !== undefined) {
|
const result = await plug.invoke(name, args);
|
||||||
responses.push(result);
|
if (result !== undefined) {
|
||||||
|
responses.push(result);
|
||||||
|
}
|
||||||
|
} catch (e: any) {
|
||||||
|
console.error(
|
||||||
|
`Error dispatching event ${eventName} to plug ${plug.name}: ${e.message}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,13 @@ const directiveUpdateQueueName = "directiveUpdateQueue";
|
|||||||
export async function updateDirectivesOnPageCommand() {
|
export async function updateDirectivesOnPageCommand() {
|
||||||
// If `arg` is a string, it's triggered automatically via an event, not explicitly via a command
|
// If `arg` is a string, it's triggered automatically via an event, not explicitly via a command
|
||||||
const currentPage = await editor.getCurrentPage();
|
const currentPage = await editor.getCurrentPage();
|
||||||
const pageMeta = await space.getPageMeta(currentPage);
|
let pageMeta: PageMeta | undefined;
|
||||||
|
try {
|
||||||
|
pageMeta = await space.getPageMeta(currentPage);
|
||||||
|
} catch {
|
||||||
|
console.info("Page not found, not updating directives");
|
||||||
|
return;
|
||||||
|
}
|
||||||
const text = await editor.getText();
|
const text = await editor.getText();
|
||||||
const tree = await markdown.parseMarkdown(text);
|
const tree = await markdown.parseMarkdown(text);
|
||||||
const metaData = await extractFrontmatter(tree, ["$disableDirectives"]);
|
const metaData = await extractFrontmatter(tree, ["$disableDirectives"]);
|
||||||
|
@ -77,8 +77,9 @@ export async function indexObjects<T>(
|
|||||||
value: obj,
|
value: obj,
|
||||||
});
|
});
|
||||||
// Index attributes
|
// Index attributes
|
||||||
if (!builtins[tag]) {
|
const builtinAttributes = builtins[tag];
|
||||||
// But only for non-builtin tags
|
if (!builtinAttributes) {
|
||||||
|
// For non-builtin tags, index all attributes
|
||||||
for (
|
for (
|
||||||
const [attrName, attrValue] of Object.entries(
|
const [attrName, attrValue] of Object.entries(
|
||||||
obj as Record<string, any>,
|
obj as Record<string, any>,
|
||||||
@ -89,6 +90,20 @@ export async function indexObjects<T>(
|
|||||||
}
|
}
|
||||||
allAttributes.set(`${tag}:${attrName}`, determineType(attrValue));
|
allAttributes.set(`${tag}:${attrName}`, determineType(attrValue));
|
||||||
}
|
}
|
||||||
|
} else if (tag !== "attribute") {
|
||||||
|
// For builtin tags, only index custom ones
|
||||||
|
for (
|
||||||
|
const [attrName, attrValue] of Object.entries(
|
||||||
|
obj as Record<string, any>,
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
// console.log("Indexing", tag, attrName, attrValue);
|
||||||
|
// Skip builtins and internal attributes
|
||||||
|
if (builtinAttributes[attrName] || attrName.startsWith("$")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
allAttributes.set(`${tag}:${attrName}`, determineType(attrValue));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,12 @@ function processClick(e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById("link-ul").addEventListener("click", processClick);
|
document.getElementById("link-ul").addEventListener("click", processClick);
|
||||||
document.getElementById("hide-button").addEventListener("click", function () {
|
document.getElementById("hide-button").addEventListener("click", () => {
|
||||||
console.log("HERE")
|
syscall("system.invokeFunction", "index.toggleMentions").catch(console.error);
|
||||||
syscall(
|
});
|
||||||
"system.invokeFunction",
|
|
||||||
"index.toggleMentions",
|
document.getElementById("reload-button").addEventListener("click", () => {
|
||||||
).catch(console.error);
|
syscall("system.invokeFunction", "index.renderMentions").catch(
|
||||||
|
console.error,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
@ -33,12 +33,25 @@ body {
|
|||||||
background-color: rgba(233, 233, 233, 0.5);
|
background-color: rgba(233, 233, 233, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
#hide-button {
|
#button-bar {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 15px;
|
right: 10px;
|
||||||
top: 15px;
|
top: 10px;
|
||||||
|
padding: 0 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#button-bar button {
|
||||||
|
border: none;
|
||||||
|
background: none;
|
||||||
|
cursor: pointer;
|
||||||
|
color: var(--root-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#edit-button {
|
||||||
|
margin-left: -10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
li code {
|
li code {
|
||||||
font-size: 80%;
|
font-size: 80%;
|
||||||
color: #a5a4a4;
|
color: #a5a4a4;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import type { CompleteEvent } from "$sb/app_event.ts";
|
import type { CompleteEvent } from "$sb/app_event.ts";
|
||||||
import { events } from "$sb/syscalls.ts";
|
import { events } from "$sb/syscalls.ts";
|
||||||
import { queryObjects } from "./api.ts";
|
import { getObjectByRef, queryObjects } from "./api.ts";
|
||||||
import { ObjectValue, QueryExpression } from "$sb/types.ts";
|
import { ObjectValue, QueryExpression } from "$sb/types.ts";
|
||||||
import { builtinPseudoPage } from "./builtins.ts";
|
import { builtinPseudoPage } from "./builtins.ts";
|
||||||
|
|
||||||
@ -85,18 +85,32 @@ export async function attributeComplete(completeEvent: CompleteEvent) {
|
|||||||
}
|
}
|
||||||
const attributeMatch = /^(\w+)$/.exec(completeEvent.linePrefix);
|
const attributeMatch = /^(\w+)$/.exec(completeEvent.linePrefix);
|
||||||
if (attributeMatch) {
|
if (attributeMatch) {
|
||||||
if (completeEvent.parentNodes.includes("FrontMatterCode")) {
|
if (completeEvent.parentNodes.includes("FrontMatter")) {
|
||||||
const completions = (await events.dispatchEvent(
|
const pageMeta = await getObjectByRef(
|
||||||
`attribute:complete:page`,
|
completeEvent.pageName,
|
||||||
{
|
"page",
|
||||||
source: "page",
|
completeEvent.pageName,
|
||||||
prefix: attributeMatch[1],
|
);
|
||||||
} as AttributeCompleteEvent,
|
let tags = ["page"];
|
||||||
)).flat() as AttributeCompletion[];
|
if (pageMeta?.tags) {
|
||||||
|
tags = pageMeta.tags;
|
||||||
|
}
|
||||||
|
const completions = (await Promise.all(tags.map((tag) =>
|
||||||
|
events.dispatchEvent(
|
||||||
|
`attribute:complete:${tag}`,
|
||||||
|
{
|
||||||
|
source: tag,
|
||||||
|
prefix: attributeMatch[1],
|
||||||
|
} as AttributeCompleteEvent,
|
||||||
|
)
|
||||||
|
))).flat(2) as AttributeCompletion[];
|
||||||
|
// console.log("Completions", completions);
|
||||||
return {
|
return {
|
||||||
from: completeEvent.pos - attributeMatch[1].length,
|
from: completeEvent.pos - attributeMatch[1].length,
|
||||||
options: attributeCompletionsToCMCompletion(
|
options: attributeCompletionsToCMCompletion(
|
||||||
completions.filter((completion) => !completion.builtin),
|
completions.filter((completion) =>
|
||||||
|
!completion.builtin
|
||||||
|
),
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ export const builtinPseudoPage = ":builtin:";
|
|||||||
|
|
||||||
export const builtins: Record<string, Record<string, string>> = {
|
export const builtins: Record<string, Record<string, string>> = {
|
||||||
page: {
|
page: {
|
||||||
|
ref: "string",
|
||||||
name: "string",
|
name: "string",
|
||||||
lastModified: "date",
|
lastModified: "date",
|
||||||
perm: "rw|ro",
|
perm: "rw|ro",
|
||||||
@ -15,6 +16,7 @@ export const builtins: Record<string, Record<string, string>> = {
|
|||||||
tags: "array",
|
tags: "array",
|
||||||
},
|
},
|
||||||
task: {
|
task: {
|
||||||
|
ref: "string",
|
||||||
name: "string",
|
name: "string",
|
||||||
done: "boolean",
|
done: "boolean",
|
||||||
page: "string",
|
page: "string",
|
||||||
@ -24,22 +26,26 @@ export const builtins: Record<string, Record<string, string>> = {
|
|||||||
tags: "array",
|
tags: "array",
|
||||||
},
|
},
|
||||||
tag: {
|
tag: {
|
||||||
|
ref: "string",
|
||||||
name: "string",
|
name: "string",
|
||||||
page: "string",
|
page: "string",
|
||||||
context: "string",
|
context: "string",
|
||||||
},
|
},
|
||||||
attribute: {
|
attribute: {
|
||||||
|
ref: "string",
|
||||||
name: "string",
|
name: "string",
|
||||||
attributeType: "string",
|
attributeType: "string",
|
||||||
type: "string",
|
type: "string",
|
||||||
page: "string",
|
page: "string",
|
||||||
},
|
},
|
||||||
anchor: {
|
anchor: {
|
||||||
|
ref: "string",
|
||||||
name: "string",
|
name: "string",
|
||||||
page: "string",
|
page: "string",
|
||||||
pos: "number",
|
pos: "number",
|
||||||
},
|
},
|
||||||
link: {
|
link: {
|
||||||
|
ref: "string",
|
||||||
name: "string",
|
name: "string",
|
||||||
page: "string",
|
page: "string",
|
||||||
pos: "number",
|
pos: "number",
|
||||||
|
@ -102,11 +102,6 @@ functions:
|
|||||||
events:
|
events:
|
||||||
- attribute:complete:*
|
- attribute:complete:*
|
||||||
|
|
||||||
# builtinAttributeCompleter:
|
|
||||||
# path: ./attributes.ts:builtinAttributeCompleter
|
|
||||||
# events:
|
|
||||||
# - attribute:complete:*
|
|
||||||
|
|
||||||
# Item indexing
|
# Item indexing
|
||||||
indexItem:
|
indexItem:
|
||||||
path: "./item.ts:indexItems"
|
path: "./item.ts:indexItems"
|
||||||
@ -172,3 +167,5 @@ functions:
|
|||||||
navigateToMention:
|
navigateToMention:
|
||||||
path: "./mentions_ps.ts:navigate"
|
path: "./mentions_ps.ts:navigate"
|
||||||
|
|
||||||
|
renderMentions:
|
||||||
|
path: "./mentions_ps.ts:renderMentions"
|
||||||
|
@ -10,8 +10,7 @@ export async function toggleMentions() {
|
|||||||
hideMentions = !hideMentions;
|
hideMentions = !hideMentions;
|
||||||
await clientStore.set(hideMentionsKey, hideMentions);
|
await clientStore.set(hideMentionsKey, hideMentions);
|
||||||
if (!hideMentions) {
|
if (!hideMentions) {
|
||||||
const name = await editor.getCurrentPage();
|
await renderMentions();
|
||||||
await renderMentions(name);
|
|
||||||
} else {
|
} else {
|
||||||
await editor.hidePanel("ps");
|
await editor.hidePanel("ps");
|
||||||
}
|
}
|
||||||
@ -22,8 +21,7 @@ export async function updateMentions() {
|
|||||||
if (await clientStore.get(hideMentionsKey)) {
|
if (await clientStore.get(hideMentionsKey)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const name = await editor.getCurrentPage();
|
await renderMentions();
|
||||||
await renderMentions(name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// use internal navigation via syscall to prevent reloading the full page.
|
// use internal navigation via syscall to prevent reloading the full page.
|
||||||
@ -39,7 +37,8 @@ function escapeHtml(unsafe: string) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function renderMentions(page: string) {
|
export async function renderMentions() {
|
||||||
|
const page = await editor.getCurrentPage();
|
||||||
const linksResult = await queryObjects<LinkObject>("link", {
|
const linksResult = await queryObjects<LinkObject>("link", {
|
||||||
// Query all links that point to this page, excluding those that are inside directives and self pointers.
|
// Query all links that point to this page, excluding those that are inside directives and self pointers.
|
||||||
filter: ["and", ["!=", ["attr", "page"], ["string", page]], ["and", ["=", [
|
filter: ["and", ["!=", ["attr", "page"], ["string", page]], ["and", ["=", [
|
||||||
@ -60,7 +59,10 @@ async function renderMentions(page: string) {
|
|||||||
` <style>${css}</style>
|
` <style>${css}</style>
|
||||||
<link rel="stylesheet" href="/.client/main.css" />
|
<link rel="stylesheet" href="/.client/main.css" />
|
||||||
<div id="sb-main"><div id="sb-editor"><div class="cm-editor">
|
<div id="sb-main"><div id="sb-editor"><div class="cm-editor">
|
||||||
<button id="hide-button">Hide</button>
|
<div id="button-bar">
|
||||||
|
<button id="reload-button" title="Reload"><svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="23 4 23 10 17 10"></polyline><polyline points="1 20 1 14 7 14"></polyline><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"></path></svg></button>
|
||||||
|
<button id="hide-button" title="Hide linked mentions"><svg viewBox="0 0 24 24" width="12" height="12" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round" class="css-i6dzq1"><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24"></path><line x1="1" y1="1" x2="23" y2="23"></line></svg></button>
|
||||||
|
</div>
|
||||||
<div class="cm-line sb-line-h2">Linked Mentions</div>
|
<div class="cm-line sb-line-h2">Linked Mentions</div>
|
||||||
<ul id="link-ul">
|
<ul id="link-ul">
|
||||||
${
|
${
|
||||||
|
Loading…
Reference in New Issue
Block a user