Per-tag page styling (#945)
PageDecorator add cssClasses --------- Co-authored-by: Zef Hemel <zef@zef.me>pull/1008/head
parent
663cb0c3e1
commit
70cb0fc226
|
@ -4,6 +4,7 @@ export type FilterOption = {
|
||||||
description?: string;
|
description?: string;
|
||||||
orderId?: number;
|
orderId?: number;
|
||||||
hint?: string;
|
hint?: string;
|
||||||
|
classes?: string;
|
||||||
} & Record<string, any>;
|
} & Record<string, any>;
|
||||||
|
|
||||||
export type Notification = {
|
export type Notification = {
|
||||||
|
|
|
@ -26,7 +26,8 @@ export type PageMeta = ObjectValue<
|
||||||
* Decorates a page when it matches certain criteria
|
* Decorates a page when it matches certain criteria
|
||||||
*/
|
*/
|
||||||
export type PageDecoration = {
|
export type PageDecoration = {
|
||||||
prefix: string;
|
prefix?: string;
|
||||||
|
cssClasses?: string[];
|
||||||
hide?: boolean;
|
hide?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -124,10 +124,10 @@ export async function pageComplete(completeEvent: CompleteEvent) {
|
||||||
from: completeEvent.pos - prefix.length,
|
from: completeEvent.pos - prefix.length,
|
||||||
options: allPages.map((pageMeta) => {
|
options: allPages.map((pageMeta) => {
|
||||||
const completions: any[] = [];
|
const completions: any[] = [];
|
||||||
let namePrefix = "";
|
const namePrefix = (pageMeta as PageMeta).pageDecoration?.prefix || "";
|
||||||
if ((pageMeta as PageMeta).pageDecoration?.prefix) {
|
const cssClass = ((pageMeta as PageMeta).pageDecoration?.cssClasses || [])
|
||||||
namePrefix = pageMeta.pageDecoration?.prefix;
|
.join(" ").replaceAll(/[^a-zA-Z0-9-_ ]/g, "");
|
||||||
}
|
|
||||||
if (isWikilink) {
|
if (isWikilink) {
|
||||||
// A [[wikilink]]
|
// A [[wikilink]]
|
||||||
if (pageMeta.displayName) {
|
if (pageMeta.displayName) {
|
||||||
|
@ -141,6 +141,7 @@ export async function pageComplete(completeEvent: CompleteEvent) {
|
||||||
: `${pageMeta.name}|${pageMeta.displayName}`,
|
: `${pageMeta.name}|${pageMeta.displayName}`,
|
||||||
detail: `displayName for: ${pageMeta.name}`,
|
detail: `displayName for: ${pageMeta.name}`,
|
||||||
type: "page",
|
type: "page",
|
||||||
|
cssClass,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (Array.isArray(pageMeta.aliases)) {
|
if (Array.isArray(pageMeta.aliases)) {
|
||||||
|
@ -155,6 +156,7 @@ export async function pageComplete(completeEvent: CompleteEvent) {
|
||||||
: `${pageMeta.name}|${alias}`,
|
: `${pageMeta.name}|${alias}`,
|
||||||
detail: `alias to: ${pageMeta.name}`,
|
detail: `alias to: ${pageMeta.name}`,
|
||||||
type: "page",
|
type: "page",
|
||||||
|
cssClass,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -167,6 +169,7 @@ export async function pageComplete(completeEvent: CompleteEvent) {
|
||||||
? "Linked but not created"
|
? "Linked but not created"
|
||||||
: undefined,
|
: undefined,
|
||||||
type: "page",
|
type: "page",
|
||||||
|
cssClass,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// A markdown link []()
|
// A markdown link []()
|
||||||
|
@ -182,9 +185,11 @@ export async function pageComplete(completeEvent: CompleteEvent) {
|
||||||
}
|
}
|
||||||
completions.push({
|
completions.push({
|
||||||
label: labelText,
|
label: labelText,
|
||||||
|
displayLabel: namePrefix + labelText,
|
||||||
boost: boost,
|
boost: boost,
|
||||||
apply: labelText.includes(" ") ? "<" + labelText + ">" : labelText,
|
apply: labelText.includes(" ") ? "<" + labelText + ">" : labelText,
|
||||||
type: "page",
|
type: "page",
|
||||||
|
cssClass,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return completions;
|
return completions;
|
||||||
|
|
|
@ -577,6 +577,13 @@ export function renderMarkdownToHtml(
|
||||||
const pageMeta = allPages.find((p) => pageRef.page === p.name);
|
const pageMeta = allPages.find((p) => pageRef.page === p.name);
|
||||||
if (pageMeta) {
|
if (pageMeta) {
|
||||||
t.body = [(pageMeta.pageDecoration?.prefix ?? "") + t.body];
|
t.body = [(pageMeta.pageDecoration?.prefix ?? "") + t.body];
|
||||||
|
if (pageMeta.pageDecoration?.cssClasses) {
|
||||||
|
t.attrs!.class += " sb-decorated-object " +
|
||||||
|
pageMeta.pageDecoration.cssClasses.join(" ").replaceAll(
|
||||||
|
/[^a-zA-Z0-9-_ ]/g,
|
||||||
|
"",
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (t.body.length === 0) {
|
if (t.body.length === 0) {
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
import type { CompletionContext, CompletionResult } from "@codemirror/autocomplete";
|
import type {
|
||||||
|
CompletionContext,
|
||||||
|
CompletionResult,
|
||||||
|
} from "@codemirror/autocomplete";
|
||||||
import type { Compartment } from "@codemirror/state";
|
import type { Compartment } from "@codemirror/state";
|
||||||
import { EditorView } from "@codemirror/view";
|
import { EditorView } from "@codemirror/view";
|
||||||
import { syntaxTree } from "@codemirror/language";
|
import { syntaxTree } from "@codemirror/language";
|
||||||
|
@ -42,7 +45,11 @@ import { createEditorState } from "./editor_state.ts";
|
||||||
import { MainUI } from "./editor_ui.tsx";
|
import { MainUI } from "./editor_ui.tsx";
|
||||||
import { cleanPageRef } from "$sb/lib/resolve.ts";
|
import { cleanPageRef } from "$sb/lib/resolve.ts";
|
||||||
import type { SpacePrimitives } from "$common/spaces/space_primitives.ts";
|
import type { SpacePrimitives } from "$common/spaces/space_primitives.ts";
|
||||||
import type { CodeWidgetButton, FileMeta, PageMeta } from "../plug-api/types.ts";
|
import type {
|
||||||
|
CodeWidgetButton,
|
||||||
|
FileMeta,
|
||||||
|
PageMeta,
|
||||||
|
} from "../plug-api/types.ts";
|
||||||
import { DataStore } from "$lib/data/datastore.ts";
|
import { DataStore } from "$lib/data/datastore.ts";
|
||||||
import { IndexedDBKvPrimitives } from "$lib/data/indexeddb_kv_primitives.ts";
|
import { IndexedDBKvPrimitives } from "$lib/data/indexeddb_kv_primitives.ts";
|
||||||
import { DataStoreMQ } from "$lib/data/mq.datastore.ts";
|
import { DataStoreMQ } from "$lib/data/mq.datastore.ts";
|
||||||
|
@ -1100,6 +1107,15 @@ export class Client {
|
||||||
// Nothing in the store, revert to default
|
// Nothing in the store, revert to default
|
||||||
enrichedMeta = doc.meta;
|
enrichedMeta = doc.meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bodyEl = this.parent.parentElement;
|
||||||
|
if (bodyEl) {
|
||||||
|
bodyEl.removeAttribute("class");
|
||||||
|
if (enrichedMeta.pageDecoration.cssClasses) {
|
||||||
|
bodyEl.className = enrichedMeta.pageDecoration.cssClasses.join(" ")
|
||||||
|
.replaceAll(/[^a-zA-Z0-9-_ ]/g, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
this.ui.viewDispatch({
|
this.ui.viewDispatch({
|
||||||
type: "update-current-page-meta",
|
type: "update-current-page-meta",
|
||||||
meta: enrichedMeta,
|
meta: enrichedMeta,
|
||||||
|
|
|
@ -77,6 +77,18 @@ export function cleanWikiLinkPlugin(client: Client) {
|
||||||
const linkText = alias ||
|
const linkText = alias ||
|
||||||
((pageMeta?.pageDecoration?.prefix ?? "") + cleanLinkText);
|
((pageMeta?.pageDecoration?.prefix ?? "") + cleanLinkText);
|
||||||
|
|
||||||
|
let cssClass = fileExists
|
||||||
|
? "sb-wiki-link-page"
|
||||||
|
: "sb-wiki-link-page-missing";
|
||||||
|
|
||||||
|
if (pageMeta?.pageDecoration?.cssClasses) {
|
||||||
|
cssClass += " sb-decorated-object " +
|
||||||
|
pageMeta.pageDecoration.cssClasses.join(" ").replaceAll(
|
||||||
|
/[^a-zA-Z0-9-_ ]/g,
|
||||||
|
"",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// And replace it with a widget
|
// And replace it with a widget
|
||||||
widgets.push(
|
widgets.push(
|
||||||
Decoration.replace({
|
Decoration.replace({
|
||||||
|
@ -87,9 +99,7 @@ export function cleanWikiLinkPlugin(client: Client) {
|
||||||
? `Navigate to ${encodePageRef(pageRef)}`
|
? `Navigate to ${encodePageRef(pageRef)}`
|
||||||
: `Create ${pageRef.page}`,
|
: `Create ${pageRef.page}`,
|
||||||
href: `/${encodePageRef(pageRef)}`,
|
href: `/${encodePageRef(pageRef)}`,
|
||||||
cssClass: fileExists
|
cssClass,
|
||||||
? "sb-wiki-link-page"
|
|
||||||
: "sb-wiki-link-page-missing",
|
|
||||||
from,
|
from,
|
||||||
callback: (e) => {
|
callback: (e) => {
|
||||||
if (e.altKey) {
|
if (e.altKey) {
|
||||||
|
|
|
@ -197,9 +197,10 @@ export function FilterList({
|
||||||
<div
|
<div
|
||||||
key={"" + idx}
|
key={"" + idx}
|
||||||
ref={selectedOption === idx ? selectedElementRef : undefined}
|
ref={selectedOption === idx ? selectedElementRef : undefined}
|
||||||
className={selectedOption === idx
|
className={(selectedOption === idx
|
||||||
? "sb-selected-option"
|
? "sb-option sb-selected-option"
|
||||||
: "sb-option"}
|
: "sb-option") +
|
||||||
|
(option.cssClass ? " sb-decorated-object " + option.cssClass : "")}
|
||||||
onMouseMove={() => {
|
onMouseMove={() => {
|
||||||
if (selectedOption !== idx) {
|
if (selectedOption !== idx) {
|
||||||
setSelectionOption(idx);
|
setSelectionOption(idx);
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
import { FilterList } from "./filter.tsx";
|
import { FilterList } from "./filter.tsx";
|
||||||
import type { FilterOption } from "$lib/web.ts";
|
import type { FilterOption } from "$lib/web.ts";
|
||||||
import type { CompletionContext, CompletionResult } from "@codemirror/autocomplete";
|
import type {
|
||||||
|
CompletionContext,
|
||||||
|
CompletionResult,
|
||||||
|
} from "@codemirror/autocomplete";
|
||||||
import type { PageMeta } from "../../plug-api/types.ts";
|
import type { PageMeta } from "../../plug-api/types.ts";
|
||||||
import { tagRegex as mdTagRegex } from "$common/markdown_parser/parser.ts";
|
import { tagRegex as mdTagRegex } from "$common/markdown_parser/parser.ts";
|
||||||
|
|
||||||
|
@ -42,6 +45,8 @@ export function PageNavigator({
|
||||||
// ... then we put it all the way to the end
|
// ... then we put it all the way to the end
|
||||||
orderId = Infinity;
|
orderId = Infinity;
|
||||||
}
|
}
|
||||||
|
const cssClass = (pageMeta.pageDecoration?.cssClasses || []).join(" ")
|
||||||
|
.replaceAll(/[^a-zA-Z0-9-_ ]/g, "");
|
||||||
|
|
||||||
if (mode === "page") {
|
if (mode === "page") {
|
||||||
// Special behavior for regular pages
|
// Special behavior for regular pages
|
||||||
|
@ -66,6 +71,7 @@ export function PageNavigator({
|
||||||
description,
|
description,
|
||||||
orderId: orderId,
|
orderId: orderId,
|
||||||
hint: pageMeta._isBrokenLink ? "Create page" : undefined,
|
hint: pageMeta._isBrokenLink ? "Create page" : undefined,
|
||||||
|
cssClass,
|
||||||
});
|
});
|
||||||
} else if (mode === "meta") {
|
} else if (mode === "meta") {
|
||||||
// Special behavior for #template and #meta pages
|
// Special behavior for #template and #meta pages
|
||||||
|
@ -81,6 +87,7 @@ export function PageNavigator({
|
||||||
description: pageMeta.name,
|
description: pageMeta.name,
|
||||||
hint: pageMeta.tags![0],
|
hint: pageMeta.tags![0],
|
||||||
orderId: orderId,
|
orderId: orderId,
|
||||||
|
cssClass,
|
||||||
});
|
});
|
||||||
} else { // all
|
} else { // all
|
||||||
// In mode "all" just show the full path and all tags
|
// In mode "all" just show the full path and all tags
|
||||||
|
@ -94,6 +101,7 @@ export function PageNavigator({
|
||||||
name: pageMeta.name,
|
name: pageMeta.name,
|
||||||
description,
|
description,
|
||||||
orderId: orderId,
|
orderId: orderId,
|
||||||
|
cssClass,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ export function TopBar({
|
||||||
onClick,
|
onClick,
|
||||||
rhs,
|
rhs,
|
||||||
pageNamePrefix,
|
pageNamePrefix,
|
||||||
|
cssClass,
|
||||||
}: {
|
}: {
|
||||||
pageName?: string;
|
pageName?: string;
|
||||||
unsavedChanges: boolean;
|
unsavedChanges: boolean;
|
||||||
|
@ -49,6 +50,7 @@ export function TopBar({
|
||||||
lhs?: ComponentChildren;
|
lhs?: ComponentChildren;
|
||||||
rhs?: ComponentChildren;
|
rhs?: ComponentChildren;
|
||||||
pageNamePrefix?: string;
|
pageNamePrefix?: string;
|
||||||
|
cssClass?: string;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
@ -63,11 +65,14 @@ export function TopBar({
|
||||||
<div className="sb-page-prefix">{pageNamePrefix}</div>
|
<div className="sb-page-prefix">{pageNamePrefix}</div>
|
||||||
<span
|
<span
|
||||||
id="sb-current-page"
|
id="sb-current-page"
|
||||||
className={isLoading
|
className={(isLoading
|
||||||
? "sb-loading"
|
? "sb-loading"
|
||||||
: unsavedChanges
|
: unsavedChanges
|
||||||
? "sb-unsaved"
|
? "sb-unsaved"
|
||||||
: "sb-saved"}
|
: "sb-saved") +
|
||||||
|
(cssClass
|
||||||
|
? " sb-decorated-object " + cssClass
|
||||||
|
: "")}
|
||||||
>
|
>
|
||||||
<MiniEditor
|
<MiniEditor
|
||||||
text={pageName ?? ""}
|
text={pageName ?? ""}
|
||||||
|
|
|
@ -105,6 +105,14 @@ export function createEditorState(
|
||||||
client.clientSystem.slashCommandHook,
|
client.clientSystem.slashCommandHook,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
optionClass(completion: any) {
|
||||||
|
console.log("Calling on", completion);
|
||||||
|
if (completion.cssClass) {
|
||||||
|
return "sb-decorated-object " + completion.cssClass;
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
inlineImagesPlugin(client),
|
inlineImagesPlugin(client),
|
||||||
codeCopyPlugin(client),
|
codeCopyPlugin(client),
|
||||||
|
|
|
@ -328,6 +328,10 @@ export class MainUI {
|
||||||
pageNamePrefix={viewState.currentPageMeta?.pageDecoration
|
pageNamePrefix={viewState.currentPageMeta?.pageDecoration
|
||||||
?.prefix ??
|
?.prefix ??
|
||||||
""}
|
""}
|
||||||
|
cssClass={viewState.currentPageMeta?.pageDecoration?.cssClasses
|
||||||
|
? viewState.currentPageMeta?.pageDecoration?.cssClasses
|
||||||
|
.join(" ").replaceAll(/[^a-zA-Z0-9-_ ]/g, "")
|
||||||
|
: ""}
|
||||||
/>
|
/>
|
||||||
<div id="sb-main">
|
<div id="sb-main">
|
||||||
{!!viewState.panels.lhs.mode && (
|
{!!viewState.panels.lhs.mode && (
|
||||||
|
|
|
@ -29,11 +29,12 @@ A few things of note:
|
||||||
* `alwaysTen: '10'` (attaches an attribute named `alwaysTen` with the numeric value `10` to all objects matching the `where` clause)
|
* `alwaysTen: '10'` (attaches an attribute named `alwaysTen` with the numeric value `10` to all objects matching the `where` clause)
|
||||||
* `alwaysTrue: 'true'` (same as `alwaysTen` but with a boolean value)
|
* `alwaysTrue: 'true'` (same as `alwaysTen` but with a boolean value)
|
||||||
* `fullName: 'firstName + " " + lastName'` (attaches a `fullName` attribute that concatenates the `firstName` and `lastName` attributes with a space in between)
|
* `fullName: 'firstName + " " + lastName'` (attaches a `fullName` attribute that concatenates the `firstName` and `lastName` attributes with a space in between)
|
||||||
* `nameLength: 'count(name)'` (attaches an attribute `nameLength` with the string length of `name` — not particularly useful, but to demonstrate you can call [[Functions]] here too)
|
* `nameLength: 'count(name)'` (attaches an attribute `nameLength` with the string length of `name` — not particularly useful, but to demonstrate you can call [[Functions]] here too).
|
||||||
|
|
||||||
## Rules
|
## Rules
|
||||||
A few rules to keep things civil:
|
A few rules and best practices to keep things civil:
|
||||||
|
|
||||||
|
* It is recommended to _always filter based on `tag`_ (so by adding e.g. `tag = "page"` to your `where` clause) to limit the radius of impact. Otherwise you may accidentally apply new attributes of all your [[Objects]] (items, tasks, pages, etc.).
|
||||||
* Dynamic attributes _cannot override already existing attributes_. If the object already has an attribute with the same name, this value will be kept as is.
|
* Dynamic attributes _cannot override already existing attributes_. If the object already has an attribute with the same name, this value will be kept as is.
|
||||||
* For performance reasons, all expressions (both filter and value expressions) need to be _synchronously evaluatable_.
|
* For performance reasons, all expressions (both filter and value expressions) need to be _synchronously evaluatable_.
|
||||||
* Generally, this means they need to be “simple expressions” that require no expensive calls.
|
* Generally, this means they need to be “simple expressions” that require no expensive calls.
|
||||||
|
|
|
@ -1,18 +1,46 @@
|
||||||
---
|
---
|
||||||
pageDecoration.prefix: "🎄 "
|
pageDecoration:
|
||||||
pageDecoration.disableTOC: true
|
prefix: "🎄 "
|
||||||
|
disableTOC: true
|
||||||
|
cssClasses:
|
||||||
|
- christmas-decoration
|
||||||
---
|
---
|
||||||
Page decorations allow you to “decorate” pages in various ways.
|
Page decorations allow you to “decorate” pages in various fun ways.
|
||||||
|
|
||||||
> **warning** Warning
|
> **warning** Warning
|
||||||
> This feature is still experimental and may change in the (near) future.
|
> This feature is still experimental and may change in the (near) future.
|
||||||
|
|
||||||
# Supported decorations
|
# Supported decorations
|
||||||
* `prefix`: A (visual) string prefix (often an emoji) to add to all page names. This prefix will appear in the top bar as well as in (live preview) links to this page. For example, the name of this page is actually “Page Decorations”, but when you link to it, you’ll see it’s prefixed with a 🎄: [[Page Decorations]]
|
* `prefix`: A (visual) string prefix (often an emoji) to add to all page names. This prefix will appear in the top bar as well as in (live preview) links to this page. For example, the name of this page is actually “Page Decorations”, but when you link to it, you’ll see it’s prefixed with a 🎄: [[Page Decorations]]
|
||||||
|
* `cssClasses`: (list of strings) Attaches one or more CSS classes the page's `<body>` tag, wiki links, auto complete items and [[Page Picker]] entries for more advanced styling through a [[Space Style]] (see below for an example for this page).
|
||||||
* `hide` When this is set to `true`, the page will not be shown in [[Page Picker]], [[Meta Picker]], or suggested for completion of [[Links]]. It will otherwise behave as normal - will be [[Plugs/Index|indexed]] and found in [[Live Queries]]. The page can be opened through [[All Pages Picker]], or linked normally when the full name is typed out without completion.
|
* `hide` When this is set to `true`, the page will not be shown in [[Page Picker]], [[Meta Picker]], or suggested for completion of [[Links]]. It will otherwise behave as normal - will be [[Plugs/Index|indexed]] and found in [[Live Queries]]. The page can be opened through [[All Pages Picker]], or linked normally when the full name is typed out without completion.
|
||||||
* `disableTOC` (not technically built-in, but a feature of the [[^Library/Core/Widget/Table of Contents]] widget): disable the [[Table of Contents]] for this particular page.
|
* `disableTOC` (not technically built-in, but a feature of the [[^Library/Core/Widget/Table of Contents]] widget): disable the [[Table of Contents]] for this particular page.
|
||||||
|
|
||||||
There are two ways to apply decorations to pages:
|
An example of using `cssClasses` on this page using [[Space Style]] (note the `pageDecoration.cssClasses` in this page’s [[Frontmatter]]):
|
||||||
|
```space-style
|
||||||
|
|
||||||
|
/* Style page links */
|
||||||
|
a.christmas-decoration {
|
||||||
|
background-color: #b4e46e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Style main editor components */
|
||||||
|
body.christmas-decoration #sb-top {
|
||||||
|
background-color: #b4e46e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Style auto complete items */
|
||||||
|
.cm-tooltip-autocomplete li.christmas-decoration {
|
||||||
|
background-color: #b4e46e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Style page picker item */
|
||||||
|
.sb-result-list .sb-option.christmas-decoration {
|
||||||
|
background-color: #b4e46e;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
There are two ways to _apply_ decorations to pages.
|
||||||
|
|
||||||
# With [[Frontmatter]] directly
|
# With [[Frontmatter]] directly
|
||||||
This is demonstrated in the [[Frontmatter]] at the top of this page, by using the special `pageDecoration` attribute. This is how we get the fancy tree in front of the page name. Sweet.
|
This is demonstrated in the [[Frontmatter]] at the top of this page, by using the special `pageDecoration` attribute. This is how we get the fancy tree in front of the page name. Sweet.
|
||||||
|
|
|
@ -60,13 +60,13 @@ shortcuts:
|
||||||
|
|
||||||
# Object decorators, see the "Page Decorators" page for more info
|
# Object decorators, see the "Page Decorators" page for more info
|
||||||
objectDecorators:
|
objectDecorators:
|
||||||
- where: 'tags = "plug"'
|
- where: 'tag = "page" and tags = "plug"'
|
||||||
attributes:
|
attributes:
|
||||||
pageDecoration.prefix: "'🔌 '"
|
pageDecoration.prefix: "'🔌 '"
|
||||||
- where: 'tag = "human"'
|
- where: 'tag = "human"'
|
||||||
attributes:
|
attributes:
|
||||||
fullName: 'firstName + " " + lastName'
|
fullName: 'firstName + " " + lastName'
|
||||||
- where: 'tags = "notoc"'
|
- where: 'tag = "page" and tags = "notoc"'
|
||||||
attributes:
|
attributes:
|
||||||
pageDecoration.disableTOC: "true"
|
pageDecoration.disableTOC: "true"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue