diff --git a/demo/sample.md b/demo/sample.md
index 141b57f..cebf727 100644
--- a/demo/sample.md
+++ b/demo/sample.md
@@ -56,6 +56,8 @@ _This is italic text_
~~Deleted text~~
+++Inserted text++
+
## Blockquotes
diff --git a/lib/configs/full.js b/lib/configs/full.js
new file mode 100644
index 0000000..c7a59cd
--- /dev/null
+++ b/lib/configs/full.js
@@ -0,0 +1,43 @@
+// Remarkable default options
+
+'use strict';
+
+
+module.exports = {
+ options: {
+ html: false, // Enable html tags in source
+ xhtmlOut: false, // Use '/' to close single tags (
)
+ breaks: false, // Convert '\n' in paragraphs into
+ langPrefix: 'language-', // CSS language prefix for fenced blocks
+ linkify: false, // autoconvert url-like texts to links
+ typographer: false, // Enable smartypants and other sweet transforms
+
+ // Highlighter function. Should return escaped html,
+ // or '' if input not changed
+ highlight: function (/*str, , lang*/) { return ''; },
+
+ maxNesting: 20 // Internal protection, recursion limit
+ },
+
+ components: {
+
+ // Don't restrict block/inline rules
+ block: {},
+ inline: {},
+
+ typographer: {
+ options: {
+ singleQuotes: '‘’', // set empty to disable
+ doubleQuotes: '“”', // set '«»' for russian, '„“' for deutch, empty to disable
+ copyright: true, // (c) (C) → ©
+ trademark: true, // (tm) (TM) → ™
+ registered: true, // (r) (R) → ®
+ plusminus: true, // +- → ±
+ paragraph: true, // (p) (P) → §
+ ellipsis: true, // ... → …
+ dupes: true, // ???????? → ???, !!!!! → !!!, `,,` → `,`
+ dashes: true // -- → —
+ }
+ }
+ }
+};
diff --git a/lib/parser_inline.js b/lib/parser_inline.js
index 62a12e0..d327acf 100644
--- a/lib/parser_inline.js
+++ b/lib/parser_inline.js
@@ -18,6 +18,7 @@ rules.push(require('./rules_inline/newline'));
rules.push(require('./rules_inline/escape'));
rules.push(require('./rules_inline/backticks'));
rules.push(require('./rules_inline/del'));
+rules.push(require('./rules_inline/ins'));
rules.push(require('./rules_inline/emphasis'));
rules.push(require('./rules_inline/links'));
rules.push(require('./rules_inline/autolink'));
@@ -50,7 +51,7 @@ function ParserInline() {
// Rule to skip pure text
// - '{$%@}' reserved for extentions
// - '<>"' added for internal html escaping
- this.textMatch = /^[^\n\\`*_\[\]!&{}$%@<>"~]+/;
+ this.textMatch = /^[^\n\\`*_\[\]!&{}$%@<>"~+]+/;
// By default CommonMark allows too much in links
// If you need to restrict it - override this with your validator.
diff --git a/lib/renderer.js b/lib/renderer.js
index c4b66c8..b0b6c9f 100644
--- a/lib/renderer.js
+++ b/lib/renderer.js
@@ -200,6 +200,14 @@ rules.del_close = function(/*tokens, idx, options*/) {
};
+rules.ins_open = function(/*tokens, idx, options*/) {
+ return '';
+};
+rules.ins_close = function(/*tokens, idx, options*/) {
+ return '';
+};
+
+
rules.hardbreak = function (tokens, idx, options) {
return options.xhtmlOut ? '
\n' : '
\n';
};
diff --git a/lib/rules_inline/del.js b/lib/rules_inline/del.js
index 0bcb2eb..0ad84ba 100644
--- a/lib/rules_inline/del.js
+++ b/lib/rules_inline/del.js
@@ -1,4 +1,4 @@
-// Process ~~strike through~~
+// Process ~~deleted text~~
'use strict';
@@ -24,7 +24,7 @@ module.exports = function del(state, silent) {
nextChar = state.src.charCodeAt(start + 2);
if (lastChar === 0x7E/* ~ */) { return false; }
- if (nextChar === 0x7E/* */) { return false; }
+ if (nextChar === 0x7E/* ~ */) { return false; }
if (nextChar === 0x20 || nextChar === 0x0A) { return false; }
pos = start + 2;
diff --git a/lib/rules_inline/ins.js b/lib/rules_inline/ins.js
new file mode 100644
index 0000000..291f625
--- /dev/null
+++ b/lib/rules_inline/ins.js
@@ -0,0 +1,78 @@
+// Process ++inserted text++
+
+'use strict';
+
+module.exports = function ins(state, silent) {
+ var found,
+ pos,
+ max = state.posMax,
+ start = state.pos,
+ lastChar,
+ nextChar;
+
+ if (state.src.charCodeAt(start) !== 0x2B/* + */) { return false; }
+ if (start + 4 >= max) { return false; }
+ if (state.src.charCodeAt(start + 1) !== 0x2B/* + */) { return false; }
+
+ // make ins lower a priority tag with respect to links, same as ;
+ // this code also prevents recursion
+ if (silent && state.isInLabel) { return false; }
+
+ if (state.level >= state.options.maxNesting) { return false; }
+
+ lastChar = start > 0 ? state.src.charCodeAt(start - 1) : -1;
+ nextChar = state.src.charCodeAt(start + 2);
+
+ if (lastChar === 0x2B/* + */) { return false; }
+ if (nextChar === 0x2B/* + */) { return false; }
+ if (nextChar === 0x20 || nextChar === 0x0A) { return false; }
+
+ pos = start + 2;
+ while (pos < max && state.src.charCodeAt(pos) === 0x2B/* + */) { pos++; }
+ if (pos !== start + 2) {
+ // sequence of 3+ markers taking as literal, same as in a emphasis
+ state.pos += pos - start;
+ if (!silent) { state.pending += state.src.slice(start, pos); }
+ return true;
+ }
+
+ state.pos = start + 2;
+
+ while (state.pos + 1 < max) {
+ if (state.src.charCodeAt(state.pos) === 0x2B/* + */) {
+ if (state.src.charCodeAt(state.pos + 1) === 0x2B/* + */) {
+ lastChar = state.src.charCodeAt(state.pos - 1);
+ nextChar = state.pos + 2 < max ? state.src.charCodeAt(state.pos + 2) : -1;
+ if (nextChar !== 0x2B/* + */ && lastChar !== 0x2B/* + */) {
+ if (lastChar !== 0x20 && lastChar !== 0x0A) {
+ // closing '++'
+ found = true;
+ break;
+ }
+ }
+ }
+ }
+
+ state.parser.skipToken(state);
+ }
+
+ if (!found) {
+ // parser failed to find ending tag, so it's not valid emphasis
+ state.pos = start;
+ return false;
+ }
+
+ // found!
+ state.posMax = state.pos;
+ state.pos = start + 2;
+
+ if (!silent) {
+ state.push({ type: 'ins_open', level: state.level++ });
+ state.parser.tokenize(state);
+ state.push({ type: 'ins_close', level: --state.level });
+ }
+
+ state.pos = state.posMax + 2;
+ state.posMax = max;
+ return true;
+};
diff --git a/test/fixtures/remarkable/ins.txt b/test/fixtures/remarkable/ins.txt
new file mode 100644
index 0000000..33fa0ae
--- /dev/null
+++ b/test/fixtures/remarkable/ins.txt
@@ -0,0 +1,93 @@
+.
+++Insert++
+.
+Insert
+.
+
+
+These are not inserts, you have to use exactly two "++":
+.
+x +++foo+++
+
+x ++foo+++
+
+x +++foo++
+.
+x +++foo+++
+x ++foo+++
+x +++foo++
+.
+
+Inserts have the same priority as emphases:
+
+.
+**++test**++
+
+++**test++**
+.
+**test**
+++test++
+.
+
+Inserts have the same priority as emphases with respect to links:
+.
+[++link]()++
+
+++[link++]()
+.
+++link++
+++link++
+.
+
+Inserts have the same priority as emphases with respect to backticks:
+.
+++`code++`
+
+`++code`++
+.
+++code++
+++code
++
+.
+
+Nested inserts:
+.
+++foo ++bar++ baz++
+.
+foo bar baz
+.
+
+.
+++f **o ++o b++ a** r++
+.
+f o o b a r
+.
+
+Should not have a whitespace between text and "++":
+.
+foo ++ bar ++ baz
+.
+foo ++ bar ++ baz
+.
+
+
+Newline should be considered a whitespace:
+
+.
+++test
+++
+
+++
+test++
+
+++
+test
+++
+.
+++test
+++
+++
+test++
+++
+test
+++
+.