1
Fork 0
mirror of https://github.com/glassflame/glassflame.github.io.git synced 2024-11-22 08:04:27 +00:00

Progress on callouts

This commit is contained in:
Steffo 2023-11-16 15:33:58 +01:00
parent eec0dace7f
commit 6ba152600a
6 changed files with 344 additions and 59 deletions

View file

@ -138,8 +138,8 @@
<template id="template-node-group"> <template id="template-node-group">
<style> <style>
.node { .node {
outline: var(--node-group-border-width) solid var(--color-node); outline: var(--node-group-border-width) solid var(--color-canvas);
background-color: color-mix(in srgb, var(--color-node) 20%, var(--color-background)); background-color: color-mix(in srgb, var(--color-canvas) 20%, var(--color-background));
border-radius: 0 8px 8px 8px; border-radius: 0 8px 8px 8px;
padding: 12px; padding: 12px;
} }
@ -152,8 +152,8 @@
display: inline-block; display: inline-block;
outline: var(--node-group-border-width) solid var(--color-node); outline: var(--node-group-border-width) solid var(--color-canvas);
background-color: color-mix(in srgb, var(--color-node) 20%, var(--color-background)); background-color: color-mix(in srgb, var(--color-canvas) 20%, var(--color-background));
border-radius: 8px 8px 0 0; border-radius: 8px 8px 0 0;
padding: 12px; padding: 12px;
} }
@ -170,8 +170,8 @@
<template id="template-node-file"> <template id="template-node-file">
<style> <style>
.node { .node {
outline: var(--node-file-border-width) solid var(--color-node); outline: var(--node-file-border-width) solid var(--color-canvas);
background-color: color-mix(in srgb, var(--color-node) 10%, var(--color-background)); background-color: color-mix(in srgb, var(--color-canvas) 10%, var(--color-background));
border-radius: 8px; border-radius: 8px;
padding: 12px; padding: 12px;
} }
@ -196,8 +196,8 @@
<template id="template-node-text"> <template id="template-node-text">
<style> <style>
.node { .node {
outline: var(--node-file-border-width) solid var(--color-node); outline: var(--node-file-border-width) solid var(--color-canvas);
background-color: color-mix(in srgb, var(--color-node) 10%, var(--color-background)); background-color: color-mix(in srgb, var(--color-canvas) 10%, var(--color-background));
border-radius: 8px; border-radius: 8px;
padding: 12px; padding: 12px;
} }
@ -249,6 +249,8 @@
<slot name="wikilink-anchor">{Wikilink}</slot></template> <slot name="wikilink-anchor">{Wikilink}</slot></template>
<template id="template-math"> <template id="template-math">
<slot name="math-katex">{Math}</slot></template> <slot name="math-katex">{Math}</slot></template>
<template id="template-callout">
<slot name="callout-contents">{Callout}</slot></template>
</head> </head>
<body is="x-browse"></body> <body is="x-browse"></body>
</html> </html>

View file

