integrate jsonschema2markdown; add support for inline markdown rendering from templates

This commit is contained in:
2023-05-13 20:31:00 -07:00
parent 4061b40eb4
commit 699c018825
19 changed files with 1793 additions and 142 deletions

View File

@@ -0,0 +1,175 @@
(() => {
const animation = 'linear .5s';
const color_scheme = 'color_scheme';
const color_scheme_attr = 'data-color-scheme';
const transition_attr = 'data-color-transition-enabled';
const prefers_dark_scheme = window.matchMedia('(prefers-color-scheme: dark)');
// Make sure we set the correct starting color scheme where loading
const override = localStorage.getItem(color_scheme);
if (override) {
document.body.setAttribute(color_scheme_attr, override);
}
setTimeout(() => {
if (document.body.scrollHeight > 30000) {
console.warn('document too large, disabling color theme transition animation');
return;
}
document.body.setAttribute(transition_attr, '');
}, 50);
const size = 1.25;
const styles = `
:host {
display: contents;
}
:host .wrapper {
width: ${size}rem;
height: ${size}rem;
padding: 0.5rem;
border-radius: 100%;
cursor: pointer;
overflow: hidden;
position: relative;
}
:host .wrapper .icons {
width: ${size * 2}rem;
display: flex;
flex-direction: row;
justify-content: space-between;
transition: transform ${animation};
pointer-events: none;
}
:host .wrapper .icons[data-mode='light'] {
/* */
}
:host .wrapper .icons[data-mode='dark'] {
transform: translateX(-${size}rem);
}
:host svg.icon {
--icon-size: ${size}rem;
transition: opacity ${animation};
}
:host svg.icon.sun {
color: var(--theme-text-body);
}
:host [data-mode='dark'] svg.icon.sun {
opacity: 0;
}
:host svg.icon.moon {
color: var(--theme-text-body);
}
:host [data-mode='light'] svg.icon.moon {
opacity: 0;
}
`;
const template = `
<style>${styles}</style>
<div class="wrapper" title="Toggle Light / Dark Mode" tabindex="0" role="button" aria-pressed="false">
<div class="icons">
{{{ icons.sun }}}
{{{ icons.moon }}}
</div>
</div>
`;
customElements.define('color-scheme-toggle-button',
class ColorSchemeToggleButton extends HTMLElement {
#wrapper = null;
#icons = null;
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = template;
this.#wrapper = this.shadowRoot.querySelector('.wrapper');
this.#icons = this.shadowRoot.querySelector('.icons');
this.update_icons();
}
connectedCallback() {
this.addEventListener('click', this.onSelect);
this.addEventListener('keydown', this.onKeydown);
this.addEventListener('keyup', this.onKeyup);
}
disconnectedCallback() {
this.removeEventListener('click', this.onSelect);
this.removeEventListener('keydown', this.onKeydown);
this.removeEventListener('keyup', this.onKeyup);
}
onKeydown = (/** @type KeyboardEvent */ event) => {
if (event.keyCode === 32) {
event.preventDefault();
}
if (event.keyCode === 13) {
event.preventDefault();
this.onSelect();
}
};
onKeyup = (/** @type KeyboardEvent */ event) => {
if (event.keyCode === 32) {
event.preventDefault();
this.onSelect();
}
};
onSelect = () => {
toggle();
this.update_icons();
};
update_icons() {
const current = get_current();
this.#icons.setAttribute('data-mode', current);
this.#wrapper.setAttribute('aria-pressed', current === 'dark');
}
}
);
function get_current() {
const override = localStorage.getItem(color_scheme);
if (override) {
return override;
}
return prefers_dark_scheme.matches ? 'dark' : 'light';
}
function toggle() {
if (document.body.hasAttribute(color_scheme_attr)) {
localStorage.removeItem(color_scheme);
document.body.removeAttribute(color_scheme_attr);
}
else {
const preference = prefers_dark_scheme.matches ? 'light' : 'dark';
localStorage.setItem(color_scheme, preference);
document.body.setAttribute(color_scheme_attr, preference);
}
}
})();

