Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extensible way to extend terminal characters in text parser #408

Open
knubie opened this issue Jun 2, 2021 · 4 comments
Open

Extensible way to extend terminal characters in text parser #408

knubie opened this issue Jun 2, 2021 · 4 comments

Comments

@knubie
Copy link

knubie commented Jun 2, 2021

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.

@jpribyl
Copy link

jpribyl commented Jun 22, 2021

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 #

@TimLaue91
Copy link

TimLaue91 commented Nov 9, 2021

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.

@DiscoNova
Copy link

function text(state: {[key: string]: any}, silent: boolean) {

Holeymoley... that looks like TypeScript - can we do that these days? Have I missed something?

@TimLaue91
Copy link

TimLaue91 commented Nov 10, 2021

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants