diff --git a/package-lock.json b/package-lock.json index ef4c6a72ae4..04e40961d17 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "@octokit/graphql": "^4.8.0", "@octokit/rest": "^18.12.0", "@primer/css": "^19.3.0", + "@primer/octicons": "^16.3.0", "axios": "^0.25.0", "clipboard": "^2.0.10", "compression": "^1.7.4", @@ -1861,6 +1862,14 @@ "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, + "node_modules/@primer/octicons": { + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/@primer/octicons/-/octicons-16.3.0.tgz", + "integrity": "sha512-kOVIGDkd7s2hx0E4FHyJblzGSTiOX+a//eu9CPSM0hYr26Sr+m0bIiTYHNPVLDh9apF9WdK8ub/eqgrE8U4iEA==", + "dependencies": { + "object-assign": "^4.1.1" + } + }, "node_modules/@primer/primitives": { "version": "7.4.0", "resolved": "https://registry.npmjs.org/@primer/primitives/-/primitives-7.4.0.tgz", @@ -7283,7 +7292,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "devOptional": true, "engines": { "node": ">=0.10.0" } @@ -11442,6 +11450,14 @@ "@primer/primitives": "^7.4.0" } }, + "@primer/octicons": { + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/@primer/octicons/-/octicons-16.3.0.tgz", + "integrity": "sha512-kOVIGDkd7s2hx0E4FHyJblzGSTiOX+a//eu9CPSM0hYr26Sr+m0bIiTYHNPVLDh9apF9WdK8ub/eqgrE8U4iEA==", + "requires": { + "object-assign": "^4.1.1" + } + }, "@primer/primitives": { "version": "7.4.0", "resolved": "https://registry.npmjs.org/@primer/primitives/-/primitives-7.4.0.tgz", @@ -15605,8 +15621,7 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "devOptional": true + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, "object-inspect": { "version": "1.4.1", diff --git a/package.json b/package.json index bf7982a2ccf..27d473e149f 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "@octokit/graphql": "^4.8.0", "@octokit/rest": "^18.12.0", "@primer/css": "^19.3.0", + "@primer/octicons": "^16.3.0", "axios": "^0.25.0", "clipboard": "^2.0.10", "compression": "^1.7.4", diff --git a/source/app/metrics/index.mjs b/source/app/metrics/index.mjs index 4c67e65496b..44bcaae1bae 100644 --- a/source/app/metrics/index.mjs +++ b/source/app/metrics/index.mjs @@ -157,6 +157,7 @@ export default async function metrics({login, q}, {graphql, rest, plugins, conf, style:extras.css, twemojis:q["config.twemoji"], gemojis:q["config.gemoji"], + octicons:q["config.octicon"], rest, }) } @@ -172,6 +173,8 @@ export default async function metrics({login, q}, {graphql, rest, plugins, conf, rendered = await imports.svg.twemojis(rendered) if (q["config.gemoji"]) rendered = await imports.svg.gemojis(rendered, {rest}) + if (q["config.octicon"]) + rendered = await imports.svg.octicons(rendered) //Optimize rendering if ((conf.settings?.optimize === true) || (conf.settings?.optimize?.includes?.("css"))) rendered = await imports.svg.optimize.css(rendered) diff --git a/source/app/metrics/utils.mjs b/source/app/metrics/utils.mjs index 630b5e1c911..954f5d0b698 100644 --- a/source/app/metrics/utils.mjs +++ b/source/app/metrics/utils.mjs @@ -30,7 +30,7 @@ import twemojis from "twemoji-parser" import url from "url" import util from "util" import xmlformat from "xml-formatter" - +import octicons from "@primer/octicons" prism_lang() //Exports @@ -367,7 +367,7 @@ export async function imgb64(image, {width, height, fallback = true} = {}) { /**SVG utils */ export const svg = { /**Render as pdf */ - async pdf(rendered, {paddings = "", style = "", twemojis = false, gemojis = false, rest = null} = {}) { + async pdf(rendered, {paddings = "", style = "", twemojis = false, gemojis = false, octicons = false, rest = null} = {}) { //Instantiate browser if needed if (!svg.resize.browser) { svg.resize.browser = await puppeteer.launch() @@ -378,6 +378,8 @@ export const svg = { rendered = await svg.twemojis(rendered, {custom:false}) if ((gemojis) && (rest)) rendered = await svg.gemojis(rendered, {rest}) + if (octicons) + rendered = await svg.octicons(rendered) rendered = marked.parse(rendered) //Render through browser and print pdf console.debug("metrics/svg/pdf > loading svg") @@ -550,6 +552,26 @@ export const svg = { rendered = rendered.replace(new RegExp(emoji, "g"), gemoji) return rendered }, + /**Render github octicons */ + async octicons(rendered) { + //Load octicons + console.debug("metrics/svg/octicons > rendering octicons") + const icons = new Map() + for (const {name, heights, toSVG} of Object.values(octicons)) { + for (const size of Object.keys(heights)) { + const octicon = `:octicon-${name}-${size}:` + if (new RegExp(`:octicon-${name}(?:-[0-9]+)?:`, "g").test(rendered)) { + icons.set(octicon, toSVG({height:size, width:size})) + if (Number(size) === 16) + icons.set(`:octicon-${name}:`, toSVG({height:size, width:size})) + } + } + } + //Apply replacements + for (const [octicon, image] of icons) + rendered = rendered.replace(new RegExp(octicon, "g"), image) + return rendered + }, /**Optimizers */ optimize:{ /**CSS optimizer */ diff --git a/source/plugins/core/metadata.yml b/source/plugins/core/metadata.yml index d998f596365..29d84773312 100644 --- a/source/plugins/core/metadata.yml +++ b/source/plugins/core/metadata.yml @@ -243,6 +243,22 @@ inputs: default: yes global: yes + config_octicon: + description: | + Use GitHub octicons + + Octicons are open-sourced icons provided by GitHub. + See full list at https://primer.style/octicons. + + To include an octicon, use the following syntax: `:octicon-{name}-{size}:`. + Size must be a supported icon size (12, 16 or 24). + 16px octicons can omit size and directly use `:octicon-{name}:` syntax. + + May increase filesize + type: boolean + default: no + global: yes + config_display: description: | Display width (for image output formats)