View File

@@ -0,0 +1,129 @@
(() => {
const size = 1.25;
const outline_attr = 'data-show-outline';
const styles = `
:host {
display: contents;
}
:host .wrapper {
width: ${size}rem;
height: ${size}rem;
padding: 0.5rem;
border-radius: 100%;
cursor: pointer;
overflow: hidden;
position: relative;
}
:host svg.icon {
--icon-size: ${size}rem;
color: var(--theme-text-body);
position: absolute;
top: 0.5rem;
left: 0.5rem;
pointer-events: none;
transition: color linear .5s;
}
`;
const template = `
<style>${styles}</style>
<div class="wrapper" title="Toggle Outline" tabindex="0" role="button" aria-pressed="false">
{{{ icons.list }}}
</div>
<nav id="outline-panel" aria-hidden="true">
<!-- todo: i18n -->
<h2>Outline</h2>
</nav>
`;
customElements.define('outline-button',
class OutlineButton extends HTMLElement {
#wrapper = null;
#outline = null;
#outline_built = false;
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = template;
this.#wrapper = this.shadowRoot.querySelector('.wrapper');
this.#outline = this.shadowRoot.querySelector('#outline-panel');
this.#outline.parentNode.removeChild(this.#outline);
document.body.appendChild(this.#outline);
}
connectedCallback() {
this.addEventListener('click', this.onSelect);
this.addEventListener('keydown', this.onKeydown);
this.addEventListener('keyup', this.onKeyup);
}
disconnectedCallback() {
this.removeEventListener('click', this.onSelect);
this.removeEventListener('keydown', this.onKeydown);
this.removeEventListener('keyup', this.onKeyup);
}
onKeydown = (/** @type KeyboardEvent */ event) => {
if (event.keyCode === 32) {
event.preventDefault();
}
if (event.keyCode === 13) {
event.preventDefault();
this.onSelect();
}
};
onKeyup = (/** @type KeyboardEvent */ event) => {
if (event.keyCode === 32) {
event.preventDefault();
this.onSelect();
}
};
onSelect = () => {
if (! this.#outline_built) {
const root_selector = this.getAttribute('content-root');
this.#outline.innerHTML += `<ol>${build_outline(root_selector)}</ol>`;
this.#outline_built = true;
}
if (document.body.hasAttribute(outline_attr)) {
document.body.removeAttribute(outline_attr);
this.#outline.setAttribute('aria-hidden', 'true');
this.#wrapper.setAttribute('aria-pressed', 'false');
}
else {
document.body.setAttribute(outline_attr, '');
this.#outline.removeAttribute('aria-hidden');
this.#wrapper.setAttribute('aria-pressed', 'true');
}
};
}
);
function build_outline(root_selector) {
const root = document.querySelector(root_selector);
const headings = root.querySelectorAll('h1, h2, h3, h4, h5, h6');
const outline = [ ];
for (const heading of headings) {
outline.push(`
<li data-depth="${heading.tagName.toLowerCase()}">
<a href="#${heading.id}">${heading.innerText}</a>
</li>
`);
}
return outline.join('');
}
})();

View File

