2020-07-15 21:30:37 +00:00
|
|
|
(() => {
|
|
|
|
let count = 1;
|
|
|
|
|
|
|
|
if (!window.$docsify) {
|
|
|
|
throw new Error('Docsify must be loaded before installing this plugin.');
|
|
|
|
}
|
|
|
|
|
|
|
|
function runScript(script) {
|
|
|
|
const newScript = document.createElement('script');
|
2020-10-06 12:17:33 +00:00
|
|
|
|
|
|
|
if (script.type === 'module') {
|
|
|
|
newScript.type = 'module';
|
|
|
|
newScript.textContent = script.innerHTML;
|
|
|
|
} else {
|
|
|
|
newScript.appendChild(document.createTextNode(`(() => { ${script.innerHTML} })();`));
|
|
|
|
}
|
|
|
|
|
2020-07-15 21:30:37 +00:00
|
|
|
script.parentNode.replaceChild(newScript, script);
|
|
|
|
}
|
|
|
|
|
|
|
|
function wrap(el, wrapper) {
|
|
|
|
el.parentNode.insertBefore(wrapper, el);
|
|
|
|
wrapper.appendChild(el);
|
|
|
|
}
|
|
|
|
|
|
|
|
window.$docsify.plugins.push((hook, vm) => {
|
|
|
|
// Convert code blocks to previews
|
|
|
|
hook.afterEach(function (html, next) {
|
|
|
|
const domParser = new DOMParser();
|
|
|
|
const doc = domParser.parseFromString(html, 'text/html');
|
|
|
|
|
|
|
|
[...doc.querySelectorAll('code[class^="lang-"]')].map(code => {
|
|
|
|
if (code.classList.contains('preview')) {
|
|
|
|
const pre = code.closest('pre');
|
|
|
|
const preId = `code-block-preview-${count}`;
|
|
|
|
const toggleId = `code-block-toggle-${count}`;
|
|
|
|
|
|
|
|
pre.id = preId;
|
|
|
|
pre.classList.add('code-block__source');
|
|
|
|
pre.setAttribute('data-lang', pre.getAttribute('data-lang').replace(/ preview$/, ''));
|
2020-08-20 13:12:13 +00:00
|
|
|
pre.setAttribute('aria-labelledby', toggleId);
|
2020-07-15 21:30:37 +00:00
|
|
|
|
2021-03-24 15:26:20 +00:00
|
|
|
const codeBlock = `
|
|
|
|
<div class="code-block">
|
|
|
|
<div class="code-block__preview">
|
|
|
|
${code.textContent}
|
|
|
|
<div class="code-block__resizer" tabindex="0">
|
|
|
|
<sl-icon name="grip-vertical"></sl-icon>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
${pre.outerHTML}
|
|
|
|
|
|
|
|
<div class="code-block__toggle" aria-expanded="false" aria-controls="${preId}">
|
|
|
|
Source
|
|
|
|
<svg
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
fill="none"
|
|
|
|
stroke="currentColor"
|
|
|
|
stroke-width="2"
|
|
|
|
stroke-linecap="round"
|
|
|
|
stroke-linejoin="round"
|
|
|
|
>
|
|
|
|
<polyline points="6 9 12 15 18 9"></polyline>
|
|
|
|
</svg>
|
|
|
|
</div>
|
|
|
|
</div>
|
2020-07-15 21:30:37 +00:00
|
|
|
`;
|
|
|
|
|
2021-03-24 15:26:20 +00:00
|
|
|
pre.replaceWith(domParser.parseFromString(codeBlock, 'text/html').body);
|
2020-07-15 21:30:37 +00:00
|
|
|
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
next(doc.body.innerHTML);
|
|
|
|
});
|
|
|
|
|
|
|
|
// After the page is done loading, force scripts in previews to execute
|
|
|
|
hook.doneEach(() => {
|
|
|
|
[...document.querySelectorAll('.code-block__preview script')].map(script => runScript(script));
|
|
|
|
});
|
|
|
|
|
|
|
|
// Horizontal resizing
|
|
|
|
hook.doneEach(() => {
|
2020-08-31 20:46:22 +00:00
|
|
|
[...document.querySelectorAll('.code-block__preview')].map(preview => {
|
|
|
|
const resizer = preview.querySelector('.code-block__resizer');
|
2020-07-15 21:30:37 +00:00
|
|
|
let startX;
|
|
|
|
let startWidth;
|
|
|
|
|
2020-08-31 20:46:22 +00:00
|
|
|
const dragStart = event => {
|
2020-09-04 21:37:50 +00:00
|
|
|
startX = event.changedTouches ? event.changedTouches[0].pageX : event.clientX;
|
2020-08-31 20:46:22 +00:00
|
|
|
startWidth = parseInt(document.defaultView.getComputedStyle(preview).width, 10);
|
|
|
|
preview.classList.add('code-block__preview--dragging');
|
2020-09-04 21:37:50 +00:00
|
|
|
event.preventDefault();
|
|
|
|
resizer.focus();
|
2020-08-31 20:46:22 +00:00
|
|
|
document.documentElement.addEventListener('mousemove', dragMove, false);
|
2020-09-04 21:37:50 +00:00
|
|
|
document.documentElement.addEventListener('touchmove', dragMove, false);
|
2020-08-31 20:46:22 +00:00
|
|
|
document.documentElement.addEventListener('mouseup', dragStop, false);
|
2020-09-04 21:37:50 +00:00
|
|
|
document.documentElement.addEventListener('touchend', dragStop, false);
|
2020-07-15 21:30:37 +00:00
|
|
|
};
|
|
|
|
|
2020-08-31 20:46:22 +00:00
|
|
|
const dragMove = event => {
|
2020-09-04 21:37:50 +00:00
|
|
|
setWidth(startWidth + (event.changedTouches ? event.changedTouches[0].pageX : event.pageX) - startX);
|
2020-07-15 21:30:37 +00:00
|
|
|
};
|
|
|
|
|
2020-08-31 20:46:22 +00:00
|
|
|
const dragStop = event => {
|
|
|
|
preview.classList.remove('code-block__preview--dragging');
|
|
|
|
document.documentElement.removeEventListener('mousemove', dragMove, false);
|
2020-09-04 21:37:50 +00:00
|
|
|
document.documentElement.removeEventListener('touchmove', dragMove, false);
|
2020-08-31 20:46:22 +00:00
|
|
|
document.documentElement.removeEventListener('mouseup', dragStop, false);
|
2020-09-04 21:37:50 +00:00
|
|
|
document.documentElement.removeEventListener('touchend', dragStop, false);
|
2020-07-15 21:30:37 +00:00
|
|
|
};
|
|
|
|
|
2020-08-26 13:09:04 +00:00
|
|
|
const handleKeyDown = event => {
|
|
|
|
if (['ArrowLeft', 'ArrowRight', 'Home', 'End'].includes(event.key)) {
|
2020-08-31 20:46:22 +00:00
|
|
|
const currentWidth = preview.clientWidth;
|
|
|
|
const maxWidth = preview.parentElement.clientWidth;
|
2020-08-26 13:09:04 +00:00
|
|
|
const incr = event.shiftKey ? 100 : 10;
|
|
|
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
|
|
if (event.key === 'ArrowLeft') setWidth(currentWidth - incr);
|
|
|
|
if (event.key === 'ArrowRight') setWidth(currentWidth + incr);
|
|
|
|
if (event.key === 'Home') setWidth(0);
|
|
|
|
if (event.key === 'End') setWidth(maxWidth);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-02-26 14:09:13 +00:00
|
|
|
const setWidth = width => (preview.style.width = width + 'px');
|
2020-08-26 13:09:04 +00:00
|
|
|
|
2020-08-31 20:46:22 +00:00
|
|
|
resizer.addEventListener('mousedown', dragStart);
|
2020-09-04 21:37:50 +00:00
|
|
|
resizer.addEventListener('touchstart', dragStart);
|
2020-08-26 13:09:04 +00:00
|
|
|
resizer.addEventListener('keydown', handleKeyDown);
|
2020-07-15 21:30:37 +00:00
|
|
|
}, false);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
// Expand and collapse code blocks
|
|
|
|
document.addEventListener('click', event => {
|
|
|
|
const toggle = event.target.closest('.code-block__toggle');
|
|
|
|
if (toggle) {
|
|
|
|
const codeBlock = event.target.closest('.code-block');
|
|
|
|
codeBlock.classList.toggle('code-block--expanded');
|
|
|
|
event.target.setAttribute('aria-expanded', codeBlock.classList.contains('code-block--expanded'));
|
|
|
|
}
|
|
|
|
});
|
|
|
|
})();
|