Skip to content

Instantly share code, notes, and snippets.

@mary-ext
Last active August 15, 2024 14:50
Show Gist options
  • Save mary-ext/a83c0c207b5e4d221d8303fb4821988d to your computer and use it in GitHub Desktop.
Save mary-ext/a83c0c207b5e4d221d8303fb4821988d to your computer and use it in GitHub Desktop.
JS console text formatter for web and Deno
export type FormatAttributes = {
'color'?: string;
'font-style'?: string;
'font-weight'?: string;
'text-decoration'?: string;
};
export interface FormattedContent {
children: string | (string | FormattedContent)[];
attrs: FormatAttributes;
}
export type Content = string | FormattedContent | (string | FormattedContent)[];
export const format = (content: Content, attrs: FormatAttributes): FormattedContent => {
if (typeof content === 'string') {
return {
children: content,
attrs: attrs,
};
} else if (!Array.isArray(content)) {
return {
...content,
attrs: {
...content.attrs,
...attrs,
},
};
} else if (content.every((v) => typeof v === 'string')) {
return {
children: content.join(''),
attrs: attrs,
};
} else {
return {
children: content,
attrs: attrs,
};
}
};
export const bold = (content: Content) => {
return format(content, { 'font-weight': 'bold' });
};
export const italic = (content: Content) => {
return format(content, { 'font-style': 'italic' });
};
export const underline = (content: Content) => {
return format(content, { 'text-decoration': 'underline' });
};
export const linethrough = (content: Content) => {
return format(content, { 'text-decoration': 'line-through' });
};
export const apply = (content: Content, parentAttrs?: FormatAttributes): string[] => {
let pretty = false;
let res: string = '';
let parts: string[] = [];
const array = !Array.isArray(content) ? [content] : content;
for (const part of array) {
if (typeof part === 'string') {
if (part === '') {
continue;
}
if (pretty) {
pretty = false;
res += `%c`;
parts.push('');
}
res += part;
} else {
const children = part.children;
const attrs = part.attrs;
const combed: Record<string, string> = parentAttrs ? { ...parentAttrs, ...attrs } : attrs;
if (typeof children === 'string') {
if (children === '') {
continue;
}
let style = '';
for (const key in combed) {
const value = combed[key];
style && (style += '; ');
style += `${key}: ${value}`;
}
pretty = true;
res += `%c${children}`;
parts.push(style);
} else {
for (let c of children) {
const [t, ...r] = typeof c !== 'string' ? apply(c, combed) : apply({ children: c, attrs: combed });
pretty = true;
res += t;
if (r.length !== 0) {
parts = [...parts, ...r];
}
}
}
}
}
return [res, ...parts];
};
console.log(apply(['lorem ', underline([bold('ipsum'), ' sit']), ' dolor', ' amet']));
// [
// 'lorem %cipsum%c sit%c dolor amet',
// 'text-decoration: underline; font-weight: bold',
// 'text-decoration: underline',
// '',
// ]
console.log(...apply(['lorem ', underline([bold('ipsum'), ' sit']), ' dolor', ' amet']));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment