From eb5e78346e894f742d08245ed6dda9baf4093e3a Mon Sep 17 00:00:00 2001 From: Hamcha Date: Wed, 23 Aug 2023 19:21:22 +0200 Subject: [PATCH] add build setup --- .gitignore | 1 + domutil.ts | 1 + makeDOM.ts | 8 +++--- scripts/build.ts | 68 ++++++++++++++++++++++++++++++++++++++++++++++++ tsconfig.json | 21 +++++++++++++++ 5 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 .gitignore create mode 100644 domutil.ts create mode 100644 scripts/build.ts create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7773828 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +dist/ \ No newline at end of file diff --git a/domutil.ts b/domutil.ts new file mode 100644 index 0000000..e133efb --- /dev/null +++ b/domutil.ts @@ -0,0 +1 @@ +export * from "./makeDOM"; diff --git a/makeDOM.ts b/makeDOM.ts index 8df375a..b80bfe9 100644 --- a/makeDOM.ts +++ b/makeDOM.ts @@ -16,7 +16,7 @@ type WithClassOrId = | `${T}#${string}` | `${T}.${string}`; -export default function $el( +export function $el( name: T | WithClassOrId, ...desc: [Partial>, ...DOMElem[]] | DOMElem[] ): HTMLElementTagNameMap[T] { @@ -45,7 +45,7 @@ export default function $el( const attributes = desc[0]; if (typeof attributes === "object" && !(attributes instanceof Node)) { for (const attr in attributes) { - const value = attributes[attr]; + const value = (attributes as Record)[attr]; if (attr.startsWith("@")) { el.addEventListener(attr.substring(1), value); } else if (attr === "dataset") { @@ -53,7 +53,7 @@ export default function $el( el.dataset[key] = value[key]; } } else { - el[attr] = value; + el[attr as keyof HTMLElementTagNameMap[T]] = value; } } desc.shift(); @@ -65,3 +65,5 @@ export default function $el( return el; } + +export default $el; diff --git a/scripts/build.ts b/scripts/build.ts new file mode 100644 index 0000000..984276d --- /dev/null +++ b/scripts/build.ts @@ -0,0 +1,68 @@ +import { build, stop } from "https://deno.land/x/esbuild@v0.19.2/mod.js"; +import ts from "npm:typescript"; + +// from https://github.com/Microsoft/TypeScript/issues/6387#issuecomment-169739615 +function error(diagnostics: ts.Diagnostic[]): void { + diagnostics.forEach((diagnostic) => { + let message = "Error"; + if (diagnostic.file) { + const { line, character } = diagnostic.file.getLineAndCharacterOfPosition( + diagnostic.start || 0 + ); + message += ` ${diagnostic.file.fileName} (${line + 1},${character + 1})`; + } + message += + ": " + ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"); + console.log(message); + }); +} + +async function readConfigFile(configFileName: string) { + const configFileText = await Deno.readTextFile(configFileName); + const result = ts.parseConfigFileTextToJson(configFileName, configFileText); + if (result.error) { + error([result.error]); + Deno.exit(1); + } + + const config = ts.parseJsonConfigFileContent( + result.config, + ts.sys, + await Deno.realPath(".") + ); + if (config.errors.length > 0) { + error(config.errors); + Deno.exit(1); + } + return config; +} + +async function buildDTS() { + const config = await readConfigFile("./tsconfig.json"); + const emitted = ts + .createProgram(config.fileNames, { + ...config.options, + emitDeclarationOnly: true, + }) + .emit(); + if (emitted.diagnostics.length > 0) { + error(emitted.diagnostics.slice()); + Deno.exit(1); + } +} + +async function buildESM() { + await build({ + bundle: true, + minify: true, + keepNames: true, + target: "es2017", // Required because OBS ships with a really old version of Chrome + entryPoints: ["./domutil.ts"], + outfile: "./dist/domutil.js", + format: "esm", + sourcemap: true, + }); + await stop(); +} + +await Promise.all([buildDTS(), buildESM()]); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..6aa1f25 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "ES2017", + "module": "ES2020", + "moduleResolution": "node", + "declaration": true, + "strict": true, + "noImplicitAny": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "strictBindCallApply": true, + "strictPropertyInitialization": true, + "noImplicitThis": true, + "alwaysStrict": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "outDir": "./dist", + "lib": ["ES2017", "dom"] + }, + "exclude": ["dist", "scripts"], +}