Skip to content

Commit

Permalink
use ES modules, simplify API
Browse files Browse the repository at this point in the history
  • Loading branch information
erikdesjardins committed Dec 4, 2017
1 parent 675c981 commit 763d145
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 151 deletions.
2 changes: 1 addition & 1 deletion .npmignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
*
!dist/snudown.js
!dist/*.js
4 changes: 3 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ deploy:
- provider: releases
api_key:
secure: HZNL8QnRFxJbB/2pMCruV/K1BnPk7q1qNWcAoCuI14K74cDlMjCUv+b1dgXg1Vcx6zBq6ob8cqjptCcsyVur2JK4bfPfwwwuAmlu1DlMfsd0DdCrHmVIWdcGrkqRmvt+1SieyIcQFarQQXU1clLdcneXiAmnFn5VvYv/YrCtc498TLpKSHAVPYXb2vHSHL4JqeXw70BWA11v2IXvzmXhMVoZmlDcZ5nfFCZaF5CTSiNcbkomWZdJYuLDiUn0W6kTpLEh+LUxteOCGKpy/D4fXkatEYGFs2iHfG25WX0RVSsw7Y7flplsPRX6voCPhpdH7Sv4C+j9Snq1yQ6Jpg7FpNO52V4QRdWUH4W1SUfxeNhrA2RvsAxdKlywbZ19ow5t0FdhHt1K5NoyDC8n9d3ufSHAMU14XdQB8Wyv0YT1+ykv7FychkIAAUiXPX8Pv6E0yw3R9cYE0vfs4Apu6yOtVq4s0vfG8Rjz9yiAS1XE1vUj2M5NqK6kOXLLpwsdBI7mTSAWkuvc6cQUBzgG9GNWPgKP1xeQXSEE1auXZoXaHLUTME6dQYT3cOn099gAU1m9yEfPTm26yJtZcrBtID2K3sLlQ3Eg0s0+SoPfxZczomLb2hkmd4TiP6BeCcG+8psArSt/apUFnrb8PNP36ebV5QtayeYwWuT27YIAJM9g53o=
file: dist/snudown.js
file:
- dist/snudown.js
- dist/snudown_es.js
skip_cleanup: true
on:
tags: true
Expand Down
4 changes: 1 addition & 3 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ snudown-js
Usage
-----

Include the [source](https://github.com/erikdesjardins/snudown-js/releases/latest) directly or import from [npm](https://www.npmjs.com/package/snudown-js): `require('snudown-js')`.

The API is as close as possible to the Python API provided by Snudown.
Import from [npm](https://www.npmjs.com/package/snudown-js): `const Snudown = require('snudown-js')`.

Basic usage:

Expand Down
15 changes: 11 additions & 4 deletions build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ gperf src/html_entities.gperf > build/html_entities.c

files="snudown.c src/autolink.c src/buffer.c src/markdown.c src/stack.c html/houdini_href_e.c html/houdini_html_e.c html/html.c build/html_entities.c"
include=("src" "html")
exported=("default_renderer" "wiki_renderer" "snudown_md" "version" "main")
exported=("default_renderer" "wiki_renderer" "snudown_md" "main")
options=("ERROR_ON_UNDEFINED_SYMBOLS=1" "NO_EXIT_RUNTIME=1" "EXPORTED_RUNTIME_METHODS=[]" "NO_FILESYSTEM=1" "MEM_INIT_METHOD=2" "NODEJS_CATCH_EXIT=0")

if [ "$1" = "-d" ] || [ "$1" = "--debug" ]; then
Expand All @@ -23,7 +23,7 @@ else
optimization="-Oz --llvm-lto 1 --closure 1 --memory-init-file 0 -DNDEBUG -s ABORTING_MALLOC=0"
fi

cmd="emcc $files -o build/snudown.js --pre-js header.js --post-js footer.js $optimization"
cmd="emcc $files -o build/snudown_emscripten.js --pre-js header.js --post-js footer.js $optimization"

for i in "${options[@]}"; do
cmd="$cmd -s $i"
Expand All @@ -44,14 +44,18 @@ $cmd

# Remove `require()` calls from compiled code
# (used for filesystem operations, but aren't removed by `-s NO_FILESYSTEM=1`)
sed -r 's/require\("[^"]*"\)/{}\/*removed &*\//g' ./build/snudown.js > ./build/snudown2.js
sed -r 's/require\("[^"]*"\)/{}\/*removed &*\//g' ./build/snudown_emscripten.js > ./build/snudown_norequire.js
# Remove IIFE wrapper (for exports)
sed -r 's/^\(function\(\)\{// ; s/\}\)\(\);//' ./build/snudown_norequire.js > ./build/snudown_nowrapper.js
# Convert window exports to ES exports
sed -r 's/window\.(\w+)=function/export function \1/g' ./build/snudown_nowrapper.js > ./build/snudown_exports.js

# Minify
compress_options=("negate_iife=false" "hoist_props" "keep_fargs=false" "passes=3" "pure_getters=true" "toplevel" "unsafe")
mangle_options=("toplevel")
beautify_options=("beautify=false" "wrap_iife")

uglify="./node_modules/uglify-js/bin/uglifyjs ./build/snudown2.js -o ./dist/snudown.js --comments"
uglify="./node_modules/uglify-es/bin/uglifyjs ./build/snudown_exports.js -o ./build/snudown_uglify.js --comments"

uglify="$uglify -c "
for i in "${compress_options[@]}"; do
Expand All @@ -73,4 +77,7 @@ uglify="${uglify:0:${#uglify} - 1}" # trim last comma

$uglify

echo "module.exports = require('@std/esm')(module, { esm: 'js' })('./snudown_es.js');" > ./dist/snudown.js
cp ./build/snudown_uglify.js ./dist/snudown_es.js

rm -r "build"
138 changes: 41 additions & 97 deletions footer.js
Original file line number Diff line number Diff line change
@@ -1,114 +1,58 @@
/**
* Snudown's version number, usually similar to: "3.2.1".
* Equivalent to python: `__version__`.
* @type {string}
*/
var version = UTF8ToString(asm['_version']());

