Skip to content

Commit

Permalink
chore: replace disable no-undef with globals whitelist - less fal…
Browse files Browse the repository at this point in the history
…se negatives

also updated tocOptions to not use JSON parse.
  • Loading branch information
TrebledJ committed Sep 22, 2024
1 parent 252dbab commit 83a484e
Show file tree
Hide file tree
Showing 14 changed files with 255 additions and 165 deletions.
2 changes: 2 additions & 0 deletions .eslintrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ env:
extends: airbnb-base
parserOptions:
ecmaVersion: latest
globals:
Prism: readonly
rules:
max-len:
- error
Expand Down
2 changes: 1 addition & 1 deletion assets/js.bundle/common/load-tooltips.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
/* global bootstrap */
const tooltips = document.querySelectorAll('[data-bs-toggle="tooltip"]');
// eslint-disable-next-line no-undef
[...tooltips].forEach(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl));
2 changes: 1 addition & 1 deletion assets/js.bundle/my-typewrite.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* eslint-disable no-undef, no-var */
/* global site, Typewriter */
// JS controller for https://github.com/tameemsafi/typewriterjs.
// For documentation, see Typewriter JS: https://safi.me.uk/typewriterjs/.

Expand Down
26 changes: 11 additions & 15 deletions assets/js.bundle/post/toc-highlight-current-section.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,24 @@
/* global tocOptions */

// --- TOC Current Section Highlight --- //
// 1. Check if post is configured to also show h3, h4, h5, etc...
// 2. Get all HTML heading elements.
// 3. Construct main calculation logic and attach to event handler.

// eslint-disable-next-line no-var
var tocOptions;

const headerOffset = document.querySelector('header').offsetHeight + 20;

