Skip to content
Snippets Groups Projects
Commit 115a7a73 authored by tatsy's avatar tatsy
Browse files

first commit

parents
No related branches found
No related tags found
No related merge requests found
coverage/
dist/
node_modules/
.eslintrc 0 → 100644
env:
node: true
browser: false
plugins:
- nodeca
rules:
block-scoped-var: 2
brace-style: [ 2, '1tbs', { allowSingleLine: true } ]
comma-spacing: 2
comma-style: 2
consistent-this: [ 2, self ]
consistent-return: 2
curly: 2
# default-case: 2
dot-notation: 2
eol-last: 2
eqeqeq: 2
guard-for-in: 2
handle-callback-err: 2
max-depth: [ 1, 6 ]
max-nested-callbacks: [ 1, 4 ]
# string can exceed 80 chars, but should not overflow github website :)
max-len: [ 2, 120, 1000 ]
new-cap: 2
new-parens: 2
no-alert: 2
no-array-constructor: 2
no-bitwise: 2
no-caller: 2
no-catch-shadow: 2
no-comma-dangle: 2
no-cond-assign: 2
no-console: 1
no-constant-condition: 2
no-control-regex: 2
no-debugger: 2
no-delete-var: 2
no-dupe-keys: 2
no-div-regex: 2
no-empty: 2
no-empty-class: 2
no-empty-label: 2
no-else-return: 2
no-eq-null: 2
no-ex-assign: 2
no-extend-native: 2
no-extra-bind: 2
no-extra-boolean-cast: 2
no-extra-semi: 2
no-extra-strict: 2
no-eval: 2
no-floating-decimal: 2
no-func-assign: 2
no-implied-eval: 2
no-inner-declarations: 2
no-invalid-regexp: 2
no-irregular-whitespace: 2
no-label-var: 2
no-labels: 2
no-lone-blocks: 2
no-lonely-if: 2
no-loop-func: 2
no-mixed-requires: 2
no-mixed-spaces-and-tabs: 2
no-multi-str: 2
no-native-reassign: 2
no-negated-in-lhs: 2
no-new: 2
no-new-func: 2
no-new-object: 2
no-new-require: 2
no-new-wrappers: 2
no-obj-calls: 2
no-octal: 2
no-octal-escape: 2
no-path-concat: 2
no-redeclare: 2
no-regex-spaces: 2
no-reserved-keys: 2
no-return-assign: 2
no-script-url: 2
no-sequences: 2
no-shadow: 2
no-shadow-restricted-names: 2
no-space-before-semi: 2
no-sparse-arrays: 2
no-trailing-spaces: 2
no-undef: 2
no-undef-init: 2
no-undefined: 2
no-unreachable: 2
no-unused-expressions: 2
no-unused-vars: 2
no-use-before-define: 2
no-with: 2
no-wrap-func: 2
quotes: [ 2, single, avoid-escape ]
radix: 2
semi: 2
space-after-keywords: [ 2, always, , { "checkFunctionKeyword": true } ]
space-before-blocks: 2
space-in-brackets: [ 2, always, { propertyName: false } ]
space-in-parens: [ 2, never ]
space-infix-ops: 2
space-return-throw-case: 2
space-unary-ops: 2
spaced-line-comment: [ 2, always, { exceptions: [ '/' ] } ]
strict: 2
use-isnan: 2
yoda: 2
valid-typeof: 2
#
# Our custom rules
#
nodeca/indent: [ 2, spaces, 2 ]
node_modules/*
npm-debug.log
language: node_js
node_js:
- '0.10'
script: makr test-ci
coverage:
rm -rf coverage
istanbul cover node_modules/.bin/_mocha
test-ci: lint
istanbul cover ./node_moudles/mocha/bin/_mocha --report lcovonly --R spec && cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage
{
"name": "markdown-it-imsize",
"version": "0.1.0",
"authors": [
"tatsy <tatsy.mail@gmail.com>"
],
"description": "Markdown-it plugin to specify image size",
"main": "index.js",
"kewords": [
"markdown-it",
"markdown-it-plugin"
],
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
]
}
'use strict';
// Hepler to [reference labels]. No better place for this code :)
// It's only for refs/links and should not be exported anywhere.
module.exports = function normalizeReference(str) {
// use .toUpperCase() instead of .toLowerCase()
// here to avoid a conflict with Object.prototype
// members (most notably, `__proto__`)
return str.trim().replace(/\s+/g, ' ').toUpperCase();
};
// Parse image size
//
'use strict';
function parseNextNumber(str, pos, max) {
var code,
start = pos,
result = {
ok: false,
pos: pos,
value: ''
};
code = str.charCodeAt(pos);
while (pos < max && (code >= 0x30 /* 0 */ && code <= 0x39 /* 9 */)) {
code = str.charCodeAt(++pos);
}
result.ok = true;
result.pos = pos;
result.value = str.slice(start, pos);
return result;
}
module.exports = function parseImageSize(str, pos, max) {
var code,
result = {
ok: false,
pos: 0,
width: '',
height: ''
};
if (pos >= max) { return result; }
code = str.charCodeAt(pos);
if (code !== 0x3d /* = */) { return result; }
pos++;
// size must follow = without any white spaces as follows
// (1) =300x200
// (2) =300x
// (3) =x200
code = str.charCodeAt(pos);
if (code !== 0x78 /* x */ && (code < 0x30 && code > 0x39) /* [0-9] */) {
return result;
}
// parse width
var resultW = parseNextNumber(str, pos, max);
pos = resultW.pos;
// next charactor must be 'x'
code = str.charCodeAt(pos);
if (code !== 0x78 /* x */) { return result; }
pos++;
// parse height
var resultH = parseNextNumber(str, pos, max);
pos = resultH.pos;
result.width = resultW.value;
result.height = resultH.value;
result.pos = pos;
result.ok = true;
return result;
};
index.js 0 → 100644
// Process ![test]( x =100x200)
// ^^^^^^^^ this size specification
'use strict';
var mdit = require('markdown-it')();
var parseImageSize = require('./helpers/parse_image_size');
var normalizeReference = require('./helpers/normalize_reference.js');
function image_with_size(state, silent) {
var code,
href,
label,
labelEnd,
labelStart,
pos,
ref,
res,
title,
width = '',
height = '',
tokens,
start,
oldPos = state.pos,
max = state.posMax;
if (state.src.charCodeAt(state.pos) !== 0x21/* ! */) { return false; }
if (state.src.charCodeAt(state.pos + 1) !== 0x5B/* [ */) { return false; }
labelStart = state.pos + 2;
labelEnd = mdit.helpers.parseLinkLabel(state, state.pos + 1, false);
// parser failed to find ']', so it's not a valid link
if (labelEnd < 0) { return false; }
pos = labelEnd + 1;
if (pos < max && state.src.charCodeAt(pos) === 0x28/* ( */) {
//
// Inline link
//
// [link]( <href> "title" )
// ^^ skipping these spaces
pos++;
for (; pos < max; pos++) {
code = state.src.charCodeAt(pos);
if (code !== 0x20 && code !== 0x0A) { break; }
}
if (pos >= max) { return false; }
// [link]( <href> "title" )
// ^^^^^^ parsing link destination
start = pos;
res = mdit.helpers.parseLinkDestination(state.src, pos, state.posMax);
if (res.ok && state.md.inline.validateLink(res.str)) {
href = res.str;
pos = res.pos;
} else {
href = '';
}
// [link]( <href> "title" )
// ^^ skipping these spaces
start = pos;
for (; pos < max; pos++) {
code = state.src.charCodeAt(pos);
if (code !== 0x20 && code !== 0x0A) { break; }
}
// [link]( <href> "title" )
// ^^^^^^^ parsing link title
res = mdit.helpers.parseLinkTitle(state.src, pos, state.posMax);
if (pos < max && start !== pos && res.ok) {
title = res.str;
pos = res.pos;
// [link]( <href> "title" )
// ^^ skipping these spaces
for (; pos < max; pos++) {
code = state.src.charCodeAt(pos);
if (code !== 0x20 && code !== 0x0A) { break; }
}
} else {
title = '';
}
// [link]( <href> "title" =WxH )
// ^^^^ parsing image size
if (pos - 1 >= 0) {
code = state.src.charCodeAt(pos - 1);
// there must be at least one white spaces
// between previous field and the size
if (code === 0x20) {
res = parseImageSize(state.src, pos, state.posMax);
if (res.ok) {
width = res.width;
height = res.height;
pos = res.pos;
// [link]( <href> "title" =WxH )
// ^^ skipping these spaces
for (; pos < max; pos++) {
code = state.src.charCodeAt(pos);
if (code !== 0x20 && code !== 0x0A) { break; }
}
}
}
}
if (pos >= max || state.src.charCodeAt(pos) !== 0x29/* ) */) {
state.pos = oldPos;
return false;
}
pos++;
} else {
//
// Link reference
//
if (typeof state.env.references === 'undefined') { return false; }
// [foo] [bar]
// ^^ optional whitespace (can include newlines)
for (; pos < max; pos++) {
code = state.src.charCodeAt(pos);
if (code !== 0x20 && code !== 0x0A) { break; }
}
if (pos < max && state.src.charCodeAt(pos) === 0x5B/* [ */) {
start = pos + 1;
pos = mdit.helpers.parseLinkLabel(state, pos);
if (pos >= 0) {
label = state.src.slice(start, pos++);
} else {
pos = labelEnd + 1;
}
} else {
pos = labelEnd + 1;
}
// covers label === '' and label === undefined
// (collapsed reference link and shortcut reference link respectively)
if (!label) { label = state.src.slice(labelStart, labelEnd); }
ref = state.env.references[normalizeReference(label)];
if (!ref) {
state.pos = oldPos;
return false;
}
href = ref.href;
title = ref.title;
}
//
// We found the end of the link, and know for a fact it's a valid link;
// so all that's left to do is to call tokenizer.
//
if (!silent) {
state.pos = labelStart;
state.posMax = labelEnd;
var newState = new state.md.inline.State(
state.src.slice(labelStart, labelEnd),
state.md,
state.env,
tokens = []
);
newState.md.inline.tokenize(newState);
state.push({
type: 'imsize',
src: href,
title: title,
tokens: tokens,
level: state.level,
width: width,
height: height
});
}
state.pos = pos;
state.posMax = max;
return true;
}
function tokenize_imsize(tokens, idx, options, env, self) {
var src = ' src="' + mdit.utils.escapeHtml(tokens[idx].src) + '"';
var title = tokens[idx].title ? (' title="' + mdit.utils.escapeHtml(mdit.utils.replaceEntities(tokens[idx].title)) + '"') : '';
var alt = ' alt="' + self.renderInlineAsText(tokens[idx].tokens, options, env) + '"';
var width = tokens[idx].width !== '' ? ' width="' + tokens[idx].width + '"' : '';
var height = tokens[idx].height !== '' ? ' height="' + tokens[idx].height + '"' : '';
var size = width + height;
var suffix = options.xhtmlOut ? ' /' : '';
return '<img' + src + alt + title + size + suffix + '>';
};
module.exports = function imsize_plugin(md) {
md.renderer.rules.imsize = tokenize_imsize;
md.inline.ruler.before('emphasis', 'imsize', image_with_size);
}
{
"name": "markdown-it-imsize",
"version": "0.1.0",
"description": "Markdown-it plugin to specify image size",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "https://github.com/tatsy/markdown-it-imsize"
},
"author": "tatsy",
"license": "MIT",
"bugs": {
"url": "https://github.com/tatsy/markdown-it-imsize/issues"
},
"homepage": "https://github.com/tatsy/markdown-it-imsize",
"keywords": [
"markdown-it",
"markdown-it-plubin"
],
"dependencies": {
"eslint": "^0.13.0",
"markdown-it": "^3.0.4",
"markdown-it-testgen": "^0.1.4"
},
"devDependencies": {
"istanbul": "^0.3.5"
}
}
Regression tests for link backtracking optimizations:
.
[[some unrelated text [link]
[link]: foo
.
<p>[[some unrelated text <a href="foo">link</a></p>
.
This is not a valid emphasis, because \n considered a whitespace:
.
**test
**
**
test**
**
test
**
.
<p>**test
**</p>
<p>**
test**</p>
<p>**
test
**</p>
.
Link label has priority over emphasis (not covered by commonmark tests):
.
[**link]()**
**[link**]()
.
<p><a href="">**link</a>**</p>
<p>**<a href="">link**</a></p>
.
Issue #55:
.
![test]
![test](foo bar)
.
<p>![test]</p>
<p>![test](foo bar)</p>
.
Issue #35. `<` shoud work as punctuation
.
an **(:**<br>
.
<p>an <strong>(:</strong><br></p>
.
Should unescape only needed things in link destinations/titles:
.
[test](<\f\o\o\>\\>)
.
<p><a href="%5Cf%5Co%5Co%3E%5C">test</a></p>
.
.
[test](foo "\\\"\b\a\r")
.
<p><a href="foo" title="\&quot;\b\a\r">test</a></p>
.
Not a closing tag
.
</ 123>
.
<p>&lt;/ 123&gt;</p>
.
Not a list item
.
1.list
.
<p>1.list</p>
.
Normalize link destination, but not text inside it:
.
<http://example.com/α%CE%B2γ%CE%B4>
.
<p><a href="http://example.com/%CE%B1%CE%B2%CE%B3%CE%B4">http://example.com/α%CE%B2γ%CE%B4</a></p>
.
Autolinks do not allow escaping:
.
<http://example.com/\[\>
.
<p><a href="http://example.com/%5C%5B%5C">http://example.com/\[\</a></p>
.
Multiline title in definitions:
.
[foo]: test '
1
2
3
'
[foo]
.
<p><a href="test" title="
1
2
3
">foo</a></p>
.
Coverage. Directive can terminate paragraph.
.
a
<?php
.
<p>a</p>
<?php
.
Coverage. Nested email autolink (silent mode)
.
*<foo@bar.com>*
.
<p><em><a href="mailto:foo@bar.com">foo@bar.com</a></em></p>
.
Coverage. Unpaired nested backtick (silent mode)
.
*`foo*
.
<p><em>`foo</em></p>
.
Coverage. Entities.
.
*&*
*&#x20;*
*&amp;*
.
<p><em>&amp;</em></p>
<p><em> </em></p>
<p><em>&amp;</em></p>
.
Coverage. Escape.
.
*\a*
.
<p><em>\a</em></p>
.
Coverage. parseLinkDestination
.
[foo](<
bar>)
[foo](<bar)
.
<p>[foo](&lt;
bar&gt;)</p>
<p>[foo](&lt;bar)</p>
.
Coverage. parseLinkTitle
.
[foo](bar "ba)
[foo](bar "ba\
z")
.
<p>[foo](bar &quot;ba)</p>
<p><a href="bar" title="ba\
z">foo</a></p>
.
Coverage. Image
.
![test]( x )
.
<p><img src="x" alt="test"></p>
.
.
![test][foo]
[bar]: 123
.
<p>![test][foo]</p>
.
.
![test][[[
[bar]: 123
.
<p>![test][[[</p>
.
.
![test](
.
<p>![test](</p>
.
.
![test]( x =100x200)
.
<p><img src="x" alt="test" width="100" height="200"></p>
.
.
![test]( x =x)
.
<p><img src="x" alt="test"></p>
.
.
![test]( x =100x)
.
<p><img src="x" alt="test" width="100"></p>
.
.
![test]( x =x200)
.
<p><img src="x" alt="test" height="200"></p>
.
.
![test]( x "title" =100x200)
.
<p><img src="x" alt="test" title="title" width="100" height="200"></p>
.
Coverage. Link
.
[test](
.
<p>[test](</p>
.
Coverage. Reference
.
[
test\
]: 123
foo
bar
.
<p>foo
bar</p>
.
'use strict';
var path = require('path');
var generate = require('markdown-it-testgen');
describe('markdown-it-imsize', function() {
var md = require('markdown-it')({
html: true,
linkify: true,
typography: true
}).use(require('../'));
generate(path.join(__dirname, 'fixtures/imsize.txt'), md);
});
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment