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

kroked

v0.1.5

Published

custom markdown parser (marked) with macros support

Downloads

6

Readme

kroked

Markdown with macros.

It defines :

  • a meta-language parsed by marked lexer/parser
  • a proposition of language based on this meta-language

See marked for config and basics usage.

If you want to play with the meta language : see meta-language

kroked macros language

substitution macros

The replace_macro simply looks in options if there is a 'context' property. It seeks in it after property pointed by path provided between macros boundaries (i.e. {{ my.path.from.context }}) and returns it.

var kroked = require("kroked/index");
kroked("{{ address.zip }}", { context:{ address:{ zip:"1190" }}})

will return '1190'.

Block macros

With :

kroked.directives.myDirective = function(args, content, options)
{
	return args[0] + " : " + content.toUpperCase();
};

and this :

{% myTag myDirective( hello world )
	My content...
%}

It will output : <myTag>hello world : MY CONTENT...</myTag>

There is three things important to know :

  • either the directive name reflects a directive defined in kroked.directives, and it will be used to render the macros. (see below to defining such macros)
  • either the directive name is "unknown" (there is no associated directive in kroked.directives), and then kroked produce a tag with the name of the unknown directive. (i.e. <myDirective>content</myDirective>)
  • directives are composed together, from right to left.

And obviously blocks could be embedded in other blocks, and blocks could contains any other macros rules.

Difference between parsed and raw block-macros

Remarque : It comes from meta language itself.

{% myTag
__this is strong__ @.myOtherTag( my content )
%}

output : <myTag><strong>this is strong</strong><myOtherTag>my content</myOtherTag></myTag>

{! myTag
__this is strong__ @.myOtherTag( my content )
!}

output : <myTag>__this is strong__ @.myOtherTag( my content )</myTag>

Compilation and reusability

Another addition to marked parser is that you could now compile markdown documents to reuse it several times.

var kroked = require("kroked/index");	// load kroked : contains language definition
var template = kroked.compile("		{{ name }} says : @.hello(world)");
template({ name:"John" });
// will output <p>John says : <hello>world</hello></p>

Table parsing.

You could combine raw macros and a small tab-delimitted-cells-lines-lexer to produce quickly any "table like" widgets.

{! table ( Nodejs specifics deepjs libraries )
autobahnjs		(restful thin server : middlewares (expressjs) + routing)

deep-shell		(sh & ssh chains and cli)

deep-nodejs		(nodejs related tools (restful fs, ...))
deep-mongo		(restful mongodb client)
deep-elastic  	(restful client : ok, index management : embryonnar, layered queries : to do)

deep-mail		(mails sender utilities)
!}
kroked.directives.table = function(args, content, options){
	var lines = kroked.parseLinesCells(content, false);
	var output = "<table>\n";
	if(args && args[0])	// args[0] === table caption
		output += "<caption>"+args[0]+"</caption>\n";
	lines.forEach(function(cells){
		if(!cells.length)
		{
			output += "<tr></tr>\n";
			return;
		}
		output += "<tr>\n";
		cells.forEach(function(cell){
			output += "<td>"+cell+"</td>";
		});
		output += "\n</tr>\n";
	})
	output  += "</table>\n";
	return output;
}

Meta-language

Remarque : "Block" and "inline" refer to concepts related to markdown. A "block" start line without any spaces (or tabulations), as heading (i.e. # this is title), and couldn't be mixed with other on the same line. For inline object, the line could start with spaces, could contains several lexems, and the line and its following (not blank) are wrapped by a paragraph (p tag).

See marked for basics concepts.

Block macros

block macro (with parsed content)

{% myDirective(arg1, ...) mySecondDirective(arg, ...) myThirdDirective ...
	any content that will be parsed before injection in block (so any markdown or macros will be parsed).
%}

raw macro (content are not parsed)

{! myDirective(arg1, ...) mySecondDirective(arg, ...) ...
	any content that will be kept "as this" (raw) before injection in block
!}

direct macro.

When use in front of line (i.e. should start line without spaces or tabulations), any following string until end of line will be used as content.

@.myDirective(arg, ...) content...

substitution macro

{{ theVar.to.be.substitute }}

Inline macros

direct macro

@.myDirective(arg, ..., content)

substitution macro

{{ theVar.to.be.substitute }}

Directives format

Any directive could have parenthesis with arguments. Parenthesis and args are optional.

e.g: hello or hello() or hello(arg, ...) are valid.

Any argument could be string (e.g. "something..."), float, integer or direct string (delimitter is '\n' or ')' or ',')

e.g. : myDirectives("my string...", 12, 34.890, this is a direct string)

Defining a language

By using the custom marked parser directly (kroked/lib/marked.js), you could define a language, based on this macros meta-language.

For this, you simply define 3 render methods that receive the directive(s), the eventual content and the options provided while parsing.

examples with "kroked/lib/directives-parser":

var marked = require("kroked/lib/marked"), // load custom marked parser (no macros language defined)
	renderer = new marked.Renderer();

renderer.block_macro = function(directives, content, options) {
	// directives is array : [{ name:"myDirective", args:[...] }, ...]
	// content is the one provided between macros boundaries (or after block direct macros)
	// options is an object that you provide when parsing

	return "<div>"+JSON.stringify(directives)+" - "+content+"<div>";
};
//________________________________________________________________________ DIRECT MACRO
renderer.inline_macro = function(directive, options) {
	// directive is a single directive : { name:"myDirective", args:[...] }
	// options is an object that you provide when parsing
	
	return "<div>"+JSON.stringify(directives)+"<div>";
};
//_________________________________________________________________________ REPLACE MACRO 
renderer.replace_macro = function(content, options) {
	// content is the one provided between macros boundaries
	// options is an object that you provide when parsing

	return "<div>"+content+"<div>";
};

var opt = {
	renderer: renderer,
	gfm: true,
	tables: true,
	breaks: false,
	pedantic: false,
	sanitize: false,
	smartLists: true,
	smartypants: false,

	codespaces:false	// disable markdown rules : every line starting with 4 spaces (or more) or tab(s) are code
};

kroked("# hello\n\n{{ to.replace }}", opt);

Remarque

The language and the meta-language proposed there is a base for future reflexions. It is already fully usable, but as it wants to be opened, lot of things are possible... If you want to contribute, you're welcome...;)

Licence

LGPL 3.0