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

creating extension based off existing rules? #177

Closed
grofit opened this issue Jul 20, 2015 · 14 comments
Closed

creating extension based off existing rules? #177

grofit opened this issue Jul 20, 2015 · 14 comments

Comments

@grofit
Copy link

grofit commented Jul 20, 2015

So say for example I want to basically make a slightly altered blockquote.

> some block quote here
:> some unique quote here

Now I know I can manually write regex to find the :> and do my own interpretation of what a block quote does, but is there any way for me to basically just extend the existing block quote handler in any way, or make any re-use of the existing logic?

In my scenario I would want to basically add a custom class to the blockquote output when using :> opposed to the normal >, also in code examples i.e

``` some-custom-type
blah blah blah
```

So hopefully this makes sense, I did look at the source but the built in rules operate differently to custom rules/extensions from what I can tell.

@tivie
Copy link
Member

tivie commented Jul 20, 2015

You can call the default subParsers inside an extension.

For instance, in your case, you can create a lang extension that looks for :> and then, in that extension, call the default blockquote subParser:with:

showdown.subParser('blockquote')(text, options, globals);

@grofit
Copy link
Author

grofit commented Jul 20, 2015

oh right, sounds good... (am I ok to pass in empty args for options and globals?)

So one other thing I found when trying to do custom code style handlers was that my custom extension seemed to get ignored in favor of built in ones, for example the code one, if I was to have a regex of:

(?:```\s?diagram[s]?)(.*)(?:```)/gm

Then I had some markdown like so:

```diagrams
woop woop
```

I would expect to grab the "woop woop" but my extensions do not seem to get run.

@tivie
Copy link
Member

tivie commented Jul 20, 2015

GFM fenced codeblocks

```
somecode
```

get parsed before calling language extensions (a necesssary evil to prevent nasty bugs). So, in order to parse the same markup, you need to disable GFM fenced blocks by default.

You do that by passing converter.setOption('ghCodeBlocks', false);

Then your extension will grab woop woop.

Inside your extension, you can call subParser('githubCodeBlocks')(text, options, globals),to grab "normal" GFM code blocks.

Keep in mind that options param passed to subParser('githubCodeBlocks') must have, at least, the property ghCodeBlocks set to true or the subParser will bail before parsing anything.

@grofit
Copy link
Author

grofit commented Jul 20, 2015

I mentioned it above but what should be passed in to options and globals? as I seem to get some errors if I leave them empty. i.e can I just get the options and globals from the current Converter? (then I would override the ghCodeBlocks bit)

@tivie
Copy link
Member

tivie commented Jul 20, 2015

You can't get options and globals from converter

subParser('githubCodeBlocks') calls hashBlock subparser that uses globals.gHtmlBlocks to extract and save references to previously parsed HTML blocks. https://github.com/showdownjs/showdown/blob/master/src/subParsers/hashBlock.js

So if you want to call a core subParser you need to make some adjustments.

You need to replicate the globals var (https://github.com/showdownjs/showdown/blob/master/src/converter.js#L189).

Then you need to change the replacement with your own token, for instance:

'\n\n~Ç' + <replacement number > + 'Ç\n\n';

Then on a output extension, you need to replace your "replacement" with the extracted code.

You should check how https://github.com/showdownjs/showdown/blob/master/src/subParsers/githubCodeBlocks.js and https://github.com/showdownjs/showdown/blob/master/src/subParsers/hashBlock.js work.

@tivie
Copy link
Member

tivie commented Jul 20, 2015

Another way is to replace the existing githubCodeBlock suybParser with your own but..

WARNING

That is an undocumented feature that should NEVER, and i repeat, SHOULD NEVER be used in an EXTENSION, specially in extensions available for third parties

Also, you should not rely too much on that feature because it can change in the feature.

Example

basically, you replace the subparser with your own (OUTSIDE THE RUNNING CODE OF THE EXTENSION)

var oldParser = subParser('githubCodeBlocks');
var newParser = function (text, options, globals) {
  // do the thing with your regex
  // (?:```\s?diagram[s]?)(.*)(?:```)/gm

  return oldParser((ext, options, globals);
}

showdown.subParser('githubCodeBlocks', newParser);

@grofit
Copy link
Author

grofit commented Jul 20, 2015

ok thanks for the info, will look more into it tomorrow and get back to you.

@tivie tivie closed this as completed Jul 20, 2015
@grofit
Copy link
Author

grofit commented Aug 19, 2015

Hey, sorry to re-raise this, I was working on some other stuff and only just got back around to looking at this area specifically.

So lets have a solid example:

:> Hello

I would want the output

<blockquote class="custom-class">hello</blockquote>

So I looked into the blockQuotes subParser, and did as you said:

return {
    type: 'lang',
    filter: function (text, converter, options) {
        var dummyGlobals = {
            gHtmlBlocks:     [],
            gUrls:           {},
            gTitles:         {},
            gDimensions:     {},
            gListLevel:      0,
            hashLinkCounts:  {},
            converter:       converter
        };

        var mainRegex = new RegExp("[\s\t]?((?:\:\>[\s\t]?.*\n*)+)", "g");
        text = text.replace(mainRegex, function(match, content){
            console.log("here");
            content = content.replace(":>", ">");
            return showdown.subParser("blockQuotes")(content, options, dummyGlobals);
        });
        return text;
    }
};

So it will look for :> and any text following it (as well as on multiple lines), not the best regex but it will do for example purposes. now when I put in :> hello it does get processed as I see "here" in the console but the output seems to be a horizontal rule, instead of the expected blockquote.

Is there any other magic I need to do in this instance?

@tivie
Copy link
Member

tivie commented Aug 20, 2015

@grofit Can you make a fiddle or codepen with that?

@grofit
Copy link
Author

grofit commented Aug 20, 2015

Sure here you go:
http://codepen.io/anon/pen/mJZrmb

That gives same output with the line appearing instead of the expected block quote.

@tivie
Copy link
Member

tivie commented Aug 21, 2015

Your parsed content is actually in dummyGlobals.gHtmlBlocks array. But need to simulate every parse count to obtain the right element.

I think your best bet is to call the converter object instead.

check the updated http://codepen.io/anon/pen/xGoYmw

@grofit
Copy link
Author

grofit commented Aug 21, 2015

That was one of the first sort of things I tried, but then I noticed that things like this occurred:

http://codepen.io/anon/pen/LVKdvd

Where things would behave a certain way with normal bqs but these custom BQs would behave differently, like having headings within them or the following headings would not get processed.

@tivie
Copy link
Member

tivie commented Aug 23, 2015

@grofit That's actually a problem with your regex and parsing.

see http://codepen.io/tivie/pen/eNqOzP for a working example.

Note:

I incidentally found a "quirk" in how showdown behaves regarding headings following blockquotes, see #191 for more info

regardless, this example I gave you is working properly

@grofit
Copy link
Author

grofit commented Aug 23, 2015

I was using the regex from the blockquote parser locally after trying stuff out I just forgot to update the regex on there, but thanks for the working one.

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

2 participants