/**
* The index of the usertext renderer.
* Can be passed to {@link markdown}.
* Equivalent to python: `RENDERER_USERTEXT`.
* @type {number}
*/
var RENDERER_USERTEXT = asm['_default_renderer']();

/**
* The index of the wiki renderer.
* Can be passed to {@link markdown}.
* Equivalent to python: `RENDERER_WIKI`.
* @type {number}
*/
var RENDERER_WIKI = asm['_wiki_renderer']();

/**
* Render markdown `text` to an HTML string.
* Arguments may be passed positionally: `markdown('#/u/hi', true, '_top', RENDERER_WIKI, true, 'prefix_')`,
* or by name in a single object: `markdown({ text: '#/u/hi', nofollow: true, target: '_top', renderer: RENDERER_WIKI, enableToc: true, tocIdPrefix: 'prefix_' })`.
* Render markdown `text` to an HTML string using the usertext renderer.
* Equivalent to python: `markdown`.
* @param {string} text
* @param {boolean} [nofollow=false] Whether to add `rel="nofollow"` to all links.
* @param {string} [target=null] The `target` property of all links.
* @param {number} [renderer=RENDERER_USERTEXT]
* @param {boolean} [enableToc=false] Whether to create a table of contents (Reddit generates the TOC separately).
* @param {string} [tocIdPrefix=null] Added to the `id` of each TOC link, i.e. `#PREFIXtoc_0`.
* @returns {string} The rendered HTML.
*/
function markdown(text, nofollow, target, renderer, enableToc, tocIdPrefix) {
if (typeof text === 'object' && text !== null) {
nofollow = text['nofollow'];
target = text['target'];
renderer = text['renderer'];
enableToc = text['enableToc'];
tocIdPrefix = text['tocIdPrefix'];
text = text['text'];
}
if (typeof text !== 'string') {
text = '';
}
if (typeof renderer !== 'number') {
renderer = RENDERER_USERTEXT;
}
return _markdown(text, nofollow, target, tocIdPrefix, renderer, enableToc);
function markdown(
text /*: string */,
options /*: ?{
nofollow, // Whether to add `rel="nofollow"` to all links.
target, // The `target` property of all links.
enableToc, // Whether to create a table of contents (Reddit does not use this to generate their TOC).
tocIdPrefix, // Added to the `id` of each TOC link, i.e. `#PREFIXtoc_0`.
} */
) /*: string */ {
return _markdown(text, options, asm['_default_renderer']());
}

/**
* Equivalent to {@link markdown}, but always uses {@link RENDERER_WIKI}.
* @param {string} text
* @param {boolean} [nofollow=false]
* @param {string} [target=null]
* @param {boolean} [enableToc=false]
* @param {string} [tocIdPrefix=null]
* @returns {string} The rendered HTML.
* Render markdown `text` to an HTML string using the wiki renderer.
* Equivalent to python: `markdown`.
*/
function markdownWiki(text, nofollow, target, enableToc, tocIdPrefix) {
if (typeof text === 'object' && text !== null) {
nofollow = text['nofollow'];
target = text['target'];
enableToc = text['enableToc'];
tocIdPrefix = text['tocIdPrefix'];
text = text['text'];
}
if (typeof text !== 'string') {
text = '';
}
return _markdown(text, nofollow, target, tocIdPrefix, RENDERER_WIKI, enableToc);
function markdownWiki(
text /*: string */,
options /*: ?{
nofollow, // Whether to add `rel="nofollow"` to all links.
target, // The `target` property of all links.
enableToc, // Whether to create a table of contents (Reddit does not use this to generate their TOC).
tocIdPrefix, // Added to the `id` of each TOC link, i.e. `#PREFIXtoc_0`.
} */
) /*: string */ {
return _markdown(text, options, asm['_wiki_renderer']());
}

/**
* @private
* @param {string} text
* @param {boolean} nofollow
* @param {string} target
* @param {string} toc_id_prefix
* @param {number} renderer
* @param {boolean} enable_toc
* @returns {string} The rendered string.
*/
function _markdown(text, nofollow, target, toc_id_prefix, renderer, enable_toc) {
// not using Emscripten's automatic string handling since 'text'.length is unreliable for UTF-8
function _markdown(text, options, renderer) {
if (typeof text !== 'string') text = '';
var size = lengthBytesUTF8(text); // excludes null terminator
var buf = allocate(intArrayFromString(text), 'i8', ALLOC_NORMAL);
var str = ccall(

if (typeof options !== 'object' || options === null) options = {};
var nofollow = options['nofollow'] ? 1 : 0;
var target = typeof options['target'] === 'string' ? options['target'] : null;
var toc_id_prefix = typeof options['tocIdPrefix'] === 'string' ? options['tocIdPrefix'] : null;
var enable_toc = options['enableToc'] ? 1 : 0;

var ptr = ccall(
'snudown_md',
'number',
['number', 'number', 'number', 'string', 'string', 'number', 'number'],
[buf, size, nofollow, target, toc_id_prefix, renderer, enable_toc]
['string', 'number', 'number', 'string', 'string', 'number', 'number'],
[text, size, nofollow, target, toc_id_prefix, renderer, enable_toc]
);
asm['_free'](buf);
var string = UTF8ToString(str);
asm['_free'](str);
return string;
}
var string = UTF8ToString(ptr);

exports['version'] = version;
exports['RENDERER_USERTEXT'] = RENDERER_USERTEXT;
exports['RENDERER_WIKI'] = RENDERER_WIKI;
exports['markdown'] = markdown;
exports['markdownWiki'] = markdownWiki;
asm['_free'](ptr);

if (typeof define === 'function') {
define(exports);
return string;
}
})(typeof exports !== 'undefined' ? exports : typeof window !== 'undefined' ? (window['Snudown'] = {}) : {});

window['markdown'] = markdown;
window['markdownWiki'] = markdownWiki;
})();
3 changes: 1 addition & 2 deletions header.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/

