diff --git a/website/config/og/basic/RobotoMono-Variable.ttf b/website/config/og/basic/RobotoMono-Variable.ttf new file mode 100644 index 0000000000..d2b4746196 Binary files /dev/null and b/website/config/og/basic/RobotoMono-Variable.ttf differ diff --git a/website/config/og/basic/template.json b/website/config/og/basic/template.json index 80fc4f6161..bf0c45b0f8 100644 --- a/website/config/og/basic/template.json +++ b/website/config/og/basic/template.json @@ -1,11 +1,22 @@ { "image": "preview.png", - "font": "RobotoMono-Bold.ttf", + "font": "RobotoMono-Variable.ttf", "layout": [ { "name": "title", - "top": 400, - "left": 210 + "transform": "translate(100, 350)", + "fontSize": 54, + "fontWeight": 600, + "fill": "white", + "stroke": "white" + }, + { + "name": "id", + "transform": "translate(100, 400)", + "fontSize": 42, + "fontWeight": 400, + "fill": "#b0b6a4", + "stroke": "#b0b6a4" } ] } diff --git a/website/plugins/docusaurus-plugin-og/font.js b/website/plugins/docusaurus-plugin-og/font.js index a6477a71bb..d636fd53d6 100644 --- a/website/plugins/docusaurus-plugin-og/font.js +++ b/website/plugins/docusaurus-plugin-og/font.js @@ -1,33 +1,22 @@ const { resolve } = require("path"); -const textToSVG = require("text-to-svg"); +const { getFontFace } = require("./svg"); function createFontsMapFromTemplates(templates) { const fonts = new Map(); templates.forEach((template) => { if (!fonts.has(template.params.font)) { - fonts.set( - template.params.font, - textToSVG.loadSync(resolve(template.path, template.name, template.params.font)), - ); + // trunc file extension + const fontName = template.params.font.slice(0, -4); + fonts.set(template.params.font, { + name: fontName, + declaration: getFontFace( + fontName, + resolve(template.path, template.name, template.params.font), + ), + }); } }); return fonts; } -function createSVGText( - font, - text, - { fontSize = 72, fill = "white", stroke = "white" }, - widthLimit = 1000, -) { - const attributes = { fill, stroke }; - const options = { fontSize, anchor: "top", attributes }; - // Remove all emoji from text - const filteredText = text.replace( - /([\u2700-\u27BF]|[\uE000-\uF8FF]|\uD83C[\uDC00-\uDFFF]|\uD83D[\uDC00-\uDFFF]|[\u2011-\u26FF]|\uD83E[\uDD10-\uDDFF])/g, - "", - ); - - return font.getSVG(filteredText, options); -} -module.exports = { createSVGText, createFontsMapFromTemplates }; +module.exports = { createFontsMapFromTemplates }; diff --git a/website/plugins/docusaurus-plugin-og/layout.js b/website/plugins/docusaurus-plugin-og/layout.js index 0d4ca790e7..e7a7da0a2c 100644 --- a/website/plugins/docusaurus-plugin-og/layout.js +++ b/website/plugins/docusaurus-plugin-og/layout.js @@ -1,5 +1,5 @@ -const { createSVGText } = require("./font"); const { Logger } = require("./utils"); +const { textToSVG } = require("./svg"); function createLayoutLayers(doc, layout, previewFont, textWidthLimit) { /* Check for all layers names exist in doc fields */ @@ -13,14 +13,16 @@ function createLayoutLayers(doc, layout, previewFont, textWidthLimit) { fontSize: layer.fontSize, fill: layer.fill, stroke: layer.stroke, + transform: layer.transform, + fontWeight: layer.fontWeight, }; return { input: Buffer.from( - createSVGText(previewFont, doc[layer.name], layoutOptions, textWidthLimit), + textToSVG(previewFont, doc[layer.name], layoutOptions, textWidthLimit), ), - top: layer.top, - left: layer.left, + top: layer.top || 0, + left: layer.left || 0, }; }); } diff --git a/website/plugins/docusaurus-plugin-og/svg.js b/website/plugins/docusaurus-plugin-og/svg.js new file mode 100644 index 0000000000..334e339986 --- /dev/null +++ b/website/plugins/docusaurus-plugin-og/svg.js @@ -0,0 +1,93 @@ +const XMLSpecifiedSymbols = [ + { from: "&", to: "&" }, + { from: ">", to: ">" }, + { from: "<", to: "<" }, +]; + +// prevent errors while parsing XML svg object +function isolateXMLSpecifiedSymbols(text) { + return XMLSpecifiedSymbols.reduce( + (result, char) => result.replace(new RegExp(char.from), char.to), + text, + ); +} + +function SVGText(text, font) { + return ` + + ${isolateXMLSpecifiedSymbols(text)} + `; +} + +function getFontFace(fontName, path) { + return ` + + + + + + `; +} + +function getTextWidth(text, options) { + return ((options.fontSize * 400) / options.fontWeight) * 0.9 * text.length; +} + +function textToSVG(font, text, options, widthLimit = 1300, textPaddingTop = -70) { + const filteredText = text.replace( + /([\u2700-\u27BF]|[[\uE000-\uF8FF]|\uD83C[\uDC00-\uDFFF]|\uD83D[\uDC00-\uDFFF]|\uD83E[\uDD10-\uDDFF])/g, + "", + ); + + let svg = ``; + svg += font.declaration; + + if (getTextWidth(text, options) > widthLimit) { + const reformat = filteredText.split(" ").reduce( + (acc, cur) => { + if (getTextWidth(`${acc.temp} ${cur}`, options) < widthLimit) { + return { ...acc, temp: `${acc.temp} ${cur}` }; + } + + return { + temp: cur, + result: [...acc.result, acc.temp], + }; + }, + { + temp: "", + result: [], + }, + ); + svg += SVGText(reformat.temp, { + ...options, + name: font.name, + }); + for (let i = reformat.result.length - 1; i >= 0; i--) { + svg += SVGText(reformat.result[i], { + ...options, + transform: `${options.transform} translate(0, ${ + (reformat.result.length - i) * textPaddingTop + })`, + name: font.name, + }); + } + + console.error(filteredText, reformat.result, reformat.temp); + } else svg += SVGText(filteredText, { ...options, name: font.name }); + svg += ``; + + return svg; +} + +module.exports = { textToSVG, getFontFace }; diff --git a/website/plugins/docusaurus-plugin-og/template.js b/website/plugins/docusaurus-plugin-og/template.js index 531a921a82..d9738657be 100644 --- a/website/plugins/docusaurus-plugin-og/template.js +++ b/website/plugins/docusaurus-plugin-og/template.js @@ -40,11 +40,13 @@ async function getTemplates(templatesDir, encode = "utf8") { const Layout = object({ type: optional(string()), name: string(), - fontSize: optional(number()), fill: optional(string()), stroke: optional(string()), - top: number(), - left: number(), + top: optional(number()), + left: optional(number()), + transform: optional(string()), + fontSize: optional(number()), + fontWeight: optional(number()), }); const Template = object({