Update how tags are rendered to allow for custom styling (#1179)
* Updated how tags are rendered to allow for custom styling via space-styles * Wrapped the existing span for a tag with an anchor element <a> to improve ux for screen readers * Added data-tag-name attribute to tags so that given a tag `#my-tag` it will have the attribute `data-tag-name="my-tag"` added to the new `<a>` element wrapper allowing for end users to target tags for styling with a css selector such as `.sb-hashtag[data-tag-name="my-tag"]{...}` * Updated Docspull/1183/head
parent
a56db78194
commit
2020e85a6f
|
@ -584,15 +584,13 @@ const NakedURL = regexParser(
|
|||
},
|
||||
);
|
||||
|
||||
const Hashtag = regexParser(
|
||||
{
|
||||
firstCharCode: 35, // #
|
||||
regex: new RegExp(`^${tagRegex.source}`),
|
||||
nodeType: "Hashtag",
|
||||
className: "sb-hashtag",
|
||||
tag: ct.HashtagTag,
|
||||
},
|
||||
);
|
||||
const Hashtag = regexParser({
|
||||
firstCharCode: 35, // #
|
||||
regex: new RegExp(`^${tagRegex.source}`),
|
||||
nodeType: "Hashtag",
|
||||
className: "sb-hashtag-text",
|
||||
tag: ct.HashtagTag,
|
||||
});
|
||||
|
||||
const TaskDeadline = regexParser({
|
||||
firstCharCode: 55357, // 📅
|
||||
|
|
|
@ -14,6 +14,7 @@ import {
|
|||
import { Fragment, renderHtml, type Tag } from "./html_render.ts";
|
||||
import { isLocalPath } from "@silverbulletmd/silverbullet/lib/resolve";
|
||||
import type { PageMeta } from "@silverbulletmd/silverbullet/types";
|
||||
import * as TagConstants from "../../plugs/index/constants.ts";
|
||||
|
||||
export type MarkdownRenderOptions = {
|
||||
failOnUnknown?: true;
|
||||
|
@ -335,15 +336,18 @@ function render(
|
|||
body: url,
|
||||
};
|
||||
}
|
||||
case "Hashtag":
|
||||
case "Hashtag": {
|
||||
const tagText: string = t.children![0].text!;
|
||||
return {
|
||||
name: "span",
|
||||
name: "a",
|
||||
attrs: {
|
||||
class: "hashtag",
|
||||
class: "hashtag sb-hashtag",
|
||||
"data-tag-name": tagText.replace("#", ""),
|
||||
href: `/${TagConstants.tagPrefix}${tagText.replace("#", "")}`,
|
||||
},
|
||||
body: t.children![0].text!,
|
||||
body: tagText,
|
||||
};
|
||||
|
||||
}
|
||||
case "Task": {
|
||||
let externalTaskRef = "";
|
||||
collectNodesOfType(t, "WikiLinkPage").forEach((wikilink) => {
|
||||
|
|
|
@ -15,6 +15,7 @@ import { fencedCodePlugin } from "./fenced_code.ts";
|
|||
import { frontmatterPlugin } from "./frontmatter.ts";
|
||||
import { cleanEscapePlugin } from "./escapes.ts";
|
||||
import { luaDirectivePlugin } from "./lua_directive.ts";
|
||||
import { hashtagPlugin } from "./hashtag.ts";
|
||||
|
||||
export function cleanModePlugins(client: Client) {
|
||||
return [
|
||||
|
@ -46,5 +47,6 @@ export function cleanModePlugins(client: Client) {
|
|||
cleanCommandLinkPlugin(client),
|
||||
cleanEscapePlugin(),
|
||||
luaDirectivePlugin(client),
|
||||
hashtagPlugin(),
|
||||
] as Extension[];
|
||||
}
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
import { syntaxTree } from "@codemirror/language";
|
||||
import { Decoration } from "@codemirror/view";
|
||||
import { decoratorStateField } from "./util.ts";
|
||||
import * as Constants from "../../plugs/index/constants.ts";
|
||||
import { extractHashtag } from "../../plug-api/lib/tags.ts";
|
||||
|
||||
export function hashtagPlugin() {
|
||||
return decoratorStateField((state) => {
|
||||
const widgets: any[] = [];
|
||||
|
||||
syntaxTree(state).iterate({
|
||||
enter: ({ type, from, to }) => {
|
||||
if (type.name !== "Hashtag") {
|
||||
return;
|
||||
}
|
||||
|
||||
const tag = state.sliceDoc(from, to);
|
||||
|
||||
if (tag.length === 1) {
|
||||
// Invalid Hashtag, a length of 1 means its just #
|
||||
return;
|
||||
}
|
||||
|
||||
const tagName = extractHashtag(tag);
|
||||
|
||||
// Wrap the tag in html anchor element
|
||||
widgets.push(
|
||||
Decoration.mark({
|
||||
tagName: "a",
|
||||
class: "sb-hashtag",
|
||||
attributes: {
|
||||
href: `/${Constants.tagPrefix}${tagName}`,
|
||||
rel: "tag",
|
||||
"data-tag-name": tagName,
|
||||
},
|
||||
}).range(from, to),
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
return Decoration.set(widgets, true);
|
||||
});
|
||||
}
|
|
@ -97,7 +97,7 @@ export function hideHeaderMarkPlugin() {
|
|||
widgets.push(
|
||||
Decoration.mark({
|
||||
tagName: "span",
|
||||
class: "sb-hashtag",
|
||||
class: "sb-hashtag-text",
|
||||
}).range(from, from + 1),
|
||||
);
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ export default function highlightStyles() {
|
|||
{ tag: t.processingInstruction, class: "sb-meta" },
|
||||
{ tag: t.punctuation, class: "sb-punctuation" },
|
||||
{ tag: ct.HorizontalRuleTag, class: "sb-hr" },
|
||||
{ tag: ct.HashtagTag, class: "sb-hashtag" },
|
||||
{ tag: ct.HashtagTag, class: "sb-hashtag-text" },
|
||||
{ tag: ct.NakedURLTag, class: "sb-naked-url" },
|
||||
{ tag: ct.TaskDeadlineTag, class: "sb-task-deadline" },
|
||||
{ tag: ct.NamedAnchorTag, class: "sb-named-anchor" },
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
}
|
||||
|
||||
// If a header only contains a tag, it's likely a line containging "#" which may turn into a hashtag, so style it as such instead of a header
|
||||
.sb-line-h1:has(> span.sb-hashtag:only-child) {
|
||||
.sb-line-h1:has(> a.sb-hashtag:only-child) {
|
||||
font-size: 1em;
|
||||
padding: 0;
|
||||
font-weight: normal;
|
||||
|
@ -276,6 +276,10 @@
|
|||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
a.sb-hashtag {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.sb-strikethrough {
|
||||
text-decoration: line-through;
|
||||
|
||||
|
|
|
@ -22,9 +22,32 @@ Beside these, any number of additional tag-specific and custom [[Attributes]] ca
|
|||
# Tags
|
||||
Every object has a main `tag`, which signifies the type of object being described. In addition, any number of additional tags can be assigned as well via the `tags` attribute. You can use either the main `tag` or any of the `tags` as query sources in [[Live Queries]] — examples below.
|
||||
|
||||
Here are the currently built-in tags:
|
||||
## Styling
|
||||
You can add custom styles to a tag by leveraging the `data-tag-name` attribute, [CSS Attribute Selectors](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors) and custom [[Speace Style]]'s. Every tag gets an attribute added to it called `data-tag-name` that is set to the tag name with the `#` symbol stripped out. So given the tag #my-cool-tag the `data-tag-name` attribute would look like:
|
||||
`data-tag-name="my-cool-tag"`.
|
||||
This allows us to do things like change the color of the #my-cool-tag to have a purple background, limegreen text and bold font by adding the following [[Space Style]]:
|
||||
```css
|
||||
.sb-hashtag[data-tag-name="my-cool-tag"] {
|
||||
background: purple;
|
||||
color: limegreen;
|
||||
font-weight: bolder;
|
||||
}
|
||||
```
|
||||
Additionally tags written using angle brackets, such as...
|
||||
#<my cool tag>
|
||||
...can be styled via [[Space Style]] like this:
|
||||
```css
|
||||
.sb-hashtag[data-tag-name="my cool tag"] {
|
||||
background: purple;
|
||||
color: limegreen;
|
||||
font-weight: bolder;
|
||||
}
|
||||
```
|
||||
|
||||
## page
|
||||
|
||||
## Built-in tags
|
||||
|
||||
### page
|
||||
Every page in your space is available via the `page` tag. You can attach _additional_ tags to a page, by either specifying them in the `tags` attribute [[Frontmatter]], or by putting additional [[Tags]] in a stand alone paragraph with no other (textual) content in them, for instance check the very first line of this page that says `#level/intermediate`.
|
||||
|
||||
In addition to `ref` and `tags`, the `page` tag defines a bunch of additional attributes as can be seen in this example query:
|
||||
|
@ -39,7 +62,7 @@ Note that you can also query this page using the `level/intermediate` directly:
|
|||
level/intermediate
|
||||
```
|
||||
|
||||
## aspiring-page
|
||||
### aspiring-page
|
||||
[[Aspiring Pages]] are pages that are linked to, but not yet created.
|
||||
|
||||
```query
|
||||
|
@ -47,7 +70,7 @@ aspiring-page
|
|||
```
|
||||
|
||||
|
||||
## table
|
||||
### table
|
||||
Markdown table rows are indexed using the `table` tag, any additional tags can be added using [[Tags]] in any of its cells.
|
||||
|
||||
| Title | Description Text |
|
||||
|
@ -62,7 +85,7 @@ table
|
|||
|
||||
Table headers will be normalized by converting them to lowercase and replacing all non alphanumeric characters with `_`.
|
||||
|
||||
## item
|
||||
### item
|
||||
List items (both bullet point and numbered items) are indexed with the `item` tag, and additional tags can be added using [[Tags]].
|
||||
|
||||
Here is an example of a #quote item using a custom [[Attributes|attribute]]:
|
||||
|
@ -108,7 +131,7 @@ upnext render [[Library/Core/Query/Task]]
|
|||
Similar to [[#item]], `task` objects have a `parent` attribute when nested (pointing to their parent `item`), and inherit their ancestor’s tags in `itags`.
|
||||
|
||||
|
||||
## taskstate
|
||||
### taskstate
|
||||
[[Plugs/Tasks]] support the default `x` and ` ` states (done and not done), but custom states as well. Custom states used across your space are kept in `taskstate`:
|
||||
|
||||
* [NOT STARTED] Task 1
|
||||
|
@ -150,7 +173,7 @@ Which then becomes queriable via the `person` tag:
|
|||
person
|
||||
```
|
||||
|
||||
## link
|
||||
### link
|
||||
All page _links_ are tagged with `link`. You cannot attach additional tags to links. The main two attributes of a link are:
|
||||
|
||||
* `toPage` the page the link is linking _to_
|
||||
|
@ -166,7 +189,7 @@ Here is a query that shows some links that appear in this particular page:
|
|||
link where page = @page.name limit 5
|
||||
```
|
||||
|
||||
## anchor
|
||||
### anchor
|
||||
[[Markdown/Anchors]] use the $myanchor notation to allow deeplinking into a page and are also indexed and queryable. It is not possible to attach additional tags to an anchor.
|
||||
|
||||
Here is an example query:
|
||||
|
@ -175,7 +198,7 @@ Here is an example query:
|
|||
anchor where page = @page.name
|
||||
```
|
||||
|
||||
## header
|
||||
### header
|
||||
Headers (lines starting with `#`, `##` etc.) are indexed as well and queriable.
|
||||
|
||||
```query
|
||||
|
@ -183,7 +206,7 @@ header where page = @page.name limit 3
|
|||
```
|
||||
|
||||
|
||||
## tag
|
||||
### tag
|
||||
The ultimate meta tag is _tag_ itself, which indexes for all tags used, in which page they appear and what their “parent tag” is (the context of the tag: either `page`, `item` or `task`).
|
||||
|
||||
Here are the tags used/defined in this page:
|
||||
|
@ -192,7 +215,7 @@ Here are the tags used/defined in this page:
|
|||
tag where page = @page.name select name, parent
|
||||
```
|
||||
|
||||
## space-config
|
||||
### space-config
|
||||
This stores all configuration picked up as part of [[Space Config]]
|
||||
|
||||
```query
|
||||
|
@ -200,16 +223,16 @@ space-config select key
|
|||
```
|
||||
|
||||
|
||||
# System tags
|
||||
## System tags
|
||||
The following tags are technically implemented a bit differently than the rest, but they are still available to be queried.
|
||||
|
||||
## command
|
||||
### command
|
||||
Enables querying of all [[Commands]] available in SilverBullet as well as their assigned keyboard shortcuts.
|
||||
```query
|
||||
command order by name limit 5
|
||||
```
|
||||
|
||||
## syscall
|
||||
### syscall
|
||||
Enables querying of all [[PlugOS]] syscalls enabled in your space. Mostly useful in the context of [[Plugs]] and [[Space Script]] development.
|
||||
|
||||
```query
|
||||
|
|
|
@ -69,6 +69,26 @@ button {
|
|||
button:hover {
|
||||
/* box-shadow: #121212 0 0 0 3px, transparent 0 0 0 0; */
|
||||
}
|
||||
|
||||
/* Add custom styling to a specific tag
|
||||
--> Example Tag: #my-cool-tag */
|
||||
.sb-hashtag[data-tag-name="my-cool-tag"] {
|
||||
background: purple;
|
||||
color: limegreen;
|
||||
font-weight: bolder;
|
||||
}
|
||||
/* --> Example Tag with angle brackets: #<my cool tag> */
|
||||
.sb-hashtag[data-tag-name="my cool tag"] {
|
||||
background: purple;
|
||||
color: limegreen;
|
||||
font-weight: bolder;
|
||||
}
|
||||
/* Custom Styling to all tags
|
||||
.sb-hashtag[data-tag-name] {
|
||||
background: yellow;
|
||||
color: goldenrod;
|
||||
border: 2px dashed goldenrod; */
|
||||
}
|
||||
```
|
||||
|
||||
Another example can be found in [[Page Decorations#Use case: pimp my page]]
|
||||
|
|
Loading…
Reference in New Issue