@@ -0,0 +1,105 @@
(() => {
const template = `
<style>
ol {
list-style: none;
padding: 0;
}
li[data-depth='h1'] {
font-size: 1.2rem;
font-weight: 700;
margin-inline-start: 1rem;
}
li[data-depth='h2'] {
font-size: 1.1rem;
font-weight: 600;
margin-inline-start: 2rem;
}
li[data-depth='h3'] {
margin-inline-start: 3rem;
}
li[data-depth='h4'] {
font-size: 0.9rem;
margin-inline-start: 4rem;
}
li[data-depth='h5'] {
font-size: 0.9rem;
margin-inline-start: 5rem;
}
li[data-depth='h6'] {
font-size: 0.9rem;
margin-inline-start: 6rem;
}
a {
color: var(--theme-text-link);
}
a:active,
a:hover,
a:focus {
color: var(--theme-text-link-active);
}
a:visited {
color: var(--theme-text-link-visited);
}
</style>
<nav id="outline-inline" aria-hidden="true">
<em>Outline will render when the page has loaded...</em>
</nav>
`;
customElements.define('outline-inline',
class OutlineButton extends HTMLElement {
#outline = null;
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = template;
this.#outline = this.shadowRoot.querySelector('#outline-inline');
}
connectedCallback() {
if (document.readyState === 'complete') {
this.#render();
}
window.addEventListener('DOMContentLoaded', () => {
this.#render();
});
}
#render() {
const root_selector = this.getAttribute('content-root');
const outline = build_outline(root_selector);
this.#outline.innerHTML = `<ol>${outline}</ol>`;
}
}
);
function build_outline(root_selector) {
const root = document.querySelector(root_selector);
const headings = root.querySelectorAll('h1, h2, h3, h4, h5, h6');
const outline = [ ];
for (const heading of headings) {
outline.push(`
<li data-depth="${heading.tagName.toLowerCase()}">
<a href="#${heading.id}">${heading.innerText}</a>
</li>
`);
}
return outline.join('');
}
})();

468
extras/prism.css Normal file
View File

