forked from sashin/sashinexists
run npm install to generate a package lock
This commit is contained in:
29
node_modules/smartypants/LICENSE
generated
vendored
Normal file
29
node_modules/smartypants/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2016, othree
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
327
node_modules/smartypants/README.md
generated
vendored
Normal file
327
node_modules/smartypants/README.md
generated
vendored
Normal file
@@ -0,0 +1,327 @@
|
||||
# SmartyPants
|
||||
|
||||
Easily translates plain ASCII punctuation characters into "smart" typographic punctuation HTML entities.
|
||||
|
||||
The following text about what is SmartyPants and how to use it is from
|
||||
the original [SmartyPants.pl][] project.
|
||||
|
||||
[SmartyPants.pl]:https://daringfireball.net/projects/smartypants/
|
||||
|
||||
by John Gruber
|
||||
<http://daringfireball.net/>
|
||||
|
||||
|
||||
SmartyPants is a free web publishing plug-in for Movable Type, Blosxom,
|
||||
and BBEdit. that easily translates plain ASCII punctuation characters
|
||||
into "smart" typographic punctuation HTML entities. SmartyPants can also
|
||||
be invoked as a standalone Perl script. smartypants.js is JavaScript
|
||||
version of Smartypants.pl. Provides the translate feature and supports
|
||||
output UTF-8 character instead of HTML entity.
|
||||
|
||||
SmartyPants can perform the following transformations:
|
||||
|
||||
* Straight quotes (`"` and `'`) into "curly" quote HTML entities
|
||||
|
||||
* Backtick-style quotes (` ``like this'' `) into "curly" quote HTML
|
||||
entities
|
||||
|
||||
* Dashes (`--` and `---`) into en- and em-dash entities
|
||||
|
||||
* Three consecutive dots (`...`) into an ellipsis entity
|
||||
|
||||
This means you can write, edit, and save your posts using plain old
|
||||
ASCII straight quotes, plain dashes, and plain dots, but your published
|
||||
posts (and final HTML output) will appear with smart quotes, em-dashes,
|
||||
and proper ellipses.
|
||||
|
||||
SmartyPants does not modify characters within `<pre>`, `<code>`,
|
||||
`<kbd>`, or `<script>` tag blocks. Typically, these tags are used to
|
||||
display text where smart quotes and other "smart punctuation" would not
|
||||
be appropriate, such as source code or example markup.
|
||||
|
||||
|
||||
### Backslash Escapes ###
|
||||
|
||||
If you need to use literal straight quotes (or plain hyphens and
|
||||
periods), SmartyPants accepts the following backslash escape sequences
|
||||
to force non-smart punctuation. It does so by transforming the escape
|
||||
sequence into a decimal-encoded HTML entity:
|
||||
|
||||
|
||||
Escape Value Character
|
||||
------ ----- ---------
|
||||
\\ \ \
|
||||
\" " "
|
||||
\' ' '
|
||||
\. . .
|
||||
\- - -
|
||||
\` ` `
|
||||
|
||||
|
||||
This is useful, for example, when you want to use straight quotes as
|
||||
foot and inch marks:
|
||||
|
||||
6\'2\" tall
|
||||
|
||||
translates into:
|
||||
|
||||
6'2" tall
|
||||
|
||||
in SmartyPants's HTML output. Which, when rendered by a web browser,
|
||||
looks like:
|
||||
|
||||
6'2" tall
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
### Node ###
|
||||
|
||||
Command line:
|
||||
|
||||
npm install -g smartypants
|
||||
|
||||
Nodejs module:
|
||||
|
||||
npm install smartypants
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
### Command Line ###
|
||||
|
||||
smartypants command line only support stdio now:
|
||||
|
||||
cat source.txt | smartypants
|
||||
|
||||
There is another command `smartypantsu` return UTF-8 character instead of HTML entity.
|
||||
|
||||
cat source.txt | smartypants
|
||||
|
||||
### Node Module ###
|
||||
|
||||
var smartypants = require('smartypants');
|
||||
|
||||
var attr = 1; // Number or string
|
||||
var sourceText = '"hello!"';
|
||||
|
||||
var educated = smartypants.smartypants(sourceText, attr);
|
||||
|
||||
### ES6 Module ###
|
||||
|
||||
ES6 module only availabe in [pkg.module][] and [mjs][] extension.
|
||||
|
||||
[pkg.module]:https://github.com/rollup/rollup/wiki/pkg.module
|
||||
[mjs]:https://nodejs.org/api/esm.html
|
||||
|
||||
import smartypants from 'smartypants';
|
||||
|
||||
var attr = 1; // Number or string
|
||||
var sourceText = '"hello!"';
|
||||
|
||||
var educated = smartypants(sourceText, attr); // default export is available
|
||||
|
||||
In node module, smartypants provides several methods, orginal provided
|
||||
only in MT Tempalte:
|
||||
|
||||
* default is smartypants (ES6 module only)
|
||||
* `smartypants` educates everything
|
||||
* `smartypantsu` educates everything, return UTF-8 characters instead of HTML entity
|
||||
* `smartquotes` only educates quotes
|
||||
* `smartdashes` only educates dashes
|
||||
* `smartellipses` only educates ellipses
|
||||
|
||||
|
||||
## Options and Configuration
|
||||
|
||||
Numeric values are the easiest way to configure SmartyPants's behavior:
|
||||
|
||||
"0"
|
||||
Suppress all transformations. (Do nothing.)
|
||||
|
||||
"1"
|
||||
Performs default SmartyPants transformations: quotes (including
|
||||
backticks-style), em-dashes, and ellipses. `--` (dash dash) is
|
||||
used to signify an em-dash; there is no support for en-dashes.
|
||||
|
||||
"2"
|
||||
Same as smarty_pants="1", except that it uses the old-school
|
||||
typewriter shorthand for dashes: `--` (dash dash) for en-dashes,
|
||||
`---` (dash dash dash) for em-dashes.
|
||||
|
||||
"3"
|
||||
Same as smarty_pants="2", but inverts the shorthand for dashes: `--`
|
||||
(dash dash) for em-dashes, and `---` (dash dash dash) for en-dashes.
|
||||
|
||||
"-1"
|
||||
Stupefy mode. Reverses the SmartyPants transformation process,
|
||||
turning the HTML entities produced by SmartyPants into their ASCII
|
||||
equivalents. E.g. `“` is turned into a simple double-quote
|
||||
(`"`), `—` is turned into two dashes, etc. This is useful if you
|
||||
are using SmartyPants from Brad Choate's MT-Textile text filter, but
|
||||
wish to suppress smart punctuation in specific MT templates, such as
|
||||
RSS feeds. Text filters do their work before templates are
|
||||
processed; but you can use smarty_pants="-1" to reverse the
|
||||
transformations in specific templates.
|
||||
|
||||
The following single-character attribute values can be combined to
|
||||
toggle individual transformations from within the smarty_pants
|
||||
attribute. For example, to educate normal quotes and em-dashes, but not
|
||||
ellipses or backticks-style quotes: `qd`
|
||||
|
||||
"q"
|
||||
Educates normal quote characters: (`"`) and (`'`).
|
||||
|
||||
"b"
|
||||
Educates ` ``backticks'' ` double quotes.
|
||||
|
||||
"B"
|
||||
Educates backticks-style double quotes and ` `single' ` quotes.
|
||||
|
||||
"d"
|
||||
Educates em-dashes.
|
||||
|
||||
"D"
|
||||
Educates em-dashes and en-dashes, using old-school typewriter
|
||||
shorthand: (dash dash) for en-dashes, (dash dash dash) for
|
||||
em-dashes.
|
||||
|
||||
"i"
|
||||
Educates em-dashes and en-dashes, using inverted old-school
|
||||
typewriter shorthand: (dash dash) for em-dashes, (dash dash dash)
|
||||
for en-dashes.
|
||||
|
||||
"e"
|
||||
Educates ellipses.
|
||||
|
||||
"w"
|
||||
Translates any instance of `"` into a normal double-quote
|
||||
character. This should be of no interest to most people, but of
|
||||
particular interest to anyone who writes their posts using
|
||||
Dreamweaver, as Dreamweaver inexplicably uses this entity to
|
||||
represent a literal double-quote character. SmartyPants only
|
||||
educates normal quotes, not entities (because ordinarily, entities
|
||||
are used for the explicit purpose of representing the specific
|
||||
character they represent). The "w" option must be used in
|
||||
conjunction with one (or both) of the other quote options ("q" or
|
||||
"b"). Thus, if you wish to apply all SmartyPants transformations
|
||||
(quotes, en- and em-dashes, and ellipses) and also translate
|
||||
`"` entities into regular quotes so SmartyPants can educate
|
||||
them, you should pass the following to the smarty_pants attribute:
|
||||
|
||||
smartypants(sourceText, 'qDew');
|
||||
|
||||
|
||||
## Caveats
|
||||
|
||||
### Why You Might Not Want to Use Smart Quotes in Your Weblog ###
|
||||
|
||||
For one thing, you might not care.
|
||||
|
||||
Most normal, mentally stable individuals do not take notice of proper
|
||||
typographic punctuation. Many design and typography nerds, however,
|
||||
break out in a nasty rash when they encounter, say, a restaurant sign
|
||||
that uses a straight apostrophe to spell "Joe's".
|
||||
|
||||
If you're the sort of person who just doesn't care, you might well want
|
||||
to continue not caring. Using straight quotes -- and sticking to the
|
||||
7-bit ASCII character set in general -- is certainly a simpler way to
|
||||
live.
|
||||
|
||||
Even if you *do* care about accurate typography, you still might want to
|
||||
think twice before educating the quote characters in your weblog. One
|
||||
side effect of publishing curly quote HTML entities is that it makes
|
||||
your weblog a bit harder for others to quote from using copy-and-paste.
|
||||
What happens is that when someone copies text from your blog, the copied
|
||||
text contains the 8-bit curly quote characters (as well as the 8-bit
|
||||
characters for em-dashes and ellipses, if you use these options). These
|
||||
characters are not standard across different text encoding methods,
|
||||
which is why they need to be encoded as HTML entities.
|
||||
|
||||
People copying text from your weblog, however, may not notice that
|
||||
you're using curly quotes, and they'll go ahead and paste the unencoded
|
||||
8-bit characters copied from their browser into an email message or
|
||||
their own weblog. When pasted as raw "smart quotes", these characters
|
||||
are likely to get mangled beyond recognition.
|
||||
|
||||
That said, my own opinion is that any decent text editor or email client
|
||||
makes it easy to stupefy smart quote characters into their 7-bit
|
||||
equivalents, and I don't consider it my problem if you're using an
|
||||
indecent text editor or email client.
|
||||
|
||||
### Algorithmic Shortcomings ###
|
||||
|
||||
One situation in which quotes will get curled the wrong way is when
|
||||
apostrophes are used at the start of leading contractions. For example:
|
||||
|
||||
'Twas the night before Christmas.
|
||||
|
||||
In the case above, SmartyPants will turn the apostrophe into an opening
|
||||
single-quote, when in fact it should be a closing one. I don't think
|
||||
this problem can be solved in the general case -- every word processor
|
||||
I've tried gets this wrong as well. In such cases, it's best to use the
|
||||
proper HTML entity for closing single-quotes (`’` or `’`) by
|
||||
hand.
|
||||
|
||||
|
||||
## Version History
|
||||
|
||||
|
||||
## Author
|
||||
|
||||
John Gruber
|
||||
http://daringfireball.net
|
||||
|
||||
|
||||
## JavaScript Port Maintainer
|
||||
|
||||
Kao, Wei-Ko(othree)
|
||||
https://blog.othree.net
|
||||
|
||||
|
||||
## Additional Credits
|
||||
|
||||
Portions of this plug-in are based on Brad Choate's nifty MTRegex
|
||||
plug-in. Brad Choate also contributed a few bits of source code to this
|
||||
plug-in. Brad Choate is a fine hacker indeed. (http://bradchoate.com/)
|
||||
|
||||
Jeremy Hedley (http://antipixel.com/) and Charles Wiltgen
|
||||
(http://playbacktime.com/) deserve mention for exemplary beta testing.
|
||||
|
||||
Rael Dornfest (http://raelity.org/) ported SmartyPants to Blosxom.
|
||||
|
||||
|
||||
## Copyright and License
|
||||
|
||||
Copyright (c) 2004 John Gruber
|
||||
(http://daringfireball.net/)
|
||||
Copyright (c) 2016 Kao, Wei-Ko(othree)
|
||||
(https://blog.othree.net/)
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name "SmartyPants" nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
This software is provided by the copyright holders and contributors "as
|
||||
is" and any express or implied warranties, including, but not limited
|
||||
to, the implied warranties of merchantability and fitness for a
|
||||
particular purpose are disclaimed. In no event shall the copyright owner
|
||||
or contributors be liable for any direct, indirect, incidental, special,
|
||||
exemplary, or consequential damages (including, but not limited to,
|
||||
procurement of substitute goods or services; loss of use, data, or
|
||||
profits; or business interruption) however caused and on any theory of
|
||||
liability, whether in contract, strict liability, or tort (including
|
||||
negligence or otherwise) arising in any way out of the use of this
|
||||
software, even if advised of the possibility of such damage.
|
||||
24
node_modules/smartypants/bin/smartypants.js
generated
vendored
Executable file
24
node_modules/smartypants/bin/smartypants.js
generated
vendored
Executable file
@@ -0,0 +1,24 @@
|
||||
#! /usr/bin/env node
|
||||
|
||||
if (process.stdin.isTTY) {
|
||||
console.error('No input!');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
var smartypants = require('..').smartypants;
|
||||
|
||||
var text = '';
|
||||
|
||||
process.stdin.setEncoding('utf8');
|
||||
|
||||
process.stdin.on('readable', () => {
|
||||
var chunk = process.stdin.read();
|
||||
if (chunk !== null) {
|
||||
text = text + chunk;
|
||||
}
|
||||
});
|
||||
|
||||
process.stdin.on('end', () => {
|
||||
process.stdout.write(smartypants(text, '1'));
|
||||
});
|
||||
|
||||
24
node_modules/smartypants/bin/smartypantsu.js
generated
vendored
Executable file
24
node_modules/smartypants/bin/smartypantsu.js
generated
vendored
Executable file
@@ -0,0 +1,24 @@
|
||||
#! /usr/bin/env node
|
||||
|
||||
if (process.stdin.isTTY) {
|
||||
console.error('No input!');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
var smartypants = require('..').smartypantsu;
|
||||
|
||||
var text = '';
|
||||
|
||||
process.stdin.setEncoding('utf8');
|
||||
|
||||
process.stdin.on('readable', () => {
|
||||
var chunk = process.stdin.read();
|
||||
if (chunk !== null) {
|
||||
text = text + chunk;
|
||||
}
|
||||
});
|
||||
|
||||
process.stdin.on('end', () => {
|
||||
process.stdout.write(smartypants(text, '1'));
|
||||
});
|
||||
|
||||
58
node_modules/smartypants/package.json
generated
vendored
Normal file
58
node_modules/smartypants/package.json
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"name": "smartypants",
|
||||
"version": "0.2.2",
|
||||
"type": "module",
|
||||
"main": "smartypants.mjs",
|
||||
"module": "smartypants.mjs",
|
||||
"browser": "smartypants.es6.js",
|
||||
"jsnext:main": "smartypants.es6.js",
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./smartypants.mjs",
|
||||
"require": "./smartypants.cjs"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"test": "node --experimental-modules test/index.mjs"
|
||||
},
|
||||
"keywords": [
|
||||
"smartypants",
|
||||
"typographic",
|
||||
"quote",
|
||||
"dash",
|
||||
"ellipses"
|
||||
],
|
||||
"repository": {
|
||||
"url": "git@github.com:othree/smartypants.js.git",
|
||||
"type": "git"
|
||||
},
|
||||
"author": {
|
||||
"name": "othree",
|
||||
"url": "https://github.com/othree"
|
||||
},
|
||||
"license": "BSD-3-Clause",
|
||||
"files": [
|
||||
"smartypants.js",
|
||||
"smartypants.mjs",
|
||||
"smartypants.cjs",
|
||||
"smartypants.es6.js",
|
||||
"bin/smartypants.js",
|
||||
"bin/smartypantsu.js"
|
||||
],
|
||||
"bin": {
|
||||
"smartypants": "./bin/smartypants.js",
|
||||
"smartypantsu": "./bin/smartypantsu.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-eslint": "^9.0.0",
|
||||
"eslint-config-standard": "^12.0.0",
|
||||
"eslint-plugin-import": "^2.14.0",
|
||||
"eslint-plugin-node": "^7.0.1",
|
||||
"eslint-plugin-pep8-blank-lines": "0.0.5",
|
||||
"eslint-plugin-promise": "^4.0.1",
|
||||
"eslint-plugin-standard": "^4.0.0",
|
||||
"tape": "^4.9.0",
|
||||
"typescript": "^3.0.3",
|
||||
"uglify-js": "3.9.4"
|
||||
}
|
||||
}
|
||||
806
node_modules/smartypants/smartypants.cjs
generated
vendored
Normal file
806
node_modules/smartypants/smartypants.cjs
generated
vendored
Normal file
@@ -0,0 +1,806 @@
|
||||
/* eslint-env browser, amd, node */
|
||||
|
||||
/**
|
||||
*
|
||||
* @file Translates plain ASCII punctuation characters into "smart" typographic punctuation
|
||||
* @desc See the readme for details, installation instructions, and * license information.
|
||||
* @version 0.0.4
|
||||
* @author othree
|
||||
*
|
||||
* Copyright (c) 2003-2004 John Gruber
|
||||
* Copyright (c) 2016 Kao, Wei-Ko(othree)
|
||||
*
|
||||
* @see {@link https://www.npmjs.com/package/smartypants|smartypants.js}
|
||||
*/
|
||||
|
||||
/*! smartypants.js 0.0.6 | (c) Kao, Wei-Ko(othree) | github.com/othree/smartypants.js/blob/master/LICENSE */
|
||||
|
||||
(function (root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD
|
||||
define('SmartyPants', ['exports'], function (exports) {
|
||||
factory((root.SmartyPants = exports));
|
||||
});
|
||||
} else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {
|
||||
// CommonJS
|
||||
factory(exports);
|
||||
} else {
|
||||
// Browser globals
|
||||
factory((root.SmartyPants = {}));
|
||||
}
|
||||
}(this, function (exports) {
|
||||
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
exports.smartypantsu = exports.smartellipses = exports.smartdashes = exports.smartquotes = exports.smartypants = void 0;
|
||||
var tags_to_skip = /<(\/?)(?:pre|code|kbd|script|math)[^>]*>/i;
|
||||
/**
|
||||
* @param text text to be parsed
|
||||
* @param attr value of the smart_quotes="" attribute
|
||||
*/
|
||||
var SmartyPants = function (text, attr) {
|
||||
if (text === void 0) { text = ''; }
|
||||
if (attr === void 0) { attr = '1'; }
|
||||
var do_quotes;
|
||||
var do_backticks;
|
||||
var do_dashes;
|
||||
var do_ellipses;
|
||||
var do_stupefy;
|
||||
var convert_quot = 0;
|
||||
if (typeof attr === 'number') {
|
||||
attr = attr.toString();
|
||||
}
|
||||
else {
|
||||
attr = attr.replace(/\s/g, '');
|
||||
}
|
||||
/**
|
||||
* Parse attributes:
|
||||
* 0 : do nothing
|
||||
* 1 : set all
|
||||
* 2 : set all, using old school en- and em- dash shortcuts
|
||||
* 3 : set all, using inverted old school en and em- dash shortcuts
|
||||
*
|
||||
* q : quotes
|
||||
* b : backtick quotes (``double'' only)
|
||||
* B : backtick quotes (``double'' and `single')
|
||||
* d : dashes
|
||||
* D : old school dashes
|
||||
* i : inverted old school dashes
|
||||
* e : ellipses
|
||||
* w : convert " entities to " for Dreamweaver users
|
||||
*/
|
||||
if (attr === '0') {
|
||||
// Do nothing
|
||||
return text;
|
||||
}
|
||||
else if (attr === '1') {
|
||||
// Do everything, turn all options on.
|
||||
do_quotes = 1;
|
||||
do_backticks = 1;
|
||||
do_dashes = 1;
|
||||
do_ellipses = 1;
|
||||
}
|
||||
else if (attr === '2') {
|
||||
// Do everything, turn all options on, use old school dash shorthand.
|
||||
do_quotes = 1;
|
||||
do_backticks = 1;
|
||||
do_dashes = 2;
|
||||
do_ellipses = 1;
|
||||
}
|
||||
else if (attr === '3') {
|
||||
// Do everything, turn all options on, use inverted old school dash shorthand.
|
||||
do_quotes = 1;
|
||||
do_backticks = 1;
|
||||
do_dashes = 3;
|
||||
do_ellipses = 1;
|
||||
}
|
||||
else if (attr === '-1') {
|
||||
// Special "stupefy" mode.
|
||||
do_stupefy = 1;
|
||||
}
|
||||
else {
|
||||
for (var i = 0; i < attr.length; i++) {
|
||||
var c = attr[i];
|
||||
if (c === 'q') {
|
||||
do_quotes = 1;
|
||||
}
|
||||
if (c === 'b') {
|
||||
do_backticks = 1;
|
||||
}
|
||||
if (c === 'B') {
|
||||
do_backticks = 2;
|
||||
}
|
||||
if (c === 'd') {
|
||||
do_dashes = 1;
|
||||
}
|
||||
if (c === 'D') {
|
||||
do_dashes = 2;
|
||||
}
|
||||
if (c === 'i') {
|
||||
do_dashes = 3;
|
||||
}
|
||||
if (c === 'e') {
|
||||
do_ellipses = 1;
|
||||
}
|
||||
if (c === 'w') {
|
||||
convert_quot = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
var tokens = _tokenize(text);
|
||||
var result = '';
|
||||
/**
|
||||
* Keep track of when we're inside <pre> or <code> tags.
|
||||
*/
|
||||
var in_pre = 0;
|
||||
/**
|
||||
* This is a cheat, used to get some context
|
||||
* for one-character tokens that consist of
|
||||
* just a quote char. What we do is remember
|
||||
* the last character of the previous text
|
||||
* token, to use as context to curl single-
|
||||
* character quote tokens correctly.
|
||||
*/
|
||||
var prev_token_last_char = '';
|
||||
for (var i = 0; i < tokens.length; i++) {
|
||||
var cur_token = tokens[i];
|
||||
if (cur_token[0] === 'tag') {
|
||||
result = result + cur_token[1];
|
||||
var matched = tags_to_skip.exec(cur_token[1]);
|
||||
if (matched) {
|
||||
if (matched[1] === '/') {
|
||||
in_pre = 0;
|
||||
}
|
||||
else {
|
||||
in_pre = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
var t = cur_token[1];
|
||||
var last_char = t.substring(t.length - 1, t.length); // Remember last char of this token before processing.
|
||||
if (!in_pre) {
|
||||
t = ProcessEscapes(t);
|
||||
if (convert_quot) {
|
||||
t = t.replace(/$quot;/g, '"');
|
||||
}
|
||||
if (do_dashes) {
|
||||
if (do_dashes === 1) {
|
||||
t = EducateDashes(t);
|
||||
}
|
||||
if (do_dashes === 2) {
|
||||
t = EducateDashesOldSchool(t);
|
||||
}
|
||||
if (do_dashes === 3) {
|
||||
t = EducateDashesOldSchoolInverted(t);
|
||||
}
|
||||
}
|
||||
if (do_ellipses) {
|
||||
t = EducateEllipses(t);
|
||||
}
|
||||
// Note: backticks need to be processed before quotes.
|
||||
if (do_backticks) {
|
||||
t = EducateBackticks(t);
|
||||
if (do_backticks === 2) {
|
||||
t = EducateSingleBackticks(t);
|
||||
}
|
||||
}
|
||||
if (do_quotes) {
|
||||
if (t === '\'') {
|
||||
// Special case: single-character ' token
|
||||
if (/\S/.test(prev_token_last_char)) {
|
||||
t = '’';
|
||||
}
|
||||
else {
|
||||
t = '‘';
|
||||
}
|
||||
}
|
||||
else if (t === '"') {
|
||||
// Special case: single-character " token
|
||||
if (/\S/.test(prev_token_last_char)) {
|
||||
t = '”';
|
||||
}
|
||||
else {
|
||||
t = '“';
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Normal case:
|
||||
t = EducateQuotes(t);
|
||||
}
|
||||
}
|
||||
if (do_stupefy) {
|
||||
t = StupefyEntities(t);
|
||||
}
|
||||
}
|
||||
prev_token_last_char = last_char;
|
||||
result = result + t;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
exports.smartypants = SmartyPants;
|
||||
var SmartQuotes = function (text, attr) {
|
||||
/**
|
||||
* should we educate ``backticks'' -style quotes?
|
||||
*/
|
||||
// var do_backticks:number;
|
||||
if (text === void 0) { text = ''; }
|
||||
if (attr === void 0) { attr = '1'; }
|
||||
if (typeof attr === 'number') {
|
||||
attr = attr.toString();
|
||||
}
|
||||
else {
|
||||
attr = attr.replace(/\s/g, '');
|
||||
}
|
||||
if (attr === '0') {
|
||||
// Do nothing
|
||||
return text;
|
||||
// } else if (attr === '2') {
|
||||
// // smarten ``backticks'' -style quotes
|
||||
// do_backticks = 1;
|
||||
// } else {
|
||||
// do_backticks = 0;
|
||||
}
|
||||
/**
|
||||
* Special case to handle quotes at the very end of $text when preceded by
|
||||
* an HTML tag. Add a space to give the quote education algorithm a bit of
|
||||
* context, so that it can guess correctly that it's a closing quote:
|
||||
*/
|
||||
var add_extra_space = 0;
|
||||
if (/>['"]$/.test(text)) {
|
||||
add_extra_space = 1; // Remember, so we can trim the extra space later.
|
||||
text = text + ' ';
|
||||
}
|
||||
var tokens = _tokenize(text);
|
||||
var result = '';
|
||||
/**
|
||||
* Keep track of when we're inside <pre> or <code> tags.
|
||||
*/
|
||||
var in_pre = 0;
|
||||
/**
|
||||
* This is a cheat, used to get some context
|
||||
* for one-character tokens that consist of
|
||||
* just a quote char. What we do is remember
|
||||
* the last character of the previous text
|
||||
* token, to use as context to curl single-
|
||||
* character quote tokens correctly.
|
||||
*/
|
||||
var prev_token_last_char = '';
|
||||
for (var i = 0; i < tokens.length; i++) {
|
||||
var cur_token = tokens[i];
|
||||
if (cur_token[0] === 'tag') {
|
||||
result = result + cur_token[1];
|
||||
var matched = tags_to_skip.exec(cur_token[1]);
|
||||
if (matched) {
|
||||
if (matched[1] === '/') {
|
||||
in_pre = 0;
|
||||
}
|
||||
else {
|
||||
in_pre = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
var t = cur_token[1];
|
||||
var last_char = t.substring(t.length - 1, t.length); // Remember last char of this token before processing.
|
||||
if (!in_pre) {
|
||||
t = ProcessEscapes(t);
|
||||
if (t === '\'') {
|
||||
// Special case: single-character ' token
|
||||
if (/\S/.test(prev_token_last_char)) {
|
||||
t = '’';
|
||||
}
|
||||
else {
|
||||
t = '‘';
|
||||
}
|
||||
}
|
||||
else if (t === '"') {
|
||||
// Special case: single-character " token
|
||||
if (/\S/.test(prev_token_last_char)) {
|
||||
t = '”';
|
||||
}
|
||||
else {
|
||||
t = '“';
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Normal case:
|
||||
t = EducateQuotes(t);
|
||||
}
|
||||
}
|
||||
prev_token_last_char = last_char;
|
||||
result = result + t;
|
||||
}
|
||||
}
|
||||
if (add_extra_space) {
|
||||
result = result.replace(/ $/, '');
|
||||
}
|
||||
return result;
|
||||
};
|
||||
exports.smartquotes = SmartQuotes;
|
||||
var SmartDashes = function (text, attr) {
|
||||
if (text === void 0) { text = ''; }
|
||||
if (attr === void 0) { attr = '1'; }
|
||||
// reference to the subroutine to use for dash education, default to EducateDashes:
|
||||
var dash_sub_ref = EducateDashes;
|
||||
if (typeof attr === 'number') {
|
||||
attr = attr.toString();
|
||||
}
|
||||
else {
|
||||
attr = attr.replace(/\s/g, '');
|
||||
}
|
||||
if (attr === '0') {
|
||||
// Do nothing
|
||||
return text;
|
||||
}
|
||||
else if (attr === '2') {
|
||||
// use old smart dash shortcuts, "--" for en, "---" for em
|
||||
dash_sub_ref = EducateDashesOldSchool;
|
||||
}
|
||||
else if (attr === '3') {
|
||||
// inverse of 2, "--" for em, "---" for en
|
||||
dash_sub_ref = EducateDashesOldSchoolInverted;
|
||||
}
|
||||
var tokens = _tokenize(text);
|
||||
var result = '';
|
||||
/**
|
||||
* Keep track of when we're inside <pre> or <code> tags.
|
||||
*/
|
||||
var in_pre = 0;
|
||||
for (var i = 0; i < tokens.length; i++) {
|
||||
var cur_token = tokens[i];
|
||||
if (cur_token[0] === 'tag') {
|
||||
result = result + cur_token[1];
|
||||
var matched = tags_to_skip.exec(cur_token[1]);
|
||||
if (matched) {
|
||||
if (matched[1] === '/') {
|
||||
in_pre = 0;
|
||||
}
|
||||
else {
|
||||
in_pre = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
var t = cur_token[1];
|
||||
if (!in_pre) {
|
||||
t = ProcessEscapes(t);
|
||||
t = dash_sub_ref(t);
|
||||
}
|
||||
result = result + t;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
exports.smartdashes = SmartDashes;
|
||||
var SmartEllipses = function (text, attr) {
|
||||
if (text === void 0) { text = ''; }
|
||||
if (attr === void 0) { attr = '1'; }
|
||||
if (typeof attr === 'number') {
|
||||
attr = attr.toString();
|
||||
}
|
||||
else {
|
||||
attr = attr.replace(/\s/g, '');
|
||||
}
|
||||
if (attr === '0') {
|
||||
// Do nothing
|
||||
return text;
|
||||
}
|
||||
var tokens = _tokenize(text);
|
||||
var result = '';
|
||||
/**
|
||||
* Keep track of when we're inside <pre> or <code> tags.
|
||||
*/
|
||||
var in_pre = 0;
|
||||
for (var i = 0; i < tokens.length; i++) {
|
||||
var cur_token = tokens[i];
|
||||
if (cur_token[0] === 'tag') {
|
||||
result = result + cur_token[1];
|
||||
var matched = tags_to_skip.exec(cur_token[1]);
|
||||
if (matched) {
|
||||
if (matched[1] === '/') {
|
||||
in_pre = 0;
|
||||
}
|
||||
else {
|
||||
in_pre = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
var t = cur_token[1];
|
||||
if (!in_pre) {
|
||||
t = ProcessEscapes(t);
|
||||
t = EducateEllipses(t);
|
||||
}
|
||||
result = result + t;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
exports.smartellipses = SmartEllipses;
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with "educated" curly quote HTML entities.
|
||||
*
|
||||
* Example input: "Isn't this fun?"
|
||||
* Example output: “Isn’t this fun?”
|
||||
*/
|
||||
var EducateQuotes = function (str) {
|
||||
/**
|
||||
* Make our own "punctuation" character class, because the POSIX-style
|
||||
* [:PUNCT:] is only available in Perl 5.6 or later:
|
||||
*
|
||||
* JavaScript don't have punctuation class neither.
|
||||
*/
|
||||
var punct_class = '[!"#\$\%\'()*+,-./:;<=>?\@\[\\\]\^_`{|}~]'; // eslint-disable-line no-useless-escape
|
||||
/**
|
||||
* Special case if the very first character is a quote
|
||||
* followed by punctuation at a non-word-break. Close the quotes by brute force:
|
||||
*/
|
||||
str = str.replace(new RegExp("^'(?=" + punct_class + "\\B)"), '’'); // eslint-disable-line no-useless-escape
|
||||
str = str.replace(new RegExp("^\"(?=" + punct_class + "\\B)"), '”'); // eslint-disable-line no-useless-escape
|
||||
/**
|
||||
* Special case for double sets of quotes, e.g.:
|
||||
* <p>He said, "'Quoted' words in a larger quote."</p>
|
||||
*/
|
||||
str = str.replace(/"'(?=\w)/, '“‘');
|
||||
str = str.replace(/'"(?=\w)/, '‘“');
|
||||
/**
|
||||
* Special case for decade abbreviations (the '80s):
|
||||
*/
|
||||
str = str.replace(/'(?=\d\d)/, '’');
|
||||
var close_class = '[^\\ \\t\\r\\n\\[\\{\\(\\-]'; // eslint-disable-line no-useless-escape
|
||||
var not_close_class = '[\\ \\t\\r\\n\\[\\{\\(\\-]'; // eslint-disable-line no-useless-escape
|
||||
var dec_dashes = '–|—';
|
||||
/**
|
||||
* Get most opening single quotes:
|
||||
* s {
|
||||
* (
|
||||
* \s | # a whitespace char, or
|
||||
* | # a non-breaking space entity, or
|
||||
* -- | # dashes, or
|
||||
* &[mn]dash; | # named dash entities
|
||||
* $dec_dashes | # or decimal entities
|
||||
* &\#x201[34]; # or hex
|
||||
* )
|
||||
* ' # the quote
|
||||
* (?=\w) # followed by a word character
|
||||
* } {$1‘}xg;
|
||||
*/
|
||||
str = str.replace(new RegExp("(\\s| |--|&[mn]dash;|" + dec_dashes + "|ȁ[34])'(?=\\w)", 'g'), '\$1‘'); // eslint-disable-line no-useless-escape
|
||||
/**
|
||||
* Single closing quotes:
|
||||
* s {
|
||||
* ($close_class)?
|
||||
* '
|
||||
* (?(1)| # If $1 captured, then do nothing;
|
||||
* (?=\s | s\b) # otherwise, positive lookahead for a whitespace
|
||||
* ) # char or an 's' at a word ending position. This
|
||||
* # is a special case to handle something like:
|
||||
* # "<i>Custer</i>'s Last Stand."
|
||||
* } {$1’}xgi;
|
||||
*/
|
||||
str = str.replace(new RegExp("(" + close_class + ")'", 'g'), '\$1’'); // eslint-disable-line no-useless-escape
|
||||
str = str.replace(new RegExp("(" + not_close_class + "?)'(?=\\s|s\\b)", 'g'), '\$1’'); // eslint-disable-line no-useless-escape
|
||||
/**
|
||||
* Any remaining single quotes should be opening ones:
|
||||
*/
|
||||
str = str.replace(/'/g, '‘');
|
||||
/**
|
||||
* Get most opening double quotes:
|
||||
* s {
|
||||
* (
|
||||
* \s | # a whitespace char, or
|
||||
* | # a non-breaking space entity, or
|
||||
* -- | # dashes, or
|
||||
* &[mn]dash; | # named dash entities
|
||||
* $dec_dashes | # or decimal entities
|
||||
* &\#x201[34]; # or hex
|
||||
* )
|
||||
* " # the quote
|
||||
* (?=\w) # followed by a word character
|
||||
* } {$1“}xg;
|
||||
*/
|
||||
str = str.replace(new RegExp("(\\s| |--|&[mn]dash;|" + dec_dashes + "|ȁ[34])\"(?=\\w)", 'g'), '\$1“'); // eslint-disable-line no-useless-escape
|
||||
/**
|
||||
* Double closing quotes:
|
||||
* s {
|
||||
* ($close_class)?
|
||||
* "
|
||||
* (?(1)|(?=\s)) # If $1 captured, then do nothing;
|
||||
* # if not, then make sure the next char is whitespace.
|
||||
* } {$1”}xg;
|
||||
*/
|
||||
str = str.replace(new RegExp("(" + close_class + ")\"", 'g'), '\$1”'); // eslint-disable-line no-useless-escape
|
||||
str = str.replace(new RegExp("(" + not_close_class + "?)\"(?=\\s)", 'g'), '\$1”'); // eslint-disable-line no-useless-escape
|
||||
/**
|
||||
* Any remaining quotes should be opening ones.
|
||||
*/
|
||||
str = str.replace(/"/g, '“');
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with ``backticks'' -style double quotes
|
||||
* translated into HTML curly quote entities.
|
||||
*
|
||||
* Example input: ``Isn't this fun?''
|
||||
* Example output: “Isn't this fun?”
|
||||
*/
|
||||
var EducateBackticks = function (str) {
|
||||
str = str.replace(/``/g, '“');
|
||||
str = str.replace(/''/g, '”');
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with `backticks' -style single quotes
|
||||
* translated into HTML curly quote entities.
|
||||
*
|
||||
* Example input: `Isn't this fun?'
|
||||
* Example output: ‘Isn’t this fun?’
|
||||
*/
|
||||
var EducateSingleBackticks = function (str) {
|
||||
str = str.replace(/`/g, '‘');
|
||||
str = str.replace(/'/g, '’');
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with each instance of "--" translated to
|
||||
* an em-dash HTML entity.
|
||||
*/
|
||||
var EducateDashes = function (str) {
|
||||
str = str.replace(/--/g, '—');
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with each instance of "--" translated to
|
||||
* an en-dash HTML entity, and each "---" translated to
|
||||
* an em-dash HTML entity.
|
||||
*/
|
||||
var EducateDashesOldSchool = function (str) {
|
||||
str = str.replace(/---/g, '—');
|
||||
str = str.replace(/--/g, '–');
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with each instance of "--" translated to
|
||||
* an em-dash HTML entity, and each "---" translated to
|
||||
* an en-dash HTML entity. Two reasons why: First, unlike the
|
||||
* en- and em-dash syntax supported by
|
||||
* EducateDashesOldSchool(), it's compatible with existing
|
||||
* entries written before SmartyPants 1.1, back when "--" was
|
||||
* only used for em-dashes. Second, em-dashes are more
|
||||
* common than en-dashes, and so it sort of makes sense that
|
||||
* the shortcut should be shorter to type. (Thanks to Aaron
|
||||
* Swartz for the idea.)
|
||||
*/
|
||||
var EducateDashesOldSchoolInverted = function (str) {
|
||||
str = str.replace(/---/g, '–');
|
||||
str = str.replace(/--/g, '—');
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with each instance of "..." translated to
|
||||
* an ellipsis HTML entity. Also converts the case where
|
||||
* there are spaces between the dots.
|
||||
*
|
||||
* Example input: Huh...?
|
||||
* Example output: Huh…?
|
||||
*/
|
||||
var EducateEllipses = function (str) {
|
||||
str = str.replace(/\.\.\./g, '…');
|
||||
str = str.replace(/\. \. \./g, '…');
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with each SmartyPants HTML entity translated to
|
||||
* its ASCII counterpart.
|
||||
*
|
||||
* Example input: “Hello — world.”
|
||||
* Example output: "Hello -- world."
|
||||
*/
|
||||
var StupefyEntities = function (str) {
|
||||
str = str.replace(/–/g, '-'); // en-dash
|
||||
str = str.replace(/—/g, '--'); // em-dash
|
||||
str = str.replace(/‘/g, '\''); // open single quote
|
||||
str = str.replace(/’/g, '\''); // close single quote
|
||||
str = str.replace(/“/g, '"'); // open double quote
|
||||
str = str.replace(/”/g, '"'); // close double quote
|
||||
str = str.replace(/…/g, '...'); // ellipsis
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with each SmartyPants HTML entity translated to
|
||||
* UTF-8 characters.
|
||||
*
|
||||
* Example input: “Hello ’ world.”
|
||||
* Example output: "Hello — world."
|
||||
*/
|
||||
var EducateEntities = function (text, attr) {
|
||||
if (attr === void 0) { attr = '1'; }
|
||||
var do_quotes;
|
||||
var do_backticks;
|
||||
var do_dashes;
|
||||
var do_ellipses;
|
||||
// var do_stupefy:number;
|
||||
if (typeof attr === 'number') {
|
||||
attr = attr.toString();
|
||||
}
|
||||
else {
|
||||
attr = attr.replace(/\s/g, '');
|
||||
}
|
||||
if (attr === '0') {
|
||||
// Do nothing
|
||||
return text;
|
||||
}
|
||||
else if (attr === '1') {
|
||||
// Do everything, turn all options on.
|
||||
do_quotes = 1;
|
||||
do_backticks = 1;
|
||||
do_dashes = 1;
|
||||
do_ellipses = 1;
|
||||
}
|
||||
else if (attr === '2') {
|
||||
// Do everything, turn all options on, use old school dash shorthand.
|
||||
do_quotes = 1;
|
||||
do_backticks = 1;
|
||||
do_dashes = 3;
|
||||
do_ellipses = 1;
|
||||
}
|
||||
else if (attr === '3') {
|
||||
// Do everything, turn all options on, use inverted old school dash shorthand.
|
||||
do_quotes = 1;
|
||||
do_backticks = 1;
|
||||
do_dashes = 3;
|
||||
do_ellipses = 1;
|
||||
// } else if (attr === '-1') {
|
||||
// // Special "stupefy" mode.
|
||||
// do_stupefy = 1;
|
||||
}
|
||||
else {
|
||||
for (var i = 0; i < attr.length; i++) {
|
||||
var c = attr[i];
|
||||
if (c === 'q') {
|
||||
do_quotes = 1;
|
||||
}
|
||||
if (c === 'b') {
|
||||
do_backticks = 1;
|
||||
}
|
||||
if (c === 'B') {
|
||||
do_backticks = 2;
|
||||
}
|
||||
if (c === 'd') {
|
||||
do_dashes = 1;
|
||||
}
|
||||
if (c === 'D') {
|
||||
do_dashes = 2;
|
||||
}
|
||||
if (c === 'i') {
|
||||
do_dashes = 3;
|
||||
}
|
||||
if (c === 'e') {
|
||||
do_ellipses = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (do_dashes) {
|
||||
text = text.replace(/–/g, '\u2013'); // en-dash
|
||||
text = text.replace(/—/g, '\u2014'); // em-dash
|
||||
}
|
||||
if (do_quotes || do_backticks) {
|
||||
text = text.replace(/‘/g, '\u2018'); // open single quote
|
||||
text = text.replace(/’/g, '\u2019'); // close single quote
|
||||
text = text.replace(/“/g, '\u201c'); // open double quote
|
||||
text = text.replace(/”/g, '\u201d'); // close double quote
|
||||
}
|
||||
if (do_ellipses) {
|
||||
text = text.replace(/…/g, '\u2026'); // ellipsis
|
||||
}
|
||||
return text;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with each SmartyPants UTF-8 chars translated to
|
||||
* its ASCII counterpart.
|
||||
*
|
||||
* Example input: “Hello — world.”
|
||||
* Example output: "Hello -- world."
|
||||
*/
|
||||
var StupifyUTF8Char = function (str) {
|
||||
str = str.replace(/\u2013/g, '-'); // en-dash
|
||||
str = str.replace(/\u2014/g, '--'); // em-dash
|
||||
str = str.replace(/\u2018/g, '\''); // open single quote
|
||||
str = str.replace(/\u2019/g, '\''); // close single quote
|
||||
str = str.replace(/\u201c/g, '"'); // open double quote
|
||||
str = str.replace(/\u201d/g, '"'); // close double quote
|
||||
str = str.replace(/\u2026/g, '...'); // ellipsis
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} string, with after processing the following backslash
|
||||
* escape sequences. This is useful if you want to force a "dumb"
|
||||
* quote or other character to appear.
|
||||
*
|
||||
* Escape Value
|
||||
* ------ -----
|
||||
* \\ \
|
||||
* \" "
|
||||
* \' '
|
||||
* \. .
|
||||
* \- -
|
||||
* \` `
|
||||
*
|
||||
*/
|
||||
var ProcessEscapes = function (str) {
|
||||
str = str.replace(/\\\\/g, '\');
|
||||
str = str.replace(/\\"/g, '"');
|
||||
str = str.replace(/\\'/g, ''');
|
||||
str = str.replace(/\\\./g, '.');
|
||||
str = str.replace(/\\-/g, '-');
|
||||
str = str.replace(/\\`/g, '`');
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String containing HTML markup.
|
||||
* @return {Array<token>} Reference to an array of the tokens comprising the input
|
||||
* string. Each token is either a tag (possibly with nested,
|
||||
* tags contained therein, such as <a href="<MTFoo>">, or a
|
||||
* run of text between tags. Each element of the array is a
|
||||
* two-element array; the first is either 'tag' or 'text';
|
||||
* the second is the actual value.
|
||||
*
|
||||
* Based on the _tokenize() subroutine from Brad Choate's MTRegex plugin.
|
||||
* <http://www.bradchoate.com/past/mtregex.php>
|
||||
*/
|
||||
var _tokenize = function (str) {
|
||||
var pos = 0;
|
||||
var len = str.length;
|
||||
var tokens = [];
|
||||
var match = /<!--[\s\S]*?-->|<\?.*?\?>|<[^>]*>/g;
|
||||
var matched = null;
|
||||
while (matched = match.exec(str)) { // eslint-disable-line no-cond-assign
|
||||
if (pos < matched.index) {
|
||||
var t_1 = ['text', str.substring(pos, matched.index)];
|
||||
tokens.push(t_1);
|
||||
}
|
||||
var t = ['tag', matched.toString()];
|
||||
tokens.push(t);
|
||||
pos = match.lastIndex;
|
||||
}
|
||||
if (pos < len) {
|
||||
var t = ['text', str.substring(pos, len)];
|
||||
tokens.push(t);
|
||||
}
|
||||
return tokens;
|
||||
};
|
||||
var smartypantsu = function (text, attr) {
|
||||
if (text === void 0) { text = ''; }
|
||||
if (attr === void 0) { attr = '1'; }
|
||||
var str = SmartyPants(text, attr);
|
||||
if (typeof attr === 'number') {
|
||||
attr = attr.toString();
|
||||
}
|
||||
else {
|
||||
attr = attr.replace(/\s/g, '');
|
||||
}
|
||||
if (attr === '-1') {
|
||||
return StupifyUTF8Char(str);
|
||||
}
|
||||
else {
|
||||
return EducateEntities(str, attr);
|
||||
}
|
||||
};
|
||||
exports.smartypantsu = smartypantsu;
|
||||
exports["default"] = SmartyPants;
|
||||
|
||||
|
||||
}));
|
||||
757
node_modules/smartypants/smartypants.es6.js
generated
vendored
Normal file
757
node_modules/smartypants/smartypants.es6.js
generated
vendored
Normal file
@@ -0,0 +1,757 @@
|
||||
const tags_to_skip = /<(\/?)(?:pre|code|kbd|script|math)[^>]*>/i;
|
||||
/**
|
||||
* @param text text to be parsed
|
||||
* @param attr value of the smart_quotes="" attribute
|
||||
*/
|
||||
const SmartyPants = (text = '', attr = '1') => {
|
||||
var do_quotes;
|
||||
var do_backticks;
|
||||
var do_dashes;
|
||||
var do_ellipses;
|
||||
var do_stupefy;
|
||||
var convert_quot = 0;
|
||||
if (typeof attr === 'number') {
|
||||
attr = attr.toString();
|
||||
}
|
||||
else {
|
||||
attr = attr.replace(/\s/g, '');
|
||||
}
|
||||
/**
|
||||
* Parse attributes:
|
||||
* 0 : do nothing
|
||||
* 1 : set all
|
||||
* 2 : set all, using old school en- and em- dash shortcuts
|
||||
* 3 : set all, using inverted old school en and em- dash shortcuts
|
||||
*
|
||||
* q : quotes
|
||||
* b : backtick quotes (``double'' only)
|
||||
* B : backtick quotes (``double'' and `single')
|
||||
* d : dashes
|
||||
* D : old school dashes
|
||||
* i : inverted old school dashes
|
||||
* e : ellipses
|
||||
* w : convert " entities to " for Dreamweaver users
|
||||
*/
|
||||
if (attr === '0') {
|
||||
// Do nothing
|
||||
return text;
|
||||
}
|
||||
else if (attr === '1') {
|
||||
// Do everything, turn all options on.
|
||||
do_quotes = 1;
|
||||
do_backticks = 1;
|
||||
do_dashes = 1;
|
||||
do_ellipses = 1;
|
||||
}
|
||||
else if (attr === '2') {
|
||||
// Do everything, turn all options on, use old school dash shorthand.
|
||||
do_quotes = 1;
|
||||
do_backticks = 1;
|
||||
do_dashes = 2;
|
||||
do_ellipses = 1;
|
||||
}
|
||||
else if (attr === '3') {
|
||||
// Do everything, turn all options on, use inverted old school dash shorthand.
|
||||
do_quotes = 1;
|
||||
do_backticks = 1;
|
||||
do_dashes = 3;
|
||||
do_ellipses = 1;
|
||||
}
|
||||
else if (attr === '-1') {
|
||||
// Special "stupefy" mode.
|
||||
do_stupefy = 1;
|
||||
}
|
||||
else {
|
||||
for (let i = 0; i < attr.length; i++) {
|
||||
let c = attr[i];
|
||||
if (c === 'q') {
|
||||
do_quotes = 1;
|
||||
}
|
||||
if (c === 'b') {
|
||||
do_backticks = 1;
|
||||
}
|
||||
if (c === 'B') {
|
||||
do_backticks = 2;
|
||||
}
|
||||
if (c === 'd') {
|
||||
do_dashes = 1;
|
||||
}
|
||||
if (c === 'D') {
|
||||
do_dashes = 2;
|
||||
}
|
||||
if (c === 'i') {
|
||||
do_dashes = 3;
|
||||
}
|
||||
if (c === 'e') {
|
||||
do_ellipses = 1;
|
||||
}
|
||||
if (c === 'w') {
|
||||
convert_quot = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
var tokens = _tokenize(text);
|
||||
var result = '';
|
||||
/**
|
||||
* Keep track of when we're inside <pre> or <code> tags.
|
||||
*/
|
||||
var in_pre = 0;
|
||||
/**
|
||||
* This is a cheat, used to get some context
|
||||
* for one-character tokens that consist of
|
||||
* just a quote char. What we do is remember
|
||||
* the last character of the previous text
|
||||
* token, to use as context to curl single-
|
||||
* character quote tokens correctly.
|
||||
*/
|
||||
var prev_token_last_char = '';
|
||||
for (let i = 0; i < tokens.length; i++) {
|
||||
let cur_token = tokens[i];
|
||||
if (cur_token[0] === 'tag') {
|
||||
result = result + cur_token[1];
|
||||
let matched = tags_to_skip.exec(cur_token[1]);
|
||||
if (matched) {
|
||||
if (matched[1] === '/') {
|
||||
in_pre = 0;
|
||||
}
|
||||
else {
|
||||
in_pre = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
let t = cur_token[1];
|
||||
let last_char = t.substring(t.length - 1, t.length); // Remember last char of this token before processing.
|
||||
if (!in_pre) {
|
||||
t = ProcessEscapes(t);
|
||||
if (convert_quot) {
|
||||
t = t.replace(/$quot;/g, '"');
|
||||
}
|
||||
if (do_dashes) {
|
||||
if (do_dashes === 1) {
|
||||
t = EducateDashes(t);
|
||||
}
|
||||
if (do_dashes === 2) {
|
||||
t = EducateDashesOldSchool(t);
|
||||
}
|
||||
if (do_dashes === 3) {
|
||||
t = EducateDashesOldSchoolInverted(t);
|
||||
}
|
||||
}
|
||||
if (do_ellipses) {
|
||||
t = EducateEllipses(t);
|
||||
}
|
||||
// Note: backticks need to be processed before quotes.
|
||||
if (do_backticks) {
|
||||
t = EducateBackticks(t);
|
||||
if (do_backticks === 2) {
|
||||
t = EducateSingleBackticks(t);
|
||||
}
|
||||
}
|
||||
if (do_quotes) {
|
||||
if (t === '\'') {
|
||||
// Special case: single-character ' token
|
||||
if (/\S/.test(prev_token_last_char)) {
|
||||
t = '’';
|
||||
}
|
||||
else {
|
||||
t = '‘';
|
||||
}
|
||||
}
|
||||
else if (t === '"') {
|
||||
// Special case: single-character " token
|
||||
if (/\S/.test(prev_token_last_char)) {
|
||||
t = '”';
|
||||
}
|
||||
else {
|
||||
t = '“';
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Normal case:
|
||||
t = EducateQuotes(t);
|
||||
}
|
||||
}
|
||||
if (do_stupefy) {
|
||||
t = StupefyEntities(t);
|
||||
}
|
||||
}
|
||||
prev_token_last_char = last_char;
|
||||
result = result + t;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
const SmartQuotes = (text = '', attr = '1') => {
|
||||
/**
|
||||
* should we educate ``backticks'' -style quotes?
|
||||
*/
|
||||
// var do_backticks:number;
|
||||
if (typeof attr === 'number') {
|
||||
attr = attr.toString();
|
||||
}
|
||||
else {
|
||||
attr = attr.replace(/\s/g, '');
|
||||
}
|
||||
if (attr === '0') {
|
||||
// Do nothing
|
||||
return text;
|
||||
// } else if (attr === '2') {
|
||||
// // smarten ``backticks'' -style quotes
|
||||
// do_backticks = 1;
|
||||
// } else {
|
||||
// do_backticks = 0;
|
||||
}
|
||||
/**
|
||||
* Special case to handle quotes at the very end of $text when preceded by
|
||||
* an HTML tag. Add a space to give the quote education algorithm a bit of
|
||||
* context, so that it can guess correctly that it's a closing quote:
|
||||
*/
|
||||
var add_extra_space = 0;
|
||||
if (/>['"]$/.test(text)) {
|
||||
add_extra_space = 1; // Remember, so we can trim the extra space later.
|
||||
text = text + ' ';
|
||||
}
|
||||
var tokens = _tokenize(text);
|
||||
var result = '';
|
||||
/**
|
||||
* Keep track of when we're inside <pre> or <code> tags.
|
||||
*/
|
||||
var in_pre = 0;
|
||||
/**
|
||||
* This is a cheat, used to get some context
|
||||
* for one-character tokens that consist of
|
||||
* just a quote char. What we do is remember
|
||||
* the last character of the previous text
|
||||
* token, to use as context to curl single-
|
||||
* character quote tokens correctly.
|
||||
*/
|
||||
var prev_token_last_char = '';
|
||||
for (let i = 0; i < tokens.length; i++) {
|
||||
let cur_token = tokens[i];
|
||||
if (cur_token[0] === 'tag') {
|
||||
result = result + cur_token[1];
|
||||
let matched = tags_to_skip.exec(cur_token[1]);
|
||||
if (matched) {
|
||||
if (matched[1] === '/') {
|
||||
in_pre = 0;
|
||||
}
|
||||
else {
|
||||
in_pre = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
let t = cur_token[1];
|
||||
let last_char = t.substring(t.length - 1, t.length); // Remember last char of this token before processing.
|
||||
if (!in_pre) {
|
||||
t = ProcessEscapes(t);
|
||||
if (t === '\'') {
|
||||
// Special case: single-character ' token
|
||||
if (/\S/.test(prev_token_last_char)) {
|
||||
t = '’';
|
||||
}
|
||||
else {
|
||||
t = '‘';
|
||||
}
|
||||
}
|
||||
else if (t === '"') {
|
||||
// Special case: single-character " token
|
||||
if (/\S/.test(prev_token_last_char)) {
|
||||
t = '”';
|
||||
}
|
||||
else {
|
||||
t = '“';
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Normal case:
|
||||
t = EducateQuotes(t);
|
||||
}
|
||||
}
|
||||
prev_token_last_char = last_char;
|
||||
result = result + t;
|
||||
}
|
||||
}
|
||||
if (add_extra_space) {
|
||||
result = result.replace(/ $/, '');
|
||||
}
|
||||
return result;
|
||||
};
|
||||
const SmartDashes = (text = '', attr = '1') => {
|
||||
// reference to the subroutine to use for dash education, default to EducateDashes:
|
||||
var dash_sub_ref = EducateDashes;
|
||||
if (typeof attr === 'number') {
|
||||
attr = attr.toString();
|
||||
}
|
||||
else {
|
||||
attr = attr.replace(/\s/g, '');
|
||||
}
|
||||
if (attr === '0') {
|
||||
// Do nothing
|
||||
return text;
|
||||
}
|
||||
else if (attr === '2') {
|
||||
// use old smart dash shortcuts, "--" for en, "---" for em
|
||||
dash_sub_ref = EducateDashesOldSchool;
|
||||
}
|
||||
else if (attr === '3') {
|
||||
// inverse of 2, "--" for em, "---" for en
|
||||
dash_sub_ref = EducateDashesOldSchoolInverted;
|
||||
}
|
||||
var tokens = _tokenize(text);
|
||||
var result = '';
|
||||
/**
|
||||
* Keep track of when we're inside <pre> or <code> tags.
|
||||
*/
|
||||
var in_pre = 0;
|
||||
for (let i = 0; i < tokens.length; i++) {
|
||||
let cur_token = tokens[i];
|
||||
if (cur_token[0] === 'tag') {
|
||||
result = result + cur_token[1];
|
||||
let matched = tags_to_skip.exec(cur_token[1]);
|
||||
if (matched) {
|
||||
if (matched[1] === '/') {
|
||||
in_pre = 0;
|
||||
}
|
||||
else {
|
||||
in_pre = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
let t = cur_token[1];
|
||||
if (!in_pre) {
|
||||
t = ProcessEscapes(t);
|
||||
t = dash_sub_ref(t);
|
||||
}
|
||||
result = result + t;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
const SmartEllipses = (text = '', attr = '1') => {
|
||||
if (typeof attr === 'number') {
|
||||
attr = attr.toString();
|
||||
}
|
||||
else {
|
||||
attr = attr.replace(/\s/g, '');
|
||||
}
|
||||
if (attr === '0') {
|
||||
// Do nothing
|
||||
return text;
|
||||
}
|
||||
var tokens = _tokenize(text);
|
||||
var result = '';
|
||||
/**
|
||||
* Keep track of when we're inside <pre> or <code> tags.
|
||||
*/
|
||||
var in_pre = 0;
|
||||
for (let i = 0; i < tokens.length; i++) {
|
||||
let cur_token = tokens[i];
|
||||
if (cur_token[0] === 'tag') {
|
||||
result = result + cur_token[1];
|
||||
let matched = tags_to_skip.exec(cur_token[1]);
|
||||
if (matched) {
|
||||
if (matched[1] === '/') {
|
||||
in_pre = 0;
|
||||
}
|
||||
else {
|
||||
in_pre = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
let t = cur_token[1];
|
||||
if (!in_pre) {
|
||||
t = ProcessEscapes(t);
|
||||
t = EducateEllipses(t);
|
||||
}
|
||||
result = result + t;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with "educated" curly quote HTML entities.
|
||||
*
|
||||
* Example input: "Isn't this fun?"
|
||||
* Example output: “Isn’t this fun?”
|
||||
*/
|
||||
const EducateQuotes = (str) => {
|
||||
/**
|
||||
* Make our own "punctuation" character class, because the POSIX-style
|
||||
* [:PUNCT:] is only available in Perl 5.6 or later:
|
||||
*
|
||||
* JavaScript don't have punctuation class neither.
|
||||
*/
|
||||
var punct_class = '[!"#\$\%\'()*+,-./:;<=>?\@\[\\\]\^_`{|}~]'; // eslint-disable-line no-useless-escape
|
||||
/**
|
||||
* Special case if the very first character is a quote
|
||||
* followed by punctuation at a non-word-break. Close the quotes by brute force:
|
||||
*/
|
||||
str = str.replace(new RegExp(`^'(?=${punct_class}\\B)`), '’'); // eslint-disable-line no-useless-escape
|
||||
str = str.replace(new RegExp(`^"(?=${punct_class}\\B)`), '”'); // eslint-disable-line no-useless-escape
|
||||
/**
|
||||
* Special case for double sets of quotes, e.g.:
|
||||
* <p>He said, "'Quoted' words in a larger quote."</p>
|
||||
*/
|
||||
str = str.replace(/"'(?=\w)/, '“‘');
|
||||
str = str.replace(/'"(?=\w)/, '‘“');
|
||||
/**
|
||||
* Special case for decade abbreviations (the '80s):
|
||||
*/
|
||||
str = str.replace(/'(?=\d\d)/, '’');
|
||||
var close_class = '[^\\ \\t\\r\\n\\[\\{\\(\\-]'; // eslint-disable-line no-useless-escape
|
||||
var not_close_class = '[\\ \\t\\r\\n\\[\\{\\(\\-]'; // eslint-disable-line no-useless-escape
|
||||
var dec_dashes = '–|—';
|
||||
/**
|
||||
* Get most opening single quotes:
|
||||
* s {
|
||||
* (
|
||||
* \s | # a whitespace char, or
|
||||
* | # a non-breaking space entity, or
|
||||
* -- | # dashes, or
|
||||
* &[mn]dash; | # named dash entities
|
||||
* $dec_dashes | # or decimal entities
|
||||
* &\#x201[34]; # or hex
|
||||
* )
|
||||
* ' # the quote
|
||||
* (?=\w) # followed by a word character
|
||||
* } {$1‘}xg;
|
||||
*/
|
||||
str = str.replace(new RegExp(`(\\s| |--|&[mn]dash;|${dec_dashes}|ȁ[34])'(?=\\w)`, 'g'), '\$1‘'); // eslint-disable-line no-useless-escape
|
||||
/**
|
||||
* Single closing quotes:
|
||||
* s {
|
||||
* ($close_class)?
|
||||
* '
|
||||
* (?(1)| # If $1 captured, then do nothing;
|
||||
* (?=\s | s\b) # otherwise, positive lookahead for a whitespace
|
||||
* ) # char or an 's' at a word ending position. This
|
||||
* # is a special case to handle something like:
|
||||
* # "<i>Custer</i>'s Last Stand."
|
||||
* } {$1’}xgi;
|
||||
*/
|
||||
str = str.replace(new RegExp(`(${close_class})'`, 'g'), '\$1’'); // eslint-disable-line no-useless-escape
|
||||
str = str.replace(new RegExp(`(${not_close_class}?)'(?=\\s|s\\b)`, 'g'), '\$1’'); // eslint-disable-line no-useless-escape
|
||||
/**
|
||||
* Any remaining single quotes should be opening ones:
|
||||
*/
|
||||
str = str.replace(/'/g, '‘');
|
||||
/**
|
||||
* Get most opening double quotes:
|
||||
* s {
|
||||
* (
|
||||
* \s | # a whitespace char, or
|
||||
* | # a non-breaking space entity, or
|
||||
* -- | # dashes, or
|
||||
* &[mn]dash; | # named dash entities
|
||||
* $dec_dashes | # or decimal entities
|
||||
* &\#x201[34]; # or hex
|
||||
* )
|
||||
* " # the quote
|
||||
* (?=\w) # followed by a word character
|
||||
* } {$1“}xg;
|
||||
*/
|
||||
str = str.replace(new RegExp(`(\\s| |--|&[mn]dash;|${dec_dashes}|ȁ[34])"(?=\\w)`, 'g'), '\$1“'); // eslint-disable-line no-useless-escape
|
||||
/**
|
||||
* Double closing quotes:
|
||||
* s {
|
||||
* ($close_class)?
|
||||
* "
|
||||
* (?(1)|(?=\s)) # If $1 captured, then do nothing;
|
||||
* # if not, then make sure the next char is whitespace.
|
||||
* } {$1”}xg;
|
||||
*/
|
||||
str = str.replace(new RegExp(`(${close_class})"`, 'g'), '\$1”'); // eslint-disable-line no-useless-escape
|
||||
str = str.replace(new RegExp(`(${not_close_class}?)"(?=\\s)`, 'g'), '\$1”'); // eslint-disable-line no-useless-escape
|
||||
/**
|
||||
* Any remaining quotes should be opening ones.
|
||||
*/
|
||||
str = str.replace(/"/g, '“');
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with ``backticks'' -style double quotes
|
||||
* translated into HTML curly quote entities.
|
||||
*
|
||||
* Example input: ``Isn't this fun?''
|
||||
* Example output: “Isn't this fun?”
|
||||
*/
|
||||
const EducateBackticks = (str) => {
|
||||
str = str.replace(/``/g, '“');
|
||||
str = str.replace(/''/g, '”');
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with `backticks' -style single quotes
|
||||
* translated into HTML curly quote entities.
|
||||
*
|
||||
* Example input: `Isn't this fun?'
|
||||
* Example output: ‘Isn’t this fun?’
|
||||
*/
|
||||
const EducateSingleBackticks = (str) => {
|
||||
str = str.replace(/`/g, '‘');
|
||||
str = str.replace(/'/g, '’');
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with each instance of "--" translated to
|
||||
* an em-dash HTML entity.
|
||||
*/
|
||||
const EducateDashes = (str) => {
|
||||
str = str.replace(/--/g, '—');
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with each instance of "--" translated to
|
||||
* an en-dash HTML entity, and each "---" translated to
|
||||
* an em-dash HTML entity.
|
||||
*/
|
||||
const EducateDashesOldSchool = (str) => {
|
||||
str = str.replace(/---/g, '—');
|
||||
str = str.replace(/--/g, '–');
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with each instance of "--" translated to
|
||||
* an em-dash HTML entity, and each "---" translated to
|
||||
* an en-dash HTML entity. Two reasons why: First, unlike the
|
||||
* en- and em-dash syntax supported by
|
||||
* EducateDashesOldSchool(), it's compatible with existing
|
||||
* entries written before SmartyPants 1.1, back when "--" was
|
||||
* only used for em-dashes. Second, em-dashes are more
|
||||
* common than en-dashes, and so it sort of makes sense that
|
||||
* the shortcut should be shorter to type. (Thanks to Aaron
|
||||
* Swartz for the idea.)
|
||||
*/
|
||||
const EducateDashesOldSchoolInverted = (str) => {
|
||||
str = str.replace(/---/g, '–');
|
||||
str = str.replace(/--/g, '—');
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with each instance of "..." translated to
|
||||
* an ellipsis HTML entity. Also converts the case where
|
||||
* there are spaces between the dots.
|
||||
*
|
||||
* Example input: Huh...?
|
||||
* Example output: Huh…?
|
||||
*/
|
||||
const EducateEllipses = (str) => {
|
||||
str = str.replace(/\.\.\./g, '…');
|
||||
str = str.replace(/\. \. \./g, '…');
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with each SmartyPants HTML entity translated to
|
||||
* its ASCII counterpart.
|
||||
*
|
||||
* Example input: “Hello — world.”
|
||||
* Example output: "Hello -- world."
|
||||
*/
|
||||
const StupefyEntities = (str) => {
|
||||
str = str.replace(/–/g, '-'); // en-dash
|
||||
str = str.replace(/—/g, '--'); // em-dash
|
||||
str = str.replace(/‘/g, '\''); // open single quote
|
||||
str = str.replace(/’/g, '\''); // close single quote
|
||||
str = str.replace(/“/g, '"'); // open double quote
|
||||
str = str.replace(/”/g, '"'); // close double quote
|
||||
str = str.replace(/…/g, '...'); // ellipsis
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with each SmartyPants HTML entity translated to
|
||||
* UTF-8 characters.
|
||||
*
|
||||
* Example input: “Hello ’ world.”
|
||||
* Example output: "Hello — world."
|
||||
*/
|
||||
const EducateEntities = (text, attr = '1') => {
|
||||
var do_quotes;
|
||||
var do_backticks;
|
||||
var do_dashes;
|
||||
var do_ellipses;
|
||||
// var do_stupefy:number;
|
||||
if (typeof attr === 'number') {
|
||||
attr = attr.toString();
|
||||
}
|
||||
else {
|
||||
attr = attr.replace(/\s/g, '');
|
||||
}
|
||||
if (attr === '0') {
|
||||
// Do nothing
|
||||
return text;
|
||||
}
|
||||
else if (attr === '1') {
|
||||
// Do everything, turn all options on.
|
||||
do_quotes = 1;
|
||||
do_backticks = 1;
|
||||
do_dashes = 1;
|
||||
do_ellipses = 1;
|
||||
}
|
||||
else if (attr === '2') {
|
||||
// Do everything, turn all options on, use old school dash shorthand.
|
||||
do_quotes = 1;
|
||||
do_backticks = 1;
|
||||
do_dashes = 3;
|
||||
do_ellipses = 1;
|
||||
}
|
||||
else if (attr === '3') {
|
||||
// Do everything, turn all options on, use inverted old school dash shorthand.
|
||||
do_quotes = 1;
|
||||
do_backticks = 1;
|
||||
do_dashes = 3;
|
||||
do_ellipses = 1;
|
||||
// } else if (attr === '-1') {
|
||||
// // Special "stupefy" mode.
|
||||
// do_stupefy = 1;
|
||||
}
|
||||
else {
|
||||
for (let i = 0; i < attr.length; i++) {
|
||||
let c = attr[i];
|
||||
if (c === 'q') {
|
||||
do_quotes = 1;
|
||||
}
|
||||
if (c === 'b') {
|
||||
do_backticks = 1;
|
||||
}
|
||||
if (c === 'B') {
|
||||
do_backticks = 2;
|
||||
}
|
||||
if (c === 'd') {
|
||||
do_dashes = 1;
|
||||
}
|
||||
if (c === 'D') {
|
||||
do_dashes = 2;
|
||||
}
|
||||
if (c === 'i') {
|
||||
do_dashes = 3;
|
||||
}
|
||||
if (c === 'e') {
|
||||
do_ellipses = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (do_dashes) {
|
||||
text = text.replace(/–/g, '\u2013'); // en-dash
|
||||
text = text.replace(/—/g, '\u2014'); // em-dash
|
||||
}
|
||||
if (do_quotes || do_backticks) {
|
||||
text = text.replace(/‘/g, '\u2018'); // open single quote
|
||||
text = text.replace(/’/g, '\u2019'); // close single quote
|
||||
text = text.replace(/“/g, '\u201c'); // open double quote
|
||||
text = text.replace(/”/g, '\u201d'); // close double quote
|
||||
}
|
||||
if (do_ellipses) {
|
||||
text = text.replace(/…/g, '\u2026'); // ellipsis
|
||||
}
|
||||
return text;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with each SmartyPants UTF-8 chars translated to
|
||||
* its ASCII counterpart.
|
||||
*
|
||||
* Example input: “Hello — world.”
|
||||
* Example output: "Hello -- world."
|
||||
*/
|
||||
const StupifyUTF8Char = (str) => {
|
||||
str = str.replace(/\u2013/g, '-'); // en-dash
|
||||
str = str.replace(/\u2014/g, '--'); // em-dash
|
||||
str = str.replace(/\u2018/g, '\''); // open single quote
|
||||
str = str.replace(/\u2019/g, '\''); // close single quote
|
||||
str = str.replace(/\u201c/g, '"'); // open double quote
|
||||
str = str.replace(/\u201d/g, '"'); // close double quote
|
||||
str = str.replace(/\u2026/g, '...'); // ellipsis
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} string, with after processing the following backslash
|
||||
* escape sequences. This is useful if you want to force a "dumb"
|
||||
* quote or other character to appear.
|
||||
*
|
||||
* Escape Value
|
||||
* ------ -----
|
||||
* \\ \
|
||||
* \" "
|
||||
* \' '
|
||||
* \. .
|
||||
* \- -
|
||||
* \` `
|
||||
*
|
||||
*/
|
||||
const ProcessEscapes = (str) => {
|
||||
str = str.replace(/\\\\/g, '\');
|
||||
str = str.replace(/\\"/g, '"');
|
||||
str = str.replace(/\\'/g, ''');
|
||||
str = str.replace(/\\\./g, '.');
|
||||
str = str.replace(/\\-/g, '-');
|
||||
str = str.replace(/\\`/g, '`');
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String containing HTML markup.
|
||||
* @return {Array<token>} Reference to an array of the tokens comprising the input
|
||||
* string. Each token is either a tag (possibly with nested,
|
||||
* tags contained therein, such as <a href="<MTFoo>">, or a
|
||||
* run of text between tags. Each element of the array is a
|
||||
* two-element array; the first is either 'tag' or 'text';
|
||||
* the second is the actual value.
|
||||
*
|
||||
* Based on the _tokenize() subroutine from Brad Choate's MTRegex plugin.
|
||||
* <http://www.bradchoate.com/past/mtregex.php>
|
||||
*/
|
||||
const _tokenize = (str) => {
|
||||
var pos = 0;
|
||||
var len = str.length;
|
||||
var tokens = [];
|
||||
var match = /<!--[\s\S]*?-->|<\?.*?\?>|<[^>]*>/g;
|
||||
var matched = null;
|
||||
while (matched = match.exec(str)) { // eslint-disable-line no-cond-assign
|
||||
if (pos < matched.index) {
|
||||
let t = ['text', str.substring(pos, matched.index)];
|
||||
tokens.push(t);
|
||||
}
|
||||
let t = ['tag', matched.toString()];
|
||||
tokens.push(t);
|
||||
pos = match.lastIndex;
|
||||
}
|
||||
if (pos < len) {
|
||||
let t = ['text', str.substring(pos, len)];
|
||||
tokens.push(t);
|
||||
}
|
||||
return tokens;
|
||||
};
|
||||
const smartypantsu = (text = '', attr = '1') => {
|
||||
var str = SmartyPants(text, attr);
|
||||
if (typeof attr === 'number') {
|
||||
attr = attr.toString();
|
||||
}
|
||||
else {
|
||||
attr = attr.replace(/\s/g, '');
|
||||
}
|
||||
if (attr === '-1') {
|
||||
return StupifyUTF8Char(str);
|
||||
}
|
||||
else {
|
||||
return EducateEntities(str, attr);
|
||||
}
|
||||
};
|
||||
export { SmartyPants as smartypants };
|
||||
export { SmartQuotes as smartquotes };
|
||||
export { SmartDashes as smartdashes };
|
||||
export { SmartEllipses as smartellipses };
|
||||
export { smartypantsu };
|
||||
export default SmartyPants;
|
||||
806
node_modules/smartypants/smartypants.js
generated
vendored
Normal file
806
node_modules/smartypants/smartypants.js
generated
vendored
Normal file
@@ -0,0 +1,806 @@
|
||||
/* eslint-env browser, amd, node */
|
||||
|
||||
/**
|
||||
*
|
||||
* @file Translates plain ASCII punctuation characters into "smart" typographic punctuation
|
||||
* @desc See the readme for details, installation instructions, and * license information.
|
||||
* @version 0.0.4
|
||||
* @author othree
|
||||
*
|
||||
* Copyright (c) 2003-2004 John Gruber
|
||||
* Copyright (c) 2016 Kao, Wei-Ko(othree)
|
||||
*
|
||||
* @see {@link https://www.npmjs.com/package/smartypants|smartypants.js}
|
||||
*/
|
||||
|
||||
/*! smartypants.js 0.0.6 | (c) Kao, Wei-Ko(othree) | github.com/othree/smartypants.js/blob/master/LICENSE */
|
||||
|
||||
(function (root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD
|
||||
define('SmartyPants', ['exports'], function (exports) {
|
||||
factory((root.SmartyPants = exports));
|
||||
});
|
||||
} else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {
|
||||
// CommonJS
|
||||
factory(exports);
|
||||
} else {
|
||||
// Browser globals
|
||||
factory((root.SmartyPants = {}));
|
||||
}
|
||||
}(this, function (exports) {
|
||||
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
exports.smartypantsu = exports.smartellipses = exports.smartdashes = exports.smartquotes = exports.smartypants = void 0;
|
||||
var tags_to_skip = /<(\/?)(?:pre|code|kbd|script|math)[^>]*>/i;
|
||||
/**
|
||||
* @param text text to be parsed
|
||||
* @param attr value of the smart_quotes="" attribute
|
||||
*/
|
||||
var SmartyPants = function (text, attr) {
|
||||
if (text === void 0) { text = ''; }
|
||||
if (attr === void 0) { attr = '1'; }
|
||||
var do_quotes;
|
||||
var do_backticks;
|
||||
var do_dashes;
|
||||
var do_ellipses;
|
||||
var do_stupefy;
|
||||
var convert_quot = 0;
|
||||
if (typeof attr === 'number') {
|
||||
attr = attr.toString();
|
||||
}
|
||||
else {
|
||||
attr = attr.replace(/\s/g, '');
|
||||
}
|
||||
/**
|
||||
* Parse attributes:
|
||||
* 0 : do nothing
|
||||
* 1 : set all
|
||||
* 2 : set all, using old school en- and em- dash shortcuts
|
||||
* 3 : set all, using inverted old school en and em- dash shortcuts
|
||||
*
|
||||
* q : quotes
|
||||
* b : backtick quotes (``double'' only)
|
||||
* B : backtick quotes (``double'' and `single')
|
||||
* d : dashes
|
||||
* D : old school dashes
|
||||
* i : inverted old school dashes
|
||||
* e : ellipses
|
||||
* w : convert " entities to " for Dreamweaver users
|
||||
*/
|
||||
if (attr === '0') {
|
||||
// Do nothing
|
||||
return text;
|
||||
}
|
||||
else if (attr === '1') {
|
||||
// Do everything, turn all options on.
|
||||
do_quotes = 1;
|
||||
do_backticks = 1;
|
||||
do_dashes = 1;
|
||||
do_ellipses = 1;
|
||||
}
|
||||
else if (attr === '2') {
|
||||
// Do everything, turn all options on, use old school dash shorthand.
|
||||
do_quotes = 1;
|
||||
do_backticks = 1;
|
||||
do_dashes = 2;
|
||||
do_ellipses = 1;
|
||||
}
|
||||
else if (attr === '3') {
|
||||
// Do everything, turn all options on, use inverted old school dash shorthand.
|
||||
do_quotes = 1;
|
||||
do_backticks = 1;
|
||||
do_dashes = 3;
|
||||
do_ellipses = 1;
|
||||
}
|
||||
else if (attr === '-1') {
|
||||
// Special "stupefy" mode.
|
||||
do_stupefy = 1;
|
||||
}
|
||||
else {
|
||||
for (var i = 0; i < attr.length; i++) {
|
||||
var c = attr[i];
|
||||
if (c === 'q') {
|
||||
do_quotes = 1;
|
||||
}
|
||||
if (c === 'b') {
|
||||
do_backticks = 1;
|
||||
}
|
||||
if (c === 'B') {
|
||||
do_backticks = 2;
|
||||
}
|
||||
if (c === 'd') {
|
||||
do_dashes = 1;
|
||||
}
|
||||
if (c === 'D') {
|
||||
do_dashes = 2;
|
||||
}
|
||||
if (c === 'i') {
|
||||
do_dashes = 3;
|
||||
}
|
||||
if (c === 'e') {
|
||||
do_ellipses = 1;
|
||||
}
|
||||
if (c === 'w') {
|
||||
convert_quot = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
var tokens = _tokenize(text);
|
||||
var result = '';
|
||||
/**
|
||||
* Keep track of when we're inside <pre> or <code> tags.
|
||||
*/
|
||||
var in_pre = 0;
|
||||
/**
|
||||
* This is a cheat, used to get some context
|
||||
* for one-character tokens that consist of
|
||||
* just a quote char. What we do is remember
|
||||
* the last character of the previous text
|
||||
* token, to use as context to curl single-
|
||||
* character quote tokens correctly.
|
||||
*/
|
||||
var prev_token_last_char = '';
|
||||
for (var i = 0; i < tokens.length; i++) {
|
||||
var cur_token = tokens[i];
|
||||
if (cur_token[0] === 'tag') {
|
||||
result = result + cur_token[1];
|
||||
var matched = tags_to_skip.exec(cur_token[1]);
|
||||
if (matched) {
|
||||
if (matched[1] === '/') {
|
||||
in_pre = 0;
|
||||
}
|
||||
else {
|
||||
in_pre = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
var t = cur_token[1];
|
||||
var last_char = t.substring(t.length - 1, t.length); // Remember last char of this token before processing.
|
||||
if (!in_pre) {
|
||||
t = ProcessEscapes(t);
|
||||
if (convert_quot) {
|
||||
t = t.replace(/$quot;/g, '"');
|
||||
}
|
||||
if (do_dashes) {
|
||||
if (do_dashes === 1) {
|
||||
t = EducateDashes(t);
|
||||
}
|
||||
if (do_dashes === 2) {
|
||||
t = EducateDashesOldSchool(t);
|
||||
}
|
||||
if (do_dashes === 3) {
|
||||
t = EducateDashesOldSchoolInverted(t);
|
||||
}
|
||||
}
|
||||
if (do_ellipses) {
|
||||
t = EducateEllipses(t);
|
||||
}
|
||||
// Note: backticks need to be processed before quotes.
|
||||
if (do_backticks) {
|
||||
t = EducateBackticks(t);
|
||||
if (do_backticks === 2) {
|
||||
t = EducateSingleBackticks(t);
|
||||
}
|
||||
}
|
||||
if (do_quotes) {
|
||||
if (t === '\'') {
|
||||
// Special case: single-character ' token
|
||||
if (/\S/.test(prev_token_last_char)) {
|
||||
t = '’';
|
||||
}
|
||||
else {
|
||||
t = '‘';
|
||||
}
|
||||
}
|
||||
else if (t === '"') {
|
||||
// Special case: single-character " token
|
||||
if (/\S/.test(prev_token_last_char)) {
|
||||
t = '”';
|
||||
}
|
||||
else {
|
||||
t = '“';
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Normal case:
|
||||
t = EducateQuotes(t);
|
||||
}
|
||||
}
|
||||
if (do_stupefy) {
|
||||
t = StupefyEntities(t);
|
||||
}
|
||||
}
|
||||
prev_token_last_char = last_char;
|
||||
result = result + t;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
exports.smartypants = SmartyPants;
|
||||
var SmartQuotes = function (text, attr) {
|
||||
/**
|
||||
* should we educate ``backticks'' -style quotes?
|
||||
*/
|
||||
// var do_backticks:number;
|
||||
if (text === void 0) { text = ''; }
|
||||
if (attr === void 0) { attr = '1'; }
|
||||
if (typeof attr === 'number') {
|
||||
attr = attr.toString();
|
||||
}
|
||||
else {
|
||||
attr = attr.replace(/\s/g, '');
|
||||
}
|
||||
if (attr === '0') {
|
||||
// Do nothing
|
||||
return text;
|
||||
// } else if (attr === '2') {
|
||||
// // smarten ``backticks'' -style quotes
|
||||
// do_backticks = 1;
|
||||
// } else {
|
||||
// do_backticks = 0;
|
||||
}
|
||||
/**
|
||||
* Special case to handle quotes at the very end of $text when preceded by
|
||||
* an HTML tag. Add a space to give the quote education algorithm a bit of
|
||||
* context, so that it can guess correctly that it's a closing quote:
|
||||
*/
|
||||
var add_extra_space = 0;
|
||||
if (/>['"]$/.test(text)) {
|
||||
add_extra_space = 1; // Remember, so we can trim the extra space later.
|
||||
text = text + ' ';
|
||||
}
|
||||
var tokens = _tokenize(text);
|
||||
var result = '';
|
||||
/**
|
||||
* Keep track of when we're inside <pre> or <code> tags.
|
||||
*/
|
||||
var in_pre = 0;
|
||||
/**
|
||||
* This is a cheat, used to get some context
|
||||
* for one-character tokens that consist of
|
||||
* just a quote char. What we do is remember
|
||||
* the last character of the previous text
|
||||
* token, to use as context to curl single-
|
||||
* character quote tokens correctly.
|
||||
*/
|
||||
var prev_token_last_char = '';
|
||||
for (var i = 0; i < tokens.length; i++) {
|
||||
var cur_token = tokens[i];
|
||||
if (cur_token[0] === 'tag') {
|
||||
result = result + cur_token[1];
|
||||
var matched = tags_to_skip.exec(cur_token[1]);
|
||||
if (matched) {
|
||||
if (matched[1] === '/') {
|
||||
in_pre = 0;
|
||||
}
|
||||
else {
|
||||
in_pre = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
var t = cur_token[1];
|
||||
var last_char = t.substring(t.length - 1, t.length); // Remember last char of this token before processing.
|
||||
if (!in_pre) {
|
||||
t = ProcessEscapes(t);
|
||||
if (t === '\'') {
|
||||
// Special case: single-character ' token
|
||||
if (/\S/.test(prev_token_last_char)) {
|
||||
t = '’';
|
||||
}
|
||||
else {
|
||||
t = '‘';
|
||||
}
|
||||
}
|
||||
else if (t === '"') {
|
||||
// Special case: single-character " token
|
||||
if (/\S/.test(prev_token_last_char)) {
|
||||
t = '”';
|
||||
}
|
||||
else {
|
||||
t = '“';
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Normal case:
|
||||
t = EducateQuotes(t);
|
||||
}
|
||||
}
|
||||
prev_token_last_char = last_char;
|
||||
result = result + t;
|
||||
}
|
||||
}
|
||||
if (add_extra_space) {
|
||||
result = result.replace(/ $/, '');
|
||||
}
|
||||
return result;
|
||||
};
|
||||
exports.smartquotes = SmartQuotes;
|
||||
var SmartDashes = function (text, attr) {
|
||||
if (text === void 0) { text = ''; }
|
||||
if (attr === void 0) { attr = '1'; }
|
||||
// reference to the subroutine to use for dash education, default to EducateDashes:
|
||||
var dash_sub_ref = EducateDashes;
|
||||
if (typeof attr === 'number') {
|
||||
attr = attr.toString();
|
||||
}
|
||||
else {
|
||||
attr = attr.replace(/\s/g, '');
|
||||
}
|
||||
if (attr === '0') {
|
||||
// Do nothing
|
||||
return text;
|
||||
}
|
||||
else if (attr === '2') {
|
||||
// use old smart dash shortcuts, "--" for en, "---" for em
|
||||
dash_sub_ref = EducateDashesOldSchool;
|
||||
}
|
||||
else if (attr === '3') {
|
||||
// inverse of 2, "--" for em, "---" for en
|
||||
dash_sub_ref = EducateDashesOldSchoolInverted;
|
||||
}
|
||||
var tokens = _tokenize(text);
|
||||
var result = '';
|
||||
/**
|
||||
* Keep track of when we're inside <pre> or <code> tags.
|
||||
*/
|
||||
var in_pre = 0;
|
||||
for (var i = 0; i < tokens.length; i++) {
|
||||
var cur_token = tokens[i];
|
||||
if (cur_token[0] === 'tag') {
|
||||
result = result + cur_token[1];
|
||||
var matched = tags_to_skip.exec(cur_token[1]);
|
||||
if (matched) {
|
||||
if (matched[1] === '/') {
|
||||
in_pre = 0;
|
||||
}
|
||||
else {
|
||||
in_pre = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
var t = cur_token[1];
|
||||
if (!in_pre) {
|
||||
t = ProcessEscapes(t);
|
||||
t = dash_sub_ref(t);
|
||||
}
|
||||
result = result + t;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
exports.smartdashes = SmartDashes;
|
||||
var SmartEllipses = function (text, attr) {
|
||||
if (text === void 0) { text = ''; }
|
||||
if (attr === void 0) { attr = '1'; }
|
||||
if (typeof attr === 'number') {
|
||||
attr = attr.toString();
|
||||
}
|
||||
else {
|
||||
attr = attr.replace(/\s/g, '');
|
||||
}
|
||||
if (attr === '0') {
|
||||
// Do nothing
|
||||
return text;
|
||||
}
|
||||
var tokens = _tokenize(text);
|
||||
var result = '';
|
||||
/**
|
||||
* Keep track of when we're inside <pre> or <code> tags.
|
||||
*/
|
||||
var in_pre = 0;
|
||||
for (var i = 0; i < tokens.length; i++) {
|
||||
var cur_token = tokens[i];
|
||||
if (cur_token[0] === 'tag') {
|
||||
result = result + cur_token[1];
|
||||
var matched = tags_to_skip.exec(cur_token[1]);
|
||||
if (matched) {
|
||||
if (matched[1] === '/') {
|
||||
in_pre = 0;
|
||||
}
|
||||
else {
|
||||
in_pre = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
var t = cur_token[1];
|
||||
if (!in_pre) {
|
||||
t = ProcessEscapes(t);
|
||||
t = EducateEllipses(t);
|
||||
}
|
||||
result = result + t;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
exports.smartellipses = SmartEllipses;
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with "educated" curly quote HTML entities.
|
||||
*
|
||||
* Example input: "Isn't this fun?"
|
||||
* Example output: “Isn’t this fun?”
|
||||
*/
|
||||
var EducateQuotes = function (str) {
|
||||
/**
|
||||
* Make our own "punctuation" character class, because the POSIX-style
|
||||
* [:PUNCT:] is only available in Perl 5.6 or later:
|
||||
*
|
||||
* JavaScript don't have punctuation class neither.
|
||||
*/
|
||||
var punct_class = '[!"#\$\%\'()*+,-./:;<=>?\@\[\\\]\^_`{|}~]'; // eslint-disable-line no-useless-escape
|
||||
/**
|
||||
* Special case if the very first character is a quote
|
||||
* followed by punctuation at a non-word-break. Close the quotes by brute force:
|
||||
*/
|
||||
str = str.replace(new RegExp("^'(?=" + punct_class + "\\B)"), '’'); // eslint-disable-line no-useless-escape
|
||||
str = str.replace(new RegExp("^\"(?=" + punct_class + "\\B)"), '”'); // eslint-disable-line no-useless-escape
|
||||
/**
|
||||
* Special case for double sets of quotes, e.g.:
|
||||
* <p>He said, "'Quoted' words in a larger quote."</p>
|
||||
*/
|
||||
str = str.replace(/"'(?=\w)/, '“‘');
|
||||
str = str.replace(/'"(?=\w)/, '‘“');
|
||||
/**
|
||||
* Special case for decade abbreviations (the '80s):
|
||||
*/
|
||||
str = str.replace(/'(?=\d\d)/, '’');
|
||||
var close_class = '[^\\ \\t\\r\\n\\[\\{\\(\\-]'; // eslint-disable-line no-useless-escape
|
||||
var not_close_class = '[\\ \\t\\r\\n\\[\\{\\(\\-]'; // eslint-disable-line no-useless-escape
|
||||
var dec_dashes = '–|—';
|
||||
/**
|
||||
* Get most opening single quotes:
|
||||
* s {
|
||||
* (
|
||||
* \s | # a whitespace char, or
|
||||
* | # a non-breaking space entity, or
|
||||
* -- | # dashes, or
|
||||
* &[mn]dash; | # named dash entities
|
||||
* $dec_dashes | # or decimal entities
|
||||
* &\#x201[34]; # or hex
|
||||
* )
|
||||
* ' # the quote
|
||||
* (?=\w) # followed by a word character
|
||||
* } {$1‘}xg;
|
||||
*/
|
||||
str = str.replace(new RegExp("(\\s| |--|&[mn]dash;|" + dec_dashes + "|ȁ[34])'(?=\\w)", 'g'), '\$1‘'); // eslint-disable-line no-useless-escape
|
||||
/**
|
||||
* Single closing quotes:
|
||||
* s {
|
||||
* ($close_class)?
|
||||
* '
|
||||
* (?(1)| # If $1 captured, then do nothing;
|
||||
* (?=\s | s\b) # otherwise, positive lookahead for a whitespace
|
||||
* ) # char or an 's' at a word ending position. This
|
||||
* # is a special case to handle something like:
|
||||
* # "<i>Custer</i>'s Last Stand."
|
||||
* } {$1’}xgi;
|
||||
*/
|
||||
str = str.replace(new RegExp("(" + close_class + ")'", 'g'), '\$1’'); // eslint-disable-line no-useless-escape
|
||||
str = str.replace(new RegExp("(" + not_close_class + "?)'(?=\\s|s\\b)", 'g'), '\$1’'); // eslint-disable-line no-useless-escape
|
||||
/**
|
||||
* Any remaining single quotes should be opening ones:
|
||||
*/
|
||||
str = str.replace(/'/g, '‘');
|
||||
/**
|
||||
* Get most opening double quotes:
|
||||
* s {
|
||||
* (
|
||||
* \s | # a whitespace char, or
|
||||
* | # a non-breaking space entity, or
|
||||
* -- | # dashes, or
|
||||
* &[mn]dash; | # named dash entities
|
||||
* $dec_dashes | # or decimal entities
|
||||
* &\#x201[34]; # or hex
|
||||
* )
|
||||
* " # the quote
|
||||
* (?=\w) # followed by a word character
|
||||
* } {$1“}xg;
|
||||
*/
|
||||
str = str.replace(new RegExp("(\\s| |--|&[mn]dash;|" + dec_dashes + "|ȁ[34])\"(?=\\w)", 'g'), '\$1“'); // eslint-disable-line no-useless-escape
|
||||
/**
|
||||
* Double closing quotes:
|
||||
* s {
|
||||
* ($close_class)?
|
||||
* "
|
||||
* (?(1)|(?=\s)) # If $1 captured, then do nothing;
|
||||
* # if not, then make sure the next char is whitespace.
|
||||
* } {$1”}xg;
|
||||
*/
|
||||
str = str.replace(new RegExp("(" + close_class + ")\"", 'g'), '\$1”'); // eslint-disable-line no-useless-escape
|
||||
str = str.replace(new RegExp("(" + not_close_class + "?)\"(?=\\s)", 'g'), '\$1”'); // eslint-disable-line no-useless-escape
|
||||
/**
|
||||
* Any remaining quotes should be opening ones.
|
||||
*/
|
||||
str = str.replace(/"/g, '“');
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with ``backticks'' -style double quotes
|
||||
* translated into HTML curly quote entities.
|
||||
*
|
||||
* Example input: ``Isn't this fun?''
|
||||
* Example output: “Isn't this fun?”
|
||||
*/
|
||||
var EducateBackticks = function (str) {
|
||||
str = str.replace(/``/g, '“');
|
||||
str = str.replace(/''/g, '”');
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with `backticks' -style single quotes
|
||||
* translated into HTML curly quote entities.
|
||||
*
|
||||
* Example input: `Isn't this fun?'
|
||||
* Example output: ‘Isn’t this fun?’
|
||||
*/
|
||||
var EducateSingleBackticks = function (str) {
|
||||
str = str.replace(/`/g, '‘');
|
||||
str = str.replace(/'/g, '’');
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with each instance of "--" translated to
|
||||
* an em-dash HTML entity.
|
||||
*/
|
||||
var EducateDashes = function (str) {
|
||||
str = str.replace(/--/g, '—');
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with each instance of "--" translated to
|
||||
* an en-dash HTML entity, and each "---" translated to
|
||||
* an em-dash HTML entity.
|
||||
*/
|
||||
var EducateDashesOldSchool = function (str) {
|
||||
str = str.replace(/---/g, '—');
|
||||
str = str.replace(/--/g, '–');
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with each instance of "--" translated to
|
||||
* an em-dash HTML entity, and each "---" translated to
|
||||
* an en-dash HTML entity. Two reasons why: First, unlike the
|
||||
* en- and em-dash syntax supported by
|
||||
* EducateDashesOldSchool(), it's compatible with existing
|
||||
* entries written before SmartyPants 1.1, back when "--" was
|
||||
* only used for em-dashes. Second, em-dashes are more
|
||||
* common than en-dashes, and so it sort of makes sense that
|
||||
* the shortcut should be shorter to type. (Thanks to Aaron
|
||||
* Swartz for the idea.)
|
||||
*/
|
||||
var EducateDashesOldSchoolInverted = function (str) {
|
||||
str = str.replace(/---/g, '–');
|
||||
str = str.replace(/--/g, '—');
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with each instance of "..." translated to
|
||||
* an ellipsis HTML entity. Also converts the case where
|
||||
* there are spaces between the dots.
|
||||
*
|
||||
* Example input: Huh...?
|
||||
* Example output: Huh…?
|
||||
*/
|
||||
var EducateEllipses = function (str) {
|
||||
str = str.replace(/\.\.\./g, '…');
|
||||
str = str.replace(/\. \. \./g, '…');
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with each SmartyPants HTML entity translated to
|
||||
* its ASCII counterpart.
|
||||
*
|
||||
* Example input: “Hello — world.”
|
||||
* Example output: "Hello -- world."
|
||||
*/
|
||||
var StupefyEntities = function (str) {
|
||||
str = str.replace(/–/g, '-'); // en-dash
|
||||
str = str.replace(/—/g, '--'); // em-dash
|
||||
str = str.replace(/‘/g, '\''); // open single quote
|
||||
str = str.replace(/’/g, '\''); // close single quote
|
||||
str = str.replace(/“/g, '"'); // open double quote
|
||||
str = str.replace(/”/g, '"'); // close double quote
|
||||
str = str.replace(/…/g, '...'); // ellipsis
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with each SmartyPants HTML entity translated to
|
||||
* UTF-8 characters.
|
||||
*
|
||||
* Example input: “Hello ’ world.”
|
||||
* Example output: "Hello — world."
|
||||
*/
|
||||
var EducateEntities = function (text, attr) {
|
||||
if (attr === void 0) { attr = '1'; }
|
||||
var do_quotes;
|
||||
var do_backticks;
|
||||
var do_dashes;
|
||||
var do_ellipses;
|
||||
// var do_stupefy:number;
|
||||
if (typeof attr === 'number') {
|
||||
attr = attr.toString();
|
||||
}
|
||||
else {
|
||||
attr = attr.replace(/\s/g, '');
|
||||
}
|
||||
if (attr === '0') {
|
||||
// Do nothing
|
||||
return text;
|
||||
}
|
||||
else if (attr === '1') {
|
||||
// Do everything, turn all options on.
|
||||
do_quotes = 1;
|
||||
do_backticks = 1;
|
||||
do_dashes = 1;
|
||||
do_ellipses = 1;
|
||||
}
|
||||
else if (attr === '2') {
|
||||
// Do everything, turn all options on, use old school dash shorthand.
|
||||
do_quotes = 1;
|
||||
do_backticks = 1;
|
||||
do_dashes = 3;
|
||||
do_ellipses = 1;
|
||||
}
|
||||
else if (attr === '3') {
|
||||
// Do everything, turn all options on, use inverted old school dash shorthand.
|
||||
do_quotes = 1;
|
||||
do_backticks = 1;
|
||||
do_dashes = 3;
|
||||
do_ellipses = 1;
|
||||
// } else if (attr === '-1') {
|
||||
// // Special "stupefy" mode.
|
||||
// do_stupefy = 1;
|
||||
}
|
||||
else {
|
||||
for (var i = 0; i < attr.length; i++) {
|
||||
var c = attr[i];
|
||||
if (c === 'q') {
|
||||
do_quotes = 1;
|
||||
}
|
||||
if (c === 'b') {
|
||||
do_backticks = 1;
|
||||
}
|
||||
if (c === 'B') {
|
||||
do_backticks = 2;
|
||||
}
|
||||
if (c === 'd') {
|
||||
do_dashes = 1;
|
||||
}
|
||||
if (c === 'D') {
|
||||
do_dashes = 2;
|
||||
}
|
||||
if (c === 'i') {
|
||||
do_dashes = 3;
|
||||
}
|
||||
if (c === 'e') {
|
||||
do_ellipses = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (do_dashes) {
|
||||
text = text.replace(/–/g, '\u2013'); // en-dash
|
||||
text = text.replace(/—/g, '\u2014'); // em-dash
|
||||
}
|
||||
if (do_quotes || do_backticks) {
|
||||
text = text.replace(/‘/g, '\u2018'); // open single quote
|
||||
text = text.replace(/’/g, '\u2019'); // close single quote
|
||||
text = text.replace(/“/g, '\u201c'); // open double quote
|
||||
text = text.replace(/”/g, '\u201d'); // close double quote
|
||||
}
|
||||
if (do_ellipses) {
|
||||
text = text.replace(/…/g, '\u2026'); // ellipsis
|
||||
}
|
||||
return text;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with each SmartyPants UTF-8 chars translated to
|
||||
* its ASCII counterpart.
|
||||
*
|
||||
* Example input: “Hello — world.”
|
||||
* Example output: "Hello -- world."
|
||||
*/
|
||||
var StupifyUTF8Char = function (str) {
|
||||
str = str.replace(/\u2013/g, '-'); // en-dash
|
||||
str = str.replace(/\u2014/g, '--'); // em-dash
|
||||
str = str.replace(/\u2018/g, '\''); // open single quote
|
||||
str = str.replace(/\u2019/g, '\''); // close single quote
|
||||
str = str.replace(/\u201c/g, '"'); // open double quote
|
||||
str = str.replace(/\u201d/g, '"'); // close double quote
|
||||
str = str.replace(/\u2026/g, '...'); // ellipsis
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} string, with after processing the following backslash
|
||||
* escape sequences. This is useful if you want to force a "dumb"
|
||||
* quote or other character to appear.
|
||||
*
|
||||
* Escape Value
|
||||
* ------ -----
|
||||
* \\ \
|
||||
* \" "
|
||||
* \' '
|
||||
* \. .
|
||||
* \- -
|
||||
* \` `
|
||||
*
|
||||
*/
|
||||
var ProcessEscapes = function (str) {
|
||||
str = str.replace(/\\\\/g, '\');
|
||||
str = str.replace(/\\"/g, '"');
|
||||
str = str.replace(/\\'/g, ''');
|
||||
str = str.replace(/\\\./g, '.');
|
||||
str = str.replace(/\\-/g, '-');
|
||||
str = str.replace(/\\`/g, '`');
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String containing HTML markup.
|
||||
* @return {Array<token>} Reference to an array of the tokens comprising the input
|
||||
* string. Each token is either a tag (possibly with nested,
|
||||
* tags contained therein, such as <a href="<MTFoo>">, or a
|
||||
* run of text between tags. Each element of the array is a
|
||||
* two-element array; the first is either 'tag' or 'text';
|
||||
* the second is the actual value.
|
||||
*
|
||||
* Based on the _tokenize() subroutine from Brad Choate's MTRegex plugin.
|
||||
* <http://www.bradchoate.com/past/mtregex.php>
|
||||
*/
|
||||
var _tokenize = function (str) {
|
||||
var pos = 0;
|
||||
var len = str.length;
|
||||
var tokens = [];
|
||||
var match = /<!--[\s\S]*?-->|<\?.*?\?>|<[^>]*>/g;
|
||||
var matched = null;
|
||||
while (matched = match.exec(str)) { // eslint-disable-line no-cond-assign
|
||||
if (pos < matched.index) {
|
||||
var t_1 = ['text', str.substring(pos, matched.index)];
|
||||
tokens.push(t_1);
|
||||
}
|
||||
var t = ['tag', matched.toString()];
|
||||
tokens.push(t);
|
||||
pos = match.lastIndex;
|
||||
}
|
||||
if (pos < len) {
|
||||
var t = ['text', str.substring(pos, len)];
|
||||
tokens.push(t);
|
||||
}
|
||||
return tokens;
|
||||
};
|
||||
var smartypantsu = function (text, attr) {
|
||||
if (text === void 0) { text = ''; }
|
||||
if (attr === void 0) { attr = '1'; }
|
||||
var str = SmartyPants(text, attr);
|
||||
if (typeof attr === 'number') {
|
||||
attr = attr.toString();
|
||||
}
|
||||
else {
|
||||
attr = attr.replace(/\s/g, '');
|
||||
}
|
||||
if (attr === '-1') {
|
||||
return StupifyUTF8Char(str);
|
||||
}
|
||||
else {
|
||||
return EducateEntities(str, attr);
|
||||
}
|
||||
};
|
||||
exports.smartypantsu = smartypantsu;
|
||||
exports["default"] = SmartyPants;
|
||||
|
||||
|
||||
}));
|
||||
757
node_modules/smartypants/smartypants.mjs
generated
vendored
Normal file
757
node_modules/smartypants/smartypants.mjs
generated
vendored
Normal file
@@ -0,0 +1,757 @@
|
||||
const tags_to_skip = /<(\/?)(?:pre|code|kbd|script|math)[^>]*>/i;
|
||||
/**
|
||||
* @param text text to be parsed
|
||||
* @param attr value of the smart_quotes="" attribute
|
||||
*/
|
||||
const SmartyPants = (text = '', attr = '1') => {
|
||||
var do_quotes;
|
||||
var do_backticks;
|
||||
var do_dashes;
|
||||
var do_ellipses;
|
||||
var do_stupefy;
|
||||
var convert_quot = 0;
|
||||
if (typeof attr === 'number') {
|
||||
attr = attr.toString();
|
||||
}
|
||||
else {
|
||||
attr = attr.replace(/\s/g, '');
|
||||
}
|
||||
/**
|
||||
* Parse attributes:
|
||||
* 0 : do nothing
|
||||
* 1 : set all
|
||||
* 2 : set all, using old school en- and em- dash shortcuts
|
||||
* 3 : set all, using inverted old school en and em- dash shortcuts
|
||||
*
|
||||
* q : quotes
|
||||
* b : backtick quotes (``double'' only)
|
||||
* B : backtick quotes (``double'' and `single')
|
||||
* d : dashes
|
||||
* D : old school dashes
|
||||
* i : inverted old school dashes
|
||||
* e : ellipses
|
||||
* w : convert " entities to " for Dreamweaver users
|
||||
*/
|
||||
if (attr === '0') {
|
||||
// Do nothing
|
||||
return text;
|
||||
}
|
||||
else if (attr === '1') {
|
||||
// Do everything, turn all options on.
|
||||
do_quotes = 1;
|
||||
do_backticks = 1;
|
||||
do_dashes = 1;
|
||||
do_ellipses = 1;
|
||||
}
|
||||
else if (attr === '2') {
|
||||
// Do everything, turn all options on, use old school dash shorthand.
|
||||
do_quotes = 1;
|
||||
do_backticks = 1;
|
||||
do_dashes = 2;
|
||||
do_ellipses = 1;
|
||||
}
|
||||
else if (attr === '3') {
|
||||
// Do everything, turn all options on, use inverted old school dash shorthand.
|
||||
do_quotes = 1;
|
||||
do_backticks = 1;
|
||||
do_dashes = 3;
|
||||
do_ellipses = 1;
|
||||
}
|
||||
else if (attr === '-1') {
|
||||
// Special "stupefy" mode.
|
||||
do_stupefy = 1;
|
||||
}
|
||||
else {
|
||||
for (let i = 0; i < attr.length; i++) {
|
||||
let c = attr[i];
|
||||
if (c === 'q') {
|
||||
do_quotes = 1;
|
||||
}
|
||||
if (c === 'b') {
|
||||
do_backticks = 1;
|
||||
}
|
||||
if (c === 'B') {
|
||||
do_backticks = 2;
|
||||
}
|
||||
if (c === 'd') {
|
||||
do_dashes = 1;
|
||||
}
|
||||
if (c === 'D') {
|
||||
do_dashes = 2;
|
||||
}
|
||||
if (c === 'i') {
|
||||
do_dashes = 3;
|
||||
}
|
||||
if (c === 'e') {
|
||||
do_ellipses = 1;
|
||||
}
|
||||
if (c === 'w') {
|
||||
convert_quot = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
var tokens = _tokenize(text);
|
||||
var result = '';
|
||||
/**
|
||||
* Keep track of when we're inside <pre> or <code> tags.
|
||||
*/
|
||||
var in_pre = 0;
|
||||
/**
|
||||
* This is a cheat, used to get some context
|
||||
* for one-character tokens that consist of
|
||||
* just a quote char. What we do is remember
|
||||
* the last character of the previous text
|
||||
* token, to use as context to curl single-
|
||||
* character quote tokens correctly.
|
||||
*/
|
||||
var prev_token_last_char = '';
|
||||
for (let i = 0; i < tokens.length; i++) {
|
||||
let cur_token = tokens[i];
|
||||
if (cur_token[0] === 'tag') {
|
||||
result = result + cur_token[1];
|
||||
let matched = tags_to_skip.exec(cur_token[1]);
|
||||
if (matched) {
|
||||
if (matched[1] === '/') {
|
||||
in_pre = 0;
|
||||
}
|
||||
else {
|
||||
in_pre = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
let t = cur_token[1];
|
||||
let last_char = t.substring(t.length - 1, t.length); // Remember last char of this token before processing.
|
||||
if (!in_pre) {
|
||||
t = ProcessEscapes(t);
|
||||
if (convert_quot) {
|
||||
t = t.replace(/$quot;/g, '"');
|
||||
}
|
||||
if (do_dashes) {
|
||||
if (do_dashes === 1) {
|
||||
t = EducateDashes(t);
|
||||
}
|
||||
if (do_dashes === 2) {
|
||||
t = EducateDashesOldSchool(t);
|
||||
}
|
||||
if (do_dashes === 3) {
|
||||
t = EducateDashesOldSchoolInverted(t);
|
||||
}
|
||||
}
|
||||
if (do_ellipses) {
|
||||
t = EducateEllipses(t);
|
||||
}
|
||||
// Note: backticks need to be processed before quotes.
|
||||
if (do_backticks) {
|
||||
t = EducateBackticks(t);
|
||||
if (do_backticks === 2) {
|
||||
t = EducateSingleBackticks(t);
|
||||
}
|
||||
}
|
||||
if (do_quotes) {
|
||||
if (t === '\'') {
|
||||
// Special case: single-character ' token
|
||||
if (/\S/.test(prev_token_last_char)) {
|
||||
t = '’';
|
||||
}
|
||||
else {
|
||||
t = '‘';
|
||||
}
|
||||
}
|
||||
else if (t === '"') {
|
||||
// Special case: single-character " token
|
||||
if (/\S/.test(prev_token_last_char)) {
|
||||
t = '”';
|
||||
}
|
||||
else {
|
||||
t = '“';
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Normal case:
|
||||
t = EducateQuotes(t);
|
||||
}
|
||||
}
|
||||
if (do_stupefy) {
|
||||
t = StupefyEntities(t);
|
||||
}
|
||||
}
|
||||
prev_token_last_char = last_char;
|
||||
result = result + t;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
const SmartQuotes = (text = '', attr = '1') => {
|
||||
/**
|
||||
* should we educate ``backticks'' -style quotes?
|
||||
*/
|
||||
// var do_backticks:number;
|
||||
if (typeof attr === 'number') {
|
||||
attr = attr.toString();
|
||||
}
|
||||
else {
|
||||
attr = attr.replace(/\s/g, '');
|
||||
}
|
||||
if (attr === '0') {
|
||||
// Do nothing
|
||||
return text;
|
||||
// } else if (attr === '2') {
|
||||
// // smarten ``backticks'' -style quotes
|
||||
// do_backticks = 1;
|
||||
// } else {
|
||||
// do_backticks = 0;
|
||||
}
|
||||
/**
|
||||
* Special case to handle quotes at the very end of $text when preceded by
|
||||
* an HTML tag. Add a space to give the quote education algorithm a bit of
|
||||
* context, so that it can guess correctly that it's a closing quote:
|
||||
*/
|
||||
var add_extra_space = 0;
|
||||
if (/>['"]$/.test(text)) {
|
||||
add_extra_space = 1; // Remember, so we can trim the extra space later.
|
||||
text = text + ' ';
|
||||
}
|
||||
var tokens = _tokenize(text);
|
||||
var result = '';
|
||||
/**
|
||||
* Keep track of when we're inside <pre> or <code> tags.
|
||||
*/
|
||||
var in_pre = 0;
|
||||
/**
|
||||
* This is a cheat, used to get some context
|
||||
* for one-character tokens that consist of
|
||||
* just a quote char. What we do is remember
|
||||
* the last character of the previous text
|
||||
* token, to use as context to curl single-
|
||||
* character quote tokens correctly.
|
||||
*/
|
||||
var prev_token_last_char = '';
|
||||
for (let i = 0; i < tokens.length; i++) {
|
||||
let cur_token = tokens[i];
|
||||
if (cur_token[0] === 'tag') {
|
||||
result = result + cur_token[1];
|
||||
let matched = tags_to_skip.exec(cur_token[1]);
|
||||
if (matched) {
|
||||
if (matched[1] === '/') {
|
||||
in_pre = 0;
|
||||
}
|
||||
else {
|
||||
in_pre = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
let t = cur_token[1];
|
||||
let last_char = t.substring(t.length - 1, t.length); // Remember last char of this token before processing.
|
||||
if (!in_pre) {
|
||||
t = ProcessEscapes(t);
|
||||
if (t === '\'') {
|
||||
// Special case: single-character ' token
|
||||
if (/\S/.test(prev_token_last_char)) {
|
||||
t = '’';
|
||||
}
|
||||
else {
|
||||
t = '‘';
|
||||
}
|
||||
}
|
||||
else if (t === '"') {
|
||||
// Special case: single-character " token
|
||||
if (/\S/.test(prev_token_last_char)) {
|
||||
t = '”';
|
||||
}
|
||||
else {
|
||||
t = '“';
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Normal case:
|
||||
t = EducateQuotes(t);
|
||||
}
|
||||
}
|
||||
prev_token_last_char = last_char;
|
||||
result = result + t;
|
||||
}
|
||||
}
|
||||
if (add_extra_space) {
|
||||
result = result.replace(/ $/, '');
|
||||
}
|
||||
return result;
|
||||
};
|
||||
const SmartDashes = (text = '', attr = '1') => {
|
||||
// reference to the subroutine to use for dash education, default to EducateDashes:
|
||||
var dash_sub_ref = EducateDashes;
|
||||
if (typeof attr === 'number') {
|
||||
attr = attr.toString();
|
||||
}
|
||||
else {
|
||||
attr = attr.replace(/\s/g, '');
|
||||
}
|
||||
if (attr === '0') {
|
||||
// Do nothing
|
||||
return text;
|
||||
}
|
||||
else if (attr === '2') {
|
||||
// use old smart dash shortcuts, "--" for en, "---" for em
|
||||
dash_sub_ref = EducateDashesOldSchool;
|
||||
}
|
||||
else if (attr === '3') {
|
||||
// inverse of 2, "--" for em, "---" for en
|
||||
dash_sub_ref = EducateDashesOldSchoolInverted;
|
||||
}
|
||||
var tokens = _tokenize(text);
|
||||
var result = '';
|
||||
/**
|
||||
* Keep track of when we're inside <pre> or <code> tags.
|
||||
*/
|
||||
var in_pre = 0;
|
||||
for (let i = 0; i < tokens.length; i++) {
|
||||
let cur_token = tokens[i];
|
||||
if (cur_token[0] === 'tag') {
|
||||
result = result + cur_token[1];
|
||||
let matched = tags_to_skip.exec(cur_token[1]);
|
||||
if (matched) {
|
||||
if (matched[1] === '/') {
|
||||
in_pre = 0;
|
||||
}
|
||||
else {
|
||||
in_pre = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
let t = cur_token[1];
|
||||
if (!in_pre) {
|
||||
t = ProcessEscapes(t);
|
||||
t = dash_sub_ref(t);
|
||||
}
|
||||
result = result + t;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
const SmartEllipses = (text = '', attr = '1') => {
|
||||
if (typeof attr === 'number') {
|
||||
attr = attr.toString();
|
||||
}
|
||||
else {
|
||||
attr = attr.replace(/\s/g, '');
|
||||
}
|
||||
if (attr === '0') {
|
||||
// Do nothing
|
||||
return text;
|
||||
}
|
||||
var tokens = _tokenize(text);
|
||||
var result = '';
|
||||
/**
|
||||
* Keep track of when we're inside <pre> or <code> tags.
|
||||
*/
|
||||
var in_pre = 0;
|
||||
for (let i = 0; i < tokens.length; i++) {
|
||||
let cur_token = tokens[i];
|
||||
if (cur_token[0] === 'tag') {
|
||||
result = result + cur_token[1];
|
||||
let matched = tags_to_skip.exec(cur_token[1]);
|
||||
if (matched) {
|
||||
if (matched[1] === '/') {
|
||||
in_pre = 0;
|
||||
}
|
||||
else {
|
||||
in_pre = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
let t = cur_token[1];
|
||||
if (!in_pre) {
|
||||
t = ProcessEscapes(t);
|
||||
t = EducateEllipses(t);
|
||||
}
|
||||
result = result + t;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with "educated" curly quote HTML entities.
|
||||
*
|
||||
* Example input: "Isn't this fun?"
|
||||
* Example output: “Isn’t this fun?”
|
||||
*/
|
||||
const EducateQuotes = (str) => {
|
||||
/**
|
||||
* Make our own "punctuation" character class, because the POSIX-style
|
||||
* [:PUNCT:] is only available in Perl 5.6 or later:
|
||||
*
|
||||
* JavaScript don't have punctuation class neither.
|
||||
*/
|
||||
var punct_class = '[!"#\$\%\'()*+,-./:;<=>?\@\[\\\]\^_`{|}~]'; // eslint-disable-line no-useless-escape
|
||||
/**
|
||||
* Special case if the very first character is a quote
|
||||
* followed by punctuation at a non-word-break. Close the quotes by brute force:
|
||||
*/
|
||||
str = str.replace(new RegExp(`^'(?=${punct_class}\\B)`), '’'); // eslint-disable-line no-useless-escape
|
||||
str = str.replace(new RegExp(`^"(?=${punct_class}\\B)`), '”'); // eslint-disable-line no-useless-escape
|
||||
/**
|
||||
* Special case for double sets of quotes, e.g.:
|
||||
* <p>He said, "'Quoted' words in a larger quote."</p>
|
||||
*/
|
||||
str = str.replace(/"'(?=\w)/, '“‘');
|
||||
str = str.replace(/'"(?=\w)/, '‘“');
|
||||
/**
|
||||
* Special case for decade abbreviations (the '80s):
|
||||
*/
|
||||
str = str.replace(/'(?=\d\d)/, '’');
|
||||
var close_class = '[^\\ \\t\\r\\n\\[\\{\\(\\-]'; // eslint-disable-line no-useless-escape
|
||||
var not_close_class = '[\\ \\t\\r\\n\\[\\{\\(\\-]'; // eslint-disable-line no-useless-escape
|
||||
var dec_dashes = '–|—';
|
||||
/**
|
||||
* Get most opening single quotes:
|
||||
* s {
|
||||
* (
|
||||
* \s | # a whitespace char, or
|
||||
* | # a non-breaking space entity, or
|
||||
* -- | # dashes, or
|
||||
* &[mn]dash; | # named dash entities
|
||||
* $dec_dashes | # or decimal entities
|
||||
* &\#x201[34]; # or hex
|
||||
* )
|
||||
* ' # the quote
|
||||
* (?=\w) # followed by a word character
|
||||
* } {$1‘}xg;
|
||||
*/
|
||||
str = str.replace(new RegExp(`(\\s| |--|&[mn]dash;|${dec_dashes}|ȁ[34])'(?=\\w)`, 'g'), '\$1‘'); // eslint-disable-line no-useless-escape
|
||||
/**
|
||||
* Single closing quotes:
|
||||
* s {
|
||||
* ($close_class)?
|
||||
* '
|
||||
* (?(1)| # If $1 captured, then do nothing;
|
||||
* (?=\s | s\b) # otherwise, positive lookahead for a whitespace
|
||||
* ) # char or an 's' at a word ending position. This
|
||||
* # is a special case to handle something like:
|
||||
* # "<i>Custer</i>'s Last Stand."
|
||||
* } {$1’}xgi;
|
||||
*/
|
||||
str = str.replace(new RegExp(`(${close_class})'`, 'g'), '\$1’'); // eslint-disable-line no-useless-escape
|
||||
str = str.replace(new RegExp(`(${not_close_class}?)'(?=\\s|s\\b)`, 'g'), '\$1’'); // eslint-disable-line no-useless-escape
|
||||
/**
|
||||
* Any remaining single quotes should be opening ones:
|
||||
*/
|
||||
str = str.replace(/'/g, '‘');
|
||||
/**
|
||||
* Get most opening double quotes:
|
||||
* s {
|
||||
* (
|
||||
* \s | # a whitespace char, or
|
||||
* | # a non-breaking space entity, or
|
||||
* -- | # dashes, or
|
||||
* &[mn]dash; | # named dash entities
|
||||
* $dec_dashes | # or decimal entities
|
||||
* &\#x201[34]; # or hex
|
||||
* )
|
||||
* " # the quote
|
||||
* (?=\w) # followed by a word character
|
||||
* } {$1“}xg;
|
||||
*/
|
||||
str = str.replace(new RegExp(`(\\s| |--|&[mn]dash;|${dec_dashes}|ȁ[34])"(?=\\w)`, 'g'), '\$1“'); // eslint-disable-line no-useless-escape
|
||||
/**
|
||||
* Double closing quotes:
|
||||
* s {
|
||||
* ($close_class)?
|
||||
* "
|
||||
* (?(1)|(?=\s)) # If $1 captured, then do nothing;
|
||||
* # if not, then make sure the next char is whitespace.
|
||||
* } {$1”}xg;
|
||||
*/
|
||||
str = str.replace(new RegExp(`(${close_class})"`, 'g'), '\$1”'); // eslint-disable-line no-useless-escape
|
||||
str = str.replace(new RegExp(`(${not_close_class}?)"(?=\\s)`, 'g'), '\$1”'); // eslint-disable-line no-useless-escape
|
||||
/**
|
||||
* Any remaining quotes should be opening ones.
|
||||
*/
|
||||
str = str.replace(/"/g, '“');
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with ``backticks'' -style double quotes
|
||||
* translated into HTML curly quote entities.
|
||||
*
|
||||
* Example input: ``Isn't this fun?''
|
||||
* Example output: “Isn't this fun?”
|
||||
*/
|
||||
const EducateBackticks = (str) => {
|
||||
str = str.replace(/``/g, '“');
|
||||
str = str.replace(/''/g, '”');
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with `backticks' -style single quotes
|
||||
* translated into HTML curly quote entities.
|
||||
*
|
||||
* Example input: `Isn't this fun?'
|
||||
* Example output: ‘Isn’t this fun?’
|
||||
*/
|
||||
const EducateSingleBackticks = (str) => {
|
||||
str = str.replace(/`/g, '‘');
|
||||
str = str.replace(/'/g, '’');
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with each instance of "--" translated to
|
||||
* an em-dash HTML entity.
|
||||
*/
|
||||
const EducateDashes = (str) => {
|
||||
str = str.replace(/--/g, '—');
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with each instance of "--" translated to
|
||||
* an en-dash HTML entity, and each "---" translated to
|
||||
* an em-dash HTML entity.
|
||||
*/
|
||||
const EducateDashesOldSchool = (str) => {
|
||||
str = str.replace(/---/g, '—');
|
||||
str = str.replace(/--/g, '–');
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with each instance of "--" translated to
|
||||
* an em-dash HTML entity, and each "---" translated to
|
||||
* an en-dash HTML entity. Two reasons why: First, unlike the
|
||||
* en- and em-dash syntax supported by
|
||||
* EducateDashesOldSchool(), it's compatible with existing
|
||||
* entries written before SmartyPants 1.1, back when "--" was
|
||||
* only used for em-dashes. Second, em-dashes are more
|
||||
* common than en-dashes, and so it sort of makes sense that
|
||||
* the shortcut should be shorter to type. (Thanks to Aaron
|
||||
* Swartz for the idea.)
|
||||
*/
|
||||
const EducateDashesOldSchoolInverted = (str) => {
|
||||
str = str.replace(/---/g, '–');
|
||||
str = str.replace(/--/g, '—');
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with each instance of "..." translated to
|
||||
* an ellipsis HTML entity. Also converts the case where
|
||||
* there are spaces between the dots.
|
||||
*
|
||||
* Example input: Huh...?
|
||||
* Example output: Huh…?
|
||||
*/
|
||||
const EducateEllipses = (str) => {
|
||||
str = str.replace(/\.\.\./g, '…');
|
||||
str = str.replace(/\. \. \./g, '…');
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with each SmartyPants HTML entity translated to
|
||||
* its ASCII counterpart.
|
||||
*
|
||||
* Example input: “Hello — world.”
|
||||
* Example output: "Hello -- world."
|
||||
*/
|
||||
const StupefyEntities = (str) => {
|
||||
str = str.replace(/–/g, '-'); // en-dash
|
||||
str = str.replace(/—/g, '--'); // em-dash
|
||||
str = str.replace(/‘/g, '\''); // open single quote
|
||||
str = str.replace(/’/g, '\''); // close single quote
|
||||
str = str.replace(/“/g, '"'); // open double quote
|
||||
str = str.replace(/”/g, '"'); // close double quote
|
||||
str = str.replace(/…/g, '...'); // ellipsis
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with each SmartyPants HTML entity translated to
|
||||
* UTF-8 characters.
|
||||
*
|
||||
* Example input: “Hello ’ world.”
|
||||
* Example output: "Hello — world."
|
||||
*/
|
||||
const EducateEntities = (text, attr = '1') => {
|
||||
var do_quotes;
|
||||
var do_backticks;
|
||||
var do_dashes;
|
||||
var do_ellipses;
|
||||
// var do_stupefy:number;
|
||||
if (typeof attr === 'number') {
|
||||
attr = attr.toString();
|
||||
}
|
||||
else {
|
||||
attr = attr.replace(/\s/g, '');
|
||||
}
|
||||
if (attr === '0') {
|
||||
// Do nothing
|
||||
return text;
|
||||
}
|
||||
else if (attr === '1') {
|
||||
// Do everything, turn all options on.
|
||||
do_quotes = 1;
|
||||
do_backticks = 1;
|
||||
do_dashes = 1;
|
||||
do_ellipses = 1;
|
||||
}
|
||||
else if (attr === '2') {
|
||||
// Do everything, turn all options on, use old school dash shorthand.
|
||||
do_quotes = 1;
|
||||
do_backticks = 1;
|
||||
do_dashes = 3;
|
||||
do_ellipses = 1;
|
||||
}
|
||||
else if (attr === '3') {
|
||||
// Do everything, turn all options on, use inverted old school dash shorthand.
|
||||
do_quotes = 1;
|
||||
do_backticks = 1;
|
||||
do_dashes = 3;
|
||||
do_ellipses = 1;
|
||||
// } else if (attr === '-1') {
|
||||
// // Special "stupefy" mode.
|
||||
// do_stupefy = 1;
|
||||
}
|
||||
else {
|
||||
for (let i = 0; i < attr.length; i++) {
|
||||
let c = attr[i];
|
||||
if (c === 'q') {
|
||||
do_quotes = 1;
|
||||
}
|
||||
if (c === 'b') {
|
||||
do_backticks = 1;
|
||||
}
|
||||
if (c === 'B') {
|
||||
do_backticks = 2;
|
||||
}
|
||||
if (c === 'd') {
|
||||
do_dashes = 1;
|
||||
}
|
||||
if (c === 'D') {
|
||||
do_dashes = 2;
|
||||
}
|
||||
if (c === 'i') {
|
||||
do_dashes = 3;
|
||||
}
|
||||
if (c === 'e') {
|
||||
do_ellipses = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (do_dashes) {
|
||||
text = text.replace(/–/g, '\u2013'); // en-dash
|
||||
text = text.replace(/—/g, '\u2014'); // em-dash
|
||||
}
|
||||
if (do_quotes || do_backticks) {
|
||||
text = text.replace(/‘/g, '\u2018'); // open single quote
|
||||
text = text.replace(/’/g, '\u2019'); // close single quote
|
||||
text = text.replace(/“/g, '\u201c'); // open double quote
|
||||
text = text.replace(/”/g, '\u201d'); // close double quote
|
||||
}
|
||||
if (do_ellipses) {
|
||||
text = text.replace(/…/g, '\u2026'); // ellipsis
|
||||
}
|
||||
return text;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} The string, with each SmartyPants UTF-8 chars translated to
|
||||
* its ASCII counterpart.
|
||||
*
|
||||
* Example input: “Hello — world.”
|
||||
* Example output: "Hello -- world."
|
||||
*/
|
||||
const StupifyUTF8Char = (str) => {
|
||||
str = str.replace(/\u2013/g, '-'); // en-dash
|
||||
str = str.replace(/\u2014/g, '--'); // em-dash
|
||||
str = str.replace(/\u2018/g, '\''); // open single quote
|
||||
str = str.replace(/\u2019/g, '\''); // close single quote
|
||||
str = str.replace(/\u201c/g, '"'); // open double quote
|
||||
str = str.replace(/\u201d/g, '"'); // close double quote
|
||||
str = str.replace(/\u2026/g, '...'); // ellipsis
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String
|
||||
* @return {string} string, with after processing the following backslash
|
||||
* escape sequences. This is useful if you want to force a "dumb"
|
||||
* quote or other character to appear.
|
||||
*
|
||||
* Escape Value
|
||||
* ------ -----
|
||||
* \\ \
|
||||
* \" "
|
||||
* \' '
|
||||
* \. .
|
||||
* \- -
|
||||
* \` `
|
||||
*
|
||||
*/
|
||||
const ProcessEscapes = (str) => {
|
||||
str = str.replace(/\\\\/g, '\');
|
||||
str = str.replace(/\\"/g, '"');
|
||||
str = str.replace(/\\'/g, ''');
|
||||
str = str.replace(/\\\./g, '.');
|
||||
str = str.replace(/\\-/g, '-');
|
||||
str = str.replace(/\\`/g, '`');
|
||||
return str;
|
||||
};
|
||||
/**
|
||||
* @param {string} str String containing HTML markup.
|
||||
* @return {Array<token>} Reference to an array of the tokens comprising the input
|
||||
* string. Each token is either a tag (possibly with nested,
|
||||
* tags contained therein, such as <a href="<MTFoo>">, or a
|
||||
* run of text between tags. Each element of the array is a
|
||||
* two-element array; the first is either 'tag' or 'text';
|
||||
* the second is the actual value.
|
||||
*
|
||||
* Based on the _tokenize() subroutine from Brad Choate's MTRegex plugin.
|
||||
* <http://www.bradchoate.com/past/mtregex.php>
|
||||
*/
|
||||
const _tokenize = (str) => {
|
||||
var pos = 0;
|
||||
var len = str.length;
|
||||
var tokens = [];
|
||||
var match = /<!--[\s\S]*?-->|<\?.*?\?>|<[^>]*>/g;
|
||||
var matched = null;
|
||||
while (matched = match.exec(str)) { // eslint-disable-line no-cond-assign
|
||||
if (pos < matched.index) {
|
||||
let t = ['text', str.substring(pos, matched.index)];
|
||||
tokens.push(t);
|
||||
}
|
||||
let t = ['tag', matched.toString()];
|
||||
tokens.push(t);
|
||||
pos = match.lastIndex;
|
||||
}
|
||||
if (pos < len) {
|
||||
let t = ['text', str.substring(pos, len)];
|
||||
tokens.push(t);
|
||||
}
|
||||
return tokens;
|
||||
};
|
||||
const smartypantsu = (text = '', attr = '1') => {
|
||||
var str = SmartyPants(text, attr);
|
||||
if (typeof attr === 'number') {
|
||||
attr = attr.toString();
|
||||
}
|
||||
else {
|
||||
attr = attr.replace(/\s/g, '');
|
||||
}
|
||||
if (attr === '-1') {
|
||||
return StupifyUTF8Char(str);
|
||||
}
|
||||
else {
|
||||
return EducateEntities(str, attr);
|
||||
}
|
||||
};
|
||||
export { SmartyPants as smartypants };
|
||||
export { SmartQuotes as smartquotes };
|
||||
export { SmartDashes as smartdashes };
|
||||
export { SmartEllipses as smartellipses };
|
||||
export { smartypantsu };
|
||||
export default SmartyPants;
|
||||
Reference in New Issue
Block a user