let tags = ['h2', 'h3']; // Default.
if (tocOptions) {
tocOptions = JSON.parse(tocOptions);
if (tocOptions.tags && tocOptions.tags.length > 0) {
const newTags = [];
for (const t of tocOptions.tags) {
// Check if it matches hN header pattern.
if (t.startsWith('h') && !Number.isNaN(t[1]) && t[1] > 0 && t[1] <= 6) {
newTags.push(t);
}
}
if (newTags.length > 0) {
tags = newTags;
if (tocOptions && tocOptions.tags && tocOptions.tags.length > 0) {
const newTags = [];
for (const t of tocOptions.tags) {
// Check if it matches hN header pattern.
if (t.startsWith('h') && !Number.isNaN(t[1]) && t[1] > 0 && t[1] <= 6) {
newTags.push(t);
}
}
if (newTags.length > 0) {
tags = newTags;
}
}

const headerSelectors = tags.map(t => `.post-body > ${t}`).join(',');
Expand Down
3 changes: 1 addition & 2 deletions assets/js.bundle/search.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/* eslint-disable no-undef */

/* global site, lunr */
// Use a modified `lunr.Builder.add` which accepts run-length-encoded
// text, so that we can pack our JSON a bit tighter.
lunr.Builder.prototype.addEncoded = function (ref, fieldName, field) {
Expand Down
2 changes: 2 additions & 0 deletions eleventy/benchmarks/codeblocks/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,10 @@ const times = [];
for (const { name, loaderFile } of cases) {
const timer = new Timer(name);
timer.time({
/* eslint-disable no-undef */
count: (typeof count === 'undefined' ? undefined : count),
seconds: (typeof seconds === 'undefined' ? undefined : seconds),
/* eslint-enable no-undef */
setup() {
const { setup } = require(loaderFile);
setup(md);
Expand Down
211 changes: 72 additions & 139 deletions eleventy/detail/markdown-it/markdown-it-prism-adapter.js
Original file line number Diff line number Diff line change
@@ -1,152 +1,85 @@
const PrismLoad = require('prismjs/components/');
const { escapeHtml, unescapeAll } = require('./markdown-it-utils');

function textToDOM(text) {
// domino: Use `template` as a workaround: https://github.com/fgnass/domino/issues/73
const templ = document.createElement('template');
templ.innerHTML = text;
return templ.content;
// domino: Use `template` as a workaround: https://github.com/fgnass/domino/issues/73
const templ = document.createElement('template');
templ.innerHTML = text;
return templ.content;
}

const HTML_ESCAPE_TEST_RE = /[&<>"]/
const HTML_ESCAPE_REPLACE_RE = /[&<>"]/g
const HTML_REPLACEMENTS = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;'
}

function replaceUnsafeChar(ch) {
return HTML_REPLACEMENTS[ch]
}

function escapeHtml(str) {
if (HTML_ESCAPE_TEST_RE.test(str)) {
return str.replace(HTML_ESCAPE_REPLACE_RE, replaceUnsafeChar)
}
return str
}


const UNESCAPE_MD_RE = /\\([!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~])/g
const ENTITY_RE = /&([a-z#][a-z0-9]{1,31});/gi
const UNESCAPE_ALL_RE = new RegExp(UNESCAPE_MD_RE.source + '|' + ENTITY_RE.source, 'gi')

const DIGITAL_ENTITY_TEST_RE = /^#((?:x[a-f0-9]{1,8}|[0-9]{1,8}))$/i

function replaceEntityPattern(match, name) {
if (name.charCodeAt(0) === 0x23/* # */ && DIGITAL_ENTITY_TEST_RE.test(name)) {
const code = name[1].toLowerCase() === 'x'
? parseInt(name.slice(2), 16)
: parseInt(name.slice(1), 10)

if (isValidEntityCode(code)) {
return fromCodePoint(code)
}

return match
}

const decoded = decodeHTML(match)
if (decoded !== match) {
return decoded
}

return match
}

// function replaceEntities(str) {
// if (str.indexOf('&') < 0) { return str; }

// return str.replace(ENTITY_RE, replaceEntityPattern);
// }

function unescapeMd(str) {
if (str.indexOf('\\') < 0) { return str }
return str.replace(UNESCAPE_MD_RE, '$1')
}

function unescapeAll(str) {
if (str.indexOf('\\') < 0 && str.indexOf('&') < 0) { return str }

return str.replace(UNESCAPE_ALL_RE, function (match, escaped, entity) {
if (escaped) { return escaped }
return replaceEntityPattern(match, entity)
})
}


// PrismJS compatibility: attributes on codeblocks should go on `pre`, not `code`.
// eslint-disable-next-line max-len
// Adapted from https://github.com/markdown-it/markdown-it/blob/0fe7ccb4b7f30236fb05f623be6924961d296d3d/lib/renderer.mjs#L29
module.exports = function (tokens, idx, options, _env, slf) {
const token = tokens[idx]
const info = token.info ? unescapeAll(token.info).trim() : ''
let langName = ''
let langAttrs = ''

if (info) {
const arr = info.split(/(\s+)/g)
langName = arr[0]
langAttrs = arr.slice(2).join('')
}

if (token.content.startsWith('\n'))
token.content = token.content.substring(1);
if (token.content.endsWith('\n'))
token.content = token.content.substring(0, token.content.length - 1);

let highlighted
// if (options.highlight) {
if (langName.startsWith('diff-')) {
let diffRemovedRawName = langName.substring("diff-".length);
if (!Prism.languages[diffRemovedRawName])
PrismLoad([diffRemovedRawName]);
if (!Prism.languages.diff)
PrismLoad(['diff']);
Prism.languages[langName] = Prism.languages.diff;
highlighted = Prism.highlight(token.content, Prism.languages.diff, langName) || escapeHtml(token.content);
// } else {
// highlighted = options.highlight(token.content, langName, langAttrs) || escapeHtml(token.content)
// }
const token = tokens[idx];
const info = token.info ? unescapeAll(token.info).trim() : '';
let langName = '';
// let langAttrs = '';

if (info) {
const arr = info.split(/(\s+)/g);
langName = arr[0];
// langAttrs = arr.slice(2).join('');
}

if (token.content.startsWith('\n'))
token.content = token.content.substring(1);
if (token.content.endsWith('\n'))
token.content = token.content.substring(0, token.content.length - 1);

let highlighted;
// if (options.highlight) {
if (langName.startsWith('diff-')) {
const diffRemovedRawName = langName.substring('diff-'.length);
if (!Prism.languages[diffRemovedRawName])
PrismLoad([diffRemovedRawName]);
if (!Prism.languages.diff)
PrismLoad(['diff']);
Prism.languages[langName] = Prism.languages.diff;
highlighted = Prism.highlight(token.content, Prism.languages.diff, langName) || escapeHtml(token.content);
// } else {
// highlighted = options.highlight(token.content, langName, langAttrs) || escapeHtml(token.content)
// }
} else {
highlighted = escapeHtml(token.content);
}

// If language exists, inject class gently, without modifying original token.
// May be, one day we will add .deepClone() for token and simplify this part, but
// now we prefer to keep things local.
if (info) {
const i = token.attrIndex('class');
const tmpAttrs = token.attrs ? token.attrs.slice() : [];

if (i < 0) {
tmpAttrs.push(['class', options.langPrefix + langName]);
} else {
highlighted = escapeHtml(token.content)
tmpAttrs[i] = tmpAttrs[i].slice();
tmpAttrs[i][1] += ` ${options.langPrefix}${langName}`;
}

// If language exists, inject class gently, without modifying original token.
// May be, one day we will add .deepClone() for token and simplify this part, but
// now we prefer to keep things local.
if (info) {
const i = token.attrIndex('class')
const tmpAttrs = token.attrs ? token.attrs.slice() : []

if (i < 0) {
tmpAttrs.push(['class', options.langPrefix + langName])
} else {
tmpAttrs[i] = tmpAttrs[i].slice()
tmpAttrs[i][1] += ' ' + options.langPrefix + langName
}
// Fake token just to render attributes
const tmpToken = {
attrs: tmpAttrs,
};

// Fake token just to render attributes
const tmpToken = {
attrs: tmpAttrs
}

if (Prism.languages[langName] === undefined) {
PrismLoad([langName])
// langObject = Prism.languages[langName]
}

// Some plugins such as toolbar venture into codeElement.parentElement.parentElement,
// so we'll wrap the `pre` in an additional `div` for class purposes.
const result = `<div><pre${slf.renderAttrs(tmpToken)}><code class="${options.langPrefix}${langName}">${highlighted}</code></pre></div>`

const el = textToDOM(result);
Prism.highlightElement(el.firstChild.firstChild.firstChild);
let newResult = el.firstChild.firstChild.outerHTML;
if (!newResult.endsWith('\n'))
newResult += '\n';
return newResult;
if (Prism.languages[langName] === undefined) {
PrismLoad([langName]);
// langObject = Prism.languages[langName]
}

return `<pre${slf.renderAttrs(token)}><code>${highlighted}</code></pre>\n`
}
// Some plugins such as toolbar venture into codeElement.parentElement.parentElement,
// so we'll wrap the `pre` in an additional `div` for class purposes.
// eslint-disable-next-line max-len
const result = `<div><pre${slf.renderAttrs(tmpToken)}><code class="${options.langPrefix}${langName}">${highlighted}</code></pre></div>`;

const el = textToDOM(result);
Prism.highlightElement(el.firstChild.firstChild.firstChild);
let newResult = el.firstChild.firstChild.outerHTML;
if (!newResult.endsWith('\n'))
newResult += '\n';
return newResult;
}

return `<pre${slf.renderAttrs(token)}><code>${highlighted}</code></pre>\n`;
};
Loading

0 comments on commit 83a484e

Please sign in to comment.