feat(banners-lib): ✨ basic title and subtitle manipulation
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<a href="packages/banners/test.html">Test</a>
|
||||
<h1> Hello, world </h1>
|
||||
</body>
|
||||
|
||||
|
||||
@@ -1,2 +1,97 @@
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('Hello world from the package!');
|
||||
/**
|
||||
* @typedef {import('./index.js').BannerObject} BannerObject
|
||||
*/
|
||||
import getLocalLayout from './layouts.js';
|
||||
|
||||
/**
|
||||
* @param {Readonly<string>} string - The string to be converted.
|
||||
* @param {Document} document - The document API to be used.
|
||||
* @returns {HTMLElement} - The DOM of the string.
|
||||
*/
|
||||
function stringToHtml(string, document) {
|
||||
const tmp = document.createElement('template');
|
||||
tmp.innerHTML = string;
|
||||
/** @type {HTMLElement} */
|
||||
const dom = tmp.children[0];
|
||||
return dom;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {HTMLElement} element - The element to be converted to string.
|
||||
* @param {Document} document - The document API to be used.
|
||||
* @returns {string} - The resulting string.
|
||||
*/
|
||||
function htmlToString(element, document) {
|
||||
const tmp = document.createElement('template');
|
||||
tmp.appendChild(element);
|
||||
return tmp.innerHTML;
|
||||
}
|
||||
/**
|
||||
* @typedef {{
|
||||
* modify(query: string, callback: (el: Element | null) => T) => T
|
||||
* }} DOMHelper
|
||||
* @param {HTMLElement} element - The element to be manipulated.
|
||||
* @returns {DOMHelper}
|
||||
*/
|
||||
function domHelper(element) {
|
||||
return {
|
||||
/**
|
||||
* @template T
|
||||
* @param {string} query - The query selector to find the element.
|
||||
* @param {(el: Element | null) => T} callback - Callback to modify the element.
|
||||
* @returns {T} - The return value of the callback.
|
||||
* @throws {Error} - Throws if the element is not found.
|
||||
*/
|
||||
modify(query, callback) {
|
||||
const el = element.querySelector(query);
|
||||
|
||||
return callback(el);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {BannerObject} object - The Banner Object to be generated from.
|
||||
* @returns {Promise<string>} - The SVG of the banner.
|
||||
*/
|
||||
async function banner(object) {
|
||||
/** @type {Document} */
|
||||
// @ts-expect-error because Document is not compatible with Readonly<Document>
|
||||
const doc = object.lib?.document ?? globalThis.document;
|
||||
/** @type {Readonly<string>} */
|
||||
const svg = await getLocalLayout('vertical');
|
||||
|
||||
const dom = stringToHtml(svg, doc);
|
||||
const helper = domHelper(dom);
|
||||
|
||||
helper.modify('[data-banner-class="title"] > tspan', (el) => {
|
||||
if (!el) return;
|
||||
|
||||
el.innerHTML = object.title;
|
||||
});
|
||||
helper.modify('[data-banner-class="subtitle"] > tspan', (el) => {
|
||||
if (!el) return;
|
||||
el.innerHTML = object.subtitle ?? '';
|
||||
});
|
||||
return htmlToString(dom, doc);
|
||||
}
|
||||
/**
|
||||
* Test function.
|
||||
*/
|
||||
async function test() {
|
||||
const testBanner = await banner({
|
||||
lib: {
|
||||
// @ts-expect-error because Document is not DeepReadonly<Document>
|
||||
document: new Document(),
|
||||
fetch,
|
||||
},
|
||||
title: 'Hello, world',
|
||||
});
|
||||
|
||||
const body = globalThis.document.getElementsByTagName('body')[0];
|
||||
body.innerHTML = testBanner;
|
||||
}
|
||||
await test();
|
||||
|
||||
export default banner;
|
||||
|
||||
|
||||
27
packages/banners/src/layouts.js
Normal file
27
packages/banners/src/layouts.js
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
/**
|
||||
* Imports a local layout from the static folder.
|
||||
*
|
||||
* @param {import('./types.d.ts').BuiltinLayouts} layout - The banner layout.
|
||||
* @param {boolean} [rtl] - Is the layout right-to-left?
|
||||
* @returns {Promise<string>} - The SVG string of the layout file.
|
||||
*/
|
||||
async function getLocalLayout(layout, rtl = false) {
|
||||
let layoutFile;
|
||||
/* eslint-disable import/no-relative-parent-imports */
|
||||
switch (layout) {
|
||||
case 'vertical': {
|
||||
layoutFile = await import('../static/vertical.svg.js');
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (rtl)
|
||||
layoutFile = await import('../static/horizontal-rtl.svg.js');
|
||||
layoutFile = await import('../static/horizontal.svg.js');
|
||||
}
|
||||
}
|
||||
/* eslint-enable */
|
||||
|
||||
return layoutFile.default;
|
||||
}
|
||||
export default getLocalLayout;
|
||||
13
packages/banners/test.html
Normal file
13
packages/banners/test.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title></title>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<script type="module" src="src/index.js"></script>
|
||||
</head>
|
||||
|
||||
<body></body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user