mirror of
https://github.com/glassflame/glassflame.github.io.git
synced 2024-11-25 09:34:27 +00:00
Progress on callouts
This commit is contained in:
parent
eec0dace7f
commit
6ba152600a
6 changed files with 344 additions and 59 deletions
18
index.html
18
index.html
|
@ -138,8 +138,8 @@
|
|||
<template id="template-node-group">
|
||||
<style>
|
||||
.node {
|
||||
outline: var(--node-group-border-width) solid var(--color-node);
|
||||
background-color: color-mix(in srgb, var(--color-node) 20%, var(--color-background));
|
||||
outline: var(--node-group-border-width) solid var(--color-canvas);
|
||||
background-color: color-mix(in srgb, var(--color-canvas) 20%, var(--color-background));
|
||||
border-radius: 0 8px 8px 8px;
|
||||
padding: 12px;
|
||||
}
|
||||
|
@ -152,8 +152,8 @@
|
|||
|
||||
display: inline-block;
|
||||
|
||||
outline: var(--node-group-border-width) solid var(--color-node);
|
||||
background-color: color-mix(in srgb, var(--color-node) 20%, var(--color-background));
|
||||
outline: var(--node-group-border-width) solid var(--color-canvas);
|
||||
background-color: color-mix(in srgb, var(--color-canvas) 20%, var(--color-background));
|
||||
border-radius: 8px 8px 0 0;
|
||||
padding: 12px;
|
||||
}
|
||||
|
@ -170,8 +170,8 @@
|
|||
<template id="template-node-file">
|
||||
<style>
|
||||
.node {
|
||||
outline: var(--node-file-border-width) solid var(--color-node);
|
||||
background-color: color-mix(in srgb, var(--color-node) 10%, var(--color-background));
|
||||
outline: var(--node-file-border-width) solid var(--color-canvas);
|
||||
background-color: color-mix(in srgb, var(--color-canvas) 10%, var(--color-background));
|
||||
border-radius: 8px;
|
||||
padding: 12px;
|
||||
}
|
||||
|
@ -196,8 +196,8 @@
|
|||
<template id="template-node-text">
|
||||
<style>
|
||||
.node {
|
||||
outline: var(--node-file-border-width) solid var(--color-node);
|
||||
background-color: color-mix(in srgb, var(--color-node) 10%, var(--color-background));
|
||||
outline: var(--node-file-border-width) solid var(--color-canvas);
|
||||
background-color: color-mix(in srgb, var(--color-canvas) 10%, var(--color-background));
|
||||
border-radius: 8px;
|
||||
padding: 12px;
|
||||
}
|
||||
|
@ -249,6 +249,8 @@
|
|||
<slot name="wikilink-anchor">{Wikilink}</slot></template>
|
||||
<template id="template-math">
|
||||
<slot name="math-katex">{Math}</slot></template>
|
||||
<template id="template-callout">
|
||||
<slot name="callout-contents">{Callout}</slot></template>
|
||||
</head>
|
||||
<body is="x-browse"></body>
|
||||
</html>
|
|
@ -5,5 +5,224 @@ export class CalloutElement extends CustomElement {
|
|||
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()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,8 +18,8 @@ export class MarkdownElement extends CustomElement {
|
|||
static MARKED = new Marked({
|
||||
tokenizer: {
|
||||
// Fix single, double, and triple equals on a single line being interpreted as headings
|
||||
lheading(src) {
|
||||
const cap = /^(?![.+*] )((?:.|\n(?!\s*?\n|[.+*] ))+?)\n {0,3}(={4,}|-{4,}) *(?:\n+|$)/.exec(src);
|
||||
lheading(raw) {
|
||||
const cap = /^(?![.+*] )((?:.|\n(?!\s*?\n|[.+*] ))+?)\n {0,3}(={4,}|-{4,}) *(?:\n+|$)/.exec(raw);
|
||||
if (cap) {
|
||||
return {
|
||||
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: [
|
||||
{
|
||||
|
@ -74,30 +91,6 @@ export class MarkdownElement extends CustomElement {
|
|||
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",
|
||||
level: "inline",
|
||||
|
@ -179,7 +172,15 @@ export class MarkdownElement extends CustomElement {
|
|||
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>`
|
||||
}
|
||||
}
|
||||
],
|
||||
})
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,17 +3,28 @@
|
|||
--color-foreground: #000000;
|
||||
--color-accent: initial;
|
||||
|
||||
--color-gray: #7E7E7E;
|
||||
--color-red: #FB464C;
|
||||
--color-orange: #E9973F;
|
||||
--color-yellow: #E0DE71;
|
||||
--color-green: #44CF6E;
|
||||
--color-blue: #53DFDD;
|
||||
--color-purple: #A882FF;
|
||||
--color-canvas-gray: #7E7E7E;
|
||||
--color-canvas-red: #FB464C;
|
||||
--color-canvas-orange: #E9973F;
|
||||
--color-canvas-yellow: #E0DE71;
|
||||
--color-canvas-green: #44CF6E;
|
||||
--color-canvas-blue: #53DFDD;
|
||||
--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;
|
||||
|
||||
--color-node: var(--color-gray);
|
||||
--node-group-border-width: 2px;
|
||||
--node-file-border-width: 2px;
|
||||
--edge-width: 2px;
|
||||
|
@ -64,7 +75,7 @@ a {
|
|||
}
|
||||
|
||||
svg line {
|
||||
stroke: var(--color-node);
|
||||
stroke: var(--color-canvas);
|
||||
stroke-width: var(--edge-width);
|
||||
}
|
||||
|
||||
|
@ -115,3 +126,55 @@ h1 a, .wikilink.wikilink-heading {
|
|||
h1 a:hover, .wikilink.wikilink-heading:hover {
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
--color-foreground: #ffffff;
|
||||
--color-accent: #218cff;
|
||||
|
||||
--color-gray: #7E7E7E;
|
||||
--color-red: #FB464C;
|
||||
--color-orange: #E9973F;
|
||||
--color-yellow: #E0DE71;
|
||||
--color-green: #44CF6E;
|
||||
--color-blue: #53DFDD;
|
||||
--color-purple: #A882FF;
|
||||
--color-canvas-gray: #7E7E7E;
|
||||
--color-canvas-red: #FB464C;
|
||||
--color-canvas-orange: #E9973F;
|
||||
--color-canvas-yellow: #E0DE71;
|
||||
--color-canvas-green: #44CF6E;
|
||||
--color-canvas-blue: #53DFDD;
|
||||
--color-canvas-purple: #A882FF;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
--color-foreground: #1e1e1e;
|
||||
--color-accent: #218cff;
|
||||
|
||||
--color-gray: #7E7E7E;
|
||||
--color-red: #FB464C;
|
||||
--color-orange: #E9973F;
|
||||
--color-yellow: #E0DE71;
|
||||
--color-green: #44CF6E;
|
||||
--color-blue: #53DFDD;
|
||||
--color-purple: #A882FF;
|
||||
--color-canvas-gray: #7E7E7E;
|
||||
--color-canvas-red: #FB464C;
|
||||
--color-canvas-orange: #E9973F;
|
||||
--color-canvas-yellow: #E0DE71;
|
||||
--color-canvas-green: #44CF6E;
|
||||
--color-canvas-blue: #53DFDD;
|
||||
--color-canvas-purple: #A882FF;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue