org-meta-filter
Version:
pandoc filter to use org-mode custom keywords as metadata
82 lines (68 loc) • 2 kB
JavaScript
const getStdin = require('get-stdin')
const {
complement,
equals,
filter,
head,
ifElse,
join,
map,
mergeAll,
nth,
pipe,
prop,
replace,
splitWhen,
tail,
// tap,
trim,
where,
} = require('ramda')
/*
const { writeFileSync } = require('fs')
const debug = (subject, chunk) =>
writeFileSync(`debug-${subject}.json`, JSON.stringify(chunk))
const debugPipe = subject => tap(chunk => debug(subject, chunk))
*/
const beforeChar = char => pipe(splitWhen(equals(char)), head, join(''))
const afterChar = char => pipe(splitWhen(equals(char)), nth(1), tail, join(''))
const getPandocValue = prop('c')
const getPandocRawBlockValue = pipe(getPandocValue, nth(1))
// '#+key:value' => ['key', 'value']
const getOrgMetadata = rawMetadata => {
const key = pipe(beforeChar(':'), replace('#+', ''))(rawMetadata)
const value = pipe(afterChar(':'), trim)(rawMetadata)
return [key, value]
}
const toPandocStr = str => [{ t: 'Str', c: str }]
const toPandocMetaInlines = str => ({ t: 'MetaInlines', c: toPandocStr(str) })
const toPandocMetaBool = bool => ({ t: 'MetaBool', c: Boolean(bool) })
const isBoolString = str => ['true', 'false'].includes(str)
const toPandocMetaValue = ifElse(
isBoolString,
toPandocMetaBool,
toPandocMetaInlines
)
const toPandocMeta = ([key, value]) => ({ [key]: toPandocMetaValue(value) })
const isMetadata = where({
t: equals('RawBlock'),
c: pipe(head, equals('org')),
})
const removeMetadata = filter(complement(isMetadata))
const main = async () => {
let ast = JSON.parse(await getStdin())
const rawMetadata = filter(isMetadata, ast.blocks)
if (rawMetadata.length > 0) {
// extract keywords
ast.blocks = removeMetadata(ast.blocks)
const metadata = pipe(
map(pipe(getPandocRawBlockValue, getOrgMetadata, toPandocMeta)),
mergeAll
)(rawMetadata)
// and add as metadata
ast.meta = mergeAll([metadata, ast.meta])
}
process.stdout.write(JSON.stringify(ast))
}
main()