mirror of
https://forgejo.ellis.link/continuwuation/continuwuity.git
synced 2026-05-26 20:49:55 +00:00
Add callouts support
Adds a colour palette Adds homemade remark-callouts package Adds tabler icons dependency
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
dist
|
||||
node_modules
|
||||
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"name": "remark-callouts",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"type": "module",
|
||||
"main": "dist/index.esm.js",
|
||||
"exports": {
|
||||
"import": "./dist/index.esm.js",
|
||||
"require": "./dist/index.cjs.js",
|
||||
"types": "./dist/index.d.ts"
|
||||
},
|
||||
"types": "dist/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "rollup -c",
|
||||
"dev": "rollup -c -w",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-typescript": "^11.1.6",
|
||||
"@types/mdast": "^4.0.4",
|
||||
"@types/node": "^20.14.2",
|
||||
"@types/svg-parser": "^2.0.6",
|
||||
"@types/trim": "^0.1.3",
|
||||
"@types/unist": "^3.0.2",
|
||||
"mdast": "^3.0.0",
|
||||
"rollup": "^4.18.0",
|
||||
"rollup-plugin-dts": "^6.1.1",
|
||||
"unified": "^6.2.0"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"dependencies": {
|
||||
"mdast-util-from-markdown": "^1.3.1",
|
||||
"svg-parser": "^2.0.4",
|
||||
"trim": "^0.0.1",
|
||||
"unist-util-visit": "^4.1.2"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// rollup.config.js
|
||||
import typescript from '@rollup/plugin-typescript';
|
||||
import { dts } from "rollup-plugin-dts";
|
||||
import pkg from './package.json' with { type: "json" };
|
||||
|
||||
export default [
|
||||
{
|
||||
input: 'src/index.ts',
|
||||
output: [
|
||||
{ file: pkg.exports.require, format: 'cjs' },
|
||||
{ file: pkg.exports.import, format: 'es' }
|
||||
],
|
||||
plugins: [typescript()]
|
||||
},
|
||||
{
|
||||
input: 'src/index.ts',
|
||||
output: [{ file: pkg.exports.types, format: 'es' }],
|
||||
plugins: [dts()],
|
||||
}
|
||||
];
|
||||
@@ -0,0 +1,326 @@
|
||||
import { visit } from "unist-util-visit";
|
||||
import { fromMarkdown } from "mdast-util-from-markdown";
|
||||
// @ts-ignore
|
||||
import type { Plugin } from "unified";
|
||||
import type { Node, Data, Parent } from "unist";
|
||||
import type { Blockquote, Heading, Text, BlockContent } from "mdast";
|
||||
import { parse } from "svg-parser";
|
||||
// import { calloutTypes } from "./calloutTypes";
|
||||
|
||||
// escape regex special characters
|
||||
function escapeRegExp(s: string) {
|
||||
return s.replace(new RegExp(`[-[\\]{}()*+?.\\\\^$|/]`, "g"), "\\$&");
|
||||
}
|
||||
|
||||
import tok from "./tokeniseCallout"
|
||||
|
||||
function trim(str: string){
|
||||
return str.replace(/^\s*|\s*$/g, '');
|
||||
}
|
||||
|
||||
export interface Config {
|
||||
// classNameMaps: {
|
||||
// block: ClassNameMap;
|
||||
// title: ClassNameMap;
|
||||
// };
|
||||
// dataMaps: {
|
||||
// block: (data: Data) => Data;
|
||||
// title: (data: Data) => Data;
|
||||
// };
|
||||
// types: { [index: string]: string | object };
|
||||
}
|
||||
|
||||
export const defaultConfig: Config = {
|
||||
// classNameMaps: {
|
||||
// block: "callout",
|
||||
// title: "callout-title",
|
||||
// },
|
||||
// dataMaps: {
|
||||
// block: (data) => data,
|
||||
// title: (data) => data,
|
||||
// },
|
||||
// types: { ...calloutTypes },
|
||||
};
|
||||
|
||||
type ClassNames = string | string[];
|
||||
type ClassNameMap = ClassNames | ((title: string) => ClassNames);
|
||||
function formatClassNameMap(gen: ClassNameMap) {
|
||||
return (title: string) => {
|
||||
const classNames = typeof gen == "function" ? gen(title) : gen;
|
||||
return typeof classNames == "object" ? classNames.join(" ") : classNames;
|
||||
};
|
||||
}
|
||||
|
||||
export const callouts: Plugin = function (providedConfig?: Partial<Config>) {
|
||||
const config: Config = { ...defaultConfig, ...providedConfig };
|
||||
// const defaultKeywords: string = Object.keys(config.types)
|
||||
// .map(escapeRegExp)
|
||||
// .join("|");
|
||||
// @ts-ignore
|
||||
const Parser = this.Parser
|
||||
console.log(Parser)
|
||||
|
||||
const blockTokenizers = Parser.prototype.blockTokenizers
|
||||
const blockMethods = Parser.prototype.blockMethods
|
||||
console.log(blockMethods, blockTokenizers)
|
||||
|
||||
|
||||
blockTokenizers.callout = tok
|
||||
// console.log(blockTokenizers.blockquote.toString())
|
||||
var insertPoint = blockMethods.indexOf('fencedCode') + 1
|
||||
blockMethods.splice(insertPoint, 0, 'callout')
|
||||
|
||||
// @ts-ignore
|
||||
const Compiler = this.Compiler
|
||||
|
||||
if (Compiler != null) {
|
||||
const visitors = Compiler.prototype.visitors
|
||||
if (visitors) {
|
||||
visitors.callout = function (node: { keyword: string; title: string; }) {
|
||||
var values = this.block(node).split('\n');
|
||||
var result = [];
|
||||
var length = values.length;
|
||||
var index = -1;
|
||||
var value;
|
||||
|
||||
while (++index < length) {
|
||||
value = values[index];
|
||||
result[index] = (value ? ' ' : '') + value;
|
||||
}
|
||||
|
||||
return '> [!'+node.keyword+'] ' + node.title + '\n' + result.join('\n>');
|
||||
}
|
||||
}
|
||||
}
|
||||
// return function (tree) {
|
||||
// visit(tree, (node: Node, index, parent: Parent) => {
|
||||
// // Filter required elems
|
||||
// if (node.type !== "blockquote") return;
|
||||
|
||||
// /** add breaks to text without needing spaces or escapes (turns enters into <br>)
|
||||
// * code taken directly from remark-breaks,
|
||||
// * see https://github.com/remarkjs/remark-breaks for more info on what this does.
|
||||
// */
|
||||
// // visit(node, "text", (node: Text, index: number, parent: Parent) => {
|
||||
// // const result = [];
|
||||
// // let start = 0;
|
||||
|
||||
// // find.lastIndex = 0;
|
||||
|
||||
// // let match = find.exec(node.value);
|
||||
|
||||
// // while (match) {
|
||||
// // const position = match.index;
|
||||
|
||||
// // if (start !== position) {
|
||||
// // result.push({
|
||||
// // type: "text",
|
||||
// // value: node.value.slice(start, position),
|
||||
// // });
|
||||
// // }
|
||||
|
||||
// // result.push({ type: "break" });
|
||||
// // start = position + match[0].length;
|
||||
// // match = find.exec(node.value);
|
||||
// // }
|
||||
|
||||
// // if (result.length > 0 && parent && typeof index === "number") {
|
||||
// // if (start < node.value.length) {
|
||||
// // result.push({ type: "text", value: node.value.slice(start) });
|
||||
// // }
|
||||
|
||||
// // parent.children.splice(index, 1, ...result);
|
||||
// // return index + result.length;
|
||||
// // }
|
||||
// // });
|
||||
|
||||
// /** add classnames to headings within blockquotes,
|
||||
// * mainly to identify when using other plugins that
|
||||
// * might interfere. for eg, rehype-auto-link-headings.
|
||||
// */
|
||||
// visit(node, "heading", (node) => {
|
||||
// const heading = node as Heading;
|
||||
// heading.data = {
|
||||
// hProperties: {
|
||||
// className: "blockquote-heading",
|
||||
// },
|
||||
// };
|
||||
// });
|
||||
|
||||
// // wrap blockquote in a div
|
||||
// const wrapper = {
|
||||
// ...node,
|
||||
// type: "element",
|
||||
// tagName: "div",
|
||||
// data: {
|
||||
// hProperties: {},
|
||||
// },
|
||||
// children: [node],
|
||||
// };
|
||||
|
||||
// parent.children.splice(Number(index), 1, wrapper);
|
||||
|
||||
// const blockquote = wrapper.children[0] as Blockquote;
|
||||
|
||||
// blockquote.data = {
|
||||
// hProperties: {
|
||||
// className: "blockquote",
|
||||
// },
|
||||
// };
|
||||
// console.log(blockquote)
|
||||
|
||||
// // check for callout syntax starts here
|
||||
// if (
|
||||
// blockquote.children.length <= 0 ||
|
||||
// blockquote.children[0].type !== "paragraph"
|
||||
// )
|
||||
// return;
|
||||
// const paragraph = blockquote.children[0];
|
||||
// console.log(paragraph)
|
||||
|
||||
// if (
|
||||
// paragraph.children.length <= 0 ||
|
||||
// paragraph.children[0].type !== "text"
|
||||
// )
|
||||
// return;
|
||||
|
||||
// const [t, ...rest] = paragraph.children;
|
||||
|
||||
// const regex = new RegExp(
|
||||
// `^\\[!(?<keyword>(.*?))\\][\t\f ]?(?<title>.*?)$`,
|
||||
// "gi"
|
||||
// );
|
||||
// const m = regex.exec(t.value);
|
||||
|
||||
// // if no callout syntax, forget about it.
|
||||
// if (!m) return;
|
||||
|
||||
// const [key, title] = [m.groups?.keyword, m.groups?.title];
|
||||
|
||||
// // if there's nothing inside the brackets, is it really a callout ?
|
||||
// if (!key) return;
|
||||
|
||||
// const keyword = key.toLowerCase();
|
||||
// // const isOneOfKeywords: boolean = new RegExp(defaultKeywords).test(
|
||||
// // keyword
|
||||
// // );
|
||||
|
||||
// if (title) {
|
||||
// const mdast = fromMarkdown(title.trim()).children[0];
|
||||
// if (mdast.type === "heading") {
|
||||
// mdast.data = {
|
||||
// ...mdast.data,
|
||||
// hProperties: {
|
||||
// className: "blockquote-heading",
|
||||
// },
|
||||
// };
|
||||
// }
|
||||
// blockquote.children.unshift(mdast as BlockContent);
|
||||
// } else {
|
||||
// t.value =
|
||||
// typeof keyword.charAt(0) === "string"
|
||||
// ? keyword.charAt(0).toUpperCase() + keyword.slice(1)
|
||||
// : keyword;
|
||||
// }
|
||||
|
||||
// const entry: { [index: string]: string } = {};
|
||||
|
||||
// // if (isOneOfKeywords) {
|
||||
// // if (typeof config?.types[keyword] === "string") {
|
||||
// // const e = String(config?.types[keyword]);
|
||||
// // Object.assign(entry, config?.types[e]);
|
||||
// // } else {
|
||||
// // Object.assign(entry, config?.types[keyword]);
|
||||
// // }
|
||||
// // } else {
|
||||
// // Object.assign(entry, config?.types["note"]);
|
||||
// // }
|
||||
|
||||
// let parsedSvg;
|
||||
|
||||
// if (entry && entry.svg) {
|
||||
// parsedSvg = parse(entry.svg);
|
||||
// }
|
||||
|
||||
// // create icon and title node wrapped in div
|
||||
// const titleNode: object = {
|
||||
// type: "element",
|
||||
// children: [
|
||||
// {
|
||||
// type: "element",
|
||||
// tagName: "span",
|
||||
// data: {
|
||||
// hName: "span",
|
||||
// hProperties: {
|
||||
// style: `color:${entry?.color}`,
|
||||
// className: "callout-icon",
|
||||
// },
|
||||
// hChildren: parsedSvg?.children ? parsedSvg.children : [],
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// type: "element",
|
||||
// children: title ? [blockquote.children[0]] : [t],
|
||||
// data: {
|
||||
// hName: "strong",
|
||||
// },
|
||||
// },
|
||||
// ],
|
||||
// data: {
|
||||
// ...blockquote.children[0]?.data,
|
||||
// hProperties: {
|
||||
// className: `${formatClassNameMap(config.classNameMaps.title)(
|
||||
// keyword
|
||||
// )} ${"note"}`,
|
||||
// style: `background-color: ${entry?.color}1a;`,
|
||||
// },
|
||||
// },
|
||||
// };
|
||||
|
||||
// // remove the callout paragraph from the content body
|
||||
// if (title) {
|
||||
// blockquote.children.shift();
|
||||
// }
|
||||
|
||||
// if (rest.length > 0) {
|
||||
// rest.shift();
|
||||
// paragraph.children = rest;
|
||||
// } else {
|
||||
// blockquote.children.shift();
|
||||
// }
|
||||
|
||||
// // wrap blockquote content in div
|
||||
// const contentNode: object = {
|
||||
// type: "element",
|
||||
// children: blockquote.children,
|
||||
// data: {
|
||||
// hProperties: {
|
||||
// className: "callout-content",
|
||||
// style:
|
||||
// parent.type !== "root"
|
||||
// ? `border-right:1px solid ${entry?.color}33;
|
||||
// border-bottom:1px solid ${entry?.color}33;`
|
||||
// : "",
|
||||
// },
|
||||
// },
|
||||
// };
|
||||
|
||||
// if (blockquote.children.length > 0)
|
||||
// blockquote.children = [contentNode] as BlockContent[];
|
||||
// blockquote.children.unshift(titleNode as BlockContent);
|
||||
|
||||
// // Add classes for the callout block
|
||||
// blockquote.data = config.dataMaps.block({
|
||||
// ...blockquote.data,
|
||||
// hProperties: {
|
||||
// className: formatClassNameMap(config.classNameMaps.block)(
|
||||
// keyword.toLowerCase()
|
||||
// ),
|
||||
// style: `border-left-color:${entry?.color};`,
|
||||
// },
|
||||
// });
|
||||
// });
|
||||
// };
|
||||
};
|
||||
|
||||
export default callouts;
|
||||
@@ -0,0 +1,245 @@
|
||||
'use strict';
|
||||
|
||||
import trim from "trim";
|
||||
|
||||
|
||||
export default blockquote;
|
||||
|
||||
var C_NEWLINE = '\n';
|
||||
var C_TAB = '\t';
|
||||
var C_SPACE = ' ';
|
||||
var C_GT = '>';
|
||||
// TODO:
|
||||
// - Grow/shrink support
|
||||
// - Customise AST output
|
||||
|
||||
/* Tokenise a blockquote. */
|
||||
function blockquote(eat: { (arg0: string): any; (arg0: string): any; now: any; }, value: string, silent: boolean) {
|
||||
var self = this;
|
||||
var offsets = self.offset;
|
||||
var tokenizers = self.blockTokenizers;
|
||||
var interruptors = [
|
||||
['indentedCode', { commonmark: true }],
|
||||
['fencedCode', { commonmark: true }],
|
||||
['atxHeading', { commonmark: true }],
|
||||
['setextHeading', { commonmark: true }],
|
||||
['thematicBreak', { commonmark: true }],
|
||||
['html', { commonmark: true }],
|
||||
['list', { commonmark: true }],
|
||||
['definition', { commonmark: false }],
|
||||
['footnote', { commonmark: false }]
|
||||
];
|
||||
var now = eat.now();
|
||||
var currentLine = now.line;
|
||||
var length = value.length;
|
||||
var values = [];
|
||||
var contents = [];
|
||||
var indents = [];
|
||||
var add;
|
||||
var index = 0;
|
||||
var character;
|
||||
var rest;
|
||||
var nextIndex;
|
||||
var content;
|
||||
var line;
|
||||
var startIndex;
|
||||
var prefixed;
|
||||
var exit;
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character !== C_SPACE && character !== C_TAB) {
|
||||
break;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
if (value.charAt(index) !== C_GT) {
|
||||
return;
|
||||
}
|
||||
|
||||
const regex = /^>\s*\[!(?<keyword>(.*?))\][\t\f ]?(?<title>.*?)$/i;
|
||||
nextIndex = value.indexOf(C_NEWLINE, index);
|
||||
content = value.slice(index, nextIndex);
|
||||
const m = regex.exec(content); // value.slice(index)
|
||||
if (!m) {
|
||||
return;
|
||||
}
|
||||
if (!m.groups?.keyword) return;
|
||||
|
||||
if (silent) {
|
||||
return true;
|
||||
}
|
||||
|
||||
index = 0;
|
||||
let titleLine = true
|
||||
while (index < length) {
|
||||
nextIndex = value.indexOf(C_NEWLINE, index);
|
||||
startIndex = index;
|
||||
prefixed = false;
|
||||
|
||||
if (nextIndex === -1) {
|
||||
nextIndex = length;
|
||||
}
|
||||
|
||||
while (index < length) {
|
||||
character = value.charAt(index);
|
||||
|
||||
if (character !== C_SPACE && character !== C_TAB) {
|
||||
break;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
if (value.charAt(index) === C_GT) {
|
||||
index++;
|
||||
prefixed = true;
|
||||
|
||||
if (value.charAt(index) === C_SPACE) {
|
||||
index++;
|
||||
}
|
||||
} else {
|
||||
index = startIndex;
|
||||
}
|
||||
|
||||
// regex.lastIndex = index
|
||||
|
||||
content = value.slice(index, nextIndex);
|
||||
|
||||
if (!prefixed && !trim(content)) {
|
||||
index = startIndex;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!prefixed) {
|
||||
rest = value.slice(index);
|
||||
|
||||
/* Check if the following code contains a possible
|
||||
* block. */
|
||||
if (interrupt(interruptors, tokenizers, self, [eat, rest, true])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
line = startIndex === index ? content : value.slice(startIndex, nextIndex);
|
||||
|
||||
indents.push(index - startIndex);
|
||||
values.push(line);
|
||||
if (titleLine) {
|
||||
titleLine = false
|
||||
} else {
|
||||
contents.push(content);
|
||||
}
|
||||
|
||||
index = nextIndex + 1;
|
||||
}
|
||||
|
||||
index = -1;
|
||||
length = indents.length;
|
||||
add = eat(values.join(C_NEWLINE));
|
||||
|
||||
while (++index < length) {
|
||||
offsets[currentLine] = (offsets[currentLine] || 0) + indents[index];
|
||||
currentLine++;
|
||||
}
|
||||
|
||||
exit = self.enterBlock();
|
||||
const title = self.tokenizeInline(m.groups?.title, now);
|
||||
contents = self.tokenizeBlock(contents.join(C_NEWLINE), now);
|
||||
exit();
|
||||
console.log(title,)
|
||||
return add({
|
||||
type: 'callout',
|
||||
children: [{
|
||||
type: "heading",
|
||||
children: title,
|
||||
data: { hName: 'svelte:fragment',
|
||||
hProperties: {
|
||||
slot: "title"
|
||||
} }
|
||||
}, {
|
||||
type: "block",
|
||||
children: contents,
|
||||
data: { hName: 'svelte:fragment',
|
||||
hProperties: {
|
||||
slot: "body"
|
||||
} }
|
||||
}],
|
||||
keyword: m.groups?.keyword,
|
||||
data: {
|
||||
hName: 'Components.Callout',
|
||||
hProperties: {
|
||||
"calloutType": m.groups?.keyword
|
||||
},
|
||||
}
|
||||
});
|
||||
// return add({
|
||||
// type: 'callout',
|
||||
// children: [{
|
||||
// type: "heading",
|
||||
// children: title,
|
||||
// data: { hName: 'div',
|
||||
// hProperties: {
|
||||
// className: "callout-title"
|
||||
// } }
|
||||
// }, {
|
||||
// type: "block",
|
||||
// children: contents,
|
||||
// data: { hName: 'div',
|
||||
// hProperties: {
|
||||
// className: "callout-content"
|
||||
// } }
|
||||
// }],
|
||||
// keyword: m.groups?.keyword,
|
||||
// data: {
|
||||
// hName: 'div',
|
||||
// hProperties: {
|
||||
// className: "callout",
|
||||
// "data-callout": m.groups?.keyword
|
||||
// },
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
function interrupt(interruptors, tokenizers, ctx, params) {
|
||||
var bools = ['pedantic', 'commonmark'];
|
||||
var count = bools.length;
|
||||
var length = interruptors.length;
|
||||
var index = -1;
|
||||
var interruptor;
|
||||
var config;
|
||||
var fn;
|
||||
var offset;
|
||||
var bool;
|
||||
var ignore;
|
||||
|
||||
while (++index < length) {
|
||||
interruptor = interruptors[index];
|
||||
config = interruptor[1] || {};
|
||||
fn = interruptor[0];
|
||||
offset = -1;
|
||||
ignore = false;
|
||||
|
||||
while (++offset < count) {
|
||||
bool = bools[offset];
|
||||
|
||||
if (config[bool] !== undefined && config[bool] !== ctx.options[bool]) {
|
||||
ignore = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ignore) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (tokenizers[fn].apply(ctx, params)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2020",
|
||||
"module": "esnext",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"moduleResolution": "node",
|
||||
"skipLibCheck": true,
|
||||
"noImplicitAny": true,
|
||||
"allowJs": true,
|
||||
"noEmit": true,
|
||||
"resolveJsonModule": true
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import remarkMath from "remark-math"
|
||||
// @ts-ignore
|
||||
import remarkAbbr from "remark-abbr"
|
||||
import remarkFootnotes from 'remark-footnotes'
|
||||
import remarkCallouts from "remark-callouts";
|
||||
|
||||
import rehypeKatexSvelte from 'rehype-katex-svelte';
|
||||
// import github from "remark-github";
|
||||
@@ -343,6 +344,8 @@ const config = {
|
||||
remarkMath,
|
||||
remarkAbbr,
|
||||
[remarkFootnotes, { inlineNotes: true }],
|
||||
remarkGfm,
|
||||
[remarkCallouts, {}],
|
||||
[remarkWikiLink, {
|
||||
// @ts-ignore
|
||||
aliasDivider: "|",
|
||||
@@ -353,7 +356,6 @@ const config = {
|
||||
// wikiLinkClassName,
|
||||
// newClassName,
|
||||
}],
|
||||
remarkGfm,
|
||||
// [citePlugin, {
|
||||
// syntax: {
|
||||
// // see micromark-extension-cite
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
"rehype-katex-svelte": "1.2",
|
||||
"rehype-slug": "^6.0.0",
|
||||
"remark-abbr": "^1.4.2",
|
||||
"remark-callouts": "workspace:^",
|
||||
"remark-footnotes": "2",
|
||||
"remark-frontmatter": "^5.0.0",
|
||||
"remark-gfm": "^4.0.0",
|
||||
@@ -74,6 +75,7 @@
|
||||
"@octokit/types": "^13.5.0",
|
||||
"@resvg/resvg-js": "^2.6.2",
|
||||
"@steeze-ui/svelte-icon": "^1.5.0",
|
||||
"@tabler/icons-svelte": "^3.11.0",
|
||||
"@tusbar/cache-control": "^1.0.2",
|
||||
"@uiw/codemirror-theme-github": "^4.22.2",
|
||||
"Notes": "file:Notes-1.0.0.tgz",
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
<script lang="ts">
|
||||
export let calloutType: string;
|
||||
import { IconExclamationCircle } from "@tabler/icons-svelte";
|
||||
</script>
|
||||
|
||||
<div class="callout" data-callout={calloutType}>
|
||||
<div class="callout-title">
|
||||
{#if $$slots.icon}
|
||||
<div class="callout-icon"><slot name="icon" /></div>
|
||||
{:else}
|
||||
<div class="callout-icon"><IconExclamationCircle /></div>
|
||||
{/if}
|
||||
<div class="callout-title-inner">
|
||||
<slot name="title"
|
||||
>{calloutType.replace(/\w\S*/g, function (txt) {
|
||||
return (
|
||||
txt.charAt(0).toUpperCase() +
|
||||
txt.substring(1).toLowerCase()
|
||||
);
|
||||
})}</slot
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
{#if $$slots.body}
|
||||
<div class="callout-body"><slot name="body" /></div>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -1,6 +1,7 @@
|
||||
<script context="module">
|
||||
import img from "$lib/htmlComponents/img.svelte";
|
||||
export { img };
|
||||
import Callout from "$lib/Callout.svelte";
|
||||
export { img, Callout };
|
||||
</script>
|
||||
|
||||
<slot />
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
:root {
|
||||
--callout-bug: var(--color-red);
|
||||
--callout-default: var(--color-blue);
|
||||
--callout-error: var(--color-red);
|
||||
--callout-example: var(--color-purple);
|
||||
--callout-fail: var(--color-red);
|
||||
--callout-important: var(--color-cyan);
|
||||
--callout-info: var(--color-blue);
|
||||
--callout-question: var(--color-orange);
|
||||
--callout-success: var(--color-green);
|
||||
--callout-summary: var(--color-cyan);
|
||||
--callout-tip: var(--color-cyan);
|
||||
--callout-todo: var(--color-blue);
|
||||
--callout-warning: var(--color-orange);
|
||||
--callout-quote: rgb(158, 158, 158);
|
||||
|
||||
--callout-title-weight: bold;
|
||||
|
||||
--callout-radius: var(--border-radius);
|
||||
|
||||
--callout-border-opacity: 25%;
|
||||
--callout-background-opacity: 10%;
|
||||
--callout-content-padding: 0;
|
||||
--callout-content-background: transparent;
|
||||
}
|
||||
.callout {
|
||||
--callout-color: var(--callout-default);
|
||||
/* --callout-icon: lucide-pencil; */
|
||||
}
|
||||
|
||||
.callout[data-callout="abstract"],
|
||||
.callout[data-callout="summary"],
|
||||
.callout[data-callout="tldr"] {
|
||||
--callout-color: var(--callout-summary);
|
||||
/* --callout-icon: lucide-clipboard-list; */
|
||||
}
|
||||
|
||||
.callout[data-callout="info"] {
|
||||
--callout-color: var(--callout-info);
|
||||
/* --callout-icon: lucide-info; */
|
||||
}
|
||||
|
||||
.callout[data-callout="todo"] {
|
||||
--callout-color: var(--callout-todo);
|
||||
/* --callout-icon: lucide-check-circle-2; */
|
||||
}
|
||||
|
||||
.callout[data-callout="important"] {
|
||||
--callout-color: var(--callout-important);
|
||||
/* --callout-icon: lucide-flame; */
|
||||
}
|
||||
|
||||
.callout[data-callout="tip"],
|
||||
.callout[data-callout="hint"] {
|
||||
--callout-color: var(--callout-tip);
|
||||
/* --callout-icon: lucide-flame; */
|
||||
}
|
||||
|
||||
.callout[data-callout="success"],
|
||||
.callout[data-callout="check"],
|
||||
.callout[data-callout="done"] {
|
||||
--callout-color: var(--callout-success);
|
||||
/* --callout-icon: lucide-check; */
|
||||
}
|
||||
|
||||
.callout[data-callout="question"],
|
||||
.callout[data-callout="help"],
|
||||
.callout[data-callout="faq"] {
|
||||
--callout-color: var(--callout-question);
|
||||
/* --callout-icon: help-circle; */
|
||||
}
|
||||
|
||||
.callout[data-callout="warning"],
|
||||
.callout[data-callout="caution"],
|
||||
.callout[data-callout="attention"] {
|
||||
--callout-color: var(--callout-warning);
|
||||
/* --callout-icon: lucide-alert-triangle; */
|
||||
}
|
||||
|
||||
.callout[data-callout="failure"],
|
||||
.callout[data-callout="fail"],
|
||||
.callout[data-callout="missing"] {
|
||||
--callout-color: var(--callout-fail);
|
||||
/* --callout-icon: lucide-x; */
|
||||
}
|
||||
|
||||
.callout[data-callout="danger"],
|
||||
.callout[data-callout="error"] {
|
||||
--callout-color: var(--callout-error);
|
||||
/* --callout-icon: lucide-zap; */
|
||||
}
|
||||
|
||||
.callout[data-callout="bug"] {
|
||||
--callout-color: var(--callout-bug);
|
||||
/* --callout-icon: lucide-bug; */
|
||||
}
|
||||
|
||||
.callout[data-callout="example"] {
|
||||
--callout-color: var(--callout-example);
|
||||
/* --callout-icon: lucide-list; */
|
||||
}
|
||||
|
||||
.callout[data-callout="quote"],
|
||||
.callout[data-callout="cite"] {
|
||||
--callout-color: var(--callout-quote);
|
||||
/* --callout-icon: quote-glyph; */
|
||||
}
|
||||
|
||||
.callout {
|
||||
overflow: hidden;
|
||||
border-style: solid;
|
||||
|
||||
border-color: color-mix(in srgb, var(--callout-color) var(--callout-border-opacity), transparent);
|
||||
border-width: var(--callout-border-width);
|
||||
border-radius: var(--callout-radius);
|
||||
margin-block: 1em;
|
||||
margin-inline: 0;
|
||||
mix-blend-mode: var(--callout-blend-mode);
|
||||
background-color: color-mix(in srgb, var(--callout-color) var(--callout-background-opacity), transparent);
|
||||
padding: 0.75em;
|
||||
padding-inline-start: 1.5em;
|
||||
--callout-title-color: var(--callout-color);
|
||||
}
|
||||
|
||||
.callout.is-collapsible .callout-title {
|
||||
cursor: var(--cursor);
|
||||
}
|
||||
|
||||
.callout-title {
|
||||
padding: var(--callout-title-padding);
|
||||
display: flex;
|
||||
gap: calc(var(--spacing)/4);
|
||||
font-size: var(--callout-title-size);
|
||||
color: rgb(var(--callout-color));
|
||||
line-height: var(--line-height-tight);
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.callout-title-inner {
|
||||
--font-weight: var(--callout-title-weight);
|
||||
font-weight: var(--font-weight);
|
||||
color: var(--callout-title-color);
|
||||
}
|
||||
/* .callout-title {
|
||||
--font-weight: var(--callout-title-weight);
|
||||
font-weight: var(--font-weight);
|
||||
color: var(--callout-title-color);
|
||||
padding: var(--callout-title-padding);
|
||||
font-size: var(--callout-title-size);
|
||||
line-height: var(--line-height-tight);
|
||||
} */
|
||||
|
||||
|
||||
.callout-content {
|
||||
overflow-block: auto;
|
||||
padding: var(--callout-content-padding);
|
||||
background-color: var(--callout-content-background);
|
||||
}
|
||||
|
||||
.callout-content .callout {
|
||||
margin-block-start: 20px;
|
||||
}
|
||||
|
||||
.callout-icon {
|
||||
flex: 0 0 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.callout-icon .tabler-icon {
|
||||
color: var(--callout-color);
|
||||
}
|
||||
|
||||
.callout-icon::after {
|
||||
content: "\200B";
|
||||
}
|
||||
|
||||
/* .callout-fold {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-inline-end: var(--size-4-2);
|
||||
}
|
||||
|
||||
.callout-fold::after {
|
||||
content: "\200B";
|
||||
}
|
||||
|
||||
.callout-fold .svg-icon {
|
||||
transition: transform 100ms ease-in-out;
|
||||
}
|
||||
|
||||
.callout-fold.is-collapsed .svg-icon {
|
||||
transform: rotate(calc(var(--direction) * -1 * 90deg));
|
||||
} */
|
||||
@@ -1,4 +1,5 @@
|
||||
@import "./style/code.css";
|
||||
@import "./style/callout.css";
|
||||
@import "./style/footnote.css";
|
||||
|
||||
:root {
|
||||
@@ -32,6 +33,15 @@
|
||||
--code-background-color: #0d1117;
|
||||
--code-color: #fff;
|
||||
|
||||
--color-red: #e93147;
|
||||
--color-orange: #ec7500;
|
||||
--color-yellow: #e0ac00;
|
||||
--color-green: #08b94e;
|
||||
--color-cyan: #00bfbc;
|
||||
--color-blue: #086ddd;
|
||||
--color-purple: #7852ee;
|
||||
--color-pink: #d53984;
|
||||
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
@@ -49,7 +59,16 @@
|
||||
--input-color: #d8d8d8;
|
||||
--font-color: rgba(255, 255, 255, .87);
|
||||
--font-color-contrast: rgba(0, 0, 0, .87);
|
||||
--font-color-secondary: rgba(255, 255, 255, .6)
|
||||
--font-color-secondary: rgba(255, 255, 255, .6);
|
||||
|
||||
--color-red: #fb464c;
|
||||
--color-orange: #e9973f;
|
||||
--color-yellow: #e0de71;
|
||||
--color-green: #44cf6e;
|
||||
--color-cyan: #53dfdd;
|
||||
--color-blue: #027aff;
|
||||
--color-purple: #a882ff;
|
||||
--color-pink: #fa99cd;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user