@podlite/schema
Version:
AST tools for Podlite markup language
146 lines • 5.94 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/**
* Plugin for fill term's for defn. From S26:
* The first non-blank line of content is treated as a term being defined,
* and the remaining content is treated as the definition for the term.
*/
const makeTransformer_1 = __importDefault(require("./helpers/makeTransformer"));
function flattenDeep(arr) {
return arr.reduce((acc, val) => (Array.isArray(val) ? acc.concat(flattenDeep(val)) : acc.concat(val)), []);
}
/**
* Helpers section
*/
// run cb in symbols pair
const strbin = (str1, str2, cb) => {
let res = [];
for (let i = 0; str1.length > i; i++) {
res.push(cb(parseInt(str1[i], 10), parseInt(str2[i], 10)));
}
return res.join('');
};
// Create mask for extract columns
const makeMask = (lines, separators) => {
// calculate template length
const tmplLength = Math.max(...[...lines, ...separators].map(s => s.length));
// make bin mask for each string
const masks = lines.map(str => {
/** make mask for each line
' The Shoveller | Eddie Stevens | King Arthur\'s singing shovel',
'0000000011111111111110001111111111111000001111111111111111111111111111' ]
then not(mask) ... then & masks
*/
// enlarge string to tmplLength
let tstr = str + ' '.repeat(tmplLength - str.length);
let mask = [];
const re = /\s+[+|\s]\s/g;
let match;
while ((match = re.exec(tstr)) != null) {
const tmpMask = '1'.repeat(match.index) + '0'.repeat(match[0].length);
mask.push(tmpMask + '1'.repeat(tmplLength - tmpMask.length));
}
return mask.reduce((a, b) => {
return strbin(a, b, (i1, i2) => i1 & i2);
}, '1'.repeat(tmplLength));
});
// make result mask
const inverted = masks.map(m => strbin(m, '', i1 => (i1 == 0 ? 1 : 0)));
const columnTemplate = inverted.reduce((a, b) => {
return strbin(a, b, (i1, i2) => i1 & i2);
}, '1'.repeat(tmplLength));
return columnTemplate;
};
const extractColumnsByTemplate = (text, template) => {
const lines = flattenDeep(text
.split(/\n/) // split each row by eol
.filter(str => str.length > 0));
const cols = lines.map(line => {
const re = /((1+|0+))/g;
let columns = [];
let match;
while ((match = re.exec(template)) != null) {
if (match[0][0] == 1)
continue;
const s = line.substring(match.index, match.index + match[0].length);
columns.push(s);
}
return columns;
});
let result = [];
result = cols.reduce((a, b) => {
for (let i = 0; i < b.length; i++) {
a[i] = (a[i] === undefined ? '' : a[i]) + ' ' + b[i];
}
return a;
}, []);
return result;
};
/**
* Main transforms
*/
exports.default = () => tree => {
const transformer = (0, makeTransformer_1.default)({
table: node => {
let rows = [];
const collectValues = row => {
rows.push(row.value);
};
// collect separators for calculate max length of rows
let seps = [];
(0, makeTransformer_1.default)({
'row:text': collectValues,
'head:text': collectValues,
':separator': sep => {
seps.push(sep.text);
},
})(node);
// add table-caption
// if table empty return node as is
if (!rows.length)
return node;
const splitToLines = row => row
.split(/\n/) // split each row by eol
.filter(str => str.length > 0); // filter empty strings ( after slit )
// split each row into lines
const lines = flattenDeep(rows.map(splitToLines));
const separators = flattenDeep(seps.map(splitToLines));
// collect text rows
let textRows = [];
(0, makeTransformer_1.default)({
'row:text': row => {
textRows.push(row.value);
},
})(node);
const columnTemplate = makeMask(lines, separators);
const makeBlock = (name, content, ...attr) => {
return { ...attr, name, type: 'block', content: Array.isArray(content) ? content : [content] };
};
// make columns
const res = (0, makeTransformer_1.default)({
'row:text': row => {
if (textRows.length == 1) {
// split each text row into lines
const textRowsLines = flattenDeep([row.value].map(splitToLines));
return textRowsLines.map(rowValue => {
const res = extractColumnsByTemplate(rowValue, columnTemplate);
return makeBlock('table_row', res.map(col => makeBlock('table_cell', { type: 'text', value: col })));
});
}
const res = extractColumnsByTemplate(row.value, columnTemplate);
return makeBlock('table_row', res.map(col => makeBlock('table_cell', { type: 'text', value: col })));
},
'head:text': head => {
const res = extractColumnsByTemplate(head.value, columnTemplate);
return makeBlock('table_head', res.map(col => makeBlock('table_cell', { type: 'text', value: col })));
},
})(node);
return res;
},
});
return transformer(tree, {});
};
//# sourceMappingURL=plugin-tables.js.map