Skip to content

Commit

Permalink
Improved types
Browse files Browse the repository at this point in the history
  • Loading branch information
FlorianRappl committed Dec 7, 2024
1 parent beaca2e commit c9e288e
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 94 deletions.
69 changes: 32 additions & 37 deletions packages/esbuild-auto-path-plugin/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { Plugin } from "esbuild";
import { readFile } from "fs/promises";
import { isAbsolute, join, resolve } from "path";
import { Plugin } from 'esbuild';
import { readFile } from 'fs/promises';
import { isAbsolute, join, resolve } from 'path';

const fallbackExtensions = [
".png",
".svg",
".jpg",
".jpeg",
".webp",
".mp4",
".mp3",
".ogg",
".wav",
".ogv",
".wasm",
".gif",
'.png',
'.svg',
'.jpg',
'.jpeg',
'.webp',
'.mp4',
'.mp3',
'.ogg',
'.wav',
'.ogv',
'.wasm',
'.gif',
];

interface AutoPathPluginOptions {
Expand All @@ -23,62 +23,57 @@ interface AutoPathPluginOptions {

function makeExtensions(extensions = fallbackExtensions) {
return extensions.reduce((obj, ext) => {
obj[ext] = "file";
obj[ext] = 'file';
return obj;
}, {} as Record<string, "file">);
}, {} as Record<string, 'file'>);
}

