mirror of
https://github.com/cheeaun/phanpy.git
synced 2024-11-21 16:55:25 +03:00
Simpler code for content enhancement
Also fixed some shortcodes not converted
This commit is contained in:
parent
19074844be
commit
3e80ee03f3
3 changed files with 69 additions and 80 deletions
|
@ -475,7 +475,6 @@ a.card:hover {
|
|||
margin: 8px 0;
|
||||
overflow: auto;
|
||||
width: 100%;
|
||||
font-size: 90%;
|
||||
border: 1px solid var(--outline-color);
|
||||
background: linear-gradient(
|
||||
to bottom right,
|
||||
|
@ -484,6 +483,10 @@ a.card:hover {
|
|||
);
|
||||
}
|
||||
|
||||
.status .content p code {
|
||||
color: var(--green-color);
|
||||
}
|
||||
|
||||
/* MISC */
|
||||
|
||||
.status-aside {
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
:root {
|
||||
--blue-color: CornflowerBlue;
|
||||
--purple-color: mediumpurple;
|
||||
--green-color: MediumSeaGreen;
|
||||
--green-color: limegreen;
|
||||
--bg-color: #242526;
|
||||
--bg-faded-color: #18191a;
|
||||
--bg-blur-color: #0009;
|
||||
|
@ -187,6 +187,13 @@ select.plain {
|
|||
background-color: transparent;
|
||||
}
|
||||
|
||||
pre code,
|
||||
code {
|
||||
font-size: 95%;
|
||||
font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier,
|
||||
monospace;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
img,
|
||||
video {
|
||||
|
|
|
@ -1,97 +1,61 @@
|
|||
import emojifyText from './emojify-text';
|
||||
|
||||
const fauxDiv = document.createElement('div');
|
||||
|
||||
export default (content, opts = {}) => {
|
||||
const { emojis, postEnhanceDOM = () => {} } = opts;
|
||||
let enhancedContent = content;
|
||||
const dom = document.createElement('div');
|
||||
dom.innerHTML = enhancedContent;
|
||||
|
||||
// 1. Emojis
|
||||
if (emojis) {
|
||||
enhancedContent = emojifyText(enhancedContent, emojis);
|
||||
}
|
||||
|
||||
// 2. Add target="_blank" to all links with no target="_blank"
|
||||
// Add target="_blank" to all links with no target="_blank"
|
||||
// E.g. `note` in `account`
|
||||
const links = Array.from(dom.querySelectorAll('a:not([target="_blank"])'));
|
||||
links.forEach((link) => {
|
||||
link.setAttribute('target', '_blank');
|
||||
});
|
||||
|
||||
// 3. Code blocks
|
||||
// Check for <p> with markdown-like content "```"
|
||||
{
|
||||
const blocks = Array.from(dom.querySelectorAll('p')).filter((p) =>
|
||||
/^```[^]+```$/g.test(p.innerText.trim()),
|
||||
);
|
||||
blocks.forEach((block) => {
|
||||
const pre = document.createElement('pre');
|
||||
const code = document.createElement('code');
|
||||
const breaks = block.querySelectorAll('br');
|
||||
breaks.forEach((br) => br.replaceWith('\n'));
|
||||
code.innerHTML = block.innerText
|
||||
.trim()
|
||||
// .replace(/^```/g, '')
|
||||
// .replace(/```$/g, '')
|
||||
.replace(/^[\n\r]+/, '');
|
||||
pre.appendChild(code);
|
||||
block.replaceWith(pre);
|
||||
});
|
||||
}
|
||||
// EMOJIS
|
||||
// ======
|
||||
// Convert :shortcode: to <img />
|
||||
let textNodes = extractTextNodes(dom);
|
||||
textNodes.forEach((node) => {
|
||||
let html = node.nodeValue;
|
||||
if (emojis) {
|
||||
html = emojifyText(html, emojis);
|
||||
}
|
||||
fauxDiv.innerHTML = html;
|
||||
const nodes = Array.from(fauxDiv.childNodes);
|
||||
node.replaceWith(...nodes);
|
||||
});
|
||||
|
||||
// 4. Inline code
|
||||
{
|
||||
// Get all text nodes in the DOM
|
||||
const textNodes = [];
|
||||
const walk = document.createTreeWalker(
|
||||
dom,
|
||||
NodeFilter.SHOW_TEXT,
|
||||
null,
|
||||
false,
|
||||
);
|
||||
let node;
|
||||
while ((node = walk.nextNode())) {
|
||||
// Only get text that contains markdown-like code syntax
|
||||
if (/`[^]+`/g.test(node.nodeValue)) {
|
||||
textNodes.push(node);
|
||||
}
|
||||
// INLINE CODE
|
||||
// ===========
|
||||
// Convert `code` to <code>code</code>
|
||||
textNodes = extractTextNodes(dom);
|
||||
textNodes.forEach((node) => {
|
||||
let html = node.nodeValue;
|
||||
if (/`[^`]+`/g.test(html)) {
|
||||
html = html.replaceAll(/(`[^]+?`)/g, '<code>$1</code>');
|
||||
}
|
||||
if (textNodes.length) {
|
||||
// - Split text nodes into array of text and DOM nodes
|
||||
// - Replace markdown-like code syntax with <code> element
|
||||
// - Apply them all back to parent node
|
||||
textNodes.forEach((node) => {
|
||||
const parent = node.parentNode;
|
||||
const text = node.nodeValue;
|
||||
const nodes = [];
|
||||
let i = 0;
|
||||
let j = 0;
|
||||
let k = 0;
|
||||
while ((i = text.indexOf('`', j)) !== -1) {
|
||||
if (i > j) {
|
||||
nodes.push(document.createTextNode(text.substring(j, i)));
|
||||
}
|
||||
j = i + 1;
|
||||
if ((k = text.indexOf('`', j)) === -1) {
|
||||
k = j;
|
||||
}
|
||||
if (j < k) {
|
||||
const code = document.createElement('code');
|
||||
code.appendChild(document.createTextNode(text.substring(j, k)));
|
||||
nodes.push(document.createTextNode('`'));
|
||||
nodes.push(code);
|
||||
nodes.push(document.createTextNode('`'));
|
||||
}
|
||||
j = k + 1;
|
||||
}
|
||||
if (j < text.length) {
|
||||
nodes.push(document.createTextNode(text.substring(j)));
|
||||
}
|
||||
nodes.forEach((n) => parent.insertBefore(n, node));
|
||||
parent.removeChild(node);
|
||||
});
|
||||
}
|
||||
}
|
||||
fauxDiv.innerHTML = html;
|
||||
const nodes = Array.from(fauxDiv.childNodes);
|
||||
node.replaceWith(...nodes);
|
||||
});
|
||||
|
||||
// CODE BLOCKS
|
||||
// ===========
|
||||
// Convert ```code``` to <pre><code>code</code></pre>
|
||||
const blocks = Array.from(dom.querySelectorAll('p')).filter((p) =>
|
||||
/^```[^]+```$/g.test(p.innerText.trim()),
|
||||
);
|
||||
blocks.forEach((block) => {
|
||||
const pre = document.createElement('pre');
|
||||
// Replace <br /> with newlines
|
||||
block.querySelectorAll('br').forEach((br) => br.replaceWith('\n'));
|
||||
pre.innerHTML = `<code>${block.innerText.trim()}</code>`;
|
||||
block.replaceWith(pre);
|
||||
});
|
||||
|
||||
if (postEnhanceDOM) {
|
||||
postEnhanceDOM(dom); // mutate dom
|
||||
|
@ -101,3 +65,18 @@ export default (content, opts = {}) => {
|
|||
|
||||
return enhancedContent;
|
||||
};
|
||||
|
||||
function extractTextNodes(dom) {
|
||||
const textNodes = [];
|
||||
const walk = document.createTreeWalker(
|
||||
dom,
|
||||
NodeFilter.SHOW_TEXT,
|
||||
null,
|
||||
false,
|
||||
);
|
||||
let node;
|
||||
while ((node = walk.nextNode())) {
|
||||
textNodes.push(node);
|
||||
}
|
||||
return textNodes;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue