mirror of
https://github.com/benjaminion/upgrading-ethereum-book.git
synced 2026-01-07 21:53:53 -05:00
Run prettier
This commit is contained in:
3
.prettierrc
Normal file
3
.prettierrc
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"singleQuote": true
|
||||
}
|
||||
@@ -6,8 +6,7 @@ import { visit } from 'unist-util-visit';
|
||||
let constantsMap = {};
|
||||
|
||||
function addTooltips() {
|
||||
|
||||
return function(tree) {
|
||||
return function (tree) {
|
||||
try {
|
||||
visit(tree, 'inlineCode', (node, index, parent) => {
|
||||
// HTML in headings causes problems for the page index, so skip these
|
||||
@@ -20,15 +19,14 @@ function addTooltips() {
|
||||
node.children = undefined;
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default function(options) {
|
||||
|
||||
export default function (options) {
|
||||
// Read the constants file and store it for later
|
||||
const constantsFile = options?.constantsFile || '';
|
||||
try {
|
||||
@@ -43,9 +41,7 @@ export default function(options) {
|
||||
'astro:config:setup': ({ updateConfig }) => {
|
||||
updateConfig({
|
||||
markdown: {
|
||||
remarkPlugins: [
|
||||
addTooltips,
|
||||
],
|
||||
remarkPlugins: [addTooltips],
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
@@ -1,60 +1,62 @@
|
||||
import { CONTINUE, SKIP, visit } from 'unist-util-visit';
|
||||
import { fromHtmlIsomorphic } from 'hast-util-from-html-isomorphic'
|
||||
import { fromHtmlIsomorphic } from 'hast-util-from-html-isomorphic';
|
||||
import { toString } from 'hast-util-to-string';
|
||||
|
||||
// Add IDs and SVG permalinks to headings h3 to h6
|
||||
// (rehype-autolink-headings is good, but can't be configured to ignore h1 and h2)
|
||||
|
||||
const anchor = fromHtmlIsomorphic('<a class="anchor" ariaHidden="true"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>', {fragment: true}).children[0];
|
||||
const anchor = fromHtmlIsomorphic(
|
||||
'<a class="anchor" ariaHidden="true"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>',
|
||||
{ fragment: true },
|
||||
).children[0];
|
||||
|
||||
// The headings to process
|
||||
const headings = ['h3', 'h4', 'h5', 'h6'];
|
||||
|
||||
// Should match the method in bin/build/checks/links.pl
|
||||
function slugIt(heading) {
|
||||
return (
|
||||
toString(heading)
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
.replace(/\s+/g, '-')
|
||||
.replace(/[^a-z0-9_-]/g, '')
|
||||
);
|
||||
return toString(heading)
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
.replace(/\s+/g, '-')
|
||||
.replace(/[^a-z0-9_-]/g, '');
|
||||
}
|
||||
|
||||
function autolinkHeadings() {
|
||||
return function(tree) {
|
||||
return function (tree) {
|
||||
try {
|
||||
visit(tree, 'element', node => {
|
||||
visit(tree, 'element', (node) => {
|
||||
if (headings.indexOf(node.tagName) === -1) {
|
||||
return CONTINUE;
|
||||
}
|
||||
const newAnchor = structuredClone(anchor);
|
||||
const newAnchor = structuredClone(anchor);
|
||||
if (node.properties.id) {
|
||||
newAnchor.properties = { ...newAnchor.properties, href: '#' + node.properties.id };
|
||||
newAnchor.properties = {
|
||||
...newAnchor.properties,
|
||||
href: '#' + node.properties.id,
|
||||
};
|
||||
} else {
|
||||
const id = slugIt(node);
|
||||
newAnchor.properties = { ...newAnchor.properties, href: '#' + id };
|
||||
node.properties.id = id;
|
||||
}
|
||||
node.children = [ newAnchor ].concat(node.children);
|
||||
node.children = [newAnchor].concat(node.children);
|
||||
return SKIP;
|
||||
})
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default function() {
|
||||
export default function () {
|
||||
return {
|
||||
name: 'myAutolinkHeadings',
|
||||
hooks: {
|
||||
'astro:config:setup': ({ updateConfig }) => {
|
||||
updateConfig({
|
||||
markdown: {
|
||||
rehypePlugins: [
|
||||
autolinkHeadings,
|
||||
],
|
||||
rehypePlugins: [autolinkHeadings],
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
@@ -5,13 +5,13 @@ function buildChecks(logger) {
|
||||
runChecks(logger, false);
|
||||
}
|
||||
|
||||
export default function() {
|
||||
export default function () {
|
||||
let doChecks;
|
||||
return {
|
||||
name: 'myBuildChecks',
|
||||
hooks: {
|
||||
'astro:config:setup': ({ command }) => {
|
||||
doChecks = (command === 'build' && process.env.UE_NOCHECK === undefined);
|
||||
doChecks = command === 'build' && process.env.UE_NOCHECK === undefined;
|
||||
},
|
||||
'astro:config:done': ({ logger }) => {
|
||||
if (doChecks) {
|
||||
|
||||
@@ -3,14 +3,12 @@ import { visit, SKIP } from 'unist-util-visit';
|
||||
// Clean up any weird HTML artefacts, especially those that fail validation
|
||||
|
||||
function cleanupHtml() {
|
||||
return function(tree) {
|
||||
return function (tree) {
|
||||
try {
|
||||
|
||||
// Remove `is:raw=""` that's on `code` elements, probably from Prism.
|
||||
visit(tree, 'element', node => {
|
||||
if (node.tagName == 'code'
|
||||
&& node.properties['is:raw'] !== undefined) {
|
||||
delete(node.properties['is:raw']);
|
||||
visit(tree, 'element', (node) => {
|
||||
if (node.tagName == 'code' && node.properties['is:raw'] !== undefined) {
|
||||
delete node.properties['is:raw'];
|
||||
}
|
||||
});
|
||||
|
||||
@@ -19,23 +17,20 @@ function cleanupHtml() {
|
||||
parent.children.splice(index, 1);
|
||||
return SKIP;
|
||||
});
|
||||
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default function() {
|
||||
export default function () {
|
||||
return {
|
||||
name: 'myCleanupHtml',
|
||||
hooks: {
|
||||
'astro:config:setup': ({ updateConfig }) => {
|
||||
updateConfig({
|
||||
markdown: {
|
||||
rehypePlugins: [
|
||||
cleanupHtml,
|
||||
],
|
||||
rehypePlugins: [cleanupHtml],
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
@@ -4,44 +4,43 @@ import { visit } from 'unist-util-visit';
|
||||
// It seems that [Astro does not do this](https://github.com/withastro/astro/issues/3626)
|
||||
|
||||
function fixupLinks(basePath) {
|
||||
return function(tree) {
|
||||
return function (tree) {
|
||||
try {
|
||||
visit(tree, 'element', node => {
|
||||
if (node.tagName == 'a'
|
||||
&& node.properties.href) {
|
||||
|
||||
visit(tree, 'element', (node) => {
|
||||
if (node.tagName == 'a' && node.properties.href) {
|
||||
// Add basePath prefix to local URLs that lack it
|
||||
// [Astro does not do this](https://github.com/withastro/astro/issues/3626)
|
||||
if(node.properties.href.startsWith('/')
|
||||
&& !node.properties.href.startsWith(basePath + '/')) {
|
||||
if (
|
||||
node.properties.href.startsWith('/') &&
|
||||
!node.properties.href.startsWith(basePath + '/')
|
||||
) {
|
||||
node.properties.href = basePath + node.properties.href;
|
||||
}
|
||||
|
||||
// Add rel="external noopener" and target="_blank" attributes to off-site links
|
||||
if(!node.properties.href.startsWith('/')
|
||||
&& !node.properties.href.startsWith('#')) {
|
||||
if (
|
||||
!node.properties.href.startsWith('/') &&
|
||||
!node.properties.href.startsWith('#')
|
||||
) {
|
||||
node.properties.rel = ['external', 'noopener'];
|
||||
node.properties.target = '_blank';
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default function() {
|
||||
export default function () {
|
||||
return {
|
||||
name: 'myFixupLinks',
|
||||
hooks: {
|
||||
'astro:config:setup': ({ config, updateConfig }) => {
|
||||
updateConfig({
|
||||
markdown: {
|
||||
rehypePlugins: [
|
||||
[fixupLinks, config.base],
|
||||
],
|
||||
rehypePlugins: [[fixupLinks, config.base]],
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
@@ -7,7 +7,7 @@ function writeHtaccess(base, dir, logger) {
|
||||
logger.info(`Wrote .htaccess file to ${file}`);
|
||||
}
|
||||
|
||||
export default function(base) {
|
||||
export default function (base) {
|
||||
return {
|
||||
name: 'myHtaccess',
|
||||
hooks: {
|
||||
|
||||
@@ -5,12 +5,14 @@ import fs from 'fs';
|
||||
// File scoped to accumulate the index across calls to mySearchIndex
|
||||
const searchIndex = [];
|
||||
|
||||
function isExcludedFrontmatter (frontmatter, exclude) {
|
||||
function isExcludedFrontmatter(frontmatter, exclude) {
|
||||
for (let i = 0; i < exclude.frontmatter.length; i++) {
|
||||
const test = exclude.frontmatter[i];
|
||||
const [key, ...rest] = Object.keys(test);
|
||||
if (Object.prototype.hasOwnProperty.call(frontmatter, key)
|
||||
&& frontmatter[key] == test[key]) {
|
||||
if (
|
||||
Object.prototype.hasOwnProperty.call(frontmatter, key) &&
|
||||
frontmatter[key] == test[key]
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -18,45 +20,42 @@ function isExcludedFrontmatter (frontmatter, exclude) {
|
||||
}
|
||||
|
||||
// Recursively concatenate all text in child nodes while respecting exclusions
|
||||
function getText (node, exclude) {
|
||||
|
||||
function getText(node, exclude) {
|
||||
if (node.type === 'text') {
|
||||
// [\u202F\u00A0] is a non-breaking space
|
||||
return node.value.replace(/[\u202F\u00A0]/, ' ');
|
||||
}
|
||||
|
||||
if (node.type !== 'element'
|
||||
|| matches(exclude.ignore, node)) {
|
||||
if (node.type !== 'element' || matches(exclude.ignore, node)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return node.children.map( node => {return getText(node, exclude)}).join('');
|
||||
return node.children
|
||||
.map((node) => {
|
||||
return getText(node, exclude);
|
||||
})
|
||||
.join('');
|
||||
}
|
||||
|
||||
function getChunks (tree, chunkTypes, exclude) {
|
||||
|
||||
function getChunks(tree, chunkTypes, exclude) {
|
||||
const counts = Array(chunkTypes.length).fill(0);
|
||||
let chunks = [];
|
||||
|
||||
// Walk the tree until we find an element we want to treat as a chunk, then get
|
||||
// all its text content.
|
||||
visit(tree, 'element', node => {
|
||||
|
||||
visit(tree, 'element', (node) => {
|
||||
if (matches(exclude.ignore, node)) {
|
||||
return SKIP;
|
||||
}
|
||||
|
||||
for (let idx = 0; idx < chunkTypes.length; idx++) {
|
||||
|
||||
const type = chunkTypes[idx];
|
||||
if (matches(type.query, node)) {
|
||||
|
||||
const text = getText(node, exclude);
|
||||
if (text !== '') {
|
||||
|
||||
const tagName = node.tagName.toLowerCase();
|
||||
let id = node.properties?.id;
|
||||
if ( id === undefined) {
|
||||
if (id === undefined) {
|
||||
// Edit the element's ID so we can find it from the search page later
|
||||
id = tagName + '_' + counts[idx];
|
||||
node.properties.id = id;
|
||||
@@ -72,7 +71,7 @@ function getChunks (tree, chunkTypes, exclude) {
|
||||
});
|
||||
}
|
||||
return SKIP;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return CONTINUE;
|
||||
@@ -82,21 +81,20 @@ function getChunks (tree, chunkTypes, exclude) {
|
||||
}
|
||||
|
||||
function includePage(frontmatter, exclude) {
|
||||
return (frontmatter !== undefined
|
||||
&& isExcludedFrontmatter(frontmatter, exclude) === false
|
||||
&& exclude.pages?.indexOf(frontmatter.path) === -1);
|
||||
return (
|
||||
frontmatter !== undefined &&
|
||||
isExcludedFrontmatter(frontmatter, exclude) === false &&
|
||||
exclude.pages?.indexOf(frontmatter.path) === -1
|
||||
);
|
||||
}
|
||||
|
||||
function buildSearchIndex(options) {
|
||||
|
||||
const { chunkTypes, exclude, logger } = { ...options };
|
||||
|
||||
return function (tree, file) {
|
||||
|
||||
const frontmatter = file.data.astro.frontmatter;
|
||||
|
||||
if (includePage(frontmatter, exclude)) {
|
||||
|
||||
logger.debug('Processing ' + frontmatter.path);
|
||||
|
||||
const chunks = getChunks(tree, chunkTypes, exclude);
|
||||
@@ -106,19 +104,15 @@ function buildSearchIndex(options) {
|
||||
titles: frontmatter.titles,
|
||||
},
|
||||
chunks: chunks,
|
||||
}
|
||||
};
|
||||
searchIndex.push(pageIndexData);
|
||||
|
||||
} else {
|
||||
|
||||
logger.debug('Ignoring ' + frontmatter.path);
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function writeSearchIndex(dir, file, logger) {
|
||||
|
||||
const fileName = dir.pathname + file;
|
||||
|
||||
if (searchIndex.length) {
|
||||
@@ -131,10 +125,9 @@ function writeSearchIndex(dir, file, logger) {
|
||||
logger.info('Wrote search index to ' + fileName);
|
||||
}
|
||||
|
||||
export default function(options) {
|
||||
|
||||
export default function (options) {
|
||||
if (options.enabled === false) {
|
||||
return {name: 'my-search-index'};
|
||||
return { name: 'my-search-index' };
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -144,9 +137,7 @@ export default function(options) {
|
||||
'astro:config:setup': ({ updateConfig, logger }) => {
|
||||
updateConfig({
|
||||
markdown: {
|
||||
rehypePlugins: [
|
||||
[buildSearchIndex, { ...options, logger: logger }],
|
||||
],
|
||||
rehypePlugins: [[buildSearchIndex, { ...options, logger: logger }]],
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
@@ -17,15 +17,15 @@ const addTitle = {
|
||||
exit: (node, parentNode) => {
|
||||
if (node.name === 'svg' && parentNode.type === 'root') {
|
||||
const hasTitle = node.children.some(
|
||||
(child) => child.type === 'element' && child.name === 'title'
|
||||
)
|
||||
(child) => child.type === 'element' && child.name === 'title',
|
||||
);
|
||||
if (!hasTitle) {
|
||||
const titleElement = {
|
||||
type: 'element',
|
||||
name: 'title',
|
||||
attributes: {},
|
||||
children: [],
|
||||
}
|
||||
};
|
||||
Object.defineProperty(titleElement, 'parentNode', {
|
||||
writable: true,
|
||||
value: node,
|
||||
@@ -33,20 +33,20 @@ const addTitle = {
|
||||
const titleContents = {
|
||||
type: 'text',
|
||||
value: params.titleText,
|
||||
}
|
||||
};
|
||||
Object.defineProperty(titleContents, 'parentNode', {
|
||||
writable: true,
|
||||
value: titleElement,
|
||||
});
|
||||
titleElement.children.push(titleContents)
|
||||
titleElement.children.push(titleContents);
|
||||
node.children.unshift(titleElement);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
// See https://www.npmjs.com/package/svgo
|
||||
const plugins = [
|
||||
@@ -56,39 +56,38 @@ const plugins = [
|
||||
'removeXMLNS',
|
||||
{
|
||||
name: 'addAttributesToSVGElement',
|
||||
params: {attribute: {'role': 'img'}},
|
||||
params: { attribute: { role: 'img' } },
|
||||
},
|
||||
]
|
||||
];
|
||||
|
||||
const addTitleSettings = {
|
||||
const addTitleSettings = {
|
||||
name: addTitle.name,
|
||||
type: addTitle.type,
|
||||
active: addTitle.active,
|
||||
fn: addTitle.fn,
|
||||
params: undefined,
|
||||
}
|
||||
};
|
||||
|
||||
const addAttributes = {
|
||||
name: 'addAttributesToSVGElement',
|
||||
params: undefined,
|
||||
}
|
||||
name: 'addAttributesToSVGElement',
|
||||
params: undefined,
|
||||
};
|
||||
|
||||
function inlineSvg(options) {
|
||||
|
||||
const filePath = options.filePath || '';
|
||||
const cachePathTmp = options.cachePath;
|
||||
const cachePath = cachePathTmp.endsWith('/') ? cachePathTmp : cachePathTmp + '/';
|
||||
const { logger, doCache} = options;
|
||||
const cachePath = cachePathTmp.endsWith('/')
|
||||
? cachePathTmp
|
||||
: cachePathTmp + '/';
|
||||
const { logger, doCache } = options;
|
||||
|
||||
return function (tree) {
|
||||
try {
|
||||
visit(tree, 'paragraph', async node => {
|
||||
visit(tree, 'paragraph', async (node) => {
|
||||
if (node.children[0].type == 'image') {
|
||||
|
||||
const image = node.children[0];
|
||||
|
||||
if (image.url.endsWith('.svg')) {
|
||||
|
||||
const originalSvg = fs.readFileSync(filePath + image.url, 'utf8');
|
||||
const basename = path.basename(image.url, '.svg');
|
||||
|
||||
@@ -96,10 +95,10 @@ function inlineSvg(options) {
|
||||
const digest = getHashDigest(basename, 'md5', 'base52', 4);
|
||||
|
||||
// Configure the SVGO addAttributes plugin to add an ID to SVG element
|
||||
addAttributes['params'] = {attribute: {id: basename + "-svg"}};
|
||||
addAttributes['params'] = { attribute: { id: basename + '-svg' } };
|
||||
|
||||
// Configure our custom plugin that adds a title element
|
||||
addTitleSettings['params'] = {titleText: image.alt};
|
||||
addTitleSettings['params'] = { titleText: image.alt };
|
||||
|
||||
// If the cachePath option is provided, we load the optimised SVG from there
|
||||
// when it exists and is newer than the original SVG. If a cached version is
|
||||
@@ -107,22 +106,20 @@ function inlineSvg(options) {
|
||||
|
||||
const origMtime = fs.statSync(filePath + image.url).mtime;
|
||||
const cacheFile = doCache ? cachePath + basename + '.svg' : null;
|
||||
const goodCache = doCache
|
||||
&& fs.existsSync(cacheFile)
|
||||
&& (fs.statSync(cacheFile).mtime > origMtime);
|
||||
const goodCache =
|
||||
doCache &&
|
||||
fs.existsSync(cacheFile) &&
|
||||
fs.statSync(cacheFile).mtime > origMtime;
|
||||
|
||||
let svg;
|
||||
if (goodCache) {
|
||||
svg = fs.readFileSync(cacheFile, 'utf8');
|
||||
logger.debug(`Using cached ${basename}.svg`);
|
||||
} else {
|
||||
svg = optimize(
|
||||
originalSvg,
|
||||
{
|
||||
path: digest,
|
||||
plugins: plugins.concat([addTitleSettings, addAttributes])
|
||||
}
|
||||
).data;
|
||||
svg = optimize(originalSvg, {
|
||||
path: digest,
|
||||
plugins: plugins.concat([addTitleSettings, addAttributes]),
|
||||
}).data;
|
||||
logger.debug(`Optimising ${basename}.svg`);
|
||||
if (doCache) {
|
||||
fs.writeFileSync(cacheFile, svg);
|
||||
@@ -138,14 +135,14 @@ function inlineSvg(options) {
|
||||
node.children = [];
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default function(options) {
|
||||
export default function (options) {
|
||||
return {
|
||||
name: 'mySvgInline',
|
||||
hooks: {
|
||||
@@ -156,10 +153,14 @@ export default function(options) {
|
||||
if (fs.statSync(options.cachePath).isDirectory()) {
|
||||
doCache = true;
|
||||
} else {
|
||||
logger.warn(`Not caching SVGs: ${options.cachePath} is not a directory`);
|
||||
logger.warn(
|
||||
`Not caching SVGs: ${options.cachePath} is not a directory`,
|
||||
);
|
||||
}
|
||||
} catch(e) {
|
||||
logger.warn(`Not caching SVGs: ${options.cachePath} does not exist`);
|
||||
} catch (e) {
|
||||
logger.warn(
|
||||
`Not caching SVGs: ${options.cachePath} does not exist`,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
logger.info('Not caching SVGs: no cachePath provided');
|
||||
|
||||
Reference in New Issue
Block a user