@ -5,5 +5,224 @@ export class CalloutElement extends CustomElement {
return document.getElementById("template-callout") return document.getElementById("template-callout")
} }
// TODO: Last time, you were here! /**
* The kind of callout this element represents, in UPPERCASE.
*
* For a list of all builtin callouts, see <https://help.obsidian.md/Editing+and+formatting/Callouts>.
*
* @return {string}
*/
get kind() {
return this.getAttribute("kind").toUpperCase()
}
set kind(value) {
this.setAttribute("kind", value.toUpperCase())
}
/**
* Whether this callout should be collapsible, and if it should start collapsed or not.
*
* Possible values are:
* - `undefined`: non-collapsible
* - `"+"`: collapsible, start expanded by default
* - `"-"`: collapsible, start collapsed by default
*
* @return {undefined|"+"|"-"}
*/
get collapse() {
const value = this.getAttribute("collapse")
if(value === "undefined") {
return undefined
}
return value
}
set collapse(value) {
if(value === undefined) {
this.removeAttribute("collapse")
return
}
this.setAttribute("collapse", value)
}
/**
* The title of this callout, in UPPERCASE, as casing is handled by CSS, or `undefined`, if the {@link kind} should be used.
*
* @return {string|undefined}
*/
get admonition() {
return this.getAttribute("admonition")?.toUpperCase()
}
set admonition(value) {
if(value === undefined) {
this.removeAttribute("admonition")
return
}
this.setAttribute("admonition", value.toUpperCase())
}
/**
* The contents of this callout, or `undefined`, if there are none.
*
* @return {string}
*/
get contents() {
const value = this.getAttribute("contents")
if(value === "undefined") {
return undefined
}
return value
}
set contents(value) {
if(value === undefined) {
this.removeAttribute("contents")
return
}
this.setAttribute("contents", value)
}
/**
* Whether this element should consume its parent {@link onConnect}.
* @return {boolean}
*/
get cronus() {
return this.hasAttribute("cronus")
}
set cronus(value) {
if(value) {
this.setAttribute("cronus", "")
}
else {
this.removeAttribute("cronus")
}
}
/**
* Replace the contents of the {@link parentElement} with this element.
* Also sets {@link cronus} to `false`.
* @returns {void}
*/
replaceParentElement() {
const grandpa = this.parentElement.parentElement
this.remove()
this.parentElement.remove()
this.cronus = false
grandpa.appendChild(this)
}
/**
* The element displaying the admonition of this callout, or `null` if {@link admonition} is `undefined`.
* Can be recreated with {@link recreateAdmonitionElement}.
* @type {HTMLElement}
*/
admonitionElement
/**
* Recreate {@link collapseElement} with the current value of {@link collapse}.
* {@link collapseElement} must not be null.
* @returns {void}
*/
recreateAdmonitionElement() {
if(this.admonitionElement) {
this.admonitionElement.remove()
this.admonitionElement = null
}
this.admonitionElement = document.createElement("summary")
this.admonitionElement.innerText = this.admonition
this.collapseElement.appendChild(this.admonitionElement)
}
/**
* The element displaying the contents of this callout, or `null` if {@link contents} is `undefined`.
* Can be recreated with {@link recreateContentsElement}.
* @type {HTMLDivElement|null}
*/
contentsElement
/**
* Recreate {@link contentsElement} with the current value of {@link contents} and {@link collapseElement} or {@link containerElement}.
* @returns {void}
*/
recreateContentsElement() {
if(this.contentsElement) {
this.contentsElement.remove()
this.contentsElement = null
}
if(this.contents) {
this.contentsElement = document.createElement("summary")
this.contentsElement.innerText = this.contents
if(this.collapseElement) {
this.collapseElement.appendChild(this.contentsElement)
}
else {
this.containerElement.appendChild(this.contentsElement)
}
}
}
/**
* The element collapsing this callout, or `null` if {@link collapse} is `undefined`.
* Can be recreated with {@link recreateCollapseElement}.
* @type {HTMLDetailsElement|null}
*/
collapseElement
/**
* Recreate {@link collapseElement} with the current value of {@link collapse}.
* @returns {void}
*/
recreateCollapseElement() {
if(this.collapseElement) {
this.collapseElement.remove()
this.collapseElement = null
}
if(this.collapse !== undefined) {
this.collapseElement = document.createElement("details")
this.containerElement.appendChild(this.collapseElement)
}
}
/**
* The element containing this callout.
* Can be recreated with {@link recreateContainerElement}.
* @type {HTMLQuoteElement}
*/
containerElement
/**
* The name of the slot where {@link containerElement} should be placed in.
* @type {string}
*/
static CONTAINER_ELEMENT_SLOT = "callout-contents"
/**
* @returns {void}
*/
recreateContainerElement() {
if(this.containerElement) {
this.containerElement.remove()
this.containerElement = null
}
this.containerElement = document.createElement("blockquote")
this.containerElement.slot = this.constructor.CONTAINER_ELEMENT_SLOT
this.appendChild(this.containerElement)
}
onConnect() {
super.onConnect()
if(this.cronus) {
this.replaceParentElement()
}
else {
this.recreateContainerElement()
this.recreateCollapseElement()
this.recreateAdmonitionElement()
this.recreateContentsElement()
}
}
} }

View file

