majas
Version:
Format-agnostic structure converter.
53 lines (52 loc) • 2.06 kB
JavaScript
import sanitize from 'sanitize-filename';
import { FormatterBase } from '../core/Formatter.js';
import {} from '../fstree.js';
import { uniqify } from '../util/string.js';
import { map } from '../util/misc.js';
export const DefaultOptions = {
baseDirname: '.',
baseFilename: 'out',
filename: title => title,
};
export default class Filesystem extends FormatterBase {
options;
constructor(format, options) {
super(format);
this.options = { ...DefaultOptions, ...options };
}
parseImpl(input) {
if (typeof input.children === 'string') {
return {
title: input.title,
content: input.children,
};
}
return {
title: input.title,
children: {
ordered: false,
items: Array.from(input.children, ([name, child]) => this.parseImpl({ title: name, children: child })),
},
};
}
emit(output) {
const children = new Map();
const walk = (parent, node, index) => {
const filename = map(t => sanitize(this.options.filename(t, index), {
replacement: this.options.invalidFilenameCharReplacement,
}), node.title) ?? index?.toString();
if (node.content !== undefined) {
const contentFilename = uniqify(`${filename ?? this.options.baseFilename}.${output.format.fileExtensions[0] ?? 'txt'}`, s => parent.has(s));
parent.set(contentFilename, (this.options.header?.(node.title, index) ?? '') + node.content);
}
if (node.children?.items.length || node.content === undefined) {
const childrenDirname = uniqify(filename ?? this.options.baseDirname, s => parent.has(s));
const children = new Map();
parent.set(childrenDirname, children);
node.children?.items.forEach((n, i) => walk(children, n, i + 1));
}
};
walk(children, output.root);
return children;
}
}