- WordPress core y plugins - Tema Twenty Twenty-Four configurado - Plugin allow-unfiltered-html.php simplificado - .gitignore configurado para excluir wp-config.php y uploads 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2087 lines
54 KiB
JavaScript
Executable File
2087 lines
54 KiB
JavaScript
Executable File
/**
|
|
* @file postscribe
|
|
* @description Asynchronously write javascript, even with document.write.
|
|
* @version v2.0.8
|
|
* @see {@link https://krux.github.io/postscribe}
|
|
* @license MIT
|
|
* @author Derek Brans
|
|
* @copyright 2016 Krux Digital, Inc
|
|
*/
|
|
(function webpackUniversalModuleDefinition(root, factory) {
|
|
if(typeof exports === 'object' && typeof module === 'object')
|
|
module.exports = factory();
|
|
else if(typeof define === 'function' && define.amd)
|
|
define([], factory);
|
|
else if(typeof exports === 'object')
|
|
exports["advads_postscribe"] = factory();
|
|
root["advads_postscribe"] = factory();
|
|
})(this, function() {
|
|
return /******/ (function(modules) { // webpackBootstrap
|
|
/******/ // The module cache
|
|
/******/ var installedModules = {};
|
|
/******/
|
|
/******/ // The require function
|
|
/******/ function __webpack_require__(moduleId) {
|
|
/******/
|
|
/******/ // Check if module is in cache
|
|
/******/ if(installedModules[moduleId])
|
|
/******/ return installedModules[moduleId].exports;
|
|
/******/
|
|
/******/ // Create a new module (and put it into the cache)
|
|
/******/ var module = installedModules[moduleId] = {
|
|
/******/ exports: {},
|
|
/******/ id: moduleId,
|
|
/******/ loaded: false
|
|
/******/ };
|
|
/******/
|
|
/******/ // Execute the module function
|
|
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
|
/******/
|
|
/******/ // Flag the module as loaded
|
|
/******/ module.loaded = true;
|
|
/******/
|
|
/******/ // Return the exports of the module
|
|
/******/ return module.exports;
|
|
/******/ }
|
|
/******/
|
|
/******/
|
|
/******/ // expose the modules object (__webpack_modules__)
|
|
/******/ __webpack_require__.m = modules;
|
|
/******/
|
|
/******/ // expose the module cache
|
|
/******/ __webpack_require__.c = installedModules;
|
|
/******/
|
|
/******/ // __webpack_public_path__
|
|
/******/ __webpack_require__.p = "";
|
|
/******/
|
|
/******/ // Load entry module and return exports
|
|
/******/ return __webpack_require__(0);
|
|
/******/ })
|
|
/************************************************************************/
|
|
/******/ ([
|
|
/* 0 */
|
|
/***/ function(module, exports, __webpack_require__) {
|
|
|
|
'use strict';
|
|
|
|
var _postscribe = __webpack_require__(1);
|
|
|
|
var _postscribe2 = _interopRequireDefault(_postscribe);
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
|
|
|
|
module.exports = _postscribe2['default'];
|
|
|
|
/***/ },
|
|
/* 1 */
|
|
/***/ function(module, exports, __webpack_require__) {
|
|
|
|
'use strict';
|
|
|
|
exports.__esModule = true;
|
|
|
|
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
|
|
|
exports['default'] = postscribe;
|
|
|
|
var _writeStream = __webpack_require__(2);
|
|
|
|
var _writeStream2 = _interopRequireDefault(_writeStream);
|
|
|
|
var _utils = __webpack_require__(4);
|
|
|
|
var utils = _interopRequireWildcard(_utils);
|
|
|
|
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
|
|
|
|
/**
|
|
* A function that intentionally does nothing.
|
|
*/
|
|
function doNothing() {}
|
|
|
|
/**
|
|
* Available options and defaults.
|
|
*
|
|
* @type {Object}
|
|
*/
|
|
var OPTIONS = {
|
|
/**
|
|
* Called when an async script has loaded.
|
|
*/
|
|
afterAsync: doNothing,
|
|
|
|
/**
|
|
* Called immediately before removing from the write queue.
|
|
*/
|
|
afterDequeue: doNothing,
|
|
|
|
/**
|
|
* Called sync after a stream's first thread release.
|
|
*/
|
|
afterStreamStart: doNothing,
|
|
|
|
/**
|
|
* Called after writing buffered document.write calls.
|
|
*/
|
|
afterWrite: doNothing,
|
|
|
|
/**
|
|
* Allows disabling the autoFix feature of prescribe
|
|
*/
|
|
autoFix: true,
|
|
|
|
/**
|
|
* Called immediately before adding to the write queue.
|
|
*/
|
|
beforeEnqueue: doNothing,
|
|
|
|
/**
|
|
* Called before writing a token.
|
|
*
|
|
* @param {Object} tok The token
|
|
*/
|
|
beforeWriteToken: function beforeWriteToken(tok) {
|
|
return tok;
|
|
},
|
|
|
|
/**
|
|
* Called before writing buffered document.write calls.
|
|
*
|
|
* @param {String} str The string
|
|
*/
|
|
beforeWrite: function beforeWrite(str) {
|
|
return str;
|
|
},
|
|
|
|
/**
|
|
* Called when evaluation is finished.
|
|
*/
|
|
done: doNothing,
|
|
|
|
/**
|
|
* Called when a write results in an error.
|
|
*
|
|
* @param {Error} e The error
|
|
*/
|
|
error: function error(e) {
|
|
throw new Error(e.msg);
|
|
},
|
|
|
|
|
|
/**
|
|
* Whether to let scripts w/ async attribute set fall out of the queue.
|
|
*/
|
|
releaseAsync: false
|
|
};
|
|
|
|
var nextId = 0;
|
|
var queue = [];
|
|
var active = null;
|
|
|
|
function nextStream() {
|
|
var args = queue.shift();
|
|
if (args) {
|
|
var options = utils.last(args);
|
|
|
|
options.afterDequeue();
|
|
args.stream = runStream.apply(undefined, args);
|
|
options.afterStreamStart();
|
|
}
|
|
}
|
|
|
|
function runStream(el, html, options) {
|
|
active = new _writeStream2['default'](el, options);
|
|
|
|
// Identify this stream.
|
|
active.id = nextId++;
|
|
active.name = options.name || active.id;
|
|
postscribe.streams[active.name] = active;
|
|
|
|
// Override document.write.
|
|
var doc = el.ownerDocument;
|
|
|
|
var stash = {
|
|
close: doc.close,
|
|
open: doc.open,
|
|
write: doc.write,
|
|
writeln: doc.writeln
|
|
};
|
|
|
|
function _write(str) {
|
|
str = options.beforeWrite(str);
|
|
active.write(str);
|
|
options.afterWrite(str);
|
|
}
|
|
|
|
_extends(doc, {
|
|
close: doNothing,
|
|
open: doNothing,
|
|
write: function write() {
|
|
for (var _len = arguments.length, str = Array(_len), _key = 0; _key < _len; _key++) {
|
|
str[_key] = arguments[_key];
|
|
}
|
|
|
|
return _write(str.join(''));
|
|
},
|
|
writeln: function writeln() {
|
|
for (var _len2 = arguments.length, str = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
|
|
str[_key2] = arguments[_key2];
|
|
}
|
|
|
|
return _write(str.join('') + '\n');
|
|
}
|
|
});
|
|
|
|
// Override window.onerror
|
|
var oldOnError = active.win.onerror || doNothing;
|
|
|
|
// This works together with the try/catch around WriteStream::insertScript
|
|
// In modern browsers, exceptions in tag scripts go directly to top level
|
|
active.win.onerror = function (msg, url, line) {
|
|
options.error({ msg: msg + ' - ' + url + ': ' + line });
|
|
oldOnError.apply(active.win, [msg, url, line]);
|
|
};
|
|
|
|
// Write to the stream
|
|
active.write(html, function () {
|
|
// restore document.write
|
|
_extends(doc, stash);
|
|
|
|
// restore window.onerror
|
|
active.win.onerror = oldOnError;
|
|
|
|
options.done();
|
|
active = null;
|
|
nextStream();
|
|
});
|
|
|
|
return active;
|
|
}
|
|
|
|
function postscribe(el, html, options) {
|
|
if (utils.isFunction(options)) {
|
|
options = { done: options };
|
|
} else if (options === 'clear') {
|
|
queue = [];
|
|
active = null;
|
|
nextId = 0;
|
|
return;
|
|
}
|
|
|
|
options = utils.defaults(options, OPTIONS);
|
|
|
|
// id selector
|
|
if (/^#/.test(el)) {
|
|
el = window.document.getElementById(el.substr(1));
|
|
} else {
|
|
el = el.jquery ? el[0] : el;
|
|
}
|
|
|
|
var args = [el, html, options];
|
|
|
|
el.postscribe = {
|
|
cancel: function cancel() {
|
|
if (args.stream) {
|
|
args.stream.abort();
|
|
} else {
|
|
args[1] = doNothing;
|
|
}
|
|
}
|
|
};
|
|
|
|
options.beforeEnqueue(args);
|
|
queue.push(args);
|
|
|
|
if (!active) {
|
|
nextStream();
|
|
}
|
|
|
|
return el.postscribe;
|
|
}
|
|
|
|
_extends(postscribe, {
|
|
// Streams by name.
|
|
streams: {},
|
|
// Queue of streams.
|
|
queue: queue,
|
|
// Expose internal classes.
|
|
WriteStream: _writeStream2['default']
|
|
});
|
|
|
|
/***/ },
|
|
/* 2 */
|
|
/***/ function(module, exports, __webpack_require__) {
|
|
|
|
'use strict';
|
|
|
|
exports.__esModule = true;
|
|
|
|
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
|
|
|
|
var _prescribe = __webpack_require__(3);
|
|
|
|
var _prescribe2 = _interopRequireDefault(_prescribe);
|
|
|
|
var _utils = __webpack_require__(4);
|
|
|
|
var utils = _interopRequireWildcard(_utils);
|
|
|
|
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
|
|
|
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
|
|
/**
|
|
* Turn on to debug how each chunk affected the DOM.
|
|
* @type {boolean}
|
|
*/
|
|
var DEBUG_CHUNK = false;
|
|
|
|
/**
|
|
* Prefix for data attributes on DOM elements.
|
|
* @type {string}
|
|
*/
|
|
var BASEATTR = 'data-ps-';
|
|
|
|
/**
|
|
* ID for the style proxy
|
|
* @type {string}
|
|
*/
|
|
var PROXY_STYLE = 'ps-style';
|
|
|
|
/**
|
|
* ID for the script proxy
|
|
* @type {string}
|
|
*/
|
|
var PROXY_SCRIPT = 'ps-script';
|
|
|
|
/**
|
|
* Get data attributes
|
|
*
|
|
* @param {Object} el The DOM element.
|
|
* @param {String} name The attribute name.
|
|
* @returns {String}
|
|
*/
|
|
function getData(el, name) {
|
|
var attr = BASEATTR + name;
|
|
|
|
var val = el.getAttribute(attr);
|
|
|
|
// IE 8 returns a number if it's a number
|
|
return !utils.existy(val) ? val : String(val);
|
|
}
|
|
|
|
/**
|
|
* Set data attributes
|
|
*
|
|
* @param {Object} el The DOM element.
|
|
* @param {String} name The attribute name.
|
|
* @param {null|*} value The attribute value.
|
|
*/
|
|
function setData(el, name) {
|
|
var value = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
|
|
|
|
var attr = BASEATTR + name;
|
|
|
|
if (utils.existy(value) && value !== '') {
|
|
el.setAttribute(attr, value);
|
|
} else {
|
|
el.removeAttribute(attr);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Stream static html to an element, where "static html" denotes "html
|
|
* without scripts".
|
|
*
|
|
* This class maintains a *history of writes devoid of any attributes* or
|
|
* "proxy history".
|
|
*
|
|
* Injecting the proxy history into a temporary div has no side-effects,
|
|
* other than to create proxy elements for previously written elements.
|
|
*
|
|
* Given the `staticHtml` of a new write, a `tempDiv`'s innerHTML is set to
|
|
* `proxy_history + staticHtml`.
|
|
* The *structure* of `tempDiv`'s contents, (i.e., the placement of new nodes
|
|
* beside or inside of proxy elements), reflects the DOM structure that would
|
|
* have resulted if all writes had been squashed into a single write.
|
|
*
|
|
* For each descendent `node` of `tempDiv` whose parentNode is a *proxy*,
|
|
* `node` is appended to the corresponding *real* element within the DOM.
|
|
*
|
|
* Proxy elements are mapped to *actual* elements in the DOM by injecting a
|
|
* `data-id` attribute into each start tag in `staticHtml`.
|
|
*
|
|
*/
|
|
|
|
var WriteStream = function () {
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* @param {Object} root The root element
|
|
* @param {?Object} options The options
|
|
*/
|
|
function WriteStream(root) {
|
|
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
|
|
_classCallCheck(this, WriteStream);
|
|
|
|
this.root = root;
|
|
this.options = options;
|
|
this.doc = root.ownerDocument;
|
|
this.win = this.doc.defaultView || this.doc.parentWindow;
|
|
this.parser = new _prescribe2['default']('', { autoFix: options.autoFix });
|
|
|
|
// Actual elements by id.
|
|
this.actuals = [root];
|
|
|
|
// Embodies the "structure" of what's been written so far,
|
|
// devoid of attributes.
|
|
this.proxyHistory = '';
|
|
|
|
// Create a proxy of the root element.
|
|
this.proxyRoot = this.doc.createElement(root.nodeName);
|
|
|
|
this.scriptStack = [];
|
|
this.writeQueue = [];
|
|
|
|
setData(this.proxyRoot, 'proxyof', 0);
|
|
}
|
|
|
|
/**
|
|
* Writes the given strings.
|
|
*
|
|
* @param {...String} str The strings to write
|
|
*/
|
|
|
|
|
|
WriteStream.prototype.write = function write() {
|
|
var _writeQueue;
|
|
|
|
(_writeQueue = this.writeQueue).push.apply(_writeQueue, arguments);
|
|
|
|
// Process writes
|
|
// When new script gets pushed or pending this will stop
|
|
// because new writeQueue gets pushed
|
|
while (!this.deferredRemote && this.writeQueue.length) {
|
|
var arg = this.writeQueue.shift();
|
|
|
|
if (utils.isFunction(arg)) {
|
|
this._callFunction(arg);
|
|
} else {
|
|
this._writeImpl(arg);
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Calls the given function.
|
|
*
|
|
* @param {Function} fn The function to call
|
|
* @private
|
|
*/
|
|
|
|
|
|
WriteStream.prototype._callFunction = function _callFunction(fn) {
|
|
var tok = { type: 'function', value: fn.name || fn.toString() };
|
|
this._onScriptStart(tok);
|
|
fn.call(this.win, this.doc);
|
|
this._onScriptDone(tok);
|
|
};
|
|
|
|
/**
|
|
* The write implementation
|
|
*
|
|
* @param {String} html The HTML to write.
|
|
* @private
|
|
*/
|
|
|
|
|
|
WriteStream.prototype._writeImpl = function _writeImpl(html) {
|
|
this.parser.append(html);
|
|
|
|
var tok = void 0;
|
|
var script = void 0;
|
|
var style = void 0;
|
|
var tokens = [];
|
|
|
|
// stop if we see a script token
|
|
while ((tok = this.parser.readToken()) && !(script = utils.isScript(tok)) && !(style = utils.isStyle(tok))) {
|
|
tok = this.options.beforeWriteToken(tok);
|
|
|
|
if (tok) {
|
|
tokens.push(tok);
|
|
}
|
|
}
|
|
|
|
if (tokens.length > 0) {
|
|
this._writeStaticTokens(tokens);
|
|
}
|
|
|
|
if (script) {
|
|
this._handleScriptToken(tok);
|
|
}
|
|
|
|
if (style) {
|
|
this._handleStyleToken(tok);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Write contiguous non-script tokens (a chunk)
|
|
*
|
|
* @param {Array<Object>} tokens The tokens
|
|
* @returns {{tokens, raw, actual, proxy}|null}
|
|
* @private
|
|
*/
|
|
|
|
|
|
WriteStream.prototype._writeStaticTokens = function _writeStaticTokens(tokens) {
|
|
var chunk = this._buildChunk(tokens);
|
|
|
|
if (!chunk.actual) {
|
|
// e.g., no tokens, or a noscript that got ignored
|
|
return null;
|
|
}
|
|
|
|
chunk.html = this.proxyHistory + chunk.actual;
|
|
this.proxyHistory += chunk.proxy;
|
|
this.proxyRoot.innerHTML = chunk.html;
|
|
|
|
if (DEBUG_CHUNK) {
|
|
chunk.proxyInnerHTML = this.proxyRoot.innerHTML;
|
|
}
|
|
|
|
this._walkChunk();
|
|
|
|
if (DEBUG_CHUNK) {
|
|
chunk.actualInnerHTML = this.root.innerHTML;
|
|
}
|
|
|
|
return chunk;
|
|
};
|
|
|
|
/**
|
|
* Build a chunk.
|
|
*
|
|
* @param {Array<Object>} tokens The tokens to use.
|
|
* @returns {{tokens: *, raw: string, actual: string, proxy: string}}
|
|
* @private
|
|
*/
|
|
|
|
|
|
WriteStream.prototype._buildChunk = function _buildChunk(tokens) {
|
|
var nextId = this.actuals.length;
|
|
|
|
// The raw html of this chunk.
|
|
var raw = [];
|
|
|
|
// The html to create the nodes in the tokens (with id's injected).
|
|
var actual = [];
|
|
|
|
// Html that can later be used to proxy the nodes in the tokens.
|
|
var proxy = [];
|
|
|
|
var len = tokens.length;
|
|
for (var i = 0; i < len; i++) {
|
|
var tok = tokens[i];
|
|
var tokenRaw = tok.toString();
|
|
|
|
raw.push(tokenRaw);
|
|
|
|
if (tok.attrs) {
|
|
// tok.attrs <==> startTag or atomicTag or cursor
|
|
// Ignore noscript tags. They are atomic, so we don't have to worry about children.
|
|
if (!/^noscript$/i.test(tok.tagName)) {
|
|
var id = nextId++;
|
|
|
|
// Actual: inject id attribute: replace '>' at end of start tag with id attribute + '>'
|
|
actual.push(tokenRaw.replace(/(\/?>)/, ' ' + BASEATTR + 'id=' + id + ' $1'));
|
|
|
|
// Don't proxy scripts: they have no bearing on DOM structure.
|
|
if (tok.attrs.id !== PROXY_SCRIPT && tok.attrs.id !== PROXY_STYLE) {
|
|
// Proxy: strip all attributes and inject proxyof attribute
|
|
proxy.push(
|
|
// ignore atomic tags (e.g., style): they have no "structural" effect
|
|
tok.type === 'atomicTag' ? '' : '<' + tok.tagName + ' ' + BASEATTR + 'proxyof=' + id + (tok.unary ? ' />' : '>'));
|
|
}
|
|
}
|
|
} else {
|
|
// Visit any other type of token
|
|
// Actual: append.
|
|
actual.push(tokenRaw);
|
|
|
|
// Proxy: append endTags. Ignore everything else.
|
|
proxy.push(tok.type === 'endTag' ? tokenRaw : '');
|
|
}
|
|
}
|
|
|
|
return {
|
|
tokens: tokens,
|
|
raw: raw.join(''),
|
|
actual: actual.join(''),
|
|
proxy: proxy.join('')
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Walk the chunks.
|
|
*
|
|
* @private
|
|
*/
|
|
|
|
|
|
WriteStream.prototype._walkChunk = function _walkChunk() {
|
|
var node = void 0;
|
|
var stack = [this.proxyRoot];
|
|
|
|
// use shift/unshift so that children are walked in document order
|
|
while (utils.existy(node = stack.shift())) {
|
|
var isElement = node.nodeType === 1;
|
|
var isProxy = isElement && getData(node, 'proxyof');
|
|
|
|
// Ignore proxies
|
|
if (!isProxy) {
|
|
if (isElement) {
|
|
// New actual element: register it and remove the the id attr.
|
|
this.actuals[getData(node, 'id')] = node;
|
|
setData(node, 'id');
|
|
}
|
|
|
|
// Is node's parent a proxy?
|
|
var parentIsProxyOf = node.parentNode && getData(node.parentNode, 'proxyof');
|
|
if (parentIsProxyOf) {
|
|
// Move node under actual parent.
|
|
this.actuals[parentIsProxyOf].appendChild(node);
|
|
}
|
|
}
|
|
|
|
// prepend childNodes to stack
|
|
stack.unshift.apply(stack, utils.toArray(node.childNodes));
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Handles Script tokens
|
|
*
|
|
* @param {Object} tok The token
|
|
*/
|
|
|
|
|
|
WriteStream.prototype._handleScriptToken = function _handleScriptToken(tok) {
|
|
var _this = this;
|
|
|
|
var remainder = this.parser.clear();
|
|
|
|
if (remainder) {
|
|
// Write remainder immediately behind this script.
|
|
this.writeQueue.unshift(remainder);
|
|
}
|
|
|
|
tok.src = tok.attrs.src || tok.attrs.SRC;
|
|
|
|
tok = this.options.beforeWriteToken(tok);
|
|
if (!tok) {
|
|
// User has removed this token
|
|
return;
|
|
}
|
|
|
|
if (tok.src && this.scriptStack.length) {
|
|
// Defer this script until scriptStack is empty.
|
|
// Assumption 1: This script will not start executing until
|
|
// scriptStack is empty.
|
|
this.deferredRemote = tok;
|
|
} else {
|
|
this._onScriptStart(tok);
|
|
}
|
|
|
|
// Put the script node in the DOM.
|
|
this._writeScriptToken(tok, function () {
|
|
_this._onScriptDone(tok);
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Handles style tokens
|
|
*
|
|
* @param {Object} tok The token
|
|
*/
|
|
|
|
|
|
WriteStream.prototype._handleStyleToken = function _handleStyleToken(tok) {
|
|
var remainder = this.parser.clear();
|
|
|
|
if (remainder) {
|
|
// Write remainder immediately behind this style.
|
|
this.writeQueue.unshift(remainder);
|
|
}
|
|
|
|
tok.type = tok.attrs.type || tok.attrs.TYPE || 'text/css';
|
|
|
|
tok = this.options.beforeWriteToken(tok);
|
|
|
|
if (tok) {
|
|
// Put the style node in the DOM.
|
|
this._writeStyleToken(tok);
|
|
}
|
|
|
|
if (remainder) {
|
|
this.write();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Build a style and insert it into the DOM.
|
|
*
|
|
* @param {Object} tok The token
|
|
*/
|
|
|
|
|
|
WriteStream.prototype._writeStyleToken = function _writeStyleToken(tok) {
|
|
var el = this._buildStyle(tok);
|
|
|
|
this._insertCursor(el, PROXY_STYLE);
|
|
|
|
// Set content
|
|
if (tok.content) {
|
|
if (el.styleSheet && !el.sheet) {
|
|
el.styleSheet.cssText = tok.content;
|
|
} else {
|
|
el.appendChild(this.doc.createTextNode(tok.content));
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Build a style element from an atomic style token.
|
|
*
|
|
* @param {Object} tok The token
|
|
* @returns {Element}
|
|
*/
|
|
|
|
|
|
WriteStream.prototype._buildStyle = function _buildStyle(tok) {
|
|
var el = this.doc.createElement(tok.tagName);
|
|
|
|
el.setAttribute('type', tok.type);
|
|
|
|
// Set attributes
|
|
utils.eachKey(tok.attrs, function (name, value) {
|
|
el.setAttribute(name, value);
|
|
});
|
|
|
|
return el;
|
|
};
|
|
|
|
/**
|
|
* Append a span to the stream. That span will act as a cursor
|
|
* (i.e. insertion point) for the element.
|
|
*
|
|
* @param {Object} el The element
|
|
* @param {string} which The type of proxy element
|
|
*/
|
|
|
|
|
|
WriteStream.prototype._insertCursor = function _insertCursor(el, which) {
|
|
this._writeImpl('<span id="' + which + '"/>');
|
|
|
|
var cursor = this.doc.getElementById(which);
|
|
|
|
if (cursor) {
|
|
cursor.parentNode.replaceChild(el, cursor);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Called when a script is started.
|
|
*
|
|
* @param {Object} tok The token
|
|
* @private
|
|
*/
|
|
|
|
|
|
WriteStream.prototype._onScriptStart = function _onScriptStart(tok) {
|
|
tok.outerWrites = this.writeQueue;
|
|
this.writeQueue = [];
|
|
this.scriptStack.unshift(tok);
|
|
};
|
|
|
|
/**
|
|
* Called when a script is done.
|
|
*
|
|
* @param {Object} tok The token
|
|
* @private
|
|
*/
|
|
|
|
|
|
WriteStream.prototype._onScriptDone = function _onScriptDone(tok) {
|
|
// Pop script and check nesting.
|
|
if (tok !== this.scriptStack[0]) {
|
|
this.options.error({ msg: 'Bad script nesting or script finished twice' });
|
|
return;
|
|
}
|
|
|
|
this.scriptStack.shift();
|
|
|
|
// Append outer writes to queue and process them.
|
|
this.write.apply(this, tok.outerWrites);
|
|
|
|
// Check for pending remote
|
|
|
|
// Assumption 2: if remote_script1 writes remote_script2 then
|
|
// the we notice remote_script1 finishes before remote_script2 starts.
|
|
// I think this is equivalent to assumption 1
|
|
if (!this.scriptStack.length && this.deferredRemote) {
|
|
this._onScriptStart(this.deferredRemote);
|
|
this.deferredRemote = null;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Build a script and insert it into the DOM.
|
|
* Done is called once script has executed.
|
|
*
|
|
* @param {Object} tok The token
|
|
* @param {Function} done The callback when complete
|
|
*/
|
|
|
|
|
|
WriteStream.prototype._writeScriptToken = function _writeScriptToken(tok, done) {
|
|
var el = this._buildScript(tok);
|
|
var asyncRelease = this._shouldRelease(el);
|
|
var afterAsync = this.options.afterAsync;
|
|
|
|
if (tok.src) {
|
|
// Fix for attribute "SRC" (capitalized). IE does not recognize it.
|
|
el.src = tok.src;
|
|
this._scriptLoadHandler(el, !asyncRelease ? function () {
|
|
done();
|
|
afterAsync();
|
|
} : afterAsync);
|
|
}
|
|
|
|
try {
|
|
this._insertCursor(el, PROXY_SCRIPT);
|
|
if (!el.src || asyncRelease) {
|
|
done();
|
|
}
|
|
} catch (e) {
|
|
this.options.error(e);
|
|
done();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Build a script element from an atomic script token.
|
|
*
|
|
* @param {Object} tok The token
|
|
* @returns {Element}
|
|
*/
|
|
|
|
|
|
WriteStream.prototype._buildScript = function _buildScript(tok) {
|
|
var el = this.doc.createElement(tok.tagName);
|
|
|
|
// Set attributes
|
|
utils.eachKey(tok.attrs, function (name, value) {
|
|
el.setAttribute(name, value);
|
|
});
|
|
|
|
// Set content
|
|
if (tok.content) {
|
|
el.text = tok.content;
|
|
}
|
|
|
|
return el;
|
|
};
|
|
|
|
/**
|
|
* Setup the script load handler on an element.
|
|
*
|
|
* @param {Object} el The element
|
|
* @param {Function} done The callback
|
|
* @private
|
|
*/
|
|
|
|
|
|
WriteStream.prototype._scriptLoadHandler = function _scriptLoadHandler(el, done) {
|
|
function cleanup() {
|
|
el = el.onload = el.onreadystatechange = el.onerror = null;
|
|
}
|
|
|
|
var error = this.options.error;
|
|
|
|
function success() {
|
|
cleanup();
|
|
if (done != null) {
|
|
done();
|
|
}
|
|
done = null;
|
|
}
|
|
|
|
function failure(err) {
|
|
cleanup();
|
|
error(err);
|
|
if (done != null) {
|
|
done();
|
|
}
|
|
done = null;
|
|
}
|
|
|
|
function reattachEventListener(el, evt) {
|
|
var handler = el['on' + evt];
|
|
if (handler != null) {
|
|
el['_on' + evt] = handler;
|
|
}
|
|
}
|
|
|
|
reattachEventListener(el, 'load');
|
|
reattachEventListener(el, 'error');
|
|
|
|
_extends(el, {
|
|
onload: function onload() {
|
|
if (el._onload) {
|
|
try {
|
|
el._onload.apply(this, Array.prototype.slice.call(arguments, 0));
|
|
} catch (err) {
|
|
failure({ msg: 'onload handler failed ' + err + ' @ ' + el.src });
|
|
}
|
|
}
|
|
success();
|
|
},
|
|
onerror: function onerror() {
|
|
if (el._onerror) {
|
|
try {
|
|
el._onerror.apply(this, Array.prototype.slice.call(arguments, 0));
|
|
} catch (err) {
|
|
failure({ msg: 'onerror handler failed ' + err + ' @ ' + el.src });
|
|
return;
|
|
}
|
|
}
|
|
failure({ msg: 'remote script failed ' + el.src });
|
|
},
|
|
onreadystatechange: function onreadystatechange() {
|
|
if (/^(loaded|complete)$/.test(el.readyState)) {
|
|
success();
|
|
}
|
|
}
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Determines whether to release.
|
|
*
|
|
* @param {Object} el The element
|
|
* @returns {boolean}
|
|
* @private
|
|
*/
|
|
|
|
|
|
WriteStream.prototype._shouldRelease = function _shouldRelease(el) {
|
|
var isScript = /^script$/i.test(el.nodeName);
|
|
return !isScript || !!(this.options.releaseAsync && el.src && el.hasAttribute('async'));
|
|
};
|
|
|
|
return WriteStream;
|
|
}();
|
|
|
|
exports['default'] = WriteStream;
|
|
|
|
/***/ },
|
|
/* 3 */
|
|
/***/ function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @file prescribe
|
|
* @description Tiny, forgiving HTML parser
|
|
* @version vundefined
|
|
* @see {@link https://github.com/krux/prescribe/}
|
|
* @license MIT
|
|
* @author Derek Brans
|
|
* @copyright 2016 Krux Digital, Inc
|
|
*/
|
|
(function webpackUniversalModuleDefinition(root, factory) {
|
|
if(true)
|
|
module.exports = factory();
|
|
else if(typeof define === 'function' && define.amd)
|
|
define([], factory);
|
|
else if(typeof exports === 'object')
|
|
exports["Prescribe"] = factory();
|
|
else
|
|
root["Prescribe"] = factory();
|
|
})(this, function() {
|
|
return /******/ (function(modules) { // webpackBootstrap
|
|
/******/ // The module cache
|
|
/******/ var installedModules = {};
|
|
|
|
/******/ // The require function
|
|
/******/ function __webpack_require__(moduleId) {
|
|
|
|
/******/ // Check if module is in cache
|
|
/******/ if(installedModules[moduleId])
|
|
/******/ return installedModules[moduleId].exports;
|
|
|
|
/******/ // Create a new module (and put it into the cache)
|
|
/******/ var module = installedModules[moduleId] = {
|
|
/******/ exports: {},
|
|
/******/ id: moduleId,
|
|
/******/ loaded: false
|
|
/******/ };
|
|
|
|
/******/ // Execute the module function
|
|
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
|
|
|
/******/ // Flag the module as loaded
|
|
/******/ module.loaded = true;
|
|
|
|
/******/ // Return the exports of the module
|
|
/******/ return module.exports;
|
|
/******/ }
|
|
|
|
|
|
/******/ // expose the modules object (__webpack_modules__)
|
|
/******/ __webpack_require__.m = modules;
|
|
|
|
/******/ // expose the module cache
|
|
/******/ __webpack_require__.c = installedModules;
|
|
|
|
/******/ // __webpack_public_path__
|
|
/******/ __webpack_require__.p = "";
|
|
|
|
/******/ // Load entry module and return exports
|
|
/******/ return __webpack_require__(0);
|
|
/******/ })
|
|
/************************************************************************/
|
|
/******/ ([
|
|
/* 0 */
|
|
/***/ function(module, exports, __webpack_require__) {
|
|
|
|
'use strict';
|
|
|
|
var _HtmlParser = __webpack_require__(1);
|
|
|
|
var _HtmlParser2 = _interopRequireDefault(_HtmlParser);
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
|
|
|
|
module.exports = _HtmlParser2['default'];
|
|
|
|
/***/ },
|
|
/* 1 */
|
|
/***/ function(module, exports, __webpack_require__) {
|
|
|
|
'use strict';
|
|
|
|
exports.__esModule = true;
|
|
|
|
var _supports = __webpack_require__(2);
|
|
|
|
var supports = _interopRequireWildcard(_supports);
|
|
|
|
var _streamReaders = __webpack_require__(3);
|
|
|
|
var streamReaders = _interopRequireWildcard(_streamReaders);
|
|
|
|
var _fixedReadTokenFactory = __webpack_require__(6);
|
|
|
|
var _fixedReadTokenFactory2 = _interopRequireDefault(_fixedReadTokenFactory);
|
|
|
|
var _utils = __webpack_require__(5);
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
|
|
|
|
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj['default'] = obj; return newObj; } }
|
|
|
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
|
|
/**
|
|
* Detection regular expressions.
|
|
*
|
|
* Order of detection matters: detection of one can only
|
|
* succeed if detection of previous didn't
|
|
|
|
* @type {Object}
|
|
*/
|
|
var detect = {
|
|
comment: /^<!--/,
|
|
endTag: /^<\//,
|
|
atomicTag: /^<\s*(script|style|noscript|iframe|textarea)[\s\/>]/i,
|
|
startTag: /^</,
|
|
chars: /^[^<]/
|
|
};
|
|
|
|
/**
|
|
* HtmlParser provides the capability to parse HTML and return tokens
|
|
* representing the tags and content.
|
|
*/
|
|
|
|
var HtmlParser = function () {
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* @param {string} stream The initial parse stream contents.
|
|
* @param {Object} options The options
|
|
* @param {boolean} options.autoFix Set to true to automatically fix errors
|
|
*/
|
|
function HtmlParser() {
|
|
var _this = this;
|
|
|
|
var stream = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
|
|
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
|
|
_classCallCheck(this, HtmlParser);
|
|
|
|
this.stream = stream;
|
|
|
|
var fix = false;
|
|
var fixedTokenOptions = {};
|
|
|
|
for (var key in supports) {
|
|
if (supports.hasOwnProperty(key)) {
|
|
if (options.autoFix) {
|
|
fixedTokenOptions[key + 'Fix'] = true; // !supports[key];
|
|
}
|
|
fix = fix || fixedTokenOptions[key + 'Fix'];
|
|
}
|
|
}
|
|
|
|
if (fix) {
|
|
this._readToken = (0, _fixedReadTokenFactory2['default'])(this, fixedTokenOptions, function () {
|
|
return _this._readTokenImpl();
|
|
});
|
|
this._peekToken = (0, _fixedReadTokenFactory2['default'])(this, fixedTokenOptions, function () {
|
|
return _this._peekTokenImpl();
|
|
});
|
|
} else {
|
|
this._readToken = this._readTokenImpl;
|
|
this._peekToken = this._peekTokenImpl;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Appends the given string to the parse stream.
|
|
*
|
|
* @param {string} str The string to append
|
|
*/
|
|
|
|
|
|
HtmlParser.prototype.append = function append(str) {
|
|
this.stream += str;
|
|
};
|
|
|
|
/**
|
|
* Prepends the given string to the parse stream.
|
|
*
|
|
* @param {string} str The string to prepend
|
|
*/
|
|
|
|
|
|
HtmlParser.prototype.prepend = function prepend(str) {
|
|
this.stream = str + this.stream;
|
|
};
|
|
|
|
/**
|
|
* The implementation of the token reading.
|
|
*
|
|
* @private
|
|
* @returns {?Token}
|
|
*/
|
|
|
|
|
|
HtmlParser.prototype._readTokenImpl = function _readTokenImpl() {
|
|
var token = this._peekTokenImpl();
|
|
if (token) {
|
|
this.stream = this.stream.slice(token.length);
|
|
return token;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* The implementation of token peeking.
|
|
*
|
|
* @returns {?Token}
|
|
*/
|
|
|
|
|
|
HtmlParser.prototype._peekTokenImpl = function _peekTokenImpl() {
|
|
for (var type in detect) {
|
|
if (detect.hasOwnProperty(type)) {
|
|
if (detect[type].test(this.stream)) {
|
|
var token = streamReaders[type](this.stream);
|
|
|
|
if (token) {
|
|
if (token.type === 'startTag' && /script|style/i.test(token.tagName)) {
|
|
return null;
|
|
} else {
|
|
token.text = this.stream.substr(0, token.length);
|
|
return token;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* The public token peeking interface. Delegates to the basic token peeking
|
|
* or a version that performs fixups depending on the `autoFix` setting in
|
|
* options.
|
|
*
|
|
* @returns {object}
|
|
*/
|
|
|
|
|
|
HtmlParser.prototype.peekToken = function peekToken() {
|
|
return this._peekToken();
|
|
};
|
|
|
|
/**
|
|
* The public token reading interface. Delegates to the basic token reading
|
|
* or a version that performs fixups depending on the `autoFix` setting in
|
|
* options.
|
|
*
|
|
* @returns {object}
|
|
*/
|
|
|
|
|
|
HtmlParser.prototype.readToken = function readToken() {
|
|
return this._readToken();
|
|
};
|
|
|
|
/**
|
|
* Read tokens and hand to the given handlers.
|
|
*
|
|
* @param {Object} handlers The handlers to use for the different tokens.
|
|
*/
|
|
|
|
|
|
HtmlParser.prototype.readTokens = function readTokens(handlers) {
|
|
var tok = void 0;
|
|
while (tok = this.readToken()) {
|
|
// continue until we get an explicit "false" return
|
|
if (handlers[tok.type] && handlers[tok.type](tok) === false) {
|
|
return;
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Clears the parse stream.
|
|
*
|
|
* @returns {string} The contents of the parse stream before clearing.
|
|
*/
|
|
|
|
|
|
HtmlParser.prototype.clear = function clear() {
|
|
var rest = this.stream;
|
|
this.stream = '';
|
|
return rest;
|
|
};
|
|
|
|
/**
|
|
* Returns the rest of the parse stream.
|
|
*
|
|
* @returns {string} The contents of the parse stream.
|
|
*/
|
|
|
|
|
|
HtmlParser.prototype.rest = function rest() {
|
|
return this.stream;
|
|
};
|
|
|
|
return HtmlParser;
|
|
}();
|
|
|
|
exports['default'] = HtmlParser;
|
|
|
|
|
|
HtmlParser.tokenToString = function (tok) {
|
|
return tok.toString();
|
|
};
|
|
|
|
HtmlParser.escapeAttributes = function (attrs) {
|
|
var escapedAttrs = {};
|
|
|
|
for (var name in attrs) {
|
|
if (attrs.hasOwnProperty(name)) {
|
|
escapedAttrs[name] = (0, _utils.escapeQuotes)(attrs[name], null);
|
|
}
|
|
}
|
|
|
|
return escapedAttrs;
|
|
};
|
|
|
|
HtmlParser.supports = supports;
|
|
|
|
for (var key in supports) {
|
|
if (supports.hasOwnProperty(key)) {
|
|
HtmlParser.browserHasFlaw = HtmlParser.browserHasFlaw || !supports[key] && key;
|
|
}
|
|
}
|
|
|
|
/***/ },
|
|
/* 2 */
|
|
/***/ function(module, exports) {
|
|
|
|
'use strict';
|
|
|
|
exports.__esModule = true;
|
|
var tagSoup = false;
|
|
var selfClose = false;
|
|
|
|
var work = window.document.createElement('div');
|
|
|
|
try {
|
|
var html = '<P><I></P></I>';
|
|
work.innerHTML = html;
|
|
exports.tagSoup = tagSoup = work.innerHTML !== html;
|
|
} catch (e) {
|
|
exports.tagSoup = tagSoup = false;
|
|
}
|
|
|
|
try {
|
|
work.innerHTML = '<P><i><P></P></i></P>';
|
|
exports.selfClose = selfClose = work.childNodes.length === 2;
|
|
} catch (e) {
|
|
exports.selfClose = selfClose = false;
|
|
}
|
|
|
|
work = null;
|
|
|
|
exports.tagSoup = tagSoup;
|
|
exports.selfClose = selfClose;
|
|
|
|
/***/ },
|
|
/* 3 */
|
|
/***/ function(module, exports, __webpack_require__) {
|
|
|
|
'use strict';
|
|
|
|
exports.__esModule = true;
|
|
|
|
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
|
|
|
|
exports.comment = comment;
|
|
exports.chars = chars;
|
|
exports.startTag = startTag;
|
|
exports.atomicTag = atomicTag;
|
|
exports.endTag = endTag;
|
|
|
|
var _tokens = __webpack_require__(4);
|
|
|
|
/**
|
|
* Regular Expressions for parsing tags and attributes
|
|
*
|
|
* @type {Object}
|
|
*/
|
|
var REGEXES = {
|
|
startTag: /^<([\-A-Za-z0-9_]+)((?:\s+[\w\-]+(?:\s*=?\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/,
|
|
endTag: /^<\/([\-A-Za-z0-9_]+)[^>]*>/,
|
|
attr: /(?:([\-A-Za-z0-9_]+)\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))|(?:([\-A-Za-z0-9_]+)(\s|$)+)/g,
|
|
fillAttr: /^(checked|compact|declare|defer|disabled|ismap|multiple|nohref|noresize|noshade|nowrap|readonly|selected)$/i
|
|
};
|
|
|
|
/**
|
|
* Reads a comment token
|
|
*
|
|
* @param {string} stream The input stream
|
|
* @returns {CommentToken}
|
|
*/
|
|
function comment(stream) {
|
|
var index = stream.indexOf('-->');
|
|
if (index >= 0) {
|
|
return new _tokens.CommentToken(stream.substr(4, index - 1), index + 3);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reads non-tag characters.
|
|
*
|
|
* @param {string} stream The input stream
|
|
* @returns {CharsToken}
|
|
*/
|
|
function chars(stream) {
|
|
var index = stream.indexOf('<');
|
|
return new _tokens.CharsToken(index >= 0 ? index : stream.length);
|
|
}
|
|
|
|
/**
|
|
* Reads start tag token.
|
|
*
|
|
* @param {string} stream The input stream
|
|
* @returns {StartTagToken}
|
|
*/
|
|
function startTag(stream) {
|
|
var endTagIndex = stream.indexOf('>');
|
|
if (endTagIndex !== -1) {
|
|
var match = stream.match(REGEXES.startTag);
|
|
if (match) {
|
|
var _ret = function () {
|
|
var attrs = {};
|
|
var booleanAttrs = {};
|
|
var rest = match[2];
|
|
|
|
match[2].replace(REGEXES.attr, function (match, name) {
|
|
if (!(arguments[2] || arguments[3] || arguments[4] || arguments[5])) {
|
|
attrs[name] = '';
|
|
} else if (arguments[5]) {
|
|
attrs[arguments[5]] = '';
|
|
booleanAttrs[arguments[5]] = true;
|
|
} else {
|
|
attrs[name] = arguments[2] || arguments[3] || arguments[4] || REGEXES.fillAttr.test(name) && name || '';
|
|
}
|
|
|
|
rest = rest.replace(match, '');
|
|
});
|
|
|
|
return {
|
|
v: new _tokens.StartTagToken(match[1], match[0].length, attrs, booleanAttrs, !!match[3], rest.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''))
|
|
};
|
|
}();
|
|
|
|
if ((typeof _ret === 'undefined' ? 'undefined' : _typeof(_ret)) === "object") return _ret.v;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reads atomic tag token.
|
|
*
|
|
* @param {string} stream The input stream
|
|
* @returns {AtomicTagToken}
|
|
*/
|
|
function atomicTag(stream) {
|
|
var start = startTag(stream);
|
|
if (start) {
|
|
var rest = stream.slice(start.length);
|
|
// for optimization, we check first just for the end tag
|
|
if (rest.match(new RegExp('<\/\\s*' + start.tagName + '\\s*>', 'i'))) {
|
|
// capturing the content is inefficient, so we do it inside the if
|
|
var match = rest.match(new RegExp('([\\s\\S]*?)<\/\\s*' + start.tagName + '\\s*>', 'i'));
|
|
if (match) {
|
|
return new _tokens.AtomicTagToken(start.tagName, match[0].length + start.length, start.attrs, start.booleanAttrs, match[1]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Reads an end tag token.
|
|
*
|
|
* @param {string} stream The input stream
|
|
* @returns {EndTagToken}
|
|
*/
|
|
function endTag(stream) {
|
|
var match = stream.match(REGEXES.endTag);
|
|
if (match) {
|
|
return new _tokens.EndTagToken(match[1], match[0].length);
|
|
}
|
|
}
|
|
|
|
/***/ },
|
|
/* 4 */
|
|
/***/ function(module, exports, __webpack_require__) {
|
|
|
|
'use strict';
|
|
|
|
exports.__esModule = true;
|
|
exports.EndTagToken = exports.AtomicTagToken = exports.StartTagToken = exports.TagToken = exports.CharsToken = exports.CommentToken = exports.Token = undefined;
|
|
|
|
var _utils = __webpack_require__(5);
|
|
|
|
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
|
|
/**
|
|
* Token is a base class for all token types parsed. Note we don't actually
|
|
* use intheritance due to IE8's non-existent ES5 support.
|
|
*/
|
|
var Token =
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* @param {string} type The type of the Token.
|
|
* @param {Number} length The length of the Token text.
|
|
*/
|
|
exports.Token = function Token(type, length) {
|
|
_classCallCheck(this, Token);
|
|
|
|
this.type = type;
|
|
this.length = length;
|
|
this.text = '';
|
|
};
|
|
|
|
/**
|
|
* CommentToken represents comment tags.
|
|
*/
|
|
|
|
|
|
var CommentToken = exports.CommentToken = function () {
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* @param {string} content The content of the comment
|
|
* @param {Number} length The length of the Token text.
|
|
*/
|
|
function CommentToken(content, length) {
|
|
_classCallCheck(this, CommentToken);
|
|
|
|
this.type = 'comment';
|
|
this.length = length || (content ? content.length : 0);
|
|
this.text = '';
|
|
this.content = content;
|
|
}
|
|
|
|
CommentToken.prototype.toString = function toString() {
|
|
return '<!--' + this.content;
|
|
};
|
|
|
|
return CommentToken;
|
|
}();
|
|
|
|
/**
|
|
* CharsToken represents non-tag characters.
|
|
*/
|
|
|
|
|
|
var CharsToken = exports.CharsToken = function () {
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* @param {Number} length The length of the Token text.
|
|
*/
|
|
function CharsToken(length) {
|
|
_classCallCheck(this, CharsToken);
|
|
|
|
this.type = 'chars';
|
|
this.length = length;
|
|
this.text = '';
|
|
}
|
|
|
|
CharsToken.prototype.toString = function toString() {
|
|
return this.text;
|
|
};
|
|
|
|
return CharsToken;
|
|
}();
|
|
|
|
/**
|
|
* TagToken is a base class for all tag-based Tokens.
|
|
*/
|
|
|
|
|
|
var TagToken = exports.TagToken = function () {
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* @param {string} type The type of the token.
|
|
* @param {string} tagName The tag name.
|
|
* @param {Number} length The length of the Token text.
|
|
* @param {Object} attrs The dictionary of attributes and values
|
|
* @param {Object} booleanAttrs If an entry has 'true' then the attribute
|
|
* is a boolean attribute
|
|
*/
|
|
function TagToken(type, tagName, length, attrs, booleanAttrs) {
|
|
_classCallCheck(this, TagToken);
|
|
|
|
this.type = type;
|
|
this.length = length;
|
|
this.text = '';
|
|
this.tagName = tagName;
|
|
this.attrs = attrs;
|
|
this.booleanAttrs = booleanAttrs;
|
|
this.unary = false;
|
|
this.html5Unary = false;
|
|
}
|
|
|
|
/**
|
|
* Formats the given token tag.
|
|
*
|
|
* @param {TagToken} tok The TagToken to format.
|
|
* @param {?string} [content=null] The content of the token.
|
|
* @returns {string} The formatted tag.
|
|
*/
|
|
|
|
|
|
TagToken.formatTag = function formatTag(tok) {
|
|
var content = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
|
|
var str = '<' + tok.tagName;
|
|
for (var key in tok.attrs) {
|
|
if (tok.attrs.hasOwnProperty(key)) {
|
|
str += ' ' + key;
|
|
|
|
var val = tok.attrs[key];
|
|
if (typeof tok.booleanAttrs === 'undefined' || typeof tok.booleanAttrs[key] === 'undefined') {
|
|
str += '="' + (0, _utils.escapeQuotes)(val) + '"';
|
|
}
|
|
}
|
|
}
|
|
|
|
if (tok.rest) {
|
|
str += ' ' + tok.rest;
|
|
}
|
|
|
|
if (tok.unary && !tok.html5Unary) {
|
|
str += '/>';
|
|
} else {
|
|
str += '>';
|
|
}
|
|
|
|
if (content !== undefined && content !== null) {
|
|
str += content + '</' + tok.tagName + '>';
|
|
}
|
|
|
|
return str;
|
|
};
|
|
|
|
return TagToken;
|
|
}();
|
|
|
|
/**
|
|
* StartTagToken represents a start token.
|
|
*/
|
|
|
|
|
|
var StartTagToken = exports.StartTagToken = function () {
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* @param {string} tagName The tag name.
|
|
* @param {Number} length The length of the Token text
|
|
* @param {Object} attrs The dictionary of attributes and values
|
|
* @param {Object} booleanAttrs If an entry has 'true' then the attribute
|
|
* is a boolean attribute
|
|
* @param {boolean} unary True if the tag is a unary tag
|
|
* @param {string} rest The rest of the content.
|
|
*/
|
|
function StartTagToken(tagName, length, attrs, booleanAttrs, unary, rest) {
|
|
_classCallCheck(this, StartTagToken);
|
|
|
|
this.type = 'startTag';
|
|
this.length = length;
|
|
this.text = '';
|
|
this.tagName = tagName;
|
|
this.attrs = attrs;
|
|
this.booleanAttrs = booleanAttrs;
|
|
this.html5Unary = false;
|
|
this.unary = unary;
|
|
this.rest = rest;
|
|
}
|
|
|
|
StartTagToken.prototype.toString = function toString() {
|
|
return TagToken.formatTag(this);
|
|
};
|
|
|
|
return StartTagToken;
|
|
}();
|
|
|
|
/**
|
|
* AtomicTagToken represents an atomic tag.
|
|
*/
|
|
|
|
|
|
var AtomicTagToken = exports.AtomicTagToken = function () {
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* @param {string} tagName The name of the tag.
|
|
* @param {Number} length The length of the tag text.
|
|
* @param {Object} attrs The attributes.
|
|
* @param {Object} booleanAttrs If an entry has 'true' then the attribute
|
|
* is a boolean attribute
|
|
* @param {string} content The content of the tag.
|
|
*/
|
|
function AtomicTagToken(tagName, length, attrs, booleanAttrs, content) {
|
|
_classCallCheck(this, AtomicTagToken);
|
|
|
|
this.type = 'atomicTag';
|
|
this.length = length;
|
|
this.text = '';
|
|
this.tagName = tagName;
|
|
this.attrs = attrs;
|
|
this.booleanAttrs = booleanAttrs;
|
|
this.unary = false;
|
|
this.html5Unary = false;
|
|
this.content = content;
|
|
}
|
|
|
|
AtomicTagToken.prototype.toString = function toString() {
|
|
return TagToken.formatTag(this, this.content);
|
|
};
|
|
|
|
return AtomicTagToken;
|
|
}();
|
|
|
|
/**
|
|
* EndTagToken represents an end tag.
|
|
*/
|
|
|
|
|
|
var EndTagToken = exports.EndTagToken = function () {
|
|
/**
|
|
* Constructor.
|
|
*
|
|
* @param {string} tagName The name of the tag.
|
|
* @param {Number} length The length of the tag text.
|
|
*/
|
|
function EndTagToken(tagName, length) {
|
|
_classCallCheck(this, EndTagToken);
|
|
|
|
this.type = 'endTag';
|
|
this.length = length;
|
|
this.text = '';
|
|
this.tagName = tagName;
|
|
}
|
|
|
|
EndTagToken.prototype.toString = function toString() {
|
|
return '</' + this.tagName + '>';
|
|
};
|
|
|
|
return EndTagToken;
|
|
}();
|
|
|
|
/***/ },
|
|
/* 5 */
|
|
/***/ function(module, exports) {
|
|
|
|
'use strict';
|
|
|
|
exports.__esModule = true;
|
|
exports.escapeQuotes = escapeQuotes;
|
|
|
|
/**
|
|
* Escape quotes in the given value.
|
|
*
|
|
* @param {string} value The value to escape.
|
|
* @param {string} [defaultValue=''] The default value to return if value is falsy.
|
|
* @returns {string}
|
|
*/
|
|
function escapeQuotes(value) {
|
|
var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
|
|
|
|
// There's no lookback in JS, so /(^|[^\\])"/ only matches the first of two `"`s.
|
|
// Instead, just match anything before a double-quote and escape if it's not already escaped.
|
|
return !value ? defaultValue : value.replace(/([^"]*)"/g, function (_, prefix) {
|
|
return (/\\/.test(prefix) ? prefix + '"' : prefix + '\\"'
|
|
);
|
|
});
|
|
}
|
|
|
|
/***/ },
|
|
/* 6 */
|
|
/***/ function(module, exports) {
|
|
|
|
'use strict';
|
|
|
|
exports.__esModule = true;
|
|
exports['default'] = fixedReadTokenFactory;
|
|
/**
|
|
* Empty Elements - HTML 4.01
|
|
*
|
|
* @type {RegExp}
|
|
*/
|
|
var EMPTY = /^(AREA|BASE|BASEFONT|BR|COL|FRAME|HR|IMG|INPUT|ISINDEX|LINK|META|PARAM|EMBED)$/i;
|
|
|
|
/**
|
|
* Elements that you can intentionally leave open (and which close themselves)
|
|
*
|
|
* @type {RegExp}
|
|
*/
|
|
var CLOSESELF = /^(COLGROUP|DD|DT|LI|OPTIONS|P|TD|TFOOT|TH|THEAD|TR)$/i;
|
|
|
|
/**
|
|
* Corrects a token.
|
|
*
|
|
* @param {Token} tok The token to correct
|
|
* @returns {Token} The corrected token
|
|
*/
|
|
function correct(tok) {
|
|
if (tok && tok.type === 'startTag') {
|
|
tok.unary = EMPTY.test(tok.tagName) || tok.unary;
|
|
tok.html5Unary = !/\/>$/.test(tok.text);
|
|
}
|
|
return tok;
|
|
}
|
|
|
|
/**
|
|
* Peeks at the next token in the parser.
|
|
*
|
|
* @param {HtmlParser} parser The parser
|
|
* @param {Function} readTokenImpl The underlying readToken implementation
|
|
* @returns {Token} The next token
|
|
*/
|
|
function peekToken(parser, readTokenImpl) {
|
|
var tmp = parser.stream;
|
|
var tok = correct(readTokenImpl());
|
|
parser.stream = tmp;
|
|
return tok;
|
|
}
|
|
|
|
/**
|
|
* Closes the last token.
|
|
*
|
|
* @param {HtmlParser} parser The parser
|
|
* @param {Array<Token>} stack The stack
|
|
*/
|
|
function closeLast(parser, stack) {
|
|
var tok = stack.pop();
|
|
|
|
// prepend close tag to stream.
|
|
parser.prepend('</' + tok.tagName + '>');
|
|
}
|
|
|
|
/**
|
|
* Create a new token stack.
|
|
*
|
|
* @returns {Array<Token>}
|
|
*/
|
|
function newStack() {
|
|
var stack = [];
|
|
|
|
stack.last = function () {
|
|
return this[this.length - 1];
|
|
};
|
|
|
|
stack.lastTagNameEq = function (tagName) {
|
|
var last = this.last();
|
|
return last && last.tagName && last.tagName.toUpperCase() === tagName.toUpperCase();
|
|
};
|
|
|
|
stack.containsTagName = function (tagName) {
|
|
for (var i = 0, tok; tok = this[i]; i++) {
|
|
if (tok.tagName === tagName) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
|
|
return stack;
|
|
}
|
|
|
|
/**
|
|
* Return a readToken implementation that fixes input.
|
|
*
|
|
* @param {HtmlParser} parser The parser
|
|
* @param {Object} options Options for fixing
|
|
* @param {boolean} options.tagSoupFix True to fix tag soup scenarios
|
|
* @param {boolean} options.selfCloseFix True to fix self-closing tags
|
|
* @param {Function} readTokenImpl The underlying readToken implementation
|
|
* @returns {Function}
|
|
*/
|
|
function fixedReadTokenFactory(parser, options, readTokenImpl) {
|
|
var stack = newStack();
|
|
|
|
var handlers = {
|
|
startTag: function startTag(tok) {
|
|
var tagName = tok.tagName;
|
|
|
|
if (tagName.toUpperCase() === 'TR' && stack.lastTagNameEq('TABLE')) {
|
|
parser.prepend('<TBODY>');
|
|
prepareNextToken();
|
|
} else if (options.selfCloseFix && CLOSESELF.test(tagName) && stack.containsTagName(tagName)) {
|
|
if (stack.lastTagNameEq(tagName)) {
|
|
closeLast(parser, stack);
|
|
} else {
|
|
parser.prepend('</' + tok.tagName + '>');
|
|
prepareNextToken();
|
|
}
|
|
} else if (!tok.unary) {
|
|
stack.push(tok);
|
|
}
|
|
},
|
|
endTag: function endTag(tok) {
|
|
var last = stack.last();
|
|
if (last) {
|
|
if (options.tagSoupFix && !stack.lastTagNameEq(tok.tagName)) {
|
|
// cleanup tag soup
|
|
closeLast(parser, stack);
|
|
} else {
|
|
stack.pop();
|
|
}
|
|
} else if (options.tagSoupFix) {
|
|
// cleanup tag soup part 2: skip this token
|
|
readTokenImpl();
|
|
prepareNextToken();
|
|
}
|
|
}
|
|
};
|
|
|
|
function prepareNextToken() {
|
|
var tok = peekToken(parser, readTokenImpl);
|
|
if (tok && handlers[tok.type]) {
|
|
handlers[tok.type](tok);
|
|
}
|
|
}
|
|
|
|
return function fixedReadToken() {
|
|
prepareNextToken();
|
|
return correct(readTokenImpl());
|
|
};
|
|
}
|
|
|
|
/***/ }
|
|
/******/ ])
|
|
});
|
|
;
|
|
|
|
/***/ },
|
|
/* 4 */
|
|
/***/ function(module, exports) {
|
|
|
|
'use strict';
|
|
|
|
exports.__esModule = true;
|
|
|
|
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
|
|
|
|
exports.existy = existy;
|
|
exports.isFunction = isFunction;
|
|
exports.each = each;
|
|
exports.eachKey = eachKey;
|
|
exports.defaults = defaults;
|
|
exports.toArray = toArray;
|
|
exports.last = last;
|
|
exports.isTag = isTag;
|
|
exports.isScript = isScript;
|
|
exports.isStyle = isStyle;
|
|
/**
|
|
* Determine if the thing is not undefined and not null.
|
|
*
|
|
* @param {*} thing The thing to test
|
|
* @returns {boolean} True if the thing is not undefined and not null.
|
|
*/
|
|
function existy(thing) {
|
|
return thing !== void 0 && thing !== null;
|
|
}
|
|
|
|
/**
|
|
* Is this a function?
|
|
*
|
|
* @param {*} x The variable to test
|
|
* @returns {boolean} True if the variable is a function
|
|
*/
|
|
function isFunction(x) {
|
|
return 'function' === typeof x;
|
|
}
|
|
|
|
/**
|
|
* Loop over each item in an array-like value.
|
|
*
|
|
* @param {Array<*>} arr The array to loop over
|
|
* @param {Function} fn The function to call
|
|
* @param {?Object} target The object to bind to the function
|
|
*/
|
|
function each(arr, fn, target) {
|
|
var i = void 0;
|
|
var len = arr && arr.length || 0;
|
|
for (i = 0; i < len; i++) {
|
|
fn.call(target, arr[i], i);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Loop over each key/value pair in a hash.
|
|
*
|
|
* @param {Object} obj The object
|
|
* @param {Function} fn The function to call
|
|
* @param {?Object} target The object to bind to the function
|
|
*/
|
|
function eachKey(obj, fn, target) {
|
|
for (var key in obj) {
|
|
if (obj.hasOwnProperty(key)) {
|
|
fn.call(target, key, obj[key]);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set default options where some option was not specified.
|
|
*
|
|
* @param {Object} options The destination
|
|
* @param {Object} _defaults The defaults
|
|
* @returns {Object}
|
|
*/
|
|
function defaults(options, _defaults) {
|
|
options = options || {};
|
|
eachKey(_defaults, function (key, val) {
|
|
if (!existy(options[key])) {
|
|
options[key] = val;
|
|
}
|
|
});
|
|
return options;
|
|
}
|
|
|
|
/**
|
|
* Convert value (e.g., a NodeList) to an array.
|
|
*
|
|
* @param {*} obj The object
|
|
* @returns {Array<*>}
|
|
*/
|
|
function toArray(obj) {
|
|
try {
|
|
return Array.prototype.slice.call(obj);
|
|
} catch (e) {
|
|
var _ret = function () {
|
|
var ret = [];
|
|
each(obj, function (val) {
|
|
ret.push(val);
|
|
});
|
|
return {
|
|
v: ret
|
|
};
|
|
}();
|
|
|
|
if ((typeof _ret === 'undefined' ? 'undefined' : _typeof(_ret)) === "object") return _ret.v;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the last item in an array
|
|
*
|
|
* @param {Array<*>} array The array
|
|
* @returns {*} The last item in the array
|
|
*/
|
|
function last(array) {
|
|
return array[array.length - 1];
|
|
}
|
|
|
|
/**
|
|
* Test if token is a script tag.
|
|
*
|
|
* @param {Object} tok The token
|
|
* @param {String} tag The tag name
|
|
* @returns {boolean} True if the token is a script tag
|
|
*/
|
|
function isTag(tok, tag) {
|
|
return !tok || !(tok.type === 'startTag' || tok.type === 'atomicTag') || !('tagName' in tok) ? !1 : !!~tok.tagName.toLowerCase().indexOf(tag);
|
|
}
|
|
|
|
/**
|
|
* Test if token is a script tag.
|
|
*
|
|
* @param {Object} tok The token
|
|
* @returns {boolean} True if the token is a script tag
|
|
*/
|
|
function isScript(tok) {
|
|
return isTag(tok, 'script');
|
|
}
|
|
|
|
/**
|
|
* Test if token is a style tag.
|
|
*
|
|
* @param {Object} tok The token
|
|
* @returns {boolean} True if the token is a style tag
|
|
*/
|
|
function isStyle(tok) {
|
|
return isTag(tok, 'style');
|
|
}
|
|
|
|
/***/ }
|
|
/******/ ])
|
|
});
|
|
;
|