Skip to content

Instantly share code, notes, and snippets.

@bigmistqke
Last active August 28, 2024 19:52
Show Gist options
  • Save bigmistqke/fa473dad0c879bf277b486ce15cceec1 to your computer and use it in GitHub Desktop.
Save bigmistqke/fa473dad0c879bf277b486ce15cceec1 to your computer and use it in GitHub Desktop.
format logs
import { type JSX } from "solid-js";
const LOG_SYMBOL = Symbol("log");
type Log = [source: string, ...styles: string[]] & {
[LOG_SYMBOL]: true;
};
type ValidValue = [string, JSX.CSSProperties?] | Log;
function fragment(array: Log[]): Log {
const source = array.map(([source]) => source).join("");
const styles = array.flatMap(([_, ...rest]) => rest);
return mark([source, ...styles]);
}
function mark(array: [source: string, ...styles: string[]]): Log {
const marked = array as Log;
marked[LOG_SYMBOL] = true;
return marked;
}
function format(template: TemplateStringsArray, ...values: ValidValue[]): Log {
let source = template.reduce((aggregator, current, index) => {
if (index > values.length - 1) {
return `${aggregator}${current}`;
}
return `${aggregator}%c${current}%c${values[index][0]}`;
}, "");
const styles = values.flatMap((value) => {
if (LOG_SYMBOL in value) {
const [_, ...rest] = value;
return ["", "", ...rest];
}
const [_, css] = value;
return ["", css ? stringifyCssProperties(css) : ""];
});
return mark([source, ...styles]);
}
import { type JSX } from "solid-js";
import { fragment, format, type ValidValue } from "./format.ts"
type YamlOptions = {
indentation?: number;
keyStyle?: JSX.CSSProperties;
valueStyle?: JSX.CSSProperties;
offset?: number;
};
function yaml(
value: Record<string, any> | any[],
options: YamlOptions = {},
layer = 0,
): Log {
const {
indentation = 2,
offset = 0,
keyStyle = { color: "darkgrey" },
valueStyle = {},
} = options;
const space: ValidValue = [
whitespace(layer, indentation) + whitespace(offset, 1),
];
if (Array.isArray(value)) {
return fragment(
value.map((value) => {
if (Array.isArray(value)) {
const result = yaml(value, options, layer + 1);
if (indentation < 2) {
return format`${space}-\n${result}`;
}
result[0] = `${whitespace(1, indentation - 2)}${trim(result[0])}`;
return format`${space}- ${result}`;
}
if (typeof value === "object") {
const result = yaml(value, options, layer + 1);
result[0] = trim(result[0]);
return format`${space}- ${result}`;
}
value = typeof value == "string" ? `"${value}"` : value;
return format`${space}- ${[value, valueStyle]}\n`;
}),
);
}
return fragment(
Object.entries(value).map(([key, value]) => {
if (typeof value === "object") {
return format`${space}${[key, keyStyle]}:\n${yaml(value, options, layer + 1)}`;
}
value = typeof value == "string" ? `"${value}"` : value;
return format`${space}${[key, keyStyle]}: ${[value, valueStyle]}\n`;
}),
);
}
function whitespace(amount: number, indentation: number) {
if (amount * indentation < 0) {
return "";
}
return " ".repeat(amount * indentation);
}
function trim(input: string) {
// Use a regular expression to match the first sequence of %c placeholders followed by whitespace
const regex = /((%c)\s*)+/;
// Find the match and then remove all whitespace from that match
const result = input.replace(regex, (match) => {
return match.replace(/\s+/g, ""); // Remove all whitespace in the matched sequence
});
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment