chore: import upstream snapshot with attribution
tests / Test (macos-latest, 3.14) (push) Has been cancelled
tests / Test (ubuntu-latest, 3.10) (push) Has been cancelled
tests / Test (ubuntu-latest, 3.11) (push) Has been cancelled
tests / Test (windows-latest, 3.13) (push) Has been cancelled
tests / Test (windows-latest, 3.14) (push) Has been cancelled
tests / Validate (push) Has been cancelled
tests / Test (macos-latest, 3.10) (push) Has been cancelled
tests / Test (macos-latest, 3.11) (push) Has been cancelled
tests / Test (macos-latest, 3.12) (push) Has been cancelled
tests / Test (macos-latest, 3.13) (push) Has been cancelled
tests / Test (ubuntu-latest, 3.12) (push) Has been cancelled
tests / Test (ubuntu-latest, 3.13) (push) Has been cancelled
tests / Test (ubuntu-latest, 3.14) (push) Has been cancelled
tests / Test (windows-latest, 3.10) (push) Has been cancelled
tests / Test (windows-latest, 3.11) (push) Has been cancelled
tests / Test (windows-latest, 3.12) (push) Has been cancelled
universe validation / Validate (push) Has been cancelled
tests / Test (macos-latest, 3.14) (push) Has been cancelled
tests / Test (ubuntu-latest, 3.10) (push) Has been cancelled
tests / Test (ubuntu-latest, 3.11) (push) Has been cancelled
tests / Test (windows-latest, 3.13) (push) Has been cancelled
tests / Test (windows-latest, 3.14) (push) Has been cancelled
tests / Validate (push) Has been cancelled
tests / Test (macos-latest, 3.10) (push) Has been cancelled
tests / Test (macos-latest, 3.11) (push) Has been cancelled
tests / Test (macos-latest, 3.12) (push) Has been cancelled
tests / Test (macos-latest, 3.13) (push) Has been cancelled
tests / Test (ubuntu-latest, 3.12) (push) Has been cancelled
tests / Test (ubuntu-latest, 3.13) (push) Has been cancelled
tests / Test (ubuntu-latest, 3.14) (push) Has been cancelled
tests / Test (windows-latest, 3.10) (push) Has been cancelled
tests / Test (windows-latest, 3.11) (push) Has been cancelled
tests / Test (windows-latest, 3.12) (push) Has been cancelled
universe validation / Validate (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
const parseAttribute = (expression) => {
|
||||
if (expression.type !== 'AssignmentExpression' || !expression.left || !expression.right) {
|
||||
return
|
||||
}
|
||||
|
||||
const { left, right } = expression
|
||||
|
||||
if (left.type !== 'Identifier' || right.type !== 'Literal' || !left.name || !right.value) {
|
||||
return
|
||||
}
|
||||
|
||||
return [left.name, right.value]
|
||||
}
|
||||
|
||||
const getProps = (estree) => {
|
||||
if (estree.type !== 'Program' || !estree.body || estree.body.length <= 0 || !estree.body[0]) {
|
||||
return {}
|
||||
}
|
||||
|
||||
const estreeBodyFirstNode =
|
||||
estree.body[0].type === 'BlockStatement' ? estree.body[0].body[0] : estree.body[0]
|
||||
|
||||
if (estreeBodyFirstNode.type !== 'ExpressionStatement' || !estreeBodyFirstNode.expression) {
|
||||
return {}
|
||||
}
|
||||
|
||||
const statement = estreeBodyFirstNode.expression
|
||||
|
||||
const attributeExpressions = [
|
||||
...(statement.type === 'SequenceExpression' && statement.expressions
|
||||
? statement.expressions
|
||||
: []),
|
||||
...(statement.type === 'AssignmentExpression' ? [statement] : []),
|
||||
]
|
||||
|
||||
return Object.fromEntries(attributeExpressions.map(parseAttribute))
|
||||
}
|
||||
|
||||
export default getProps
|
||||
@@ -0,0 +1,20 @@
|
||||
import remarkGfm from 'remark-gfm'
|
||||
import remarkUnwrapImages from 'remark-unwrap-images'
|
||||
import remarkSmartypants from 'remark-smartypants'
|
||||
|
||||
import remarkCustomAttrs from './remarkCustomAttrs.mjs'
|
||||
import remarkWrapSections from './remarkWrapSections.mjs'
|
||||
import remarkCodeBlocks from './remarkCodeBlocks.mjs'
|
||||
import remarkFindAndReplace from './remarkFindAndReplace.mjs'
|
||||
|
||||
const remarkPlugins = [
|
||||
remarkGfm,
|
||||
remarkSmartypants,
|
||||
remarkFindAndReplace,
|
||||
remarkUnwrapImages,
|
||||
remarkCustomAttrs,
|
||||
remarkCodeBlocks,
|
||||
remarkWrapSections,
|
||||
]
|
||||
|
||||
export default remarkPlugins
|
||||
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* Support titles, line highlights and more for code blocks
|
||||
*/
|
||||
import { Parser } from 'acorn'
|
||||
import { visit } from 'unist-util-visit'
|
||||
import parseAttr from 'md-attr-parser'
|
||||
|
||||
import getProps from './getProps.mjs'
|
||||
|
||||
const defaultOptions = {
|
||||
defaultPrefix: '###',
|
||||
prefixMap: {
|
||||
javascript: '///',
|
||||
jsx: '///',
|
||||
},
|
||||
languageAliases: {},
|
||||
prompts: ['$'],
|
||||
}
|
||||
|
||||
function remarkCodeBlocks(userOptions = {}) {
|
||||
const options = Object.assign({}, defaultOptions, userOptions)
|
||||
|
||||
function transformer(tree) {
|
||||
visit(tree, 'code', (node) => {
|
||||
if (node.value) {
|
||||
const langName = node.lang || 'none'
|
||||
const lang = options.languageAliases[langName] || langName
|
||||
const prefix = options.prefixMap[lang] || options.defaultPrefix
|
||||
const lines = node.value.split('\n')
|
||||
let attrs = { lang }
|
||||
const firstLine = lines[0].trim()
|
||||
if (firstLine && firstLine.startsWith(prefix)) {
|
||||
const title = firstLine.slice(prefix.length).trim()
|
||||
attrs.title = title
|
||||
// Check for attributes in title, e.g. {executable="true"}
|
||||
const parsed = title.split(/\{(.*?)\}/)
|
||||
if (parsed.length >= 2 && parsed[1]) {
|
||||
const { prop } = parseAttr(parsed[1])
|
||||
attrs = { ...attrs, ...prop, title: parsed[0].trim(), lang }
|
||||
}
|
||||
// Overwrite the code text with the rest of the lines
|
||||
node.value = lines.slice(1).join('\n')
|
||||
} else if (
|
||||
(firstLine && /^https:\/\/github.com/.test(firstLine)) ||
|
||||
firstLine.startsWith('%%GITHUB_')
|
||||
) {
|
||||
// GitHub URL
|
||||
attrs.github = node.value
|
||||
}
|
||||
|
||||
const data = node.data || (node.data = {})
|
||||
const hProps = data.hProperties || (data.hProperties = {})
|
||||
|
||||
const meta = getProps(Parser.parse(node.meta, { ecmaVersion: 'latest' }))
|
||||
|
||||
node.data.hProperties = Object.assign({}, hProps, attrs, meta)
|
||||
}
|
||||
})
|
||||
|
||||
visit(tree, 'inlineCode', (node) => {
|
||||
node.type = 'mdxJsxTextElement'
|
||||
node.name = 'InlineCode'
|
||||
node.children = [
|
||||
{
|
||||
type: 'text',
|
||||
value: node.value,
|
||||
},
|
||||
]
|
||||
node.data = { _mdxExplicitJsx: true }
|
||||
})
|
||||
|
||||
return tree
|
||||
}
|
||||
return transformer
|
||||
}
|
||||
|
||||
export default remarkCodeBlocks
|
||||
@@ -0,0 +1,38 @@
|
||||
import getProps from './getProps.mjs'
|
||||
|
||||
const handleNode = (node) => {
|
||||
if (node.type === 'section' && node.children) {
|
||||
return {
|
||||
...node,
|
||||
children: node.children.map(handleNode),
|
||||
}
|
||||
}
|
||||
|
||||
if (node.type !== 'heading' || !node.children || node.children < 2) {
|
||||
return node
|
||||
}
|
||||
|
||||
const indexLast = node.children.length - 1
|
||||
const lastNode = node.children[indexLast]
|
||||
|
||||
if (lastNode.type !== 'mdxTextExpression' || !lastNode.data || !lastNode.data.estree) {
|
||||
return node
|
||||
}
|
||||
|
||||
const data = node.data || (node.data = {})
|
||||
data.hProperties = getProps(lastNode.data.estree)
|
||||
|
||||
// Only keep the text, drop the rest
|
||||
node.children = [node.children[0]]
|
||||
|
||||
return node
|
||||
}
|
||||
|
||||
const parseAstTree = (markdownAST) => ({
|
||||
...markdownAST,
|
||||
children: markdownAST.children.map(handleNode),
|
||||
})
|
||||
|
||||
const remarkCustomAttrs = () => parseAstTree
|
||||
|
||||
export default remarkCustomAttrs
|
||||
@@ -0,0 +1,42 @@
|
||||
import { visit } from 'unist-util-visit'
|
||||
import { replacements } from '../meta/dynamicMeta.mjs'
|
||||
|
||||
const prefix = '%%'
|
||||
|
||||
// Attaches prefix to the start of the string.
|
||||
const attachPrefix = (str) => (prefix || '') + str
|
||||
|
||||
// RegExp to find any replacement keys.
|
||||
const regexp = RegExp(
|
||||
'(' +
|
||||
Object.keys(replacements)
|
||||
.map((key) => attachPrefix(key))
|
||||
.join('|') +
|
||||
')',
|
||||
'g'
|
||||
)
|
||||
|
||||
// Removes prefix from the start of the string.
|
||||
const stripPrefix = (str) => (prefix ? str.replace(RegExp(`^${prefix}`), '') : str)
|
||||
|
||||
const replacer = (_match, name) => replacements[stripPrefix(name)]
|
||||
|
||||
const remarkFindAndReplace = () => (markdownAST) => {
|
||||
// Go through all text, html, code, inline code, and links.
|
||||
visit(markdownAST, ['text', 'html', 'code', 'link'], (node) => {
|
||||
if (node.type === 'link') {
|
||||
// For links, the text value is replaced by text node, so we change the
|
||||
// URL value.
|
||||
const processedText = node.url.replace(regexp, replacer)
|
||||
node.url = processedText
|
||||
} else {
|
||||
// For all other nodes, replace the node value.
|
||||
const processedText = node.value.replace(regexp, replacer)
|
||||
node.value = processedText
|
||||
}
|
||||
})
|
||||
|
||||
return markdownAST
|
||||
}
|
||||
|
||||
export default remarkFindAndReplace
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Check the tree for headlines of a certain depth and wrap the headline and
|
||||
* all content up to the next headline in a section.
|
||||
* Based on: https://github.com/luhmann/tufte-markdown
|
||||
*/
|
||||
|
||||
import { visit } from 'unist-util-visit'
|
||||
|
||||
const defaultOptions = {
|
||||
element: 'section',
|
||||
prefix: 'section-',
|
||||
depth: 2,
|
||||
slugify: true,
|
||||
}
|
||||
|
||||
function remarkWrapSection(userOptions = {}) {
|
||||
const options = Object.assign({}, defaultOptions, userOptions)
|
||||
|
||||
function transformer(tree) {
|
||||
const headingsMap = []
|
||||
const newTree = []
|
||||
|
||||
visit(tree, 'import', (node) => {
|
||||
// For compatibility with MDX / gatsby-mdx, make sure import nodes
|
||||
// are not moved further down into children (which means they're not
|
||||
// recognized and interpreted anymore). Add them to the very start
|
||||
// of the tree.
|
||||
newTree.push(node)
|
||||
})
|
||||
|
||||
visit(tree, 'heading', (node, index) => {
|
||||
if (node.depth === options.depth) {
|
||||
const data = node.data || (node.data = {})
|
||||
const hProps = data.hProperties || (data.hProperties = {})
|
||||
headingsMap.push({ index, id: hProps.id })
|
||||
}
|
||||
})
|
||||
|
||||
if (headingsMap.length) {
|
||||
for (let index = 0; index <= headingsMap.length; index++) {
|
||||
const sectionStartIndex = index === 0 ? 0 : headingsMap[index - 1].index
|
||||
const sectionEndIndex =
|
||||
index === headingsMap.length ? tree.children.length : headingsMap[index].index
|
||||
const children = tree.children
|
||||
.slice(sectionStartIndex, sectionEndIndex)
|
||||
.filter((node) => node.type !== 'import')
|
||||
|
||||
if (children.length) {
|
||||
const headingId = index === 0 ? 0 : headingsMap[index - 1].id
|
||||
const sectionId = headingId ? options.prefix + headingId : undefined
|
||||
const wrapperNode = {
|
||||
type: 'section',
|
||||
children,
|
||||
data: { hName: options.element, hProperties: { id: sectionId } },
|
||||
}
|
||||
newTree.push(wrapperNode)
|
||||
}
|
||||
}
|
||||
tree.children = newTree
|
||||
}
|
||||
return tree
|
||||
}
|
||||
return transformer
|
||||
}
|
||||
|
||||
export default remarkWrapSection
|
||||
Reference in New Issue
Block a user