From 6b69c9cbf18dfe3a75d1880de59c218a0d18d1f7 Mon Sep 17 00:00:00 2001 From: Vitaly Puzrin Date: Tue, 4 Nov 2014 10:32:14 +0300 Subject: [PATCH] Removed singleton in linkify (thread safety) --- lib/rules_core/linkify.js | 45 ++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/lib/rules_core/linkify.js b/lib/rules_core/linkify.js index acb2f36..f865d90 100644 --- a/lib/rules_core/linkify.js +++ b/lib/rules_core/linkify.js @@ -1,6 +1,6 @@ // Replace link-like texts with link nodes. // -// Currently restricted to http/https/ftp +// Currently restricted by `inline.validateLink()` to http/https/ftp // 'use strict'; @@ -10,17 +10,6 @@ var Autolinker = require('autolinker'); var LINK_SCAN_RE = /www|\:\/\//; -var links = []; -var autolinker = new Autolinker({ - stripPrefix: false, - replaceFn: function (autolinker, match) { - // Only collect matched strings but don't change anything. - if (match.getType() === 'url') { - links.push({ text: match.matchedText, url: match.getUrl() }); - } - return false; - } -}); function isLinkOpen(str) { return /^\s]/i.test(str); @@ -29,10 +18,33 @@ function isLinkClose(str) { return /^<\/a\s*>/i.test(str); } +// Stupid fabric to avoid singletons, for thread safety. +// Required for engines like Nashorn. +// +function createLinkifier() { + var links = []; + var autolinker = new Autolinker({ + stripPrefix: false, + replaceFn: function (autolinker, match) { + // Only collect matched strings but don't change anything. + if (match.getType() === 'url') { + links.push({ text: match.matchedText, url: match.getUrl() }); + } + return false; + } + }); + + return { + links: links, + autolinker: autolinker + }; +} + module.exports = function linkify(state) { var i, j, l, tokens, token, text, nodes, ln, pos, level, htmlLinkLevel, - blockTokens = state.tokens; + blockTokens = state.tokens, + linkifier = null, links, autolinker; if (!state.options.linkify) { return; } @@ -69,6 +81,13 @@ module.exports = function linkify(state) { if (token.type === 'text' && LINK_SCAN_RE.test(token.content)) { + // Init linkifier in lazy manner, only if required. + if (!linkifier) { + linkifier = createLinkifier(); + links = linkifier.links; + autolinker = linkifier.autolinker; + } + text = token.content; links.length = 0; autolinker.link(text);