npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

remarkably

v0.1.10

Published

a collection of MarkDown syntax extensions for https://github.com/jonschlinkert/remarkable

Downloads

3

Readme

Table of Contents generated with DocToc

ReMarkably

ReMarkably is a collection of MarkDown syntax extension to be used with the truly remarkable Remarkable MarkDown parser.

Install with

npm install --save remarkably

What is it for?

Finally, it's possible to easily extend your all-time favorite liteweight markup language, MarkDown.

Heretofore, it has been difficult to extend the syntax of markup languages because their parsers were not often written with extensibility in mind—as in programming languages, many markup designers are caught in a frame of thinking that makes them want to create the best language with the best syntax, the final one to rule them all.

LISPers were never interested in syntax, because, hey, what can surpass a homoiconic language (yes, they really call it that) with gazillions of brackets, right?

ReStructuredText (also once known as ReStructuredTextNG) used to be a strong contender to MarkDown, but IMHO it lost out because it's just too complicated—too many rules, and to setup a parser and just parse means jumping through too many Java-Enterprisy hoops (at least when i last checked five years ago). Is it extensible? Don't try at home.

In the Python community, extending syntax is seen as something dangerous, as an activity that can't be left to users but must be firmely policed by an inner circle of senior contributors. Given the fairly traditional Lex-YACC-Bison-ish tooling of the parser, that's even true because you'd have to make changes in like four or six files to add a trivial tidbit to the language, and then re-compile the entire thing, which makes development feel like you're back to mainframes and please come back tomorrow to pick up your printouts. Assuming you took that month-long upfront training class so you sorta know-what'cherdoing. Sort of. It's really difficult. And, having done that, anyone interested in your extension must download the entire source tree and compile that themselves, or else you must provide binary packages. It's not least this factor that has caused a lot of digital rot in the Python world, because compiling C sources tends to be much more fragile than relying on an 'interpreted' (i.e. low-level-compilation-free) idiom. In order to implement the tiniest of changes, you have to submit to a month-long or year-long period of intense scrutiny and deliberation, and your proposal will likely get downvoted.

Such strict procedures are necessary to uphold the quality of monolithic languages. After all, uncounted numbers of users will be confronted with your changes, and any addition to the language will likely be kept indefinitely because even correcting a mistake may break backward compatibility. JavaScript programmers know this very well: they have to live with lots of 'original sins' because their language was born under a very swiftly wandering star, and there was no time to correct oversights. Now those flaws are baked into the language, and any change for the better in JS core could potentially break many millions of websites.

As Douglas Crockford convincingly demonstrates in his 2013 MLOCJS Syntaxation talk, those times should be over. Languages should be extensible, and given the right tools, parsing can be much easier than it used to be.

Sadly, as of this writing (2014-11-09), there is very little documentation on how to extend remarkable, so the foremost purpose of ReMarkably is filling that gap. Anyone interested can fork the repo, develop their own extensions, and issue pull requests to make more syntax extensions available to the masses.

Usage

It's quite simple (using CoffeeScript here):

log         = console.log
RMY         = require 'remarkably'

enable      = 'full'
settings    =
  html:           yes,            # Enable HTML tags in source
  xhtmlOut:       no,             # Use '/' to close single tags (<br />)
  breaks:         no,             # Convert '\n' in paragraphs into <br>
  langPrefix:     'language-',    # CSS language prefix for fenced blocks
  linkify:        yes,            # Autoconvert URL-like text to links
  typographer:    yes,
  quotes:         '“”‘’'

RM                    = new RMY.ReMarkable enable, settings
RMY.use RM, video     = RMY.get.examples.video()
RMY.use RM, emphasis  = RMY.get.examples.emphasis()
RMY.use RM, emphasis2 = RMY.get.examples.emphasis2()
RMY.use RM, braces    = RMY.get.examples.brackets opener: '{',  closer: '}', arity: 2, name: 'braces'
RMY.use RM, angles    = RMY.get.examples.brackets opener: '<',  closer: '>', arity: 2, name: 'angles'
RMY.use RM, brackets  = RMY.get.examples.brackets opener: '[',  closer: ']', arity: 3, name: 'brackets-3'
RMY.use RM, smh       = RMY.get.examples.brackets opener: '《',  closer: '》', arity: 1, name: 'book-title'
source        = """
  =This= ==is== ===very=== _awesome_(c): %[example movie](http://example.com)
  *A* **B** ***C*** ****D****

  Here are
  * <<double pointy brackets>>,
  * {{double braces}},
  * [[[triple square brackets]]],
  * 也可以用 《中文書名号》 。
  """.trim()