export const autoPathPlugin = (options: AutoPathPluginOptions = {}): Plugin => ({
name: "auto-path-plugin",
name: 'auto-path-plugin',
setup(build) {
const { loader = makeExtensions(options.defaultExtensions) } =
build.initialOptions;
const { loader = makeExtensions(options.defaultExtensions) } = build.initialOptions;
const extensions: Array<string> = [];

for (const ext of Object.keys(loader)) {
const l = loader[ext];

if (l === "file") {
if (l === 'file') {
extensions.push(ext);
delete loader[ext];
}
}

const filter = new RegExp(
`(${extensions.map((ext) => `\\${ext}`).join("|")})$`
);
const filter = new RegExp(`(${extensions.map((ext) => `\\${ext}`).join('|')})$`);

build.onResolve({ filter }, (args) => {
if (args.namespace === "ref-stub") {
if (args.namespace === 'ref-stub') {
return {
path: args.path,
namespace: "ref-binary",
namespace: 'ref-binary',
};
} else if (args.resolveDir !== "") {
} else if (args.resolveDir !== '') {
return {
path: isAbsolute(args.path)
? args.path
: join(args.resolveDir, args.path),
path: isAbsolute(args.path) ? args.path : join(args.resolveDir, args.path),
// for CSS we'll just use the path; no intermediate module needed
namespace: args.kind === "url-token" ? "ref-binary" : "ref-stub",
namespace: args.kind === 'url-token' ? 'ref-binary' : 'ref-stub',
};
} else {
return; // Ignore unresolvable paths
}
});

build.onLoad({ filter: /.*/, namespace: "ref-stub" }, async (args) => ({
build.onLoad({ filter: /.*/, namespace: 'ref-stub' }, async (args) => ({
resolveDir: resolve(__dirname),
contents: [
`import path from ${JSON.stringify(args.path)}`,
`import { __bundleUrl__ } from ${JSON.stringify("../set-path.js")}`,
`import { __bundleUrl__ } from ${JSON.stringify('../set-path.js')}`,
`export default __bundleUrl__ + path;`,
].join("\n"),
].join('\n'),
}));

build.onLoad({ filter: /.*/, namespace: "ref-binary" }, async (args) => ({
contents: await readFile(args.path),
loader: "file",
build.onLoad({ filter: /.*/, namespace: 'ref-binary' }, async (args) => ({
contents: (await readFile(args.path)) as unknown as Uint8Array,
loader: 'file',
}));
},
});
94 changes: 37 additions & 57 deletions packages/piral-cli-esbuild/src/plugins/html.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { Plugin } from "esbuild";
import { load, Element, CheerioAPI } from "cheerio";
import { mkdirSync, readFileSync, writeFileSync } from "fs";
import { basename, dirname, extname, resolve } from "path";
import { Plugin } from 'esbuild';
import { load, CheerioAPI } from 'cheerio';
import { mkdirSync, readFileSync, writeFileSync } from 'fs';
import { basename, dirname, extname, resolve } from 'path';

function isLocal(path: string) {
if (path) {
if (path.startsWith(":")) {
if (path.startsWith(':')) {
return false;
} else if (path.startsWith("http:")) {
} else if (path.startsWith('http:')) {
return false;
} else if (path.startsWith("https:")) {
} else if (path.startsWith('https:')) {
return false;
} else if (path.startsWith("data:")) {
} else if (path.startsWith('data:')) {
return false;
}

Expand All @@ -24,8 +24,8 @@ function isLocal(path: string) {
function getName(path: string) {
const name = filename(path);

if (/\.(jsx?|tsx?)$/.test(path) && name === "index") {
return "main";
if (/\.(jsx?|tsx?)$/.test(path) && name === 'index') {
return 'main';
} else {
return name;
}
Expand All @@ -38,64 +38,55 @@ function filename(path: string) {
}

function extractParts(content: CheerioAPI, publicPath: string) {
const sheets = content("link[href][rel=stylesheet]")
.filter((_, e: Element) => isLocal(e.attribs.href))
const sheets = content('link[href][rel=stylesheet]')
.filter((_, e) => isLocal(e.attribs.href))
.remove()
.toArray() as Array<Element>;
const scripts = content("script[src]")
.filter((_, e: Element) => isLocal(e.attribs.src))
.toArray();
const scripts = content('script[src]')
.filter((_, e) => isLocal(e.attribs.src))
.remove()
.toArray() as Array<Element>;
.toArray();
const files = [];
const prefix = publicPath.endsWith("/") ? publicPath : `${publicPath}/`;
const prefix = publicPath.endsWith('/') ? publicPath : `${publicPath}/`;

for (const script of scripts) {
const src = script.attribs.src;
const name = getName(src);
files.push(src);
content("body").append(`<script src="${prefix}${name}.js"></script>`);
content('body').append(`<script src="${prefix}${name}.js"></script>`);
}

for (const sheet of sheets) {
const href = sheet.attribs.href;
const name = filename(href);
files.push(href);
content("head").append(
`<link href="${prefix}${name}.css" rel="stylesheet" />`
);
content('head').append(`<link href="${prefix}${name}.css" rel="stylesheet" />`);
}

return files;
}

function modifyHtmlFile(
rootDir: string,
htmlFile: string,
publicPath: string,
outDir: string
) {
function modifyHtmlFile(rootDir: string, htmlFile: string, publicPath: string, outDir: string) {
const template = resolve(rootDir, htmlFile);
const src = dirname(template);
const dest = resolve(outDir, "index.html");
const templateContent = load(readFileSync(template, "utf8"));
const newEntries = extractParts(templateContent, publicPath).map((entry) =>
resolve(src, entry)
);
templateContent("*")
const dest = resolve(outDir, 'index.html');
const templateContent = load(readFileSync(template, 'utf8'));
const newEntries = extractParts(templateContent, publicPath).map((entry) => resolve(src, entry));
templateContent('*')
.contents()
.filter((_, m) => m.type === "text")
.filter((_, m) => m.type === 'text')
.each((_, m: any) => {
m.nodeValue = m.nodeValue.replace(/\s+/g, " ");
m.nodeValue = m.nodeValue.replace(/\s+/g, ' ');
});
writeFileSync(dest, templateContent.html({}), "utf8");
writeFileSync(dest, templateContent.html({}), 'utf8');
return newEntries;
}

export const htmlPlugin = (): Plugin => ({
name: "html-loader",
name: 'html-loader',
setup(build) {
const rootDir = process.cwd();
const publicPath = build.initialOptions.publicPath || "/";
const publicPath = build.initialOptions.publicPath || '/';
const outDir = build.initialOptions.outdir
? resolve(rootDir, build.initialOptions.outdir)
: dirname(resolve(rootDir, build.initialOptions.outfile));
Expand All @@ -107,18 +98,12 @@ export const htmlPlugin = (): Plugin => ({

if (Array.isArray(entries)) {
const allEntries = [...entries];
allEntries
.forEach((htmlFile, index) => {
if (typeof htmlFile === 'string' && htmlFile.endsWith(".html")) {
const newEntries = modifyHtmlFile(
rootDir,
htmlFile,
publicPath,
outDir
);
allEntries.splice(index, 1, ...newEntries);
}
});
allEntries.forEach((htmlFile, index) => {
if (typeof htmlFile === 'string' && htmlFile.endsWith('.html')) {
const newEntries = modifyHtmlFile(rootDir, htmlFile, publicPath, outDir);
allEntries.splice(index, 1, ...newEntries);
}
});

build.initialOptions.entryPoints = allEntries.reduce((entries, entry) => {
if (typeof entry === 'string') {
Expand All @@ -132,15 +117,10 @@ export const htmlPlugin = (): Plugin => ({
}, {});
} else {
Object.keys(entries)
.filter((m) => entries[m].endsWith(".html"))
.filter((m) => entries[m].endsWith('.html'))
.forEach((m) => {
const htmlFile = entries[m];
const newEntries = modifyHtmlFile(
rootDir,
htmlFile,
publicPath,
outDir
);
const newEntries = modifyHtmlFile(rootDir, htmlFile, publicPath, outDir);
delete entries[m];

for (const entry of newEntries) {
Expand Down

0 comments on commit c9e288e

Please sign in to comment.