@ -18,8 +18,8 @@ export class MarkdownElement extends CustomElement {
static MARKED = new Marked({ static MARKED = new Marked({
tokenizer: { tokenizer: {
// Fix single, double, and triple equals on a single line being interpreted as headings // Fix single, double, and triple equals on a single line being interpreted as headings
lheading(src) { lheading(raw) {
const cap = /^(?![.+*] )((?:.|\n(?!\s*?\n|[.+*] ))+?)\n {0,3}(={4,}|-{4,}) *(?:\n+|$)/.exec(src); const cap = /^(?![.+*] )((?:.|\n(?!\s*?\n|[.+*] ))+?)\n {0,3}(={4,}|-{4,}) *(?:\n+|$)/.exec(raw);
if (cap) { if (cap) {
return { return {
type: 'heading', type: 'heading',
@ -30,6 +30,23 @@ export class MarkdownElement extends CustomElement {
}; };
} }
}, },
blockquote(raw) {
console.log(raw)
const calloutMatch = raw.match(/^\[!(.+)]([-+])? ?([^\n]+)?(?:\n+(.*))?/)
if(calloutMatch) {
const [, kind, collapse, admonition, contents] = calloutMatch
const result = {
type: "callout",
raw,
kind,
collapse,
admonition,
contents,
}
return result
}
return false
}
}, },
extensions: [ extensions: [
{ {
@ -74,30 +91,6 @@ export class MarkdownElement extends CustomElement {
return `<x-math document="${token.document}" block></x-math>` return `<x-math document="${token.document}" block></x-math>`
} }
}, },
{
name: "callout",
level: "block",
start(src) {
return src.match(/[$][$]/)?.index
},
tokenizer(src, _) {
const match = src.match(/^ {0,3}> ?\[!(.+)]([-+])? ?(.+)?\n+( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/)
if(match) {
return {
type: "callout",
raw: match[0],
kind: match[1],
collapse: match[2],
admonition: match[3],
contents: match[4],
}
}
},
renderer(token) {
console.log(token)
return `<x-callout kind="${token.kind}" collapse="${token.collapse}" admonition="${token.admonition}" contents="${token.contents}"></x-callout>`
}
},
{ {
name: "wikilink", name: "wikilink",
level: "inline", level: "inline",
@ -179,7 +172,15 @@ export class MarkdownElement extends CustomElement {
return `<mark>${token.text}</mark>` return `<mark>${token.text}</mark>`
}, },
}, },
] {
name: "callout",
level: "block",
renderer(token) {
console.log(token)
return `<x-callout kind="${token.kind}" collapse="${token.collapse}" admonition="${token.admonition}" contents="${token.contents}" cronus></x-callout>`
}
}
],
}) })
/** /**

View file

@ -3,17 +3,28 @@
--color-foreground: #000000; --color-foreground: #000000;
--color-accent: initial; --color-accent: initial;
--color-gray: #7E7E7E; --color-canvas-gray: #7E7E7E;
--color-red: #FB464C; --color-canvas-red: #FB464C;
--color-orange: #E9973F; --color-canvas-orange: #E9973F;
--color-yellow: #E0DE71; --color-canvas-yellow: #E0DE71;
--color-green: #44CF6E; --color-canvas-green: #44CF6E;
--color-blue: #53DFDD; --color-canvas-blue: #53DFDD;
--color-purple: #A882FF; --color-canvas-purple: #A882FF;
--color-canvas: var(--color-canvas-gray);
--color-callout-gray: #9e9e9e;
--color-callout-red: #e93147;
--color-callout-orange: #ec7500;
--color-callout-yellow: #e0ac00;
--color-callout-green: #08b94e;
--color-callout-cyan: #00bfbc;
--color-callout-blue: #086ddd;
--color-callout-purple: #7852ee;
--color-callout-pink: #d53984;
--color-callout: var(--color-callout-gray);
--margins: 0; --margins: 0;
--color-node: var(--color-gray);
--node-group-border-width: 2px; --node-group-border-width: 2px;
--node-file-border-width: 2px; --node-file-border-width: 2px;
--edge-width: 2px; --edge-width: 2px;
@ -64,7 +75,7 @@ a {
} }
svg line { svg line {
stroke: var(--color-node); stroke: var(--color-canvas);
stroke-width: var(--edge-width); stroke-width: var(--edge-width);
} }
@ -115,3 +126,55 @@ h1 a, .wikilink.wikilink-heading {
h1 a:hover, .wikilink.wikilink-heading:hover { h1 a:hover, .wikilink.wikilink-heading:hover {
color: var(--color-foreground); color: var(--color-foreground);
} }
.callout {
}
.callout-abstract, .callout-summary, .callout-tldr {
--color-callout: var(--color-callout-cyan);
}
.callout-info {
--color-callout: var(--color-callout-blue);
}
.callout-todo {
--color-callout: var(--color-callout-blue)
}
.callout-tip, .callout-hint, .callout-important {
--color-callout: var(--color-callout-cyan);
}
.callout-success, .callout-check, .callout-done {
--color-callout: var(--color-callout-green);
}
.callout-question, .callout-help, .callout-faq {
--color-callout: var(--color-callout-orange);
}
.callout-warning, .callout-caution, .callout-attention {
--color-callout: var(--color-callout-orange);
}
.callout-failure, .callout-fail, .callout-mission {
--color-callout: var(--color-callout-red);
}
.callout-danger, .callout-error {
--color-callout: var(--color-callout-red);
}
.callout-bug {
--color-callout: var(--color-callout-red);
}
.callout-example {
--color-callout: var(--color-callout-purple);
}
.callout-quote, .callout-cite {
--color-callout: var(--color-callout-gray);
}

View file

@ -4,12 +4,12 @@
--color-foreground: #ffffff; --color-foreground: #ffffff;
--color-accent: #218cff; --color-accent: #218cff;
--color-gray: #7E7E7E; --color-canvas-gray: #7E7E7E;
--color-red: #FB464C; --color-canvas-red: #FB464C;
--color-orange: #E9973F; --color-canvas-orange: #E9973F;
--color-yellow: #E0DE71; --color-canvas-yellow: #E0DE71;
--color-green: #44CF6E; --color-canvas-green: #44CF6E;
--color-blue: #53DFDD; --color-canvas-blue: #53DFDD;
--color-purple: #A882FF; --color-canvas-purple: #A882FF;
} }
} }

View file

@ -4,12 +4,12 @@
--color-foreground: #1e1e1e; --color-foreground: #1e1e1e;
--color-accent: #218cff; --color-accent: #218cff;
--color-gray: #7E7E7E; --color-canvas-gray: #7E7E7E;
--color-red: #FB464C; --color-canvas-red: #FB464C;
--color-orange: #E9973F; --color-canvas-orange: #E9973F;
--color-yellow: #E0DE71; --color-canvas-yellow: #E0DE71;
--color-green: #44CF6E; --color-canvas-green: #44CF6E;
--color-blue: #53DFDD; --color-canvas-blue: #53DFDD;
--color-purple: #A882FF; --color-canvas-purple: #A882FF;
} }
} }