Context sensitive slashCommands (with onlyContexts and exceptContexts)
parent
236b2a7fdd
commit
a28c3fd5b8
|
@ -53,8 +53,10 @@ export type SlashCommandDef = {
|
||||||
name: string;
|
name: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
boost?: number;
|
boost?: number;
|
||||||
// Parent AST nodes in which this slash command is available
|
// Parent AST nodes in which this slash command is available, defaults to everywhere
|
||||||
contexts?: string[];
|
onlyContexts?: string[];
|
||||||
|
// Parent AST nodes in which this slash command is not available
|
||||||
|
exceptContexts?: string[];
|
||||||
};
|
};
|
||||||
export type SlashCommandHookT = {
|
export type SlashCommandHookT = {
|
||||||
slashCommand?: SlashCommandDef;
|
slashCommand?: SlashCommandDef;
|
||||||
|
|
|
@ -29,20 +29,37 @@ export async function snippetSlashComplete(
|
||||||
// where hooks.snippet.slashCommand exists
|
// where hooks.snippet.slashCommand exists
|
||||||
filter: ["attr", ["attr", ["attr", "hooks"], "snippet"], "slashCommand"],
|
filter: ["attr", ["attr", ["attr", "hooks"], "snippet"], "slashCommand"],
|
||||||
}, 5);
|
}, 5);
|
||||||
return {
|
const options: SlashCompletionOption[] = [];
|
||||||
options: allTemplates.map((template) => {
|
for (const template of allTemplates) {
|
||||||
const snippetTemplate = template.hooks!.snippet!;
|
const snippetTemplate = template.hooks!.snippet!;
|
||||||
|
|
||||||
return {
|
if (
|
||||||
|
snippetTemplate.onlyContexts && !snippetTemplate.onlyContexts.some(
|
||||||
|
(context) =>
|
||||||
|
completeEvent.parentNodes.some((node) => node.startsWith(context)),
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
snippetTemplate.exceptContexts && snippetTemplate.exceptContexts.some(
|
||||||
|
(context) =>
|
||||||
|
completeEvent.parentNodes.some((node) => node.startsWith(context)),
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
options.push({
|
||||||
label: snippetTemplate.slashCommand,
|
label: snippetTemplate.slashCommand,
|
||||||
detail: template.description,
|
detail: template.description,
|
||||||
order: snippetTemplate.order || 0,
|
order: snippetTemplate.order || 0,
|
||||||
templatePage: template.ref,
|
templatePage: template.ref,
|
||||||
pageName: completeEvent.pageName,
|
pageName: completeEvent.pageName,
|
||||||
invoke: "template.insertSnippetTemplate",
|
invoke: "template.insertSnippetTemplate",
|
||||||
};
|
});
|
||||||
}),
|
}
|
||||||
};
|
return { options };
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function insertSnippetTemplate(
|
export async function insertSnippetTemplate(
|
||||||
|
|
|
@ -31,6 +31,8 @@ export type SnippetConfig = CommandConfig & {
|
||||||
// Deprecated: use matchRegex instead (for backwards compatibility)
|
// Deprecated: use matchRegex instead (for backwards compatibility)
|
||||||
match?: string;
|
match?: string;
|
||||||
insertAt?: "cursor" | "line-start" | "line-end" | "page-start" | "page-end"; // defaults to cursor
|
insertAt?: "cursor" | "line-start" | "line-end" | "page-start" | "page-end"; // defaults to cursor
|
||||||
|
onlyContexts?: string[];
|
||||||
|
exceptContexts?: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export type WidgetConfig = {
|
export type WidgetConfig = {
|
||||||
|
@ -97,6 +99,12 @@ export const SnippetConfigSchema: JSONSchemaType<SnippetConfig> = {
|
||||||
order: { type: "number", nullable: true },
|
order: { type: "number", nullable: true },
|
||||||
matchRegex: { type: "string", nullable: true },
|
matchRegex: { type: "string", nullable: true },
|
||||||
match: { type: "string", nullable: true },
|
match: { type: "string", nullable: true },
|
||||||
|
onlyContexts: { type: "array", items: { type: "string" }, nullable: true },
|
||||||
|
exceptContexts: {
|
||||||
|
type: "array",
|
||||||
|
items: { type: "string" },
|
||||||
|
nullable: true,
|
||||||
|
},
|
||||||
insertAt: {
|
insertAt: {
|
||||||
type: "string",
|
type: "string",
|
||||||
enum: [
|
enum: [
|
||||||
|
|
|
@ -110,10 +110,16 @@ export class SlashCommandHook implements Hook<SlashCommandHookT> {
|
||||||
|
|
||||||
// Check if the slash command is available in the current context
|
// Check if the slash command is available in the current context
|
||||||
const parentNodes = this.editor.extractParentNodes(ctx.state, currentNode);
|
const parentNodes = this.editor.extractParentNodes(ctx.state, currentNode);
|
||||||
// console.log("Parent nodes", parentNodes);
|
|
||||||
for (const def of this.slashCommands.values()) {
|
for (const def of this.slashCommands.values()) {
|
||||||
if (
|
if (
|
||||||
def.slashCommand.contexts && !def.slashCommand.contexts.some(
|
def.slashCommand.onlyContexts && !def.slashCommand.onlyContexts.some(
|
||||||
|
(context) => parentNodes.some((node) => node.startsWith(context)),
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
def.slashCommand.exceptContexts && def.slashCommand.exceptContexts.some(
|
||||||
(context) => parentNodes.some((node) => node.startsWith(context)),
|
(context) => parentNodes.some((node) => node.startsWith(context)),
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
---
|
---
|
||||||
description: Insert a fenced code block
|
description: Insert a fenced code block
|
||||||
tags: template
|
tags: template
|
||||||
hooks.snippet.slashCommand: code
|
hooks.snippet:
|
||||||
|
slashCommand: code
|
||||||
|
exceptContexts:
|
||||||
|
- FencedCode
|
||||||
---
|
---
|
||||||
```|^|
|
```|^|
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@ tags: template
|
||||||
hooks.snippet:
|
hooks.snippet:
|
||||||
slashCommand: "#each"
|
slashCommand: "#each"
|
||||||
order: 10
|
order: 10
|
||||||
|
onlyContexts:
|
||||||
|
- FencedCode:template
|
||||||
---
|
---
|
||||||
{{escapeDirective("#each |^|")}}
|
{{escapeDirective("#each |^|")}}
|
||||||
|
|
||||||
|
|
|
@ -4,5 +4,7 @@ description: Make this a level 1 heading
|
||||||
hooks.snippet:
|
hooks.snippet:
|
||||||
slashCommand: h1
|
slashCommand: h1
|
||||||
matchRegex: "^#*\\s*"
|
matchRegex: "^#*\\s*"
|
||||||
|
exceptContexts:
|
||||||
|
- FencedCode
|
||||||
---
|
---
|
||||||
#
|
#
|
|
@ -4,5 +4,7 @@ description: Make this a level 2 heading
|
||||||
hooks.snippet:
|
hooks.snippet:
|
||||||
slashCommand: h2
|
slashCommand: h2
|
||||||
matchRegex: "^#*\\s*"
|
matchRegex: "^#*\\s*"
|
||||||
|
exceptContexts:
|
||||||
|
- FencedCode
|
||||||
---
|
---
|
||||||
##
|
##
|
|
@ -4,5 +4,7 @@ description: Make this a level 3 heading
|
||||||
hooks.snippet:
|
hooks.snippet:
|
||||||
slashCommand: h3
|
slashCommand: h3
|
||||||
matchRegex: "^#*\\s*"
|
matchRegex: "^#*\\s*"
|
||||||
|
exceptContexts:
|
||||||
|
- FencedCode
|
||||||
---
|
---
|
||||||
###
|
###
|
|
@ -4,5 +4,7 @@ description: Make this a level 4 heading
|
||||||
hooks.snippet:
|
hooks.snippet:
|
||||||
slashCommand: h4
|
slashCommand: h4
|
||||||
matchRegex: "^#*\\s*"
|
matchRegex: "^#*\\s*"
|
||||||
|
exceptContexts:
|
||||||
|
- FencedCode
|
||||||
---
|
---
|
||||||
####
|
####
|
|
@ -1,6 +1,9 @@
|
||||||
---
|
---
|
||||||
tags: template
|
tags: template
|
||||||
description: Insert a horizontal rule
|
description: Insert a horizontal rule
|
||||||
hooks.snippet.slashCommand: hr
|
hooks.snippet:
|
||||||
|
slashCommand: hr
|
||||||
|
exceptContexts:
|
||||||
|
- FencedCode
|
||||||
---
|
---
|
||||||
---
|
---
|
||||||
|
|
|
@ -4,6 +4,9 @@ tags: template
|
||||||
hooks.snippet:
|
hooks.snippet:
|
||||||
slashCommand: "#if"
|
slashCommand: "#if"
|
||||||
order: 10
|
order: 10
|
||||||
|
onlyContexts:
|
||||||
|
- FencedCode:template
|
||||||
|
|
||||||
---
|
---
|
||||||
{{escapeDirective("#if |^|")}}
|
{{escapeDirective("#if |^|")}}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@ tags: template
|
||||||
hooks.snippet:
|
hooks.snippet:
|
||||||
slashCommand: "#if-else"
|
slashCommand: "#if-else"
|
||||||
order: 10
|
order: 10
|
||||||
|
onlyContexts:
|
||||||
|
- FencedCode:template
|
||||||
---
|
---
|
||||||
{{escapeDirective("#if |^|")}}
|
{{escapeDirective("#if |^|")}}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
---
|
---
|
||||||
tags: template
|
tags: template
|
||||||
description: Add a live preview of a page
|
description: Add a live preview of a page
|
||||||
hooks.snippet.slashCommand: include-page
|
hooks.snippet:
|
||||||
|
slashCommand: include-page
|
||||||
|
exceptContexts:
|
||||||
|
- FencedCode
|
||||||
---
|
---
|
||||||
```include
|
```include
|
||||||
raw: "[[|^|]]"
|
raw: "[[|^|]]"
|
||||||
|
|
|
@ -6,5 +6,7 @@ hooks.snippet:
|
||||||
matchRegex: "^(\\s*)[\\-\\*]?\\s*"
|
matchRegex: "^(\\s*)[\\-\\*]?\\s*"
|
||||||
command: "Text: Turn into a bullet item"
|
command: "Text: Turn into a bullet item"
|
||||||
key: "Ctrl-q i"
|
key: "Ctrl-q i"
|
||||||
|
exceptContexts:
|
||||||
|
- FencedCode
|
||||||
---
|
---
|
||||||
$1*
|
$1*
|
|
@ -4,6 +4,8 @@ tags: template
|
||||||
hooks.snippet:
|
hooks.snippet:
|
||||||
slashCommand: "#let"
|
slashCommand: "#let"
|
||||||
order: 10
|
order: 10
|
||||||
|
onlyContexts:
|
||||||
|
- FencedCode:template
|
||||||
---
|
---
|
||||||
{{escapeDirective("#let @|^| = ")}}
|
{{escapeDirective("#let @|^| = ")}}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
---
|
---
|
||||||
description: Insert a live query
|
description: Insert a live query
|
||||||
tags: template
|
tags: template
|
||||||
hooks.snippet.slashCommand: query
|
hooks.snippet:
|
||||||
|
slashCommand: query
|
||||||
|
exceptContexts:
|
||||||
|
- FencedCode
|
||||||
---
|
---
|
||||||
```query
|
```query
|
||||||
|^|
|
|^|
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
---
|
---
|
||||||
tags: template
|
tags: template
|
||||||
description: Insert a table
|
description: Insert a table
|
||||||
hooks.snippet.slashCommand: table
|
hooks.snippet:
|
||||||
|
slashCommand: table
|
||||||
|
exceptContexts:
|
||||||
|
- FencedCode
|
||||||
---
|
---
|
||||||
| Header A | Header B |
|
| Header A | Header B |
|
||||||
|----------|----------|
|
|----------|----------|
|
||||||
|
|
|
@ -6,5 +6,7 @@ hooks.snippet:
|
||||||
matchRegex: "^(\\s*)[\\-\\*]?\\s*(\\[[ xX]\\])?\\s*"
|
matchRegex: "^(\\s*)[\\-\\*]?\\s*(\\[[ xX]\\])?\\s*"
|
||||||
command: "Text: Turn into task"
|
command: "Text: Turn into task"
|
||||||
key: "Ctrl-q t"
|
key: "Ctrl-q t"
|
||||||
|
exceptContexts:
|
||||||
|
- FencedCode
|
||||||
---
|
---
|
||||||
$1* [ ]
|
$1* [ ]
|
|
@ -1,7 +1,10 @@
|
||||||
---
|
---
|
||||||
description: Insert a template
|
description: Insert a template
|
||||||
tags: template
|
tags: template
|
||||||
hooks.snippet.slashCommand: "template"
|
hooks.snippet:
|
||||||
|
slashCommand: "template"
|
||||||
|
exceptContexts:
|
||||||
|
- FencedCode
|
||||||
---
|
---
|
||||||
```template
|
```template
|
||||||
|^|
|
|^|
|
||||||
|
|
Loading…
Reference in New Issue