remarkable
remarkable copied to clipboard
Extensible way to extend terminal characters in text parser
To implement some inline plugins we need to be able to add characters to the isTerminatorChar
function in /lib/rules_inline/text.js
. If your plugin's parser relies on a character that's not in that list (e.g. #
), then the parser will never run.
One solution is to override the function with a different function, but that would conflict with other plugins that need to add their own character(s) to the list.
I also just ran into this issue. Use case here is if you're trying to do something like adding a hashtag mention plugin. Plenty of workarounds, but feels weird to require a break on @
when the real character you want is #
I ran into this problem trying to implement iaWriter-style image links (just beginning with a slash, like '/myImage.jpeg'). I went with the workaround suggested by @knubie, which works, but feels bad:
const md = new Remarkable();
const parse = function(state: Remarkable.StateInline) {
// Parse...
};
// Part 1 of the hack (taken from text.js and adjusted)
function isTerminatorChar(ch: number) {
switch (ch) {
case 0x0A/* \n */:
case 0x5C/* \ */:
case 0x2F/* / */: // Added this line to make '/' a terminator character
case 0x60/* ` */:
case 0x2A/* * */:
case 0x5F/* _ */:
case 0x5E/* ^ */:
case 0x5B/* [ */:
case 0x5D/* ] */:
case 0x21/* ! */:
case 0x26/* & */:
case 0x3C/* < */:
case 0x3E/* > */:
case 0x7B/* { */:
case 0x7D/* } */:
case 0x24/* $ */:
case 0x25/* % */:
case 0x40/* @ */:
case 0x7E/* ~ */:
case 0x2B/* + */:
case 0x3D/* = */:
case 0x3A/* : */:
return true;
default:
return false;
}
}
// Part 2 of the hack (taken from text.js, unchanged)
function text(state: Remarkable.StateInline, silent: boolean) {
var pos = state.pos;
while (pos < state.posMax && !isTerminatorChar(state.src.charCodeAt(pos))) {
pos++;
}
if (pos === state.pos) { return false; }
if (!silent) { state.pending += state.src.slice(state.pos, pos); }
state.pos = pos;
return true;
};
const myPlugin = function(md: Remarkable) {
const options = {};
md.inline.ruler.at('text', text, options) // Replace default text parser with adjusted one
md.inline.ruler.push('myPlugin', parse, options);
};
md.use(myPlugin);
Edit: Added correct type annotations.
function text(state: {[key: string]: any}, silent: boolean) {
Holeymoley... that looks like TypeScript - can we do that these days? Have I missed something?
I'm afraid I don't understand your question.
~~If you mean the incrdibly general type annotation: I didn't find a matching type definition in the Remarkable package and I was too lazy to spell out the properties of the state
object. I'm also very new to Typescript.~~
Edit: Added correct type annotation.