vue-highlight.js
Version:
Highlight.js syntax highlighter component for Vue.
626 lines (562 loc) • 21.4 kB
JavaScript
var VueHighlightJS = (function (hljs, Vue) {
'use strict';
hljs = hljs && hljs.hasOwnProperty('default') ? hljs['default'] : hljs;
Vue = Vue && Vue.hasOwnProperty('default') ? Vue['default'] : Vue;
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/* global Reflect, Promise */
var extendStatics = function(d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
function __extends(d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
}
function __decorate(decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
}
function unwrapExports (x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x.default : x;
}
function createCommonjsModule(fn, module) {
return module = { exports: {} }, fn(module, module.exports), module.exports;
}
var vueClassComponent_common = createCommonjsModule(function (module, exports) {
Object.defineProperty(exports, '__esModule', { value: true });
function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
var Vue$1 = _interopDefault(Vue);
var reflectionIsSupported = typeof Reflect !== 'undefined' && Reflect.defineMetadata;
function copyReflectionMetadata(to, from) {
forwardMetadata(to, from);
Object.getOwnPropertyNames(from.prototype).forEach(function (key) {
forwardMetadata(to.prototype, from.prototype, key);
});
Object.getOwnPropertyNames(from).forEach(function (key) {
forwardMetadata(to, from, key);
});
}
function forwardMetadata(to, from, propertyKey) {
var metaKeys = propertyKey
? Reflect.getOwnMetadataKeys(from, propertyKey)
: Reflect.getOwnMetadataKeys(from);
metaKeys.forEach(function (metaKey) {
var metadata = propertyKey
? Reflect.getOwnMetadata(metaKey, from, propertyKey)
: Reflect.getOwnMetadata(metaKey, from);
if (propertyKey) {
Reflect.defineMetadata(metaKey, metadata, to, propertyKey);
}
else {
Reflect.defineMetadata(metaKey, metadata, to);
}
});
}
var fakeArray = { __proto__: [] };
var hasProto = fakeArray instanceof Array;
function createDecorator(factory) {
return function (target, key, index) {
var Ctor = typeof target === 'function'
? target
: target.constructor;
if (!Ctor.__decorators__) {
Ctor.__decorators__ = [];
}
if (typeof index !== 'number') {
index = undefined;
}
Ctor.__decorators__.push(function (options) { return factory(options, key, index); });
};
}
function mixins() {
var Ctors = [];
for (var _i = 0; _i < arguments.length; _i++) {
Ctors[_i] = arguments[_i];
}
return Vue$1.extend({ mixins: Ctors });
}
function isPrimitive(value) {
var type = typeof value;
return value == null || (type !== 'object' && type !== 'function');
}
function collectDataFromConstructor(vm, Component) {
// override _init to prevent to init as Vue instance
var originalInit = Component.prototype._init;
Component.prototype._init = function () {
var _this = this;
// proxy to actual vm
var keys = Object.getOwnPropertyNames(vm);
// 2.2.0 compat (props are no longer exposed as self properties)
if (vm.$options.props) {
for (var key in vm.$options.props) {
if (!vm.hasOwnProperty(key)) {
keys.push(key);
}
}
}
keys.forEach(function (key) {
if (key.charAt(0) !== '_') {
Object.defineProperty(_this, key, {
get: function () { return vm[key]; },
set: function (value) { vm[key] = value; },
configurable: true
});
}
});
};
// should be acquired class property values
var data = new Component();
// restore original _init to avoid memory leak (#209)
Component.prototype._init = originalInit;
// create plain data object
var plainData = {};
Object.keys(data).forEach(function (key) {
if (data[key] !== undefined) {
plainData[key] = data[key];
}
});
return plainData;
}
var $internalHooks = [
'data',
'beforeCreate',
'created',
'beforeMount',
'mounted',
'beforeDestroy',
'destroyed',
'beforeUpdate',
'updated',
'activated',
'deactivated',
'render',
'errorCaptured' // 2.5
];
function componentFactory(Component, options) {
if (options === void 0) { options = {}; }
options.name = options.name || Component._componentTag || Component.name;
// prototype props.
var proto = Component.prototype;
Object.getOwnPropertyNames(proto).forEach(function (key) {
if (key === 'constructor') {
return;
}
// hooks
if ($internalHooks.indexOf(key) > -1) {
options[key] = proto[key];
return;
}
var descriptor = Object.getOwnPropertyDescriptor(proto, key);
if (descriptor.value !== void 0) {
// methods
if (typeof descriptor.value === 'function') {
(options.methods || (options.methods = {}))[key] = descriptor.value;
}
else {
// typescript decorated data
(options.mixins || (options.mixins = [])).push({
data: function () {
var _a;
return _a = {}, _a[key] = descriptor.value, _a;
}
});
}
}
else if (descriptor.get || descriptor.set) {
// computed properties
(options.computed || (options.computed = {}))[key] = {
get: descriptor.get,
set: descriptor.set
};
}
});
(options.mixins || (options.mixins = [])).push({
data: function () {
return collectDataFromConstructor(this, Component);
}
});
// decorate options
var decorators = Component.__decorators__;
if (decorators) {
decorators.forEach(function (fn) { return fn(options); });
delete Component.__decorators__;
}
// find super
var superProto = Object.getPrototypeOf(Component.prototype);
var Super = superProto instanceof Vue$1
? superProto.constructor
: Vue$1;
var Extended = Super.extend(options);
forwardStaticMembers(Extended, Component, Super);
if (reflectionIsSupported) {
copyReflectionMetadata(Extended, Component);
}
return Extended;
}
function forwardStaticMembers(Extended, Original, Super) {
// We have to use getOwnPropertyNames since Babel registers methods as non-enumerable
Object.getOwnPropertyNames(Original).forEach(function (key) {
// `prototype` should not be overwritten
if (key === 'prototype') {
return;
}
// Some browsers does not allow reconfigure built-in properties
var extendedDescriptor = Object.getOwnPropertyDescriptor(Extended, key);
if (extendedDescriptor && !extendedDescriptor.configurable) {
return;
}
var descriptor = Object.getOwnPropertyDescriptor(Original, key);
// If the user agent does not support `__proto__` or its family (IE <= 10),
// the sub class properties may be inherited properties from the super class in TypeScript.
// We need to exclude such properties to prevent to overwrite
// the component options object which stored on the extended constructor (See #192).
// If the value is a referenced value (object or function),
// we can check equality of them and exclude it if they have the same reference.
// If it is a primitive value, it will be forwarded for safety.
if (!hasProto) {
// Only `cid` is explicitly exluded from property forwarding
// because we cannot detect whether it is a inherited property or not
// on the no `__proto__` environment even though the property is reserved.
if (key === 'cid') {
return;
}
var superDescriptor = Object.getOwnPropertyDescriptor(Super, key);
if (!isPrimitive(descriptor.value) &&
superDescriptor &&
superDescriptor.value === descriptor.value) {
return;
}
}
Object.defineProperty(Extended, key, descriptor);
});
}
function Component(options) {
if (typeof options === 'function') {
return componentFactory(options);
}
return function (Component) {
return componentFactory(Component, options);
};
}
Component.registerHooks = function registerHooks(keys) {
$internalHooks.push.apply($internalHooks, keys);
};
exports.default = Component;
exports.createDecorator = createDecorator;
exports.mixins = mixins;
});
var Component = unwrapExports(vueClassComponent_common);
var vueClassComponent_common_1 = vueClassComponent_common.createDecorator;
var vueClassComponent_common_2 = vueClassComponent_common.mixins;
/** vue-property-decorator verson 7.3.0 MIT LICENSE copyright 2018 kaorun343 */
/**
* decorator of a prop
* @param options the options for the prop
* @return PropertyDecorator | void
*/
function Prop(options) {
if (options === void 0) { options = {}; }
return vueClassComponent_common_1(function (componentOptions, k) {
(componentOptions.props || (componentOptions.props = {}))[k] = options;
});
}
/**
* Escape code.
*
* @export
* @param {string} code Code.
* @returns {string}
*/
function escape(code) {
if (typeof code === 'string') {
return code
.replace(/&/g, '&')
.replace(/"/g, '"')
.replace(/'/g, ''')
.replace(/</g, '<')
.replace(/>/g, '>');
}
else {
return code;
}
}
/**
* Deeply get concatenated text from slot.
*
* @export
* @param {VNode[]} slot A slot. (The collection of VNode)
* @returns {string}
*/
function getSlotText(slot) {
if (Array.isArray(slot)) {
return slot
.map(function (node) {
if (Array.isArray(node.children) && node.children.length > 0) {
return getSlotText(node.children);
}
else {
return node.text;
}
})
.join('');
}
else {
return '';
}
}
// detect either spaces or tabs but not both to properly handle tabs
// for indentation and spaces for alignment
const INDENT_RE = /^(?:( )+|\t+)/;
function getMostUsed(indents) {
let result = 0;
let maxUsed = 0;
let maxWeight = 0;
for (const entry of indents) {
// TODO: use destructuring when targeting Node.js 6
const key = entry[0];
const val = entry[1];
const u = val[0];
const w = val[1];
if (u > maxUsed || (u === maxUsed && w > maxWeight)) {
maxUsed = u;
maxWeight = w;
result = Number(key);
}
}
return result;
}
var detectIndent = str => {
if (typeof str !== 'string') {
throw new TypeError('Expected a string');
}
// used to see if tabs or spaces are the most used
let tabs = 0;
let spaces = 0;
// remember the size of previous line's indentation
let prev = 0;
// remember how many indents/unindents as occurred for a given size
// and how much lines follow a given indentation
//
// indents = {
// 3: [1, 0],
// 4: [1, 5],
// 5: [1, 0],
// 12: [1, 0],
// }
const indents = new Map();
// pointer to the array of last used indent
let current;
// whether the last action was an indent (opposed to an unindent)
let isIndent;
for (const line of str.split(/\n/g)) {
if (!line) {
// ignore empty lines
continue;
}
let indent;
const matches = line.match(INDENT_RE);
if (matches) {
indent = matches[0].length;
if (matches[1]) {
spaces++;
} else {
tabs++;
}
} else {
indent = 0;
}
const diff = indent - prev;
prev = indent;
if (diff) {
// an indent or unindent has been detected
isIndent = diff > 0;
current = indents.get(isIndent ? diff : -diff);
if (current) {
current[0]++;
} else {
current = [1, 0];
indents.set(diff, current);
}
} else if (current) {
// if the last action was an indent, increment the weight
current[1] += Number(isIndent);
}
}
const amount = getMostUsed(indents);
let type;
let indent;
if (!amount) {
type = null;
indent = '';
} else if (spaces >= tabs) {
type = 'space';
indent = ' '.repeat(amount);
} else {
type = 'tab';
indent = '\t'.repeat(amount);
}
return {
amount,
type,
indent
};
};
var stripIndent = str => {
const match = str.match(/^[ \t]*(?=\S)/gm);
if (!match) {
return str;
}
// TODO: use spread operator when targeting Node.js 6
const indent = Math.min.apply(Math, match.map(x => x.length)); // eslint-disable-line
const re = new RegExp(`^[ \\t]{${indent}}`, 'gm');
return indent > 0 ? str.replace(re, '') : str;
};
var indentString = (str, count, opts) => {
// Support older versions: use the third parameter as options.indent
// TODO: Remove the workaround in the next major version
const options = typeof opts === 'object' ? Object.assign({indent: ' '}, opts) : {indent: opts || ' '};
count = count === undefined ? 1 : count;
if (typeof str !== 'string') {
throw new TypeError(`Expected \`input\` to be a \`string\`, got \`${typeof str}\``);
}
if (typeof count !== 'number') {
throw new TypeError(`Expected \`count\` to be a \`number\`, got \`${typeof count}\``);
}
if (typeof options.indent !== 'string') {
throw new TypeError(`Expected \`options.indent\` to be a \`string\`, got \`${typeof options.indent}\``);
}
if (count === 0) {
return str;
}
const regex = options.includeEmptyLines ? /^/mg : /^(?!\s*$)/mg;
return str.replace(regex, options.indent.repeat(count));
}
;
var redent = (str, count, indent) => indentString(stripIndent(str), count || 0, indent);
/**
* Indent code.
*
* @export
* @param {string} code Code.
* @returns {string}
*/
function indentCode(code) {
if (typeof code === 'string') {
var indent = detectIndent(code).indent || '\t';
code = redent(code, 0, indent);
return code.trim();
}
else {
return code;
}
}
var inlineStyles = {
display: 'inline !important',
'vertical-align': 'middle'
};
var HighlightCode = /** @class */ (function (_super) {
__extends(HighlightCode, _super);
function HighlightCode() {
return _super !== null && _super.apply(this, arguments) || this;
}
Object.defineProperty(HighlightCode.prototype, "hasCode", {
get: function () {
return typeof this.code === 'string' && this.code.length > 0;
},
enumerable: true,
configurable: true
});
HighlightCode.prototype.render = function (h) {
var _a;
var _b = this, hasCode = _b.hasCode, inline = _b.inline, auto = _b.auto;
var lang = this.lang;
var code = hasCode ? this.code : getSlotText(this.$slots.default); // If no `code`, get text from default slot.
// Indent code if not use inline mode.
if (!inline) {
code = indentCode(code);
}
var highlightedCode;
try {
if (auto) {
(_a = hljs.highlightAuto(code), lang = _a.language, highlightedCode = _a.value);
}
else {
highlightedCode = lang
? hljs.highlight(lang, code).value
: escape(code); // If no `lang`, just display plain code.
}
}
catch (err) {
highlightedCode = escape(code);
console.error(err);
}
return h(!inline ? 'pre' : 'span', [
h('code', {
class: ['hljs'].concat((lang ? [lang] : [])),
style: inline ? inlineStyles : {},
domProps: {
innerHTML: highlightedCode
}
})
]);
};
__decorate([
Prop(String)
], HighlightCode.prototype, "lang", void 0);
__decorate([
Prop({ type: Boolean, default: false })
], HighlightCode.prototype, "inline", void 0);
__decorate([
Prop(String)
], HighlightCode.prototype, "code", void 0);
__decorate([
Prop(Boolean)
], HighlightCode.prototype, "auto", void 0);
HighlightCode = __decorate([
Component({
name: 'HighlightCode'
})
], HighlightCode);
return HighlightCode;
}(Vue));
/**
* Install Vue Highlight.js as plugin.
*
* @param {typeof Vue} vue Vue
* @param {Options} [options={ languages: {} }] Options
*/
var install = function (vue, options) {
if (options === void 0) { options = { languages: {} }; }
var languages = options.languages;
{
// Register additional `vue` language from highlight.js `xml` in web bundle
var xml_1 = window.hljs.getLanguage('xml');
window.hljs.registerLanguage('vue', function () { return xml_1; });
}
vue.component('highlight-code', HighlightCode);
};
if (typeof window !== 'undefined' && window.Vue) {
install(window.Vue);
}
var index = {
install: install
};
return index;
}(hljs, Vue));
//# sourceMappingURL=vue-highlight.web.js.map