log RM.render source

You can run the above with

remarkably/build && node remarkably/lib/main.js

which should output

<p><i>This</i> <b>is</b> <b><i>very</i></b> <em>awesome</em>©: <video href='http://example.com'>example movie</video>
<em>A</em> <strong>B</strong> <strong><em>C</em></strong> ****D****</p>
<p>Here are</p>
<ul>
<li><span class='angles'>double pointy brackets</span>,</li>
<li><span class='braces'>double braces</span>,</li>
<li><span class='brackets-3'>triple square brackets</span>,</li>
<li>也可以用 <span class='book-title'>中文書名号</span> 。</li>
</ul>

Writing Your Own Extension

Paste and copy one of the existing sources. A dynamic extension (one that accepts parameters) should return an object with a get method. I'm in the middle of developing this, so details may change without notice; you probably want to copy from the avaible sources.

Here is an example for a dynamic extension that accepts an opening and a closing bracket character, an 'arity' (number of repetitions), and a rule name, and turns those into a rule to render markup like [[[this]]] as <span class='yournamehere'>this</span>:


#===========================================================================================================
@get = ( settings ) ->

  #---------------------------------------------------------------------------------------------------------
  rule                = {}
  rule._opener        = settings?[ 'opener'  ] ? '<'
  rule._closer        = settings?[ 'closer'  ] ? '>'
  rule.terminators    = rule._opener
  rule._arity         = settings?[ 'arity'   ] ? 2
  rule._class_name    = settings?[ 'name' ] ? 'angles'
  rule.name           = 'REMARKABLY/examples/' + rule._class_name

  #---------------------------------------------------------------------------------------------------------
  rule.about = """$name$ recognizes text stretches enclosed by multiple brackets."""

  #---------------------------------------------------------------------------------------------------------
  rule._get_multiple_bracket_pattern = ( opener, closer, arity = 2, anchor = no ) ->
    opener      = "(?:#{BNP.escape_regex opener})"
    closer      = "(?:#{BNP.escape_regex closer})"
    anchor      = if anchor then '^' else ''
    repeat_all  = if arity is 1 then '' else "{#{arity}}"
    repeat_some = if arity is 1 then '' else "{1,#{arity}}"
    #.......................................................................................................
    return """
      #{anchor}
      (#{opener}#{repeat_all}(?!#{opener}))
        ((?:
          \\\\#{closer}|
          [^#{closer}]|
          #{closer}#{repeat_some}(?!#{closer})
        )*)
        (#{closer}#{repeat_all})(?!#{closer})
      """.replace /\n\s*/g, ''

  #---------------------------------------------------------------------------------------------------------
  rule._pattern = rule._get_multiple_bracket_pattern rule._opener, rule._closer, rule._arity, no
  rule._re      = new RegExp rule._pattern, 'g' # need `g` for `lastIndex`

  #---------------------------------------------------------------------------------------------------------
  rule.parse = ( state, silent ) ->
    #.......................................................................................................
    { src, pos, }       = state
    rule._re.lastIndex  = pos
    return false if ( not ( match = rule._re.exec src )? ) or match[ 'index' ] isnt pos
    [ all, opener, content, closer, ] = match
    unless silent
      state.push
        type:     rule.name
        opener:   opener
        closer:   closer
        content:  content
        block:    false
        level:    state.level
    #.......................................................................................................
    state.pos += all.length
    return true

  #---------------------------------------------------------------------------------------------------------
  rule.render = ( tokens, idx ) -> # options
    { content, opener, closer, } = tokens[ idx ]
    return "<span class='#{rule._class_name}'>#{content}</span>"

  #---------------------------------------------------------------------------------------------------------
  rule.extend = ( self ) ->
    self.inline.ruler.before self.inline.ruler[ 'rules' ][ 0 ][ 'name' ], rule.name, rule.parse
    self.renderer.rules[ rule.name ] = rule.render
    return null

  #---------------------------------------------------------------------------------------------------------
  return rule

remarkable Compatibility

ReMarkably is comaptible with [email protected].