Skip to content

Commit

Permalink
Core: Faster Token.stringify (#2171)
Browse files Browse the repository at this point in the history
This removes temporary arrays in `Token.stringify`.

All these changes make `Prism.highlight` about 10~23% faster.
  • Loading branch information
RunDevelopment committed Feb 19, 2020
1 parent e9dab85 commit f683972
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 33 deletions.
38 changes: 22 additions & 16 deletions components/prism-core.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ var _ = {
manual: _self.Prism && _self.Prism.manual,
disableWorkerMessageHandler: _self.Prism && _self.Prism.disableWorkerMessageHandler,
util: {
encode: function (tokens) {
encode: function encode(tokens) {
if (tokens instanceof Token) {
return new Token(tokens.type, _.util.encode(tokens.content), tokens.alias);
return new Token(tokens.type, encode(tokens.content), tokens.alias);
} else if (Array.isArray(tokens)) {
return tokens.map(_.util.encode);
return tokens.map(encode);
} else {
return tokens.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/\u00a0/g, ' ');
}
Expand Down Expand Up @@ -513,38 +513,44 @@ function Token(type, content, alias, matchedStr, greedy) {
this.greedy = !!greedy;
}

Token.stringify = function(o, language) {
Token.stringify = function stringify(o, language) {
if (typeof o == 'string') {
return o;
}

if (Array.isArray(o)) {
return o.map(function(element) {
return Token.stringify(element, language);
}).join('');
var s = '';
o.forEach(function (e) {
s += stringify(e, language);
});
return s;
}

var env = {
type: o.type,
content: Token.stringify(o.content, language),
content: stringify(o.content, language),
tag: 'span',
classes: ['token', o.type],
attributes: {},
language: language
};

if (o.alias) {
var aliases = Array.isArray(o.alias) ? o.alias : [o.alias];
Array.prototype.push.apply(env.classes, aliases);
var aliases = o.alias;
if (aliases) {
if (Array.isArray(aliases)) {
Array.prototype.push.apply(env.classes, aliases);
} else {
env.classes.push(aliases);
}
}

_.hooks.run('wrap', env);

var attributes = Object.keys(env.attributes).map(function(name) {
return name + '="' + (env.attributes[name] || '').replace(/"/g, '&quot;') + '"';
}).join(' ');
var attributes = '';
for (var name in env.attributes) {
attributes += ' ' + name + '="' + (env.attributes[name] || '').replace(/"/g, '&quot;') + '"';
}

return '<' + env.tag + ' class="' + env.classes.join(' ') + '"' + (attributes ? ' ' + attributes : '') + '>' + env.content + '</' + env.tag + '>';
return '<' + env.tag + ' class="' + env.classes.join(' ') + '"' + attributes + '>' + env.content + '</' + env.tag + '>';
};

if (!_self.document) {
Expand Down
2 changes: 1 addition & 1 deletion components/prism-core.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 22 additions & 16 deletions prism.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ var _ = {
manual: _self.Prism && _self.Prism.manual,
disableWorkerMessageHandler: _self.Prism && _self.Prism.disableWorkerMessageHandler,
util: {
encode: function (tokens) {
encode: function encode(tokens) {
if (tokens instanceof Token) {
return new Token(tokens.type, _.util.encode(tokens.content), tokens.alias);
return new Token(tokens.type, encode(tokens.content), tokens.alias);
} else if (Array.isArray(tokens)) {
return tokens.map(_.util.encode);
return tokens.map(encode);
} else {
return tokens.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/\u00a0/g, ' ');
}
Expand Down Expand Up @@ -518,38 +518,44 @@ function Token(type, content, alias, matchedStr, greedy) {
this.greedy = !!greedy;
}

Token.stringify = function(o, language) {
Token.stringify = function stringify(o, language) {
if (typeof o == 'string') {
return o;
}

if (Array.isArray(o)) {
return o.map(function(element) {
return Token.stringify(element, language);
}).join('');
var s = '';
o.forEach(function (e) {
s += stringify(e, language);
});
return s;
}

var env = {
type: o.type,
content: Token.stringify(o.content, language),
content: stringify(o.content, language),
tag: 'span',
classes: ['token', o.type],
attributes: {},
language: language
};

if (o.alias) {
var aliases = Array.isArray(o.alias) ? o.alias : [o.alias];
Array.prototype.push.apply(env.classes, aliases);
var aliases = o.alias;
if (aliases) {
if (Array.isArray(aliases)) {
Array.prototype.push.apply(env.classes, aliases);
} else {
env.classes.push(aliases);
}
}

_.hooks.run('wrap', env);

var attributes = Object.keys(env.attributes).map(function(name) {
return name + '="' + (env.attributes[name] || '').replace(/"/g, '&quot;') + '"';
}).join(' ');
var attributes = '';
for (var name in env.attributes) {
attributes += ' ' + name + '="' + (env.attributes[name] || '').replace(/"/g, '&quot;') + '"';
}

return '<' + env.tag + ' class="' + env.classes.join(' ') + '"' + (attributes ? ' ' + attributes : '') + '>' + env.content + '</' + env.tag + '>';
return '<' + env.tag + ' class="' + env.classes.join(' ') + '"' + attributes + '>' + env.content + '</' + env.tag + '>';
};

if (!_self.document) {
Expand Down

0 comments on commit f683972

Please sign in to comment.