mirror of
https://github.com/Kir-Antipov/mc-publish.git
synced 2024-11-22 08:20:58 -05:00
This *generates* warnings for auto-*generated* content
*Did you get it?*
This commit is contained in:
parent
cc3f33cdb2
commit
3367d6a02d
2 changed files with 258 additions and 0 deletions
163
src/utils/auto-generated.ts
Normal file
163
src/utils/auto-generated.ts
Normal file
|
@ -0,0 +1,163 @@
|
|||
import { pad, splitLines, StringPadOptions } from "@/utils/string-utils";
|
||||
import { $i } from "@/utils/collections/iterable";
|
||||
import { DEFAULT_NEWLINE } from "@/utils/environment";
|
||||
|
||||
/**
|
||||
* Options for generating an auto-generated warning frame.
|
||||
*/
|
||||
export interface AutoGeneratedWarningFrameOptions {
|
||||
/**
|
||||
* An optional string representing the name of the source file.
|
||||
*
|
||||
* If provided, this will be displayed in the generated warning message.
|
||||
*/
|
||||
sourceFileName?: string;
|
||||
|
||||
/**
|
||||
* An optional string representing the warning message to display in the generated warning frame.
|
||||
*
|
||||
* If not provided, the default warning message will be used.
|
||||
*/
|
||||
message?: string;
|
||||
|
||||
/**
|
||||
* An optional string or array of strings representing how to align the contents of each line in the generated frame.
|
||||
*
|
||||
* If multiple values are provided, they will be used in order for each successive line.
|
||||
*/
|
||||
align?: StringPadOptions["align"] | StringPadOptions["align"][];
|
||||
|
||||
/**
|
||||
* Options for customizing the style of a frame.
|
||||
*/
|
||||
style?: FrameStyle;
|
||||
|
||||
/**
|
||||
* An optional number representing the maximum length of each line in the generated frame.
|
||||
*
|
||||
* If not provided, the length of each line will not be limited.
|
||||
*/
|
||||
lineWidth?: number;
|
||||
|
||||
/**
|
||||
* An optional string representing the character(s) to use for the newline sequence.
|
||||
*
|
||||
* If not provided, the value of {@link DEFAULT_NEWLINE} (`\r\n` on Windows, `\n` on Unix) will be used.
|
||||
*/
|
||||
newline?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for generating an auto-generated warning frame, with an additional property for toggling whether or not to generate the warning message at all.
|
||||
*/
|
||||
export interface OptionalAutoGeneratedWarningFrameOptions extends AutoGeneratedWarningFrameOptions {
|
||||
/**
|
||||
* A boolean indicating whether or not to generate an auto-generated warning message in the formatted output.
|
||||
*
|
||||
* Defaults to `true`.
|
||||
*/
|
||||
generateAutoGeneratedWarningMessage?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for customizing the style of a frame.
|
||||
*/
|
||||
export interface FrameStyle {
|
||||
/**
|
||||
* An optional string to prepend to each line of the generated frame.
|
||||
*
|
||||
* If not provided, the value of {@link filler} will be used.
|
||||
*/
|
||||
lineStart?: string;
|
||||
|
||||
/**
|
||||
* An optional string representing the character to use for the frame border.
|
||||
*
|
||||
* If not provided, `"#"` will be used.
|
||||
*/
|
||||
filler?: string;
|
||||
|
||||
/**
|
||||
* An optional string to append to each line of the generated frame.
|
||||
*
|
||||
* If not provided, the value of {@link filler} will be used.
|
||||
*/
|
||||
lineEnd?: string;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A predefined frame style for generating YAML-style frames with `#` characters.
|
||||
*/
|
||||
export const YAML_FRAME_STYLE: FrameStyle = { filler: "#" };
|
||||
|
||||
/**
|
||||
* A predefined frame style for generating JavaScript-style multiline comment frames with `/*...*/` syntax.
|
||||
*/
|
||||
export const JS_MULTILINE_FRAME_STYLE: FrameStyle = { lineStart: "/* ", filler: "*", lineEnd: " */" };
|
||||
|
||||
/**
|
||||
* A predefined frame-style for generating JavaScript-style single-line comment frames with `//` syntax.
|
||||
*/
|
||||
export const JS_SINGLELINE_FRAME_STYLE: FrameStyle = { filler: "//" };
|
||||
|
||||
/**
|
||||
* The default frame style to use if no style is specified.
|
||||
*
|
||||
* Uses the `YAML_FRAME_STYLE` style with `#` characters.
|
||||
*/
|
||||
export const DEFAULT_FRAME_STYLE: FrameStyle = YAML_FRAME_STYLE;
|
||||
|
||||
/**
|
||||
* The default alignment settings to use for the contents of each line in the generated frame.
|
||||
*/
|
||||
export const DEFAULT_FRAME_ALIGN = ["center"] as const;
|
||||
|
||||
|
||||
/**
|
||||
* Generates a warning message that indicates the file is auto-generated and should not be edited.
|
||||
*
|
||||
* @param sourceFileName - An optional string that represents the name of the source file. If provided, the warning message will include instructions for modifying the source file instead of the auto-generated file.
|
||||
*
|
||||
* @returns A warning message that indicates the file is auto-generated and should not be edited.
|
||||
*/
|
||||
export function generateAutoGeneratedWarningText(sourceFileName?: string): string {
|
||||
const baseWarning = "WARNING: AUTO-GENERATED FILE - DO NOT EDIT!\n\nPlease be advised that this is an auto-generated file and should NOT be modified. Any changes made to this file WILL BE OVERWRITTEN.";
|
||||
if (!sourceFileName) {
|
||||
return baseWarning;
|
||||
}
|
||||
|
||||
return `${baseWarning}\n\nTo make changes to the contents of this file, please modify the ${sourceFileName} file instead. This will ensure that your changes are properly reflected in the auto-generated file.`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a warning frame containing an auto-generated warning message.
|
||||
*
|
||||
* @param options - Options for generating the warning frame.
|
||||
*
|
||||
* @returns A string representing the generated warning frame.
|
||||
*/
|
||||
export function generateAutoGeneratedWarningFrame(options?: AutoGeneratedWarningFrameOptions): string {
|
||||
const message = options?.message ?? generateAutoGeneratedWarningText(options?.sourceFileName);
|
||||
const align = Array.isArray(options?.align) ? options.align : typeof options?.align === "string" ? [options.align] : DEFAULT_FRAME_ALIGN;
|
||||
const filler = options?.style?.filler ?? DEFAULT_FRAME_STYLE.filler;
|
||||
const lineStart = options?.style?.lineStart ?? `${filler} `;
|
||||
const lineEnd = options?.style?.lineEnd ?? ` ${filler}`;
|
||||
const newline = options?.newline ?? DEFAULT_NEWLINE
|
||||
|
||||
const minLineLength = lineStart.length + lineEnd.length;
|
||||
const maxLineLength = Math.max((options?.lineWidth || 0) - minLineLength, 0);
|
||||
const lines = splitLines(message, { maxLength: maxLineLength });
|
||||
|
||||
const frameSize = $i(lines).map(x => x.length).max() || 0;
|
||||
const fillerCount = Math.ceil(frameSize / filler.length);
|
||||
const frameLine = `${lineStart}${filler.repeat(fillerCount)}${lineEnd}`;
|
||||
const builtFrame = $i(lines)
|
||||
.map((x, i) => pad(x, frameSize, { align: align[Math.min(i, align.length - 1)] }))
|
||||
.map(x => `${lineStart}${x}${lineEnd}`)
|
||||
.append(frameLine)
|
||||
.prepend(frameLine)
|
||||
.join(newline);
|
||||
|
||||
return builtFrame;
|
||||
}
|
95
tests/unit/utils/auto-generated.spec.ts
Normal file
95
tests/unit/utils/auto-generated.spec.ts
Normal file
|
@ -0,0 +1,95 @@
|
|||
import { generateAutoGeneratedWarningText, generateAutoGeneratedWarningFrame, YAML_FRAME_STYLE } from "@/utils/auto-generated";
|
||||
|
||||
describe("generateAutoGeneratedWarningText", () => {
|
||||
test("generates the correct warning text without a source file name", () => {
|
||||
const warning = generateAutoGeneratedWarningText();
|
||||
|
||||
expect(warning).toMatch("WARNING: AUTO-GENERATED FILE - DO NOT EDIT!");
|
||||
expect(warning).not.toMatch("To make changes to the contents of this file, please modify");
|
||||
});
|
||||
|
||||
test("generates the correct warning text with a source file name", () => {
|
||||
const warning = generateAutoGeneratedWarningText("test.ts");
|
||||
|
||||
expect(warning).toMatch("WARNING: AUTO-GENERATED FILE - DO NOT EDIT!");
|
||||
expect(warning).toMatch("To make changes to the contents of this file, please modify the test.ts file instead.");
|
||||
});
|
||||
});
|
||||
|
||||
describe("generateAutoGeneratedWarningFrame", () => {
|
||||
test("generates a warning frame with default options", () => {
|
||||
const frame = generateAutoGeneratedWarningFrame();
|
||||
|
||||
expect(frame).toMatch(/^#\s+WARNING: AUTO-GENERATED FILE - DO NOT EDIT!\s+#$/m);
|
||||
expect(frame).toMatch(/^#\s+Please be advised that this is an auto-generated file and should NOT be modified. Any changes made to this file WILL BE OVERWRITTEN.\s+#$/m);
|
||||
});
|
||||
|
||||
test("generates a warning frame with a custom message", () => {
|
||||
const frame = generateAutoGeneratedWarningFrame({ message: "Custom message" });
|
||||
|
||||
expect(frame).toMatch(/^#\sCustom message\s#$/m);
|
||||
});
|
||||
|
||||
test("generates a warning frame with custom frame style", () => {
|
||||
const frame = generateAutoGeneratedWarningFrame({
|
||||
style: {
|
||||
lineStart: "/** ",
|
||||
filler: "=",
|
||||
lineEnd: " **/",
|
||||
},
|
||||
});
|
||||
expect(frame).toMatch(/^\/\*\*\s=+\s\*\*\/$/m);
|
||||
expect(frame).toMatch(/^\/\*\*\s+WARNING: AUTO-GENERATED FILE - DO NOT EDIT!\s+\*\*\/$/m);
|
||||
expect(frame).toMatch(/^\/\*\*\s+Please be advised that this is an auto-generated file and should NOT be modified. Any changes made to this file WILL BE OVERWRITTEN.\s+\*\*\/$/m);
|
||||
});
|
||||
|
||||
test("generates a warning frame respecting the lineWidth option", () => {
|
||||
const frame = generateAutoGeneratedWarningFrame({ lineWidth: 40 });
|
||||
const lines = frame.split(/\r?\n/);
|
||||
const lineWidths = new Set(lines.map(x => x.length));
|
||||
const lineWidth = [...lineWidths.values()][0];
|
||||
|
||||
expect(lineWidths.size).toBe(1);
|
||||
expect(Math.abs(40 - lineWidth)).toBeLessThanOrEqual(1);
|
||||
});
|
||||
|
||||
test("aligns message to the left when align option is 'left'", () => {
|
||||
const frame = generateAutoGeneratedWarningFrame({ align: "left" });
|
||||
|
||||
expect(frame).toMatch(/^#\sWARNING: AUTO-GENERATED FILE - DO NOT EDIT!\s{2,}#$/m);
|
||||
});
|
||||
|
||||
test("aligns message to the center when align option is 'center'", () => {
|
||||
const frame = generateAutoGeneratedWarningFrame({ align: "center" });
|
||||
|
||||
expect(frame).toMatch(/^#\s{2,}WARNING: AUTO-GENERATED FILE - DO NOT EDIT!\s{2,}#$/m);
|
||||
});
|
||||
|
||||
test("aligns message to the right when align option is 'right'", () => {
|
||||
const frame = generateAutoGeneratedWarningFrame({ align: "right" });
|
||||
|
||||
expect(frame).toMatch(/^#\s{2,}WARNING: AUTO-GENERATED FILE - DO NOT EDIT!\s#$/m);
|
||||
});
|
||||
|
||||
test("uses \\n as newline sequence when newline option is '\\n'", () => {
|
||||
const frame = generateAutoGeneratedWarningFrame({ newline: "\n" });
|
||||
|
||||
expect(frame).toMatch(/\n/);
|
||||
expect(frame).not.toMatch(/\r\n/);
|
||||
});
|
||||
|
||||
test("uses \\r\\n as newline sequence when newline option is '\\r\\n'", () => {
|
||||
const frame = generateAutoGeneratedWarningFrame({ newline: "\r\n" });
|
||||
|
||||
expect(frame).toMatch(/\r\n/);
|
||||
expect(frame).not.toMatch(/[^\r]\n/);
|
||||
});
|
||||
|
||||
test("uses custom string as newline sequence when newline option is a custom string", () => {
|
||||
const frame = generateAutoGeneratedWarningFrame({ newline: "NEWLINE" });
|
||||
|
||||
expect(frame).toMatch(/NEWLINE/);
|
||||
expect(frame).not.toMatch(/\n/);
|
||||
expect(frame).not.toMatch(/\r\n/);
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue