-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- add the submodule
/src/fs.ts
that presents utility functions for …
…writing to the filesystem. - update the example build script `/examples/1_html/build.ts` to write the esbuild output to the filesystem.
- Loading branch information
Showing
3 changed files
with
131 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ import { denoPlugins } from "jsr:@luca/[email protected]" | |
import { fromFileUrl } from "jsr:@std/path" | ||
import esbuild from "npm:esbuild" | ||
import { resolveAsUrl } from "../../src/deps.ts" | ||
import { writeOutputFiles } from "../../src/fs.ts" | ||
import { HtmlLoader } from "./loader.ts" | ||
|
||
|
||
|
@@ -11,15 +12,15 @@ const | |
html_file_content = await (await fetch(html_file_path)).text() | ||
|
||
const html_file_loader = new HtmlLoader({ path: fromFileUrl(html_file_path) }) | ||
const js_txt = await html_file_loader.parseToJs(html_file_content) | ||
const html_in_js = await html_file_loader.parseToJs(html_file_content) | ||
|
||
const results = await esbuild.build({ | ||
absWorkingDir: fromFileUrl(this_dir_path), | ||
format: "esm", | ||
target: "esnext", | ||
platform: "browser", | ||
stdin: { | ||
contents: js_txt, | ||
contents: html_in_js, | ||
loader: "ts", | ||
resolveDir: fromFileUrl(resolveAsUrl("./", html_file_path)), | ||
sourcefile: fromFileUrl(html_file_path), | ||
|
@@ -34,11 +35,24 @@ const results = await esbuild.build({ | |
plugins: [...denoPlugins()], | ||
}) | ||
|
||
const js_compiled_text = results.outputFiles[0].text | ||
const html_compiled_text = await html_file_loader.unparseFromJs(js_compiled_text) | ||
console.log("%c" + "bundled html file output:", "color: green; font-weight: bold;") | ||
const | ||
[html_in_js_compiled, ...other_output_files] = results.outputFiles, | ||
html_compiled_text = await html_file_loader.unparseFromJs(html_in_js_compiled.text) | ||
|
||
console.log("%c" + `bundled html file: "0", path: "${html_in_js_compiled.path}"`, "color: green; font-weight: bold;") | ||
console.log(html_compiled_text) | ||
results.outputFiles.slice(1).forEach((js_file, index) => { | ||
console.log("%c" + `bundled js file: ${index}`, "color: green; font-weight: bold;") | ||
other_output_files.forEach((js_file, index) => { | ||
console.log("%c" + `bundled js file: "${index + 1}", path: "${js_file.path}"`, "color: green; font-weight: bold;") | ||
console.log(js_file.text) | ||
}) | ||
|
||
await writeOutputFiles([ | ||
{ | ||
path: html_in_js_compiled.path.replace(/\.js$/, ".html"), | ||
text: html_compiled_text | ||
}, ...other_output_files | ||
], { | ||
dir: "./output/", | ||
log: "verbose", | ||
dryrun: false, | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
export { json_parse, json_stringify, math_min, object_entries, object_fromEntries, object_keys, object_values, promise_all } from "jsr:@oazmi/[email protected]/alias" | ||
export { getUriScheme, joinPaths, relativePath, resolveAsUrl } from "jsr:@oazmi/[email protected]/pathman" | ||
export { console_log, json_parse, json_stringify, math_min, object_entries, object_fromEntries, object_keys, object_values, promise_all } from "jsr:@oazmi/[email protected]/alias" | ||
export { ensureEndSlash, getUriScheme, joinPaths, pathToPosixPath, relativePath, resolveAsUrl, resolvePathFactory } from "jsr:@oazmi/[email protected]/pathman" | ||
export { isArray, isString } from "jsr:@oazmi/[email protected]/struct" | ||
|
||
/** flags used for minifying (or eliminating) debugging logs and asserts, when an intelligent bundler, such as `esbuild`, is used. */ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
/** this submodule contains utility functions for writing esbuild's virtual output to the filesystem. | ||
* | ||
* this submodule is separated from the rest since it performs filesystem operations, which is runtime-dependant, | ||
* and we don't want to impact the portability of the main module. | ||
* | ||
* @module | ||
*/ | ||
|
||
import { ensureFile } from "jsr:@std/[email protected]" | ||
import { console_log, ensureEndSlash, pathToPosixPath, promise_all, resolvePathFactory } from "./deps.ts" | ||
|
||
|
||
/** get the current working directory (`Deno.cwd`) in posix path format. */ | ||
export const getCwdPath = () => { return ensureEndSlash(pathToPosixPath(Deno.cwd())) } | ||
|
||
/** resolve a file path so that it becomes absolute, with unix directory separator ("/"). | ||
* TODO: refactor the name `pathResolve` to `resolvePath` | ||
*/ | ||
export const pathResolve = resolvePathFactory(getCwdPath) | ||
|
||
/** the tuple description of a writable (or appendable) file. | ||
* - the first entry of the array must describe the destination path of the file, | ||
* relative to the directory defined in {@link CreateFilesConfig.dir}). | ||
* - the second entry should be the file's contents, which can either be a `string` text, a `ReadableStream`, or a `Uint8Array` binary. | ||
* - the third and optional entry lets you specify additional {@link Deno.WriteFileOptions | deno specific file writing options}, | ||
* such as `"append"` the new text, or permit the creation (`"create"`) of new file if it doesn't exist, etc... | ||
*/ | ||
export type WritableFileConfig = [ | ||
destination: string, | ||
content: string | Uint8Array, | ||
options?: Deno.WriteFileOptions, | ||
] | ||
|
||
/** configuration options for {@link createFiles}. */ | ||
export interface CreateFilesConfig { | ||
/** the desired output directory. | ||
* if a relative path is provided, then it will be resolved as a path relative to Deno's current working directory. (which is generally where `deno.json` resides.) | ||
*/ | ||
dir?: string | ||
|
||
/** select logging level: | ||
* - `false` or `"none"`: skip logging. | ||
* - `true` or `"basic"`: log what is being carried out at the top level. | ||
* - `"verbose"`: in addition to basic logging, it also logs which files/folders are being copied or generated. | ||
* | ||
* @defaultValue `"basic"` | ||
*/ | ||
log?: boolean | "none" | "basic" | "verbose" | ||
|
||
/** enable `dryrun` if you wish for nothing to be written onto the the filesystem. | ||
* | ||
* @defaultValue `false` | ||
*/ | ||
dryrun?: boolean | ||
} | ||
|
||
/** the in-memory output file description generated by `esbuild`. */ | ||
export interface EsbuildOutputFile { | ||
path: string | ||
text?: string | ||
contents?: Uint8Array | ||
hash?: string | ||
} | ||
|
||
/** print some basic useful information on the console. | ||
* the print will only appear if the logging-level is either set to `"basic"` or `"verbose"` via {@link setLog} | ||
*/ | ||
const logBasic = (log_level: NonNullable<CreateFilesConfig["log"]>, ...data: any[]): void => { | ||
if (log_level === "basic" || log_level === "verbose") { console_log(...data) } | ||
} | ||
|
||
/** print verbose details on the console. | ||
* the print will only appear if the logging-level is either set to `"verbose"` via {@link setLog} | ||
*/ | ||
const logVerbose = (log_level: NonNullable<CreateFilesConfig["log"]>, ...data: any[]): void => { | ||
if (log_level === "verbose") { console_log(...data) } | ||
} | ||
|
||
/** write a collection of virtual files to your filesystem. | ||
* this function accepts virtual files that are either in text (`string`), binary (`Uint8Array`), or streamable text/binary (`ReadableStream<string | Uint8Array>`) formats. | ||
* it is important that you provide the configuration parameter's {@link config["dir"] | `dir`} field, so that relative paths can be resolved according to the provided directory. | ||
*/ | ||
export const createFiles = async (virtual_files: Array<WritableFileConfig>, config: CreateFilesConfig = {}): Promise<void> => { | ||
const { dir = "./", log = "basic", dryrun = false } = config | ||
// writing text or binary files | ||
logBasic(log, "[in-fs] writing additional text/binary files to your build directory") | ||
await promise_all(virtual_files.map(async ([dst_path, content, options]) => { | ||
const abs_dst = pathResolve(dir, dst_path) | ||
logVerbose(log, `[in-fs] writing file to: "${abs_dst}"`, "with the configuration:", options) | ||
if (!dryrun) { | ||
await ensureFile(abs_dst) | ||
if (typeof content === "string") { | ||
await Deno.writeTextFile(abs_dst, content, options) | ||
} else { | ||
await Deno.writeFile(abs_dst, content, options) | ||
} | ||
} | ||
})) | ||
} | ||
|
||
export const writeOutputFiles = async (virtual_files: Array<EsbuildOutputFile>, config: CreateFilesConfig = {}): Promise<void> => { | ||
return createFiles(virtual_files.map((virtual_file): WritableFileConfig => { | ||
const | ||
{ path, contents, text } = virtual_file, | ||
content = contents ?? text ?? "" | ||
return [path, content] | ||
}), config) | ||
} |