(function(exports) {'use strict';
(function() {'use strict';
Module = {
'ENVIRONMENT': 'WEB'
};

8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,16 @@
"version": "2.0.4",
"description": "a 'native' port of Snudown to JavaScript",
"main": "dist/snudown.js",
"module": "dist/snudown_es.js",
"repository": {
"type": "git",
"url": "https://github.com/erikdesjardins/snudown-js.git"
},
"devDependencies": {
"uglify-js": "3.2.0"
"uglify-es": "3.2.1"
},
"license": "MIT"
"license": "MIT",
"dependencies": {
"@std/esm": "^0.18.0"
}
}
68 changes: 27 additions & 41 deletions test_snudown.js
Original file line number Diff line number Diff line change
Expand Up @@ -456,85 +456,71 @@ var wiki_cases = {
'<p><table scope="foo"></p>\n',
};

function runTest(input, expected_output, fn) {
fn = fn || Snudown.markdown;
function runTest(fn, input, expected_output) {
var output = fn.apply(null, input);
if (output !== expected_output)
throw new Error(
"TEST FAILED:" +
"\n input: " + (input[0].text || input[0]) +
"\n input: " + input[0] +
"\n expected: " + expected_output +
"\n actual: " + output
);
}

for (var input in wiki_cases) {
runTest([{ text: input, renderer: Snudown.RENDERER_WIKI }], wiki_cases[input]);
runTest(Snudown.markdownWiki, [input], wiki_cases[input]);
}

for (var input in cases) {
runTest([input], cases[input]);
runTest(Snudown.markdown, [input], cases[input]);
}

[[
['/u/test', true, '_top'],
Snudown.markdown,
['/u/test', { nofollow: true, target: '_top' }],
'<p><a href="/u/test" rel="nofollow" target="_top">/u/test</a></p>\n'
], [
[{ text: '/u/test', nofollow: true, target: '_top' }],
'<p><a href="/u/test" rel="nofollow" target="_top">/u/test</a></p>\n'
], [
['<table scope="foo">', null, null, Snudown.RENDERER_WIKI],
'<p><table scope="foo"></p>\n'
Snudown.markdownWiki,
['<table scope="foo">', { nofollow: null, target: null }],
'<p><table scope="foo"></p>\n',
], [
['<table scope="foo">', null, null, Snudown.RENDERER_USERTEXT],
Snudown.markdown,
['<table scope="foo">', { nofollow: null, target: null }],
'<p>&lt;table scope=&quot;foo&quot;&gt;</p>\n'
], [
['###Test', null, null, null, true, 'prefixed_'],
Snudown.markdown,
['###Test', { enableToc: true, tocIdPrefix: 'prefixed_' }],
'<div class="toc">\n<ul>\n<li>\n<a href="#prefixed_toc_0">Test</a>\n</li>\n</ul>\n</div>\n\n<h3 id="prefixed_toc_0">Test</h3>\n'
], [
[{ text: '###Test', enableToc: true, tocIdPrefix: 'prefixed_' }],
'<div class="toc">\n<ul>\n<li>\n<a href="#prefixed_toc_0">Test</a>\n</li>\n</ul>\n</div>\n\n<h3 id="prefixed_toc_0">Test</h3>\n'
], [
// undefined text, markdown
// undefined text
Snudown.markdown,
[],
''
], [
// null text, markdown
// null text
Snudown.markdown,
[null],
''
], [
// undefined text, markdownWiki
// undefined text
Snudown.markdownWiki,
[],
'',
Snudown.markdownWiki
], [
// null text, markdownWiki
// null text
Snudown.markdownWiki,
[null],
'',
Snudown.markdownWiki
], [
// passing a renderer to markdownWiki doesn't override RENDERER_WIKI
[{ text: '<table scope="foo">', renderer: Snudown.RENDERER_USERTEXT }],
'<p><table scope="foo"></p>\n',
Snudown.markdownWiki
], [
// all positional arguments, markdown
['###Test\n<table scope="foo">\n/u/test', true, '_top', null, true, 'prefixed_'],
'<div class="toc">\n<ul>\n<li>\n<a href="#prefixed_toc_0">Test</a>\n</li>\n</ul>\n</div>\n\n<h3 id="prefixed_toc_0">Test</h3>\n\n<p>&lt;table scope=&quot;foo&quot;&gt;\n<a href="/u/test" rel="nofollow" target="_top">/u/test</a></p>\n'
], [
// all named arguments, markdown
[{ text: '###Test\n<table scope="foo">\n/u/test', nofollow: true, target: '_top', enableToc: true, tocIdPrefix: 'prefixed_' }],
// all named arguments
Snudown.markdown,
['###Test\n<table scope="foo">\n/u/test', { nofollow: true, target: '_top', enableToc: true, tocIdPrefix: 'prefixed_' }],
'<div class="toc">\n<ul>\n<li>\n<a href="#prefixed_toc_0">Test</a>\n</li>\n</ul>\n</div>\n\n<h3 id="prefixed_toc_0">Test</h3>\n\n<p>&lt;table scope=&quot;foo&quot;&gt;\n<a href="/u/test" rel="nofollow" target="_top">/u/test</a></p>\n'
], [
// all positional arguments, markdownWiki
['###Test\n<table scope="foo">\n/u/test', true, '_top', true, 'prefixed_'],
'<div class="toc">\n<ul>\n<li>\n<a href="#prefixed_toc_0">Test</a>\n</li>\n</ul>\n</div>\n\n<h3 id="prefixed_toc_0">Test</h3>\n\n<p><table scope="foo">\n<a href="/u/test" rel="nofollow" target="_top">/u/test</a></p>\n',
Snudown.markdownWiki
], [
// all named arguments, markdownWiki
[{ text: '###Test\n<table scope="foo">\n/u/test', nofollow: true, target: '_top', enableToc: true, tocIdPrefix: 'prefixed_' }],
// all named arguments
Snudown.markdownWiki,
['###Test\n<table scope="foo">\n/u/test', { nofollow: true, target: '_top', enableToc: true, tocIdPrefix: 'prefixed_' }],
'<div class="toc">\n<ul>\n<li>\n<a href="#prefixed_toc_0">Test</a>\n</li>\n</ul>\n</div>\n\n<h3 id="prefixed_toc_0">Test</h3>\n\n<p><table scope="foo">\n<a href="/u/test" rel="nofollow" target="_top">/u/test</a></p>\n',
Snudown.markdownWiki
]].forEach(function(testArgs) {
runTest.apply(null, testArgs);
});
Expand Down

0 comments on commit 763d145

Please sign in to comment.