+1
-1
@@ -1,2 +0,2 @@ | ||
| Copyright (c) 2018 Matteo Merola | ||
| Copyright (c) 2019 Matteo Merola | ||
| Permission is hereby granted, free of charge, to any person obtaining | ||
@@ -3,0 +3,0 @@ a copy of this software and associated documentation files (the |
+2
-1
| { | ||
| "name": "msgdown", | ||
| "version": "1.0.1", | ||
| "version": "1.0.2", | ||
| "description": "A simple message formatter for bold, strikthrough, underline, sub, sup, italic and code.", | ||
@@ -10,2 +10,3 @@ "main": "src/msgdown.js", | ||
| "devDependencies": { | ||
| "standard": "^12.0.1", | ||
| "tape": "^4.9.1" | ||
@@ -12,0 +13,0 @@ }, |
+1
-1
@@ -64,2 +64,2 @@ msgdown | ||
| Matteo Merola <mattmezza@gmail.com> | ||
| Matteo Merola <mattmezza@gmail.com> |
+51
-45
@@ -0,5 +1,15 @@ | ||
| const defaultTokens = { | ||
| bold: { delimiter: '*', tag: 'strong' }, | ||
| italic: { delimiter: '/', tag: 'em' }, | ||
| underline: { delimiter: '_', tag: 'u' }, | ||
| strike: { delimiter: '~', tag: 'del' }, | ||
| code: { delimiter: '`', tag: 'code' }, | ||
| sup: { delimiter: '^', tag: 'sup' }, | ||
| sub: { delimiter: '¡', tag: 'sub' } | ||
| } | ||
| const openTag = tag => `<${tag}>` | ||
| const closeTag = tag => `</${tag}>` | ||
| const encloseTag = (text, tag) => `${openTag(tag)}${text}${closeTag(tag)}` | ||
| const consumeToken = (text, stopDelimiter) => { | ||
| const parseToken = (text, stopDelimiter) => { | ||
| let index = 0 | ||
@@ -11,61 +21,57 @@ let content = '' | ||
| } | ||
| return content | ||
| if (index === text.length) { | ||
| return '' | ||
| } else { | ||
| return content | ||
| } | ||
| } | ||
| const defaultTokens = { | ||
| bold: {delimiter: '*', tag: 'strong'}, | ||
| italic: {delimiter: '/', tag: 'em'}, | ||
| underline: {delimiter: '_', tag: 'u'}, | ||
| strike: {delimiter: '~', tag: 'del'}, | ||
| code: {delimiter: '`', tag: 'code'}, | ||
| sup: {delimiter: '^', tag: 'sup'}, | ||
| sub: {delimiter: '¡', tag: 'sub'} | ||
| } | ||
| module.exports = (text, tokens = defaultTokens) => { | ||
| tokens = Object.assign({}, defaultTokens, tokens) | ||
| const appendDefault = () => { | ||
| let html = '' | ||
| let index = 0 | ||
| const consumeChar = () => { | ||
| html += text[index] | ||
| index++ | ||
| } | ||
| const parseToken = token => { | ||
| const consumeAll = (textRemaining, delimiter) => { | ||
| html += delimiter + textRemaining | ||
| index += textRemaining.length | ||
| } | ||
| const consumeToken = token => { | ||
| index++ | ||
| if (text[index] === ' ') { | ||
| html += token.delimiter | ||
| appendDefault() | ||
| consumeChar() | ||
| } else { | ||
| let tokenContent = consumeToken(text.substr(index), token.delimiter) | ||
| html += encloseTag(tokenContent, token.tag) | ||
| index += tokenContent.length + 1 | ||
| const textRemaining = text.substr(index) | ||
| const tokenContent = parseToken(textRemaining, token.delimiter) | ||
| if (tokenContent.length === 0) { | ||
| consumeAll(textRemaining, token.delimiter) | ||
| } else { | ||
| html += encloseTag(tokenContent, token.tag) | ||
| index += tokenContent.length + 1 | ||
| } | ||
| } | ||
| } | ||
| let html = '' | ||
| let index = 0 | ||
| while (index < text.length) { | ||
| switch (text[index]) { | ||
| case tokens.bold.delimiter: | ||
| parseToken(tokens.bold) | ||
| break | ||
| case tokens.italic.delimiter: | ||
| parseToken(tokens.italic) | ||
| break | ||
| case tokens.underline.delimiter: | ||
| parseToken(tokens.underline) | ||
| break | ||
| case tokens.strike.delimiter: | ||
| parseToken(tokens.strike) | ||
| break | ||
| case tokens.code.delimiter: | ||
| parseToken(tokens.code) | ||
| break | ||
| case tokens.sup.delimiter: | ||
| parseToken(tokens.sup) | ||
| break | ||
| case tokens.sub.delimiter: | ||
| parseToken(tokens.sub) | ||
| break | ||
| default: | ||
| appendDefault() | ||
| const charCurrent = text[index] | ||
| if (charCurrent === tokens.bold.delimiter) { | ||
| consumeToken(tokens.bold) | ||
| } else if (charCurrent === tokens.italic.delimiter) { | ||
| consumeToken(tokens.italic) | ||
| } else if (charCurrent === tokens.underline.delimiter) { | ||
| consumeToken(tokens.underline) | ||
| } else if (charCurrent === tokens.strike.delimiter) { | ||
| consumeToken(tokens.strike) | ||
| } else if (charCurrent === tokens.code.delimiter) { | ||
| consumeToken(tokens.code) | ||
| } else if (charCurrent === tokens.sup.delimiter) { | ||
| consumeToken(tokens.sup) | ||
| } else if (charCurrent === tokens.sub.delimiter) { | ||
| consumeToken(tokens.sub) | ||
| } else { | ||
| consumeChar() | ||
| } | ||
@@ -72,0 +78,0 @@ } |
+72
-51
@@ -5,74 +5,95 @@ const test = require('tape') | ||
| test('Should properly format bold.', t => { | ||
| t.equal(fmt('*pippo*'), '<strong>pippo</strong>') | ||
| t.equal(fmt('*pippo* due'), '<strong>pippo</strong> due') | ||
| t.equal(fmt('uno *pippo* due'), 'uno <strong>pippo</strong> due') | ||
| t.equal(fmt('uno *pippo*'), 'uno <strong>pippo</strong>') | ||
| t.end() | ||
| t.equal(fmt('*pippo*'), '<strong>pippo</strong>') | ||
| t.equal(fmt('*pippo* due'), '<strong>pippo</strong> due') | ||
| t.equal(fmt('uno *pippo* due'), 'uno <strong>pippo</strong> due') | ||
| t.equal(fmt('uno *pippo*'), 'uno <strong>pippo</strong>') | ||
| t.end() | ||
| }) | ||
| test('Should properly format italic.', t => { | ||
| t.equal(fmt('/pippo/'), '<em>pippo</em>') | ||
| t.equal(fmt('/pippo/ due'), '<em>pippo</em> due') | ||
| t.equal(fmt('uno /pippo/ due'), 'uno <em>pippo</em> due') | ||
| t.equal(fmt('uno /pippo/'), 'uno <em>pippo</em>') | ||
| t.end() | ||
| t.equal(fmt('/pippo/'), '<em>pippo</em>') | ||
| t.equal(fmt('/pippo/ due'), '<em>pippo</em> due') | ||
| t.equal(fmt('uno /pippo/ due'), 'uno <em>pippo</em> due') | ||
| t.equal(fmt('uno /pippo/'), 'uno <em>pippo</em>') | ||
| t.end() | ||
| }) | ||
| test('Should properly format underline.', t => { | ||
| t.equal(fmt('_pippo_'), '<u>pippo</u>') | ||
| t.equal(fmt('_pippo_ due'), '<u>pippo</u> due') | ||
| t.equal(fmt('uno _pippo_ due'), 'uno <u>pippo</u> due') | ||
| t.equal(fmt('uno _pippo_'), 'uno <u>pippo</u>') | ||
| t.end() | ||
| t.equal(fmt('_pippo_'), '<u>pippo</u>') | ||
| t.equal(fmt('_pippo_ due'), '<u>pippo</u> due') | ||
| t.equal(fmt('uno _pippo_ due'), 'uno <u>pippo</u> due') | ||
| t.equal(fmt('uno _pippo_'), 'uno <u>pippo</u>') | ||
| t.end() | ||
| }) | ||
| test('Should properly format strike through.', t => { | ||
| t.equal(fmt('~pippo~'), '<del>pippo</del>') | ||
| t.equal(fmt('~pippo~ due'), '<del>pippo</del> due') | ||
| t.equal(fmt('uno ~pippo~ due'), 'uno <del>pippo</del> due') | ||
| t.equal(fmt('uno ~pippo~'), 'uno <del>pippo</del>') | ||
| t.end() | ||
| t.equal(fmt('~pippo~'), '<del>pippo</del>') | ||
| t.equal(fmt('~pippo~ due'), '<del>pippo</del> due') | ||
| t.equal(fmt('uno ~pippo~ due'), 'uno <del>pippo</del> due') | ||
| t.equal(fmt('uno ~pippo~'), 'uno <del>pippo</del>') | ||
| t.end() | ||
| }) | ||
| test('Should properly format code.', t => { | ||
| t.equal(fmt('`pippo`'), '<code>pippo</code>') | ||
| t.equal(fmt('`pippo` due'), '<code>pippo</code> due') | ||
| t.equal(fmt('uno `pippo` due'), 'uno <code>pippo</code> due') | ||
| t.equal(fmt('uno `pippo`'), 'uno <code>pippo</code>') | ||
| t.end() | ||
| t.equal(fmt('`pippo`'), '<code>pippo</code>') | ||
| t.equal(fmt('`pippo` due'), '<code>pippo</code> due') | ||
| t.equal(fmt('uno `pippo` due'), 'uno <code>pippo</code> due') | ||
| t.equal(fmt('uno `pippo`'), 'uno <code>pippo</code>') | ||
| t.end() | ||
| }) | ||
| test('Should properly format sub.', t => { | ||
| t.equal(fmt('¡pippo¡'), '<sub>pippo</sub>') | ||
| t.equal(fmt('¡pippo¡ due'), '<sub>pippo</sub> due') | ||
| t.equal(fmt('uno ¡pippo¡ due'), 'uno <sub>pippo</sub> due') | ||
| t.equal(fmt('uno ¡pippo¡'), 'uno <sub>pippo</sub>') | ||
| t.end() | ||
| t.equal(fmt('¡pippo¡'), '<sub>pippo</sub>') | ||
| t.equal(fmt('¡pippo¡ due'), '<sub>pippo</sub> due') | ||
| t.equal(fmt('uno ¡pippo¡ due'), 'uno <sub>pippo</sub> due') | ||
| t.equal(fmt('uno ¡pippo¡'), 'uno <sub>pippo</sub>') | ||
| t.end() | ||
| }) | ||
| test('Should properly format sup.', t => { | ||
| t.equal(fmt('^pippo^'), '<sup>pippo</sup>') | ||
| t.equal(fmt('^pippo^ due'), '<sup>pippo</sup> due') | ||
| t.equal(fmt('uno ^pippo^ due'), 'uno <sup>pippo</sup> due') | ||
| t.equal(fmt('uno ^pippo^'), 'uno <sup>pippo</sup>') | ||
| t.end() | ||
| t.equal(fmt('^pippo^'), '<sup>pippo</sup>') | ||
| t.equal(fmt('^pippo^ due'), '<sup>pippo</sup> due') | ||
| t.equal(fmt('uno ^pippo^ due'), 'uno <sup>pippo</sup> due') | ||
| t.equal(fmt('uno ^pippo^'), 'uno <sup>pippo</sup>') | ||
| t.end() | ||
| }) | ||
| test('Should properly format with custom tokens.', t => { | ||
| const customTokens = { | ||
| bold: {delimiter: '#', tag: 'strong'}, | ||
| italic: {delimiter: '%', tag: 'em'}, | ||
| underline: {delimiter: '…', tag: 'u'}, | ||
| strike: {delimiter: '—', tag: 'del'}, | ||
| code: {delimiter: '&', tag: 'code'}, | ||
| } | ||
| const customTokens = { | ||
| bold: { delimiter: '#', tag: 'strong' }, | ||
| italic: { delimiter: '%', tag: 'em' }, | ||
| underline: { delimiter: '…', tag: 'u' }, | ||
| strike: { delimiter: '—', tag: 'del' }, | ||
| code: { delimiter: '&', tag: 'code' } | ||
| } | ||
| t.equal(fmt('#pippo#', customTokens), '<strong>pippo</strong>') | ||
| t.equal(fmt('%pippo%', customTokens), '<em>pippo</em>') | ||
| t.equal(fmt('…pippo…', customTokens), '<u>pippo</u>') | ||
| t.equal(fmt('—pippo—', customTokens), '<del>pippo</del>') | ||
| t.equal(fmt('&pippo&', customTokens), '<code>pippo</code>') | ||
| t.equal(fmt('^pippo^', customTokens), '<sup>pippo</sup>') | ||
| t.equal(fmt('¡pippo¡', customTokens), '<sub>pippo</sub>') | ||
| t.end() | ||
| }) | ||
| t.equal(fmt('#pippo#', customTokens), '<strong>pippo</strong>') | ||
| t.equal(fmt('%pippo%', customTokens), '<em>pippo</em>') | ||
| t.equal(fmt('…pippo…', customTokens), '<u>pippo</u>') | ||
| t.equal(fmt('—pippo—', customTokens), '<del>pippo</del>') | ||
| t.equal(fmt('&pippo&', customTokens), '<code>pippo</code>') | ||
| t.equal(fmt('^pippo^', customTokens), '<sup>pippo</sup>') | ||
| t.equal(fmt('¡pippo¡', customTokens), '<sub>pippo</sub>') | ||
| t.end() | ||
| }) | ||
| test('Should not parse anything.', t => { | ||
| [ | ||
| 'user_name', | ||
| 'https://www.dio.it/', | ||
| 'dir/', | ||
| 'first^', | ||
| '~5', | ||
| '5*4=20' | ||
| ].map(s => { | ||
| t.equal(fmt(s), s) | ||
| }) | ||
| t.end() | ||
| }) | ||
| test('Should not epic fail.', t => { | ||
| const msg = `*Attention:* /msgdown/^TM^ is great¡1¡. _Use it_ or ~don't~ it is \`console.log('up to you!')\`` | ||
| const oracle = `<strong>Attention:</strong> <em>msgdown</em><sup>TM</sup> is great<sub>1</sub>. <u>Use it</u> or <del>don't</del> it is <code>console.log('up to you!')</code>` | ||
| t.equal(fmt(msg), oracle) | ||
| t.end() | ||
| }) |
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
102364
0.89%162
19.12%65
1.56%2
100%2
100%