@@ -0,0 +1,468 @@
/* PrismJS 1.24.1
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+bash+http+jsx+tsx+typescript&plugins=line-highlight+line-numbers+treeview */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*
* ---
* Modified for use with customizable color variables and light/dark theming
*/
code[class*="language-"],
pre[class*="language-"] {
color: var(--theme-code-normal);
background: none;
text-shadow: 0 1px var(--theme-code-shadow);
font-family: var(--font-monospace);
font-weight: 400;
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: var(--theme-code-selection);
}
pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
code[class*="language-"]::selection, code[class*="language-"] ::selection {
text-shadow: none;
background: var(--theme-code-selection);
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
overflow: auto;
}
:not(pre) > code[class*="language-"],
pre[class*="language-"] {
background: var(--theme-code-background);
}
/* Inline code */
:not(pre) > code[class*="language-"] {
padding: .1rem;
border-radius: .3rem;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: var(--theme-code-comment);
}
.token.punctuation {
color: var(--theme-code-punc);
}
.token.namespace {
opacity: .7;
}
.token.constant,
.token.symbol,
.token.deleted {
color: var(--theme-code-const-literal);
}
.token.tag {
color: var(--theme-code-tag);
}
.token.number {
color: var(--theme-code-number-literal);
}
.token.boolean {
color: var(--theme-code-boolean-literal);
}
.token.selector,
.token.attr-name {
color: var(--theme-code-attr-name);
}
.token.builtin {
color: var(--theme-code-builtin);
}
.token.string,
.token.char,
.token.inserted {
color: var(--theme-code-string);
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: var(--theme-code-operator);
}
.token.atrule,
.token.attr-value,
.token.keyword,
.token.request-line .token.method,
.token.request-line .token.http-version,
.token.response-status .token.http-version {
color: var(--theme-code-keyword);
}
.token.function {
color: var(--theme-code-func-name);
}
.token.class-name {
color: var(--theme-code-class-name);
}
.token.regex,
.token.important {
color: var(--theme-code-regex-important);
}
.token.property,
.token.variable {
color: var(--theme-code-variable);
}
.token.important,
.token.bold {
font-weight: 700;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}
pre[data-line] {
position: relative;
padding: 1rem 0 1rem 3rem;
}
.line-highlight {
position: absolute;
left: 0;
right: 0;
padding: inherit 0;
margin-top: 1rem;
background: var(--theme-code-line-highlight);
pointer-events: none;
line-height: inherit;
white-space: pre;
}
@media print {
.line-highlight {
/*
* This will prevent browsers from replacing the background color with white.
* It's necessary because the element is layered on top of the displayed code.
*/
-webkit-print-color-adjust: exact;
color-adjust: exact;
}
}
.line-highlight:before,
.line-highlight[data-end]:after {
content: attr(data-start);
position: absolute;
top: .4rem;
left: .6rem;
min-width: 1rem;
padding: 0 .5rem;
background: var(--theme-code-line-highlight);
font: bold 65%/1.5 sans-serif;
text-align: center;
vertical-align: .3rem;
border-radius: 999px;
text-shadow: none;
box-shadow: 0 1px white;
}
.line-highlight[data-end]:after {
content: attr(data-end);
top: auto;
bottom: .4rem;
}
.line-numbers .line-highlight:before,
.line-numbers .line-highlight:after {
content: none;
}
pre[id].linkable-line-numbers span.line-numbers-rows {
pointer-events: all;
}
pre[id].linkable-line-numbers span.line-numbers-rows > span:before {
cursor: pointer;
}
pre[id].linkable-line-numbers span.line-numbers-rows > span:hover:before {
/* TODO: Do something with this color */
background-color: rgba(128, 128, 128, .2);
}
pre[class*="language-"].line-numbers {
position: relative;
padding-left: 3.8rem;
counter-reset: linenumber;
}
pre[class*="language-"].line-numbers > code {
position: relative;
white-space: inherit;
}
.line-numbers .line-numbers-rows {
position: absolute;
pointer-events: none;
top: 0;
font-size: 100%;
left: -3.8rem;
width: 3rem; /* works for line-numbers below 1000 lines */
letter-spacing: -1px;
border-right: 1px solid var(--theme-code-gutter-divider);
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.line-numbers-rows > span {
display: block;
counter-increment: linenumber;
}
.line-numbers-rows > span:before {
content: counter(linenumber);
color: var(--theme-code-line-number);
display: block;
padding-right: 0.8rem;
text-align: right;
}
.token.treeview-part .entry-line {
position: relative;
text-indent: -99rem;
display: inline-block;
vertical-align: top;
width: 1.2rem;
}
.token.treeview-part .entry-line:before,
.token.treeview-part .line-h:after {
content: "";
position: absolute;
top: 0;
left: 50%;
width: 50%;
height: 100%;
}
/* TODO: Do something with these colors */
.token.treeview-part .line-h:before,
.token.treeview-part .line-v:before {
border-left: 1px solid #ccc;
}
.token.treeview-part .line-v-last:before {
height: 50%;
border-left: 1px solid #ccc;
border-bottom: 1px solid #ccc;
}
.token.treeview-part .line-h:after {
height: 50%;
border-bottom: 1px solid #ccc;
}
.token.treeview-part .entry-name {
position: relative;
display: inline-block;
vertical-align: top;
}
.token.treeview-part .entry-name.dotfile {
opacity: 0.5;
}
/* @GENERATED-FONT */
@font-face {
font-family: "PrismTreeview";
/**
* This font is generated from the .svg files in the `icons` folder. See the `treeviewIconFont` function in
* `gulpfile.js/index.js` for more information.
*
* Use the following escape sequences to refer to a specific icon:
*
* - \ea01 file
* - \ea02 folder
* - \ea03 image
* - \ea04 audio
* - \ea05 video
* - \ea06 text
* - \ea07 code
* - \ea08 archive
* - \ea09 pdf
* - \ea0a excel
* - \ea0b powerpoint
* - \ea0c word
*/
src: url("data:application/font-woff;base64,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")
format("woff");
}
.token.treeview-part .entry-name:before {
content: "\ea01";
font-family: "PrismTreeview";
font-size: inherit;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
width: 2.5ex;
display: inline-block;
}
.token.treeview-part .entry-name.dir:before {
content: "\ea02";
}
.token.treeview-part .entry-name.ext-bmp:before,
.token.treeview-part .entry-name.ext-eps:before,
.token.treeview-part .entry-name.ext-gif:before,
.token.treeview-part .entry-name.ext-jpe:before,
.token.treeview-part .entry-name.ext-jpg:before,
.token.treeview-part .entry-name.ext-jpeg:before,
.token.treeview-part .entry-name.ext-png:before,
.token.treeview-part .entry-name.ext-svg:before,
.token.treeview-part .entry-name.ext-tiff:before {
content: "\ea03";
}
.token.treeview-part .entry-name.ext-cfg:before,
.token.treeview-part .entry-name.ext-conf:before,
.token.treeview-part .entry-name.ext-config:before,
.token.treeview-part .entry-name.ext-csv:before,
.token.treeview-part .entry-name.ext-ini:before,
.token.treeview-part .entry-name.ext-log:before,
.token.treeview-part .entry-name.ext-md:before,
.token.treeview-part .entry-name.ext-nfo:before,
.token.treeview-part .entry-name.ext-txt:before {
content: "\ea06";
}
.token.treeview-part .entry-name.ext-asp:before,
.token.treeview-part .entry-name.ext-aspx:before,
.token.treeview-part .entry-name.ext-c:before,
.token.treeview-part .entry-name.ext-cc:before,
.token.treeview-part .entry-name.ext-cpp:before,
.token.treeview-part .entry-name.ext-cs:before,
.token.treeview-part .entry-name.ext-css:before,
.token.treeview-part .entry-name.ext-h:before,
.token.treeview-part .entry-name.ext-hh:before,
.token.treeview-part .entry-name.ext-htm:before,
.token.treeview-part .entry-name.ext-html:before,
.token.treeview-part .entry-name.ext-jav:before,
.token.treeview-part .entry-name.ext-java:before,
.token.treeview-part .entry-name.ext-js:before,
.token.treeview-part .entry-name.ext-php:before,
.token.treeview-part .entry-name.ext-rb:before,
.token.treeview-part .entry-name.ext-xml:before {
content: "\ea07";
}
.token.treeview-part .entry-name.ext-7z:before,
.token.treeview-part .entry-name.ext-bz:before,
.token.treeview-part .entry-name.ext-bz2:before,
.token.treeview-part .entry-name.ext-gz:before,
.token.treeview-part .entry-name.ext-rar:before,
.token.treeview-part .entry-name.ext-tar:before,
.token.treeview-part .entry-name.ext-tgz:before,
.token.treeview-part .entry-name.ext-zip:before {
content: "\ea08";
}
.token.treeview-part .entry-name.ext-aac:before,
.token.treeview-part .entry-name.ext-au:before,
.token.treeview-part .entry-name.ext-cda:before,
.token.treeview-part .entry-name.ext-flac:before,
.token.treeview-part .entry-name.ext-mp3:before,
.token.treeview-part .entry-name.ext-oga:before,
.token.treeview-part .entry-name.ext-ogg:before,
.token.treeview-part .entry-name.ext-wav:before,
.token.treeview-part .entry-name.ext-wma:before {
content: "\ea04";
}
.token.treeview-part .entry-name.ext-avi:before,
.token.treeview-part .entry-name.ext-flv:before,
.token.treeview-part .entry-name.ext-mkv:before,
.token.treeview-part .entry-name.ext-mov:before,
.token.treeview-part .entry-name.ext-mp4:before,
.token.treeview-part .entry-name.ext-mpeg:before,
.token.treeview-part .entry-name.ext-mpg:before,
.token.treeview-part .entry-name.ext-ogv:before,
.token.treeview-part .entry-name.ext-webm:before {
content: "\ea05";
}
.token.treeview-part .entry-name.ext-pdf:before {
content: "\ea09";
}
.token.treeview-part .entry-name.ext-xls:before,
.token.treeview-part .entry-name.ext-xlsx:before {
content: "\ea0a";
}
.token.treeview-part .entry-name.ext-doc:before,
.token.treeview-part .entry-name.ext-docm:before,
.token.treeview-part .entry-name.ext-docx:before {
content: "\ea0c";
}
.token.treeview-part .entry-name.ext-pps:before,
.token.treeview-part .entry-name.ext-ppt:before,
.token.treeview-part .entry-name.ext-pptx:before {
content: "\ea0b";
}