refactor(text-rendering): ♻️ use embeded fonts
Removed the text to path conversion, it was too complicated to align the generated paths with the dynamic layouts' texts. So embeded font files using data URIs is being used, this is experimental and a "quick-fix", because data URIs could be not compatible and/or work in some environments and browsers. A comment and/or issue with more details about this will be created.
This commit is contained in:
@@ -5,7 +5,6 @@
|
||||
<title></title>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="css/style.css" rel="stylesheet">
|
||||
<!-- auto-refresh in dev -->
|
||||
<!-- <script type="text/javascript" src="https://livejs.com/live.js"></script> -->
|
||||
<script type="module" src="./packages/banners/src/index.js"></script>
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
"@commitlint/config-conventional": "^18.4.3",
|
||||
"@commitlint/types": "^18.4.3",
|
||||
"@vercel/node": "^3.0.11",
|
||||
"cal-sans": "^1.0.1",
|
||||
"eslint": "^8.54.0",
|
||||
"husky": "^8.0.0",
|
||||
"turbo": "^1.10.16",
|
||||
|
||||
@@ -16,8 +16,5 @@
|
||||
"@types/node": "^20.10.0",
|
||||
"eslint": "^8.54.0",
|
||||
"linkedom": "^0.16.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fredli74/typr": "^0.3.8"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
*/
|
||||
import getLocalLayout from './layouts.js';
|
||||
import { isValidIcon } from './utils.js';
|
||||
import fontSvg from './text-svg.js';
|
||||
|
||||
/**
|
||||
* @param {Readonly<string>} string - The string to be converted.
|
||||
@@ -106,7 +105,7 @@ function regexHelper(string) {
|
||||
* @returns {[number, number]}
|
||||
*/
|
||||
getTranslate() {
|
||||
if (!string.includes('translate')) return [ 0, 0 ];
|
||||
if (!string.includes('translate')) return [0, 0];
|
||||
|
||||
const translateRegex = /translate\((?:[^,]+),(?:[^)]+)\)/gu;
|
||||
|
||||
@@ -122,6 +121,25 @@ function regexHelper(string) {
|
||||
/* eslint-enable */
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
async function getSvgCSS() {
|
||||
const buffer = await fetch(
|
||||
import.meta.resolve('/packages/banners/static/CalSans-SemiBold.ttf'),
|
||||
);
|
||||
// eslint-disable-next-line unicorn/prefer-code-point, max-len
|
||||
const base64 = btoa(String.fromCharCode(...new Uint8Array(await buffer.arrayBuffer())));
|
||||
|
||||
const css = `
|
||||
@font-face {
|
||||
font-family: 'Cal Sans';
|
||||
src: url('data:application/x-font-ttf;base64,${base64}') format('truetype');
|
||||
}
|
||||
`;
|
||||
return css;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {BannerObject} object - The Banner Object to be generated from.
|
||||
* @returns {Promise<string>} - The SVG of the banner.
|
||||
@@ -134,15 +152,19 @@ async function banner(object) {
|
||||
// @ts-expect-error because fetch is Readonly in Banner object;
|
||||
const lFetch = object.lib?.fetch ?? globalThis.fetch;
|
||||
/** @type {Readonly<string>} */
|
||||
const svg = await getLocalLayout('horizontal');
|
||||
const layoutSvg = await getLocalLayout('horizontal');
|
||||
|
||||
const dom = stringToHtml(svg, doc);
|
||||
const dom = stringToHtml(layoutSvg, doc);
|
||||
const helper = domHelper(dom);
|
||||
|
||||
await helper.asyncModify('svg > defs', async el =>
|
||||
el?.appendChild(stringToHtml(`<style>${await getSvgCSS()}</style>`, doc)),
|
||||
);
|
||||
|
||||
await helper.asyncModify('[data-banner-class="icon"]', async (el) => {
|
||||
if (!el || !object.icon || !isValidIcon(object.icon)) return;
|
||||
|
||||
const [ iconSet, iconName ] = object.icon.split(':');
|
||||
const [iconSet, iconName] = object.icon.split(':');
|
||||
|
||||
const res = await lFetch(`https://api.iconify.design/${iconSet}/${iconName}.svg`);
|
||||
|
||||
@@ -171,7 +193,6 @@ async function banner(object) {
|
||||
|
||||
el.parentElement?.setAttribute('transform', `${transform ?? ''} translate(${coords.join(',')})`);
|
||||
|
||||
|
||||
const styles = el.getAttribute('style');
|
||||
const size = regexHelper(styles ?? '').getFontSize();
|
||||
|
||||
@@ -199,8 +220,6 @@ async function banner(object) {
|
||||
},
|
||||
);
|
||||
|
||||
dom.appendChild(stringToHtml(`<g transform="translate(30, 40)"><path d="${fontSvg}" transform="scale(0.01, -0.01)" fill="#ff0000" /></g>`, doc));
|
||||
|
||||
return htmlToString(dom, doc);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
import * as typr from '@fredli74/typr';
|
||||
|
||||
const buffer = await fetch(
|
||||
import.meta.resolve('/packages/banners/static/CalSans-SemiBold.ttf'),
|
||||
);
|
||||
const font = new typr.Font(await buffer.arrayBuffer());
|
||||
const glyhps = font.stringToGlyphs('Hello world');
|
||||
|
||||
const path = font.glyphsToPath(glyhps);
|
||||
const svg = font.pathToSVG(path);
|
||||
|
||||
export default svg;
|
||||
|
||||
|
||||
15
pnpm-lock.yaml
generated
15
pnpm-lock.yaml
generated
@@ -24,6 +24,9 @@ importers:
|
||||
'@vercel/node':
|
||||
specifier: ^3.0.11
|
||||
version: 3.0.11
|
||||
cal-sans:
|
||||
specifier: ^1.0.1
|
||||
version: 1.0.1
|
||||
eslint:
|
||||
specifier: ^8.54.0
|
||||
version: 8.54.0
|
||||
@@ -41,10 +44,6 @@ importers:
|
||||
version: 0.34.6
|
||||
|
||||
packages/banners:
|
||||
dependencies:
|
||||
'@fredli74/typr':
|
||||
specifier: ^0.3.8
|
||||
version: 0.3.8
|
||||
devDependencies:
|
||||
'@types/node':
|
||||
specifier: ^20.10.0
|
||||
@@ -601,10 +600,6 @@ packages:
|
||||
engines: {node: '>=14'}
|
||||
dev: true
|
||||
|
||||
/@fredli74/typr@0.3.8:
|
||||
resolution: {integrity: sha512-0Wr3arrJUOoF5HyE8/nusPsdOQaUEd9t0dq8GTHBgSakuh543VqQklIpuRWF/nEnoxkIJzHpCYYesWTyEqgrFg==}
|
||||
dev: false
|
||||
|
||||
/@humanwhocodes/config-array@0.11.13:
|
||||
resolution: {integrity: sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==}
|
||||
engines: {node: '>=10.10.0'}
|
||||
@@ -1615,6 +1610,10 @@ packages:
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/cal-sans@1.0.1:
|
||||
resolution: {integrity: sha512-XwN3/7jez8WmFVcNnNqO2K9lh133KiIcURCyGFnSM+ZmNZ8zIcOTNfr3SpenLAkRceYsq+fQNX/PL4C1rIkEPQ==}
|
||||
dev: true
|
||||
|
||||
/call-bind@1.0.5:
|
||||
resolution: {integrity: sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==}
|
||||
dependencies:
|
||||
|
||||
Reference in New Issue
Block a user