Organize into folders
This commit is contained in:
parent
84b8f1c9d6
commit
2e0d4b45ea
12 changed files with 121 additions and 64 deletions
|
@ -7,7 +7,8 @@
|
|||
},
|
||||
"files": {
|
||||
"ignoreUnknown": false,
|
||||
"ignore": ["*.d.ts", "*.json"]
|
||||
"ignore": ["*.d.ts", "*.json"],
|
||||
"include": ["./src/**/*.ts"]
|
||||
},
|
||||
"formatter": {
|
||||
"enabled": true,
|
||||
|
|
42
src/index.ts
42
src/index.ts
|
@ -1,15 +1,32 @@
|
|||
import { watch } from "node:fs/promises";
|
||||
import {
|
||||
serializePlaybill,
|
||||
ValidatedPlaybillSchema,
|
||||
serializePlaybill,
|
||||
} from "@proscenium/playbill";
|
||||
import chalk from "chalk";
|
||||
import { watch } from "node:fs/promises";
|
||||
import { loadFromBinding, resolveBindingPath } from "./filetypes/binding";
|
||||
import { usage } from "./usage";
|
||||
import { CLIError, MuseError } from "./errors";
|
||||
import { renderAsHTML } from "./renderers/html";
|
||||
import { parseCLIArguments, type CLIArguments } from "./args";
|
||||
import { fullDirname } from "./util/files";
|
||||
import { loadFromBinding, resolveBindingPath } from "#filetypes/binding";
|
||||
import { CLIError, MuseError } from "#lib/errors";
|
||||
import { renderAsHTML } from "#renderers/html";
|
||||
import { type CLIArguments, parseCLIArguments } from "#util/args";
|
||||
import { getAbsoluteDirname } from "#util/files";
|
||||
import { version } from "../package.json" with { type: "json" };
|
||||
|
||||
const usage = `
|
||||
${chalk.bold("muse")} - Compile and validate Playbills for Proscenium
|
||||
${chalk.dim(`v${version}`)}
|
||||
|
||||
Usage:
|
||||
muse [/path/to/binding.yaml] <options>
|
||||
|
||||
Options:
|
||||
--check Only load and check the current binding and resources, but do not compile
|
||||
--write Write the output to a file. If not specified, outputs to stdout
|
||||
--outfile Specify the output file path [default: playbill.json]
|
||||
--verbose, -v Verbose output
|
||||
--minify, -m Minify the output JSON
|
||||
--watch Watch the directory for changes and recompile
|
||||
--help, -h Show this help message
|
||||
`.trim();
|
||||
|
||||
enum ExitCode {
|
||||
Success = 0,
|
||||
|
@ -71,17 +88,14 @@ async function main(): Promise<number> {
|
|||
return ExitCode.Success;
|
||||
}
|
||||
|
||||
// -- ARG VALIDATION -- //
|
||||
if (options.check && options.write) {
|
||||
throw new CLIError("Cannot use --check and --write together");
|
||||
}
|
||||
|
||||
console.log(`Processing ${cliArguments.inputFilePath}`);
|
||||
let lastProcessResult = await processBinding(cliArguments);
|
||||
|
||||
if (options.watch) {
|
||||
const watchDir = fullDirname(cliArguments.inputFilePath);
|
||||
const watchDir = getAbsoluteDirname(cliArguments.inputFilePath);
|
||||
|
||||
console.log(`Watching ${watchDir} for changes`);
|
||||
|
||||
const watcher = watch(watchDir, {
|
||||
recursive: true,
|
||||
});
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import path from "node:path";
|
||||
import {
|
||||
type Playbill,
|
||||
type UnknownResource,
|
||||
getEmptyPlaybill,
|
||||
} from "@proscenium/playbill";
|
||||
import { Glob } from "bun";
|
||||
import z from "zod";
|
||||
import {
|
||||
getEmptyPlaybill,
|
||||
type UnknownResource,
|
||||
type Playbill,
|
||||
} from "@proscenium/playbill";
|
||||
import { loadYAMLFileOrFail } from "../util/files";
|
||||
import { FileNotFoundError } from "#lib/errors";
|
||||
import { loadYAMLFileOrFail } from "#util/files";
|
||||
import { loadResourceFile } from "./resource";
|
||||
import { FileNotFoundError } from "../errors";
|
||||
|
||||
const HTMLRenderOptionsSchema = z.object({
|
||||
styles: z.array(z.string()).optional(),
|
|
@ -27,6 +27,11 @@ export function extractFrontmatter(content: string) {
|
|||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a string of a markdown document, extract the markdown content
|
||||
* @param content The raw markdown content
|
||||
* @returns The markdown content without frontmatter
|
||||
*/
|
||||
export function extractMarkdown(content: string): string {
|
||||
if (content.trim().indexOf("---") !== 0) {
|
||||
return content;
|
||||
|
@ -54,6 +59,12 @@ ${markdown.trim()}
|
|||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a string of markdown, convert it to HTML
|
||||
*
|
||||
* @param markdown The markdown to convert
|
||||
* @returns A promise resolving to the HTML representation of the markdown
|
||||
*/
|
||||
export async function markdownToHtml(markdown: string): Promise<string> {
|
||||
const rendered = await unified()
|
||||
.use(remarkParse)
|
|
@ -1,13 +1,13 @@
|
|||
import {
|
||||
ResourceMap,
|
||||
type UnknownResource,
|
||||
UnknownResourceSchema,
|
||||
ResourceMap,
|
||||
} from "@proscenium/playbill";
|
||||
import YAML, { YAMLParseError } from "yaml";
|
||||
import { ZodError } from "zod";
|
||||
import { MalformedResourceFileError } from "../errors";
|
||||
import { MalformedResourceFileError } from "#lib/errors";
|
||||
import { loadFileOrFail } from "#util/files";
|
||||
import { extractFrontmatter, extractMarkdown } from "./markdown";
|
||||
import { loadFileOrFail } from "../util/files";
|
||||
|
||||
type FileFormat = "yaml" | "markdown";
|
||||
|
|
@ -6,14 +6,14 @@ import type {
|
|||
Rule,
|
||||
ValidatedPlaybill,
|
||||
} from "@proscenium/playbill";
|
||||
import { markdownToHtml } from "../filetypes/markdown";
|
||||
import type { PlaybillBinding } from "../filetypes/binding";
|
||||
import rehypeParse from "rehype-parse";
|
||||
import { unified } from "unified";
|
||||
import rehypeFormat from "rehype-format";
|
||||
import rehypeStringify from "rehype-stringify";
|
||||
import type { PlaybillBinding } from "lib/binding";
|
||||
import { markdownToHtml } from "lib/markdown";
|
||||
import capitalize from "lodash-es/capitalize";
|
||||
import { FileNotFoundError } from "../errors";
|
||||
import rehypeFormat from "rehype-format";
|
||||
import rehypeParse from "rehype-parse";
|
||||
import rehypeStringify from "rehype-stringify";
|
||||
import { unified } from "unified";
|
||||
import { FileNotFoundError } from "#lib/errors";
|
||||
|
||||
async function renderGuide(guide: Guide): Promise<string> {
|
||||
const html = await markdownToHtml(guide.description);
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
import { z } from "zod";
|
||||
|
||||
const Renderers = ["json", "html"] as const;
|
||||
export const RendererSchema = z.enum(Renderers);
|
||||
export type Renderer = "json" | "html";
|
18
src/usage.ts
18
src/usage.ts
|
@ -1,18 +0,0 @@
|
|||
import chalk from "chalk";
|
||||
import { version } from "../package.json" with { type: "json" };
|
||||
|
||||
export const usage = `
|
||||
${chalk.bold("muse")} - Compile and validate Playbills for Proscenium
|
||||
${chalk.dim(`v${version}`)}
|
||||
|
||||
Usage:
|
||||
muse [/path/to/binding.yaml] <options>
|
||||
|
||||
Options:
|
||||
--check Only load and check the current binding and resources, but do not compile
|
||||
--write Write the output to a file. If not specified, outputs to stdout
|
||||
--outfile Specify the output file path [default: playbill.json]
|
||||
--verbose, -v Verbose output
|
||||
--minify, -m Minify the output JSON
|
||||
--help, -h Show this help message
|
||||
`.trim();
|
|
@ -1,7 +1,14 @@
|
|||
import { parseArgs } from "node:util";
|
||||
import { RendererSchema, type Renderer } from "./types";
|
||||
import { MuseError } from "./errors";
|
||||
import { z } from "zod";
|
||||
import { CLIError, MuseError } from "#lib/errors";
|
||||
|
||||
const Renderers = ["json", "html"] as const;
|
||||
const RendererSchema = z.enum(Renderers);
|
||||
type Renderer = z.infer<typeof RendererSchema>;
|
||||
|
||||
/**
|
||||
* A shape representing the arguments passed to the CLI
|
||||
*/
|
||||
export interface CLIArguments {
|
||||
inputFilePath: string;
|
||||
|
||||
|
@ -16,6 +23,14 @@ export interface CLIArguments {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an array of CLI arguments, parse them into a structured object
|
||||
*
|
||||
* @param argv The arguments to parse
|
||||
* @returns The parsed CLI arguments
|
||||
*
|
||||
* @throws {CLIError} if the arguments are invalid
|
||||
*/
|
||||
export function parseCLIArguments(argv: string[]): CLIArguments {
|
||||
const { values: options, positionals: args } = parseArgs({
|
||||
args: argv,
|
||||
|
@ -59,6 +74,11 @@ export function parseCLIArguments(argv: string[]): CLIArguments {
|
|||
allowPositionals: true,
|
||||
});
|
||||
|
||||
// -- ARG VALIDATION -- //
|
||||
if (options.check && options.write) {
|
||||
throw new CLIError("Cannot use --check and --write together");
|
||||
}
|
||||
|
||||
const parsedRenderer = RendererSchema.safeParse(options.renderer);
|
||||
|
||||
if (!parsedRenderer.success) {
|
|
@ -1,7 +1,14 @@
|
|||
import YAML from "yaml";
|
||||
import { FileError, FileNotFoundError } from "../errors";
|
||||
import path from "node:path";
|
||||
import YAML from "yaml";
|
||||
import { FileError, FileNotFoundError } from "../lib/errors";
|
||||
|
||||
/**
|
||||
* Load a file from the filesystem or throw an error if it does not exist.
|
||||
* @param filePath The path to the file to load
|
||||
* @returns The contents of the file as a string
|
||||
*
|
||||
* @throws {FileNotFoundError} if the file does not exist
|
||||
*/
|
||||
export async function loadFileOrFail(filePath: string): Promise<string> {
|
||||
const fileToLoad = Bun.file(filePath);
|
||||
const fileExists = await fileToLoad.exists();
|
||||
|
@ -13,6 +20,15 @@ export async function loadFileOrFail(filePath: string): Promise<string> {
|
|||
return await fileToLoad.text();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load and parse a YAML file or throw an error if the file doesnt exist
|
||||
* or the yaml fails to parse
|
||||
* @param filePath The path to the file to load
|
||||
* @returns The parsed contents of the file
|
||||
*
|
||||
* @throws {FileNotFoundError} if the file does not exist
|
||||
* @throws {FileError} if the file is not valid YAML
|
||||
*/
|
||||
export async function loadYAMLFileOrFail(filePath: string): Promise<unknown> {
|
||||
try {
|
||||
return YAML.parse(await loadFileOrFail(filePath));
|
||||
|
@ -21,6 +37,12 @@ export async function loadYAMLFileOrFail(filePath: string): Promise<unknown> {
|
|||
}
|
||||
}
|
||||
|
||||
export function fullDirname(inputPath: string): string {
|
||||
return path.resolve(path.dirname(inputPath));
|
||||
/**
|
||||
* Returns the absolute path of the directory containing the given file
|
||||
*
|
||||
* @param filePath The path to the file
|
||||
* @returns The absolute path of the directory containing the file
|
||||
*/
|
||||
export function getAbsoluteDirname(filePath: string): string {
|
||||
return path.resolve(path.dirname(filePath));
|
||||
}
|
||||
|
|
|
@ -22,6 +22,18 @@
|
|||
// Some stricter flags (disabled by default)
|
||||
"noUnusedLocals": false,
|
||||
"noUnusedParameters": false,
|
||||
"noPropertyAccessFromIndexSignature": false
|
||||
"noPropertyAccessFromIndexSignature": false,
|
||||
"baseUrl": "./src",
|
||||
"paths": {
|
||||
"#lib/*": [
|
||||
"./lib/*"
|
||||
],
|
||||
"#renderers/*": [
|
||||
"./renderers/*"
|
||||
],
|
||||
"#util/*": [
|
||||
"./util/*"
|
||||
],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue