/**
* This file exports the stuff required by external extensions.
*
* @module
*/
'use strict';
// Note that extension code gets core-upgrade when they load the extension API.
require('../../core-upgrade.js');
const semver = require('semver');
const parsoidJson = require('../../package.json');
const Promise = require('../utils/promise.js');
const { ContentUtils } = require('../utils/ContentUtils.js');
const { DOMDataUtils } = require('../utils/DOMDataUtils.js');
const { DOMUtils } = require('../utils/DOMUtils.js');
const { PipelineUtils } = require('../utils/PipelineUtils.js');
const { TokenUtils } = require('../utils/TokenUtils.js');
const { Util } = require('../utils/Util.js');
const { WTUtils } = require('../utils/WTUtils.js');
const { Sanitizer } = require('../wt2html/tt/Sanitizer.js');
/**
* Create a parsing pipeline to parse wikitext.
*
* @param {Object} state
* @param {Object} state.manager
* @param {string} wikitext
* @param {Array} srcOffsets
* @param {Object} parseOpts
* @param parseOpts.extTag
* @param parseOpts.extTagOpts
* @param parseOpts.inTemplate
* @param parseOpts.inlineContext
* @param parseOpts.inPHPBlock
* @param {boolean} sol
* @return {Document}
*/
const parseWikitextToDOM = Promise.async(function *(state, wikitext, parseOpts, sol) {
let doc;
if (!wikitext) {
doc = state.env.createDocument();
} else {
// Parse content to DOM and pass DOM-fragment token back to the main pipeline.
// The DOM will get unwrapped and integrated when processing the top level document.
const pipelineOpts = parseOpts.pipelineOpts || {};
const opts = {
// Full pipeline for processing content
pipelineType: 'text/x-mediawiki/full',
pipelineOpts: {
expandTemplates: true,
extTag: pipelineOpts.extTag,
extTagOpts: pipelineOpts.extTagOpts,
inTemplate: pipelineOpts.inTemplate,
inlineContext: pipelineOpts.inlineContext,
// FIXME: Hack for backward compatibility
// support for extensions that rely on this behavior.
inPHPBlock: pipelineOpts.inPHPBlock,
},
srcOffsets: parseOpts.srcOffsets,
sol,
};
// Actual processing now
doc = yield PipelineUtils.promiseToProcessContent(state.env, parseOpts.frame || state.frame, wikitext, opts);
}
return doc;
});
/**
* FIXME: state is only required for performance reasons so that
* we can overlap extension wikitext parsing with main pipeline.
* Otherwise, we can simply parse this sync in an independent pipeline
* without any state.
*
* @param {Object} state
* @param {Array} extArgs
* @param {string} leadingWS
* @param {string} wikitext
* @param {Object} parseOpts
* @return {Document}
*/
const parseTokenContentsToDOM = Promise.async(function *(state, extArgs, leadingWS, wikitext, parseOpts) {
const dataAttribs = state.extToken.dataAttribs;
const extTagOffsets = dataAttribs.extTagOffsets;
const srcOffsets = [
extTagOffsets[0] + extTagOffsets[2] + leadingWS.length,
extTagOffsets[1] - extTagOffsets[3]
];
const doc = yield parseWikitextToDOM(
state,
wikitext,
Object.assign({ srcOffsets }, parseOpts),
/* sol */true
);
// Create a wrapper and migrate content into the wrapper
const wrapper = doc.createElement(parseOpts.wrapperTag);
DOMUtils.migrateChildren(doc.body, wrapper);
doc.body.appendChild(wrapper);
// Sanitize argDict.attrs and set on the wrapper
Sanitizer.applySanitizedArgs(state.env, wrapper, extArgs);
// Mark empty content DOMs
if (!wikitext) {
DOMDataUtils.getDataParsoid(wrapper).empty = true;
}
if (state.extToken.dataAttribs.selfClose) {
DOMDataUtils.getDataParsoid(wrapper).selfClose = true;
}
return doc;
});
module.exports = {
versionCheck: function(requestedVersion) {
// Throw exception if the supplied major/minor version is
// incompatible with the currently running Parsoid.
if (!semver.satisfies(parsoidJson.version, requestedVersion)) {
throw new Error(
"Parsoid version " + parsoidJson.version + " is inconsistent " +
"with required version " + requestedVersion
);
}
// Return the exports to support chaining. We could also elect
// to return a slightly different version of the exports here if
// we wanted to support multiple API versions.
return {
// XXX we may wish to export a subset of Util/DOMUtils/defines
// and explicitly mark the exported functions as "stable", ie
// we need to bump Parsoid's major version if the exported
// functions are changed.
addMetaData: require('../wt2html/DOMPostProcessor.js').DOMPostProcessor.addMetaData,
ContentUtils,
DOMDataUtils,
DOMUtils,
JSUtils: require('../utils/jsutils.js').JSUtils,
parseTokenContentsToDOM,
parseWikitextToDOM,
Promise: Promise,
Sanitizer,
TemplateRequest: require('../mw/ApiRequest.js').TemplateRequest,
TokenTypes: require('../tokens/TokenTypes.js'),
TokenUtils,
Util,
WTUtils,
};
},
};