syntax higlighting ✔ (needs proper theming)

This commit is contained in:
dragonwocky 2021-04-21 11:51:21 +10:00
parent 93e764fb0a
commit d58d5b1850
8 changed files with 910 additions and 102 deletions

507
extension/dep/prism.css Normal file
View File

@ -0,0 +1,507 @@
/* PrismJS 1.23.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+abap+abnf+actionscript+ada+agda+al+antlr4+apacheconf+apex+apl+applescript+aql+arduino+arff+asciidoc+aspnet+asm6502+autohotkey+autoit+bash+basic+batch+bbcode+birb+bison+bnf+brainfuck+brightscript+bro+bsl+c+csharp+cpp+cfscript+chaiscript+cil+clojure+cmake+cobol+coffeescript+concurnas+csp+coq+crystal+css-extras+csv+cypher+d+dart+dataweave+dax+dhall+diff+django+dns-zone-file+docker+dot+ebnf+editorconfig+eiffel+ejs+elixir+elm+etlua+erb+erlang+excel-formula+fsharp+factor+false+firestore-security-rules+flow+fortran+ftl+gml+gcode+gdscript+gedcom+gherkin+git+glsl+go+graphql+groovy+haml+handlebars+haskell+haxe+hcl+hlsl+http+hpkp+hsts+ichigojam+icon+icu-message-format+idris+ignore+inform7+ini+io+j+java+javadoc+javadoclike+javastacktrace+jexl+jolie+jq+jsdoc+js-extras+json+json5+jsonp+jsstacktrace+js-templates+julia+keyman+kotlin+kumir+latex+latte+less+lilypond+liquid+lisp+livescript+llvm+log+lolcode+lua+makefile+markdown+markup-templating+matlab+mel+mizar+mongodb+monkey+moonscript+n1ql+n4js+nand2tetris-hdl+naniscript+nasm+neon+nevod+nginx+nim+nix+nsis+objectivec+ocaml+opencl+openqasm+oz+parigp+parser+pascal+pascaligo+psl+pcaxis+peoplecode+perl+php+phpdoc+php-extras+plsql+powerquery+powershell+processing+prolog+promql+properties+protobuf+pug+puppet+pure+purebasic+purescript+python+qsharp+q+qml+qore+r+racket+jsx+tsx+reason+regex+rego+renpy+rest+rip+roboconf+robotframework+ruby+rust+sas+sass+scss+scala+scheme+shell-session+smali+smalltalk+smarty+sml+solidity+solution-file+soy+sparql+splunk-spl+sqf+sql+squirrel+stan+iecst+stylus+swift+t4-templating+t4-cs+t4-vb+tap+tcl+tt2+textile+toml+turtle+twig+typescript+typoscript+unrealscript+uri+v+vala+vbnet+velocity+verilog+vhdl+vim+visual-basic+warpscript+wasm+wiki+xeora+xml-doc+xojo+xquery+yaml+yang+zig&plugins=autolinker+show-language+inline-color+previewers+normalize-whitespace+data-uri-highlight+toolbar+copy-to-clipboard */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*='language-'],
pre[class*='language-'] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
font-size: 1em;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*='language-']::-moz-selection,
pre[class*='language-'] ::-moz-selection,
code[class*='language-']::-moz-selection,
code[class*='language-'] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*='language-']::selection,
pre[class*='language-'] ::selection,
code[class*='language-']::selection,
code[class*='language-'] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*='language-'],
pre[class*='language-'] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*='language-'] {
padding: 1em;
margin: 0.5em 0;
overflow: auto;
}
:not(pre) > code[class*='language-'],
pre[class*='language-'] {
background: #f5f2f0;
}
/* Inline code */
:not(pre) > code[class*='language-'] {
padding: 0.1em;
border-radius: 0.3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.token.namespace {
opacity: 0.7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
/* This background color was intended by the author of this theme. */
background: hsla(0, 0%, 100%, 0.5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function,
.token.class-name {
color: #dd4a68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}
.token a {
color: inherit;
}
div.code-toolbar {
position: relative;
}
div.code-toolbar > .toolbar {
position: absolute;
top: 0.3em;
right: 0.2em;
transition: opacity 0.3s ease-in-out;
opacity: 0;
}
div.code-toolbar:hover > .toolbar {
opacity: 1;
}
/* Separate line b/c rules are thrown out if selector is invalid.
IE11 and old Edge versions don't support :focus-within. */
div.code-toolbar:focus-within > .toolbar {
opacity: 1;
}
div.code-toolbar > .toolbar .toolbar-item {
display: inline-block;
}
div.code-toolbar > .toolbar a {
cursor: pointer;
}
div.code-toolbar > .toolbar button {
background: none;
border: 0;
color: inherit;
font: inherit;
line-height: normal;
overflow: visible;
padding: 0;
-webkit-user-select: none; /* for button */
-moz-user-select: none;
-ms-user-select: none;
}
div.code-toolbar > .toolbar a,
div.code-toolbar > .toolbar button,
div.code-toolbar > .toolbar span {
color: #bbb;
font-size: 0.8em;
padding: 0 0.5em;
background: #f5f2f0;
background: rgba(224, 224, 224, 0.2);
box-shadow: 0 2px 0 0 rgba(0, 0, 0, 0.2);
border-radius: 0.5em;
}
div.code-toolbar > .toolbar a:hover,
div.code-toolbar > .toolbar a:focus,
div.code-toolbar > .toolbar button:hover,
div.code-toolbar > .toolbar button:focus,
div.code-toolbar > .toolbar span:hover,
div.code-toolbar > .toolbar span:focus {
color: inherit;
text-decoration: none;
}
span.inline-color-wrapper {
/*
* The background image is the following SVG inline in base 64:
*
* <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2 2">
* <path fill="gray" d="M0 0h2v2H0z"/>
* <path fill="white" d="M0 0h1v1H0zM1 1h1v1H1z"/>
* </svg>
*
* SVG-inlining explained:
* https://stackoverflow.com/a/21626701/7595472
*/
background: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyIDIiPjxwYXRoIGZpbGw9ImdyYXkiIGQ9Ik0wIDBoMnYySDB6Ii8+PHBhdGggZmlsbD0id2hpdGUiIGQ9Ik0wIDBoMXYxSDB6TTEgMWgxdjFIMXoiLz48L3N2Zz4=');
/* This is to prevent visual glitches where one pixel from the repeating pattern could be seen. */
background-position: center;
background-size: 110%;
display: inline-block;
height: 1.333ch;
width: 1.333ch;
margin: 0 0.333ch;
box-sizing: border-box;
border: 1px solid white;
outline: 1px solid rgba(0, 0, 0, 0.5);
overflow: hidden;
}
span.inline-color {
display: block;
/* To prevent visual glitches again */
height: 120%;
width: 120%;
}
.prism-previewer,
.prism-previewer:before,
.prism-previewer:after {
position: absolute;
pointer-events: none;
}
.prism-previewer,
.prism-previewer:after {
left: 50%;
}
.prism-previewer {
margin-top: -48px;
width: 32px;
height: 32px;
margin-left: -16px;
opacity: 0;
-webkit-transition: opacity 0.25s;
-o-transition: opacity 0.25s;
transition: opacity 0.25s;
}
.prism-previewer.flipped {
margin-top: 0;
margin-bottom: -48px;
}
.prism-previewer:before,
.prism-previewer:after {
content: '';
position: absolute;
pointer-events: none;
}
.prism-previewer:before {
top: -5px;
right: -5px;
left: -5px;
bottom: -5px;
border-radius: 10px;
border: 5px solid #fff;
box-shadow: 0 0 3px rgba(0, 0, 0, 0.5) inset, 0 0 10px rgba(0, 0, 0, 0.75);
}
.prism-previewer:after {
top: 100%;
width: 0;
height: 0;
margin: 5px 0 0 -7px;
border: 7px solid transparent;
border-color: rgba(255, 0, 0, 0);
border-top-color: #fff;
}
.prism-previewer.flipped:after {
top: auto;
bottom: 100%;
margin-top: 0;
margin-bottom: 5px;
border-top-color: rgba(255, 0, 0, 0);
border-bottom-color: #fff;
}
.prism-previewer.active {
opacity: 1;
}
.prism-previewer-angle:before {
border-radius: 50%;
background: #fff;
}
.prism-previewer-angle:after {
margin-top: 4px;
}
.prism-previewer-angle svg {
width: 32px;
height: 32px;
-webkit-transform: rotate(-90deg);
-moz-transform: rotate(-90deg);
-ms-transform: rotate(-90deg);
-o-transform: rotate(-90deg);
transform: rotate(-90deg);
}
.prism-previewer-angle[data-negative] svg {
-webkit-transform: scaleX(-1) rotate(-90deg);
-moz-transform: scaleX(-1) rotate(-90deg);
-ms-transform: scaleX(-1) rotate(-90deg);
-o-transform: scaleX(-1) rotate(-90deg);
transform: scaleX(-1) rotate(-90deg);
}
.prism-previewer-angle circle {
fill: transparent;
stroke: hsl(200, 10%, 20%);
stroke-opacity: 0.9;
stroke-width: 32;
stroke-dasharray: 0, 500;
}
.prism-previewer-gradient {
background-image: linear-gradient(
45deg,
#bbb 25%,
transparent 25%,
transparent 75%,
#bbb 75%,
#bbb
),
linear-gradient(45deg, #bbb 25%, #eee 25%, #eee 75%, #bbb 75%, #bbb);
background-size: 10px 10px;
background-position: 0 0, 5px 5px;
width: 64px;
margin-left: -32px;
}
.prism-previewer-gradient:before {
content: none;
}
.prism-previewer-gradient div {
position: absolute;
top: -5px;
left: -5px;
right: -5px;
bottom: -5px;
border-radius: 10px;
border: 5px solid #fff;
box-shadow: 0 0 3px rgba(0, 0, 0, 0.5) inset, 0 0 10px rgba(0, 0, 0, 0.75);
}
.prism-previewer-color {
background-image: linear-gradient(
45deg,
#bbb 25%,
transparent 25%,
transparent 75%,
#bbb 75%,
#bbb
),
linear-gradient(45deg, #bbb 25%, #eee 25%, #eee 75%, #bbb 75%, #bbb);
background-size: 10px 10px;
background-position: 0 0, 5px 5px;
}
.prism-previewer-color:before {
background-color: inherit;
background-clip: padding-box;
}
.prism-previewer-easing {
margin-top: -76px;
margin-left: -30px;
width: 60px;
height: 60px;
background: #333;
}
.prism-previewer-easing.flipped {
margin-bottom: -116px;
}
.prism-previewer-easing svg {
width: 60px;
height: 60px;
}
.prism-previewer-easing circle {
fill: hsl(200, 10%, 20%);
stroke: white;
}
.prism-previewer-easing path {
fill: none;
stroke: white;
stroke-linecap: round;
stroke-width: 4;
}
.prism-previewer-easing line {
stroke: white;
stroke-opacity: 0.5;
stroke-width: 2;
}
@-webkit-keyframes prism-previewer-time {
0% {
stroke-dasharray: 0, 500;
stroke-dashoffset: 0;
}
50% {
stroke-dasharray: 100, 500;
stroke-dashoffset: 0;
}
100% {
stroke-dasharray: 0, 500;
stroke-dashoffset: -100;
}
}
@-o-keyframes prism-previewer-time {
0% {
stroke-dasharray: 0, 500;
stroke-dashoffset: 0;
}
50% {
stroke-dasharray: 100, 500;
stroke-dashoffset: 0;
}
100% {
stroke-dasharray: 0, 500;
stroke-dashoffset: -100;
}
}
@-moz-keyframes prism-previewer-time {
0% {
stroke-dasharray: 0, 500;
stroke-dashoffset: 0;
}
50% {
stroke-dasharray: 100, 500;
stroke-dashoffset: 0;
}
100% {
stroke-dasharray: 0, 500;
stroke-dashoffset: -100;
}
}
@keyframes prism-previewer-time {
0% {
stroke-dasharray: 0, 500;
stroke-dashoffset: 0;
}
50% {
stroke-dasharray: 100, 500;
stroke-dashoffset: 0;
}
100% {
stroke-dasharray: 0, 500;
stroke-dashoffset: -100;
}
}
.prism-previewer-time:before {
border-radius: 50%;
background: #fff;
}
.prism-previewer-time:after {
margin-top: 4px;
}
.prism-previewer-time svg {
width: 32px;
height: 32px;
-webkit-transform: rotate(-90deg);
-moz-transform: rotate(-90deg);
-ms-transform: rotate(-90deg);
-o-transform: rotate(-90deg);
transform: rotate(-90deg);
}
.prism-previewer-time circle {
fill: transparent;
stroke: hsl(200, 10%, 20%);
stroke-opacity: 0.9;
stroke-width: 32;
stroke-dasharray: 0, 500;
stroke-dashoffset: 0;
-webkit-animation: prism-previewer-time linear infinite 3s;
-moz-animation: prism-previewer-time linear infinite 3s;
-o-animation: prism-previewer-time linear infinite 3s;
animation: prism-previewer-time linear infinite 3s;
}

268
extension/dep/prism.js Normal file

File diff suppressed because one or more lines are too long

View File

@ -54,14 +54,29 @@ web.createElement = (html) => {
.join(' ');
return template.content.firstElementChild;
};
web.htmlEscape = (str) =>
web.escapeHtml = (str) =>
str
.replace(/&/g, '&amp;')
.replace(/&(?![^\s]+;)/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/'/g, '&#39;')
.replace(/"/g, '&quot;');
// why a tagged template? because it syntax highlights
// https://marketplace.visualstudio.com/items?itemName=bierner.lit-html
web.html = (html, ...templates) => html.map((str) => str + (templates.shift() || '')).join('');
web.Prism = async () => {
try {
return Prism;
} catch {
await import('./dep/prism.js');
Prism.manual = true;
web.loadStyleset('./dep/prism.css');
}
return Prism;
};
/**
* @param {string} sheet
*/
@ -379,8 +394,12 @@ registry.errors = async (callback = () => {}) => {
export const markdown = new markdownit({
linkify: true,
highlight(...args) {
console.log(args);
return '';
},
highlight: (str, lang) =>
web.html`<pre${lang ? ` class="language-${lang}"` : ''}><code>${web.escapeHtml(
str
)}</code></pre>`,
});
markdown.renderer.rules.code_block = (tokens, idx, options, env, slf) =>
web.html`<pre${slf.renderAttrs(tokens[idx])}><code>${web.escapeHtml(
tokens[idx].content
)}</code></pre>\n`;

View File

@ -1,3 +1,10 @@
```js
const check = (prop, value, condition) =>
Promise.resolve(condition ? value : err(`invalid ${prop} ${JSON.stringify(value)}`)),
validation = await registry.validate(mod, err, check);
if (validation.every((condition) => condition !== ERROR)) registry._list.push(mod);
```
# markdown tester
## table
@ -14,25 +21,21 @@
# Markdown: Syntax
- [Overview](#overview)
- [Philosophy](#philosophy)
- [Inline HTML](#html)
- [Automatic Escaping for Special Characters](#autoescape)
- [Block Elements](#block)
- [Paragraphs and Line Breaks](#p)
- [Headers](#header)
- [Blockquotes](#blockquote)
- [Lists](#list)
- [Code Blocks](#precode)
- [Horizontal Rules](#hr)
- [Span Elements](#span)
- [Links](#link)
- [Emphasis](#em)
- [Code](#code)
- [Images](#img)
- [Miscellaneous](#misc)
- [Backslash Escapes](#backslash)
- [Automatic Links](#autolink)
- [markdown tester](#markdown-tester)
- [table](#table)
- [Markdown: Syntax](#markdown-syntax)
- [Overview](#overview)
- [Philosophy](#philosophy)
- [Block Elements](#block-elements)
- [Paragraphs and Line Breaks](#paragraphs-and-line-breaks)
- [Headers](#headers)
- [Blockquotes](#blockquotes)
- [Lists](#lists)
- [Code Blocks](#code-blocks)
- [Span Elements](#span-elements)
- [Links](#links)
- [Emphasis](#emphasis)
- [Code](#code)
**Note:** This document is itself written using Markdown; you
can [see the source for it by adding '.text' to the URL](/projects/markdown/syntax.text).
@ -267,9 +270,9 @@ easy to include example HTML source code using Markdown -- just paste
it and indent it, and Markdown will handle the hassle of encoding the
ampersands and angle brackets. For example, this:
<div class="footer">
&copy; 2004 Foo Corporation
</div>
```html
<div class="footer">&copy; 2004 Foo Corporation</div>
```
Regular Markdown syntax is not processed within code blocks. E.g.,
asterisks are just literal asterisks within a code block. This means

View File

@ -6,6 +6,7 @@
.enhancer--sidebarMenuTrigger {
user-select: none;
-webkit-user-select: none;
transition: background 20ms ease-in 0s;
cursor: pointer;
}

View File

@ -8,6 +8,7 @@
box-sizing: border-box;
word-break: break-word;
text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
font-family: var(--theme--font_sans);
color: var(--theme--text);
}
@ -40,7 +41,7 @@ header h1 a:not([data-active]) {
text-decoration: none;
}
main section[data-container] {
[data-container] {
display: grid;
grid-gap: 1.25em;
grid-template-columns: 1fr;
@ -48,58 +49,55 @@ main section[data-container] {
transition: opacity 200ms ease-out;
}
@media (min-width: 550px) {
main section[data-container] {
[data-container] {
grid-template-columns: 1fr 1fr;
}
main section[data-container='mod'] > .documentation--buttons {
[data-container='mod'] > .documentation--buttons {
grid-column: span 2;
}
}
@media (min-width: 850px) {
main section[data-container] {
[data-container] {
grid-template-columns: 1fr 1fr 1fr;
}
main section[data-container='mod'] > .documentation--buttons {
[data-container='mod'] > .documentation--buttons {
grid-column: span 3;
}
main section[data-container='mod'] > .documentation--body {
[data-container='mod'] > .documentation--body {
grid-column: span 2;
}
}
@media (min-width: 1350px) {
main section[data-container] {
[data-container] {
grid-template-columns: 1fr 1fr 1fr 1fr;
}
main section[data-container='mod'] > .documentation--buttons {
[data-container='mod'] > .documentation--buttons {
grid-column: span 4;
}
main section[data-container='mod'] > .documentation--body {
[data-container='mod'] > .documentation--body {
grid-column: span 3;
}
}
@media (min-width: 2050px) {
main section[data-container] {
[data-container] {
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
}
main section[data-container='mod'] > .documentation--buttons {
[data-container='mod'] > .documentation--buttons {
grid-column: span 5;
}
main section[data-container='mod'] > .documentation--body {
[data-container='mod'] > .documentation--body {
grid-column: span 4;
}
}
main section[data-container] article {
[data-container] article {
border-radius: 5px;
box-shadow: rgb(0 0 0 / 10%) 0px 20px 25px -5px, rgb(0 0 0 / 4%) 0px 10px 10px -5px;
border: 1px solid var(--theme--divider);
background: var(--theme--page);
}
main section[data-container] article img {
[data-container] article img {
max-width: 100%;
}
main section[data-container] article > div {
padding: 1rem;
}
.documentation--buttons,
.library--expand {
@ -322,7 +320,11 @@ main section[data-container] article > div {
padding-bottom: 0.25rem;
}
main section[data-container='mod'] .library--card,
.library--card {
padding: 1rem;
}
[data-container='mod'] .library--card,
.documentation--body {
max-height: calc(100vh - 10rem);
overflow: auto;

View File

@ -2,13 +2,12 @@
<html lang="en" style="opacity: 0">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>notion-enhancer</title>
</head>
<body>
<header>
<p><img width="24" src="../../icons/colour.svg" /></p>
<p><img alt="" width="24" src="../../icons/colour.svg" /></p>
<h1><a href="?view=library" data-target="library">library</a></h1>
<h1><a href="?view=alerts" data-target="alerts">alerts</a></h1>
<h1><a href="https://github.com/notion-enhancer/extension">github</a></h1>

View File

@ -14,50 +14,45 @@ for (let mod of await registry.get()) {
}
}
// why a tagged template? because it syntax highlights
// https://marketplace.visualstudio.com/items?itemName=bierner.lit-html
const html = (html, ...templates) =>
html.map((str) => str + (templates.shift() || '')).join('');
const components = {};
components.card = {
preview: ({ preview = '' }) =>
web.createElement(html`<img
web.createElement(web.html`<img
alt=""
class="library--preview"
src="${web.htmlEscape(preview)}"
src="${web.escapeHtml(preview)}"
/>`),
name: ({ name, id, version }) =>
web.createElement(html`<label
for="enable--${web.htmlEscape(id)}"
web.createElement(web.html`<label
for="enable--${web.escapeHtml(id)}"
class="library--title library--toggle_label"
>
<input type="checkbox" id="enable--${web.htmlEscape(id)}" />
<input type="checkbox" id="enable--${web.escapeHtml(id)}" />
<h2>
<span>
${web.htmlEscape(name)}
<span class="library--version">v${web.htmlEscape(version)}</span>
${web.escapeHtml(name)}
<span class="library--version">v${web.escapeHtml(version)}</span>
</span>
<span class="library--toggle"></span>
</h2>
</label>`),
tags: ({ tags = [] }) =>
web.createElement(html`<ul class="library--tags">
${tags.map((tag) => html`<li>#${web.htmlEscape(tag)}</li>`).join('')}
web.createElement(web.html`<ul class="library--tags">
${tags.map((tag) => web.html`<li>#${web.escapeHtml(tag)}</li>`).join('')}
</ul>`),
description: ({ description }) =>
web.createElement(
html`<p class="library--description">${markdown.renderInline(description)}</p>`
web.html`<p class="library--description">${markdown.renderInline(description)}</p>`
),
authors: ({ authors }) =>
web.createElement(html`<ul class="library--authors">
web.createElement(web.html`<ul class="library--authors">
${authors
.map(
(author) =>
html`<li>
<a href="${web.htmlEscape(author.url)}">
<img src="${web.htmlEscape(author.icon)}" />
<span>${web.htmlEscape(author.name)}</span>
web.html`<li>
<a href="${web.escapeHtml(author.url)}">
<img alt="" src="${web.escapeHtml(author.icon)}" />
<span>${web.escapeHtml(author.name)}</span>
</a>
</li>`
)
@ -65,16 +60,16 @@ components.card = {
</ul>`),
expand: async ({ id }) =>
web.createElement(
html`<p class="library--expand">
<a href="?view=mod&id=${web.htmlEscape(id)}">
web.html`<p class="library--expand">
<a href="?view=mod&id=${web.escapeHtml(id)}">
<span>${await fs.getText('icons/fontawesome/long-arrow-alt-right.svg')}</span>
<span>settings & documentation</span>
</a>
</p>`
),
async _generate(mod) {
const card = web.createElement(html`<article class="library--card"></article>`),
body = web.createElement(html`<div></div>`);
const card = web.createElement(web.html`<article class="library--card"></article>`),
body = web.createElement(web.html`<div></div>`);
card.append(this.preview(mod));
body.append(this.name(mod));
body.append(this.tags(mod));
@ -87,36 +82,38 @@ components.card = {
};
components.options = {
toggle: (id, { key, label, value }) =>
web.createElement(html`<label
for="toggle--${web.htmlEscape(`${id}.${key}`)}"
web.createElement(web.html`<label
for="toggle--${web.escapeHtml(`${id}.${key}`)}"
class="library--toggle_label"
>
<input type="checkbox" id="toggle--${web.htmlEscape(`${id}.${key}`)}" />
<input type="checkbox" id="toggle--${web.escapeHtml(`${id}.${key}`)}" />
<p><span>${label}</span><span class="library--toggle"></span></p
></label>`),
select: async (id, { key, label, values }) =>
web.createElement(html`<label
for="select--${web.htmlEscape(`${id}.${key}`)}"
web.createElement(web.html`<label
for="select--${web.escapeHtml(`${id}.${key}`)}"
class="library--select_label"
>
<p>${label}</p>
<p class="library--select">
<span> ${await fs.getText('icons/fontawesome/caret-down.svg')}</span>
<select id="select--${web.htmlEscape(`${id}.${key}`)}">
<select id="select--${web.escapeHtml(`${id}.${key}`)}">
${values.map(
(value) =>
html`<option value="${web.htmlEscape(value)}">${web.htmlEscape(value)}</option>`
web.html`<option value="${web.escapeHtml(value)}">${web.escapeHtml(
value
)}</option>`
)}
</select>
</p>
</label>`),
text(id, { key, label, value }) {
const opt = web.createElement(html`<label
for="text--${web.htmlEscape(`${id}.${key}`)}"
const opt = web.createElement(web.html`<label
for="text--${web.escapeHtml(`${id}.${key}`)}"
class="library--text_label"
>
<p>${label}</p>
<textarea id="text--${web.htmlEscape(`${id}.${key}`)}" rows="1"></textarea>
<textarea id="text--${web.escapeHtml(`${id}.${key}`)}" rows="1"></textarea>
</label>`);
opt.querySelector('textarea').addEventListener('input', (ev) => {
ev.target.style.removeProperty('--txt--scroll-height');
@ -125,29 +122,29 @@ components.options = {
return opt;
},
number: (id, { key, label, value }) =>
web.createElement(html`<label
for="number--${web.htmlEscape(`${id}.${key}`)}"
web.createElement(web.html`<label
for="number--${web.escapeHtml(`${id}.${key}`)}"
class="library--number_label"
>
<p>${web.htmlEscape(label)}</p>
<input id="number--${web.htmlEscape(`${id}.${key}`)}" type="number" />
<p>${web.escapeHtml(label)}</p>
<input id="number--${web.escapeHtml(`${id}.${key}`)}" type="number" />
</label>`),
async file(id, { key, label, extensions }) {
const opt = web.createElement(html`<label
for="file--${web.htmlEscape(`${id}.${key}`)}"
const opt = web.createElement(web.html`<label
for="file--${web.escapeHtml(`${id}.${key}`)}"
class="library--file_label"
>
<input
type="file"
id="file--${web.htmlEscape(`${id}.${key}`)}"
${web.htmlEscape(
id="file--${web.escapeHtml(`${id}.${key}`)}"
${web.escapeHtml(
extensions && extensions.length
? ` accept="${web.htmlEscape(extensions.join(','))}"`
? ` accept="${web.escapeHtml(extensions.join(','))}"`
: ''
)}
/>
<p>${web.htmlEscape(label)}</p>
<p>${web.escapeHtml(label)}</p>
<p class="library--file">
<span>${await fs.getText('icons/fontawesome/file.svg')}</span>
<span class="library--file_path">choose file...</span>
@ -162,7 +159,7 @@ components.options = {
const card = await components.card._generate(mod);
card.querySelector('.library--expand').remove();
if (mod.options && mod.options.length) {
const options = web.createElement(html`<div class="library--options"></div>`),
const options = web.createElement(web.html`<div class="library--options"></div>`),
inputs = await Promise.all(mod.options.map((opt) => this[opt.type](mod.id, opt)));
inputs.forEach((opt) => options.append(opt));
card.append(options);
@ -172,7 +169,7 @@ components.options = {
};
components.documentation = {
buttons: async ({ _dir }) =>
web.createElement(html`<p class="documentation--buttons">
web.createElement(web.html`<p class="documentation--buttons">
<a href="?view=library">
<span>${await fs.getText('icons/fontawesome/long-arrow-alt-left.svg')}</span>
<span>back to library</span>
@ -186,12 +183,17 @@ components.documentation = {
<span>view source code</span>
</a>
</p>`),
readme: async (mod) =>
web.createElement(html`<article class="documentation--body">
${(await fs.isFile(`repo/${mod._dir}/README.md`))
? markdown.render(await fs.getText(`repo/${mod._dir}/README.md`))
: ''}
</article>`),
readme: async (mod) => {
const readme = web.createElement(web.html`<article class="documentation--body">
${
(await fs.isFile(`repo/${mod._dir}/README.md`))
? markdown.render(await fs.getText(`repo/${mod._dir}/README.md`))
: ''
}
</article>`);
(await web.Prism()).highlightAllUnder(readme);
return readme;
},
};
const views = {
$container: document.querySelector('[data-container]'),
@ -204,10 +206,14 @@ const views = {
i++;
} while (anchor.nodeName !== 'A');
if (location.search !== anchor.getAttribute('href')) {
window.history.pushState({}, '', anchor.href);
window.history.pushState({ search: anchor.href }, '', anchor.href);
this._load();
}
},
_navigator(event) {
event.preventDefault();
console.log(event);
},
_reset() {
document
.querySelectorAll('a[href^="?"]')
@ -278,8 +284,11 @@ const views = {
},
};
views._router = views._router.bind(views);
views._navigator = views._navigator.bind(views);
views._load();
window.addEventListener('popstate', (ev) => views._load());
window.addEventListener('popstate', (ev) => {
if (ev.state) views._load();
});
function theme() {
chrome.storage.local.get(['notion.theme'], (result) => {