1
0
mirror of synced 2025-12-23 11:54:18 -05:00
Files
docs/lib/render-content/plugins/code-header.js
Kevin Heis 0c34f6d648 Code-headers plugin rewrite (#37654)
Co-authored-by: Peter Bengtsson <peterbe@github.com>
2023-06-12 15:04:49 +00:00

81 lines
2.2 KiB
JavaScript

/**
* Adds a bar above code blocks that shows the language and a copy button
*/
import yaml from 'js-yaml'
import fs from 'fs'
import { visit } from 'unist-util-visit'
import { h } from 'hastscript'
import octicons from '@primer/octicons'
import { parse } from 'parse5'
import { fromParse5 } from 'hast-util-from-parse5'
const languages = yaml.load(fs.readFileSync('./data/variables/code-languages.yml', 'utf8'))
const matcher = (node) =>
node.type === 'element' &&
node.tagName === 'pre' &&
// For now, limit to ones with the copy meta,
// but we may enable for all examples later.
getPreMeta(node).copy &&
// Don't add this header for annotated examples.
!getPreMeta(node).annotate
export default function codeHeader() {
return (tree) => {
visit(tree, matcher, (node, index, parent) => {
parent.children[index] = wrapCodeExample(node)
})
}
}
function wrapCodeExample(node) {
const lang = node.children[0].properties.className?.[0].replace('language-', '')
const code = node.children[0].children[0].value
return h('div', { className: 'code-example' }, [header(lang, code), node])
}
export function header(lang, code) {
return h(
'header',
{
class: [
'd-flex',
'flex-items-center',
'flex-justify-between',
'p-2',
'text-small',
'rounded-top-1',
'border-top',
'border-left',
'border-right',
],
},
[
h('span', languages[lang]?.name),
h(
'button',
{
class: ['js-btn-copy', 'btn', 'btn-sm', 'tooltipped', 'tooltipped-nw'],
'data-clipboard-text': code,
'aria-label': 'Copy code to clipboard',
},
btnIcon()
),
]
)
}
function btnIcon() {
const btnIconHtml = octicons.copy.toSVG()
const btnIconAst = parse(String(btnIconHtml), { sourceCodeLocationInfo: true })
const btnIcon = fromParse5(btnIconAst, { file: btnIconHtml })
return btnIcon
}
function getPreMeta(node) {
// Here's why this monstrosity works:
// https://github.com/syntax-tree/mdast-util-to-hast/blob/c87cd606731c88a27dbce4bfeaab913a9589bf83/lib/handlers/code.js#L40-L42
return node.children[0]?.data?.meta || {}
}