2013-03-26 00:40:20 +00:00
|
|
|
/* ----------------------------------------------------------------------
|
|
|
|
* This file implements <ref> and <references> extension tag handling
|
|
|
|
* natively in Parsoid.
|
|
|
|
* ---------------------------------------------------------------------- */
|
2012-10-30 00:51:07 +00:00
|
|
|
"use strict";
|
2014-01-22 20:24:23 +00:00
|
|
|
require('./core-upgrade.js');
|
2012-10-30 00:51:07 +00:00
|
|
|
|
Extension handling rewrite + cite extension refactoring.
Tokenization
------------
* Fixed tokenizer to correctly parse extension tags in different
contexts: with start and end tags, in self-closing tag mode,
and to correctly handle scenarios when the exension end-tag is
followed by a '#' (the special char used to skip over extension
content).
* Removed the distinction in the tokenizer between installed
extensions and natively supported extension tags (<ref> and
<references> for ex.). They all tokenize and get processed
identically and get handled by different paths in the extension
handler.
* Template and TemplateArg tokens now carry tpl. transclusion
source alongwith them since tsr information will not be
accurate when they show up in extension contexts that in turn
showed up in template context that were expanded by the php
preprocessor.
Ex: {{echo|<ref>{{echo|foo}}</ref>}}
The tsr for the ref-tag will correspond to the
template-source of the echo-template, NOT the original top-level
page. So, env.page.src.substring(..) will return incorrect
source for the innermost {{echo|foo}}. This fix of carrying
along tpl transclusion source in the token itself eliminates
this problem.
Knowledge of native extensions
------------------------------
* Natively implemented extension tags (<ref> and <references>)
are hardcoded in env.conf.parsoid. At some point, it would
be good to have a registration mechanism for parsoid-native
extensions.
Extension handling
------------------
* Extracted extension handling out of the template handler into
its own handler class. Right now, this class inherits from the
template handler in order to be able to reuse a lot of the
expansion and encapsulation functionality currently in the
Template Handler.
* This handler now handles extensions that are:
(a) natively implemented and registered with Parsoid.
(b) implemented as a PHP extension and expanded by relying on
the PHP preprocessor.
For (a), it uses information from env.conf.parsoid to find
ext-handlers for natively implemented ext-tags. However, this
can be cleaned up at some point by making available a registration
mechanism.
Cite/Ref/References
-------------------
* Reworked the cite handler to split up ref-token processing
and references token processing.
* The handler now processes ref-tokens, parses content all
the way to html output and encapsulates the html in an
attribute of a meta-token that serves as a placeholder for
where the ref-token occured.
* References are handled as a DOM post-pass where these meta
placeholder tokens are collected, content extracted from
the attribute and spit out at the site of a references tag.
The DOM walking is in DOMPostProcessor.js, but the actual
processing is part of the Cite.js to keep all cite extension
handling code in one place.
Parser pipeline
---------------
* Restructured parser pipeline recipes based on changes to Cite,
TemplateHandler, and ExtensionHandler.
* Added a couple functions to the parser pipeline:
1. resetState to reset state before starting a new top-level parse
when pipelines are reused across top-level parses (ex: parser
tests)
2. setSourceOffsets to set start/end offsets of the source being
handled by the pipeline. This is required to correctly set tsr
values when extension content (which is a substring of original
top-level text) is parsed in its own pipeline.
Other fixes
-----------
* Removed env parameter from the Params object since it was not
being used and seemed like unnecessary state propagation.
* Removed a FIXME in DOMUtils.buildTokensFromDOM by reusing code
in the tokenizer that converts "\n" in text to NlTks.
* Cleanup of Util.shiftTokenTSR.
* ext.util.TokenCollection is now no longer used by anything.
Added a FIXME and left around in case we are able to improve
tokenizing and handling of *include* tags that can eliminate the
need for the messy TokenAndAttrCollector.
Test results
------------
* No change in parser tests results.
* Tested with a few different files.
- en:BO page seems to be parsed about 10% faster than before
(needs verification).
- Referencs on the en:BO page seem to be more accurate than
before.
Change-Id: I8a095fa9fa976c7b3a2a4bd968dc9db4270b105f
2013-03-09 00:07:59 +00:00
|
|
|
var Util = require( './mediawiki.Util.js' ).Util,
|
2013-05-02 16:17:08 +00:00
|
|
|
DU = require( './mediawiki.DOMUtils.js').DOMUtils,
|
2013-06-26 17:35:08 +00:00
|
|
|
coreutil = require('util'),
|
2014-12-20 12:49:12 +00:00
|
|
|
defines = require('./mediawiki.parser.defines.js'),
|
|
|
|
entities = require('entities');
|
2013-05-02 16:17:08 +00:00
|
|
|
|
2013-04-22 19:51:09 +00:00
|
|
|
// define some constructor shortcuts
|
|
|
|
var KV = defines.KV,
|
2013-09-30 17:37:07 +00:00
|
|
|
EOFTk = defines.EOFTk,
|
2013-04-25 13:43:49 +00:00
|
|
|
SelfclosingTagTk = defines.SelfclosingTagTk;
|
2012-05-03 11:05:28 +00:00
|
|
|
|
2013-03-26 00:40:20 +00:00
|
|
|
// FIXME: Move out to some common helper file?
|
|
|
|
// Helper function to process extension source
|
|
|
|
function processExtSource(manager, extToken, opts) {
|
|
|
|
var extSrc = extToken.getAttribute('source'),
|
|
|
|
tagWidths = extToken.dataAttribs.tagWidths,
|
|
|
|
content = extSrc.substring(tagWidths[0], extSrc.length - tagWidths[1]);
|
|
|
|
|
|
|
|
// FIXME: Should this be specific to the extension
|
2013-10-07 19:55:59 +00:00
|
|
|
// Or is it okay to do this unconditionally for all?
|
2013-03-26 00:40:20 +00:00
|
|
|
// Right now, this code is run only for ref and references,
|
|
|
|
// so not a real problem, but if this is used on other extensions,
|
|
|
|
// requires addressing.
|
|
|
|
//
|
2014-12-03 00:47:32 +00:00
|
|
|
// FIXME: SSS: This stripping maybe be unnecessary after all.
|
2013-10-07 19:55:59 +00:00
|
|
|
//
|
2013-06-13 16:27:27 +00:00
|
|
|
// Strip all leading white-space
|
2013-06-28 20:54:15 +00:00
|
|
|
var wsMatch = content.match(/^(\s*)([^]*)$/),
|
2013-03-26 00:40:20 +00:00
|
|
|
leadingWS = wsMatch[1];
|
|
|
|
|
|
|
|
// Update content to normalized form
|
|
|
|
content = wsMatch[2];
|
|
|
|
|
|
|
|
if (!content || content.length === 0) {
|
|
|
|
opts.emptyContentCB(opts.res);
|
|
|
|
} else {
|
|
|
|
// Pass an async signal since the ext-content is not processed completely.
|
|
|
|
opts.parentCB({tokens: opts.res, async: true});
|
|
|
|
|
2013-09-30 17:37:07 +00:00
|
|
|
// Wrap templates always
|
|
|
|
opts.pipelineOpts = Util.extendProps({}, opts.pipelineOpts, { wrapTemplates: true });
|
2013-03-26 00:40:20 +00:00
|
|
|
|
|
|
|
var tsr = extToken.dataAttribs.tsr;
|
2015-04-06 21:07:04 +00:00
|
|
|
opts.srcOffsets = [ tsr[0] +tagWidths[0] +leadingWS.length, tsr[1] -tagWidths[1] ];
|
2013-03-26 00:40:20 +00:00
|
|
|
|
2013-09-30 17:37:07 +00:00
|
|
|
// Process ref content
|
2014-02-11 22:38:28 +00:00
|
|
|
Util.processContentInPipeline(manager.env, manager.frame, content, opts);
|
2013-03-26 00:40:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-13 14:48:47 +00:00
|
|
|
/**
|
2013-03-26 00:40:20 +00:00
|
|
|
* Simple token transform version of the Ref extension tag
|
2011-12-13 14:48:47 +00:00
|
|
|
*
|
2011-12-13 18:45:09 +00:00
|
|
|
* @class
|
|
|
|
* @constructor
|
2011-12-13 14:48:47 +00:00
|
|
|
*/
|
2013-03-26 00:40:20 +00:00
|
|
|
function Ref(cite) {
|
|
|
|
this.cite = cite;
|
|
|
|
this.reset();
|
2011-12-13 14:48:47 +00:00
|
|
|
}
|
|
|
|
|
Extension handling rewrite + cite extension refactoring.
Tokenization
------------
* Fixed tokenizer to correctly parse extension tags in different
contexts: with start and end tags, in self-closing tag mode,
and to correctly handle scenarios when the exension end-tag is
followed by a '#' (the special char used to skip over extension
content).
* Removed the distinction in the tokenizer between installed
extensions and natively supported extension tags (<ref> and
<references> for ex.). They all tokenize and get processed
identically and get handled by different paths in the extension
handler.
* Template and TemplateArg tokens now carry tpl. transclusion
source alongwith them since tsr information will not be
accurate when they show up in extension contexts that in turn
showed up in template context that were expanded by the php
preprocessor.
Ex: {{echo|<ref>{{echo|foo}}</ref>}}
The tsr for the ref-tag will correspond to the
template-source of the echo-template, NOT the original top-level
page. So, env.page.src.substring(..) will return incorrect
source for the innermost {{echo|foo}}. This fix of carrying
along tpl transclusion source in the token itself eliminates
this problem.
Knowledge of native extensions
------------------------------
* Natively implemented extension tags (<ref> and <references>)
are hardcoded in env.conf.parsoid. At some point, it would
be good to have a registration mechanism for parsoid-native
extensions.
Extension handling
------------------
* Extracted extension handling out of the template handler into
its own handler class. Right now, this class inherits from the
template handler in order to be able to reuse a lot of the
expansion and encapsulation functionality currently in the
Template Handler.
* This handler now handles extensions that are:
(a) natively implemented and registered with Parsoid.
(b) implemented as a PHP extension and expanded by relying on
the PHP preprocessor.
For (a), it uses information from env.conf.parsoid to find
ext-handlers for natively implemented ext-tags. However, this
can be cleaned up at some point by making available a registration
mechanism.
Cite/Ref/References
-------------------
* Reworked the cite handler to split up ref-token processing
and references token processing.
* The handler now processes ref-tokens, parses content all
the way to html output and encapsulates the html in an
attribute of a meta-token that serves as a placeholder for
where the ref-token occured.
* References are handled as a DOM post-pass where these meta
placeholder tokens are collected, content extracted from
the attribute and spit out at the site of a references tag.
The DOM walking is in DOMPostProcessor.js, but the actual
processing is part of the Cite.js to keep all cite extension
handling code in one place.
Parser pipeline
---------------
* Restructured parser pipeline recipes based on changes to Cite,
TemplateHandler, and ExtensionHandler.
* Added a couple functions to the parser pipeline:
1. resetState to reset state before starting a new top-level parse
when pipelines are reused across top-level parses (ex: parser
tests)
2. setSourceOffsets to set start/end offsets of the source being
handled by the pipeline. This is required to correctly set tsr
values when extension content (which is a substring of original
top-level text) is parsed in its own pipeline.
Other fixes
-----------
* Removed env parameter from the Params object since it was not
being used and seemed like unnecessary state propagation.
* Removed a FIXME in DOMUtils.buildTokensFromDOM by reusing code
in the tokenizer that converts "\n" in text to NlTks.
* Cleanup of Util.shiftTokenTSR.
* ext.util.TokenCollection is now no longer used by anything.
Added a FIXME and left around in case we are able to improve
tokenizing and handling of *include* tags that can eliminate the
need for the messy TokenAndAttrCollector.
Test results
------------
* No change in parser tests results.
* Tested with a few different files.
- en:BO page seems to be parsed about 10% faster than before
(needs verification).
- Referencs on the en:BO page seem to be more accurate than
before.
Change-Id: I8a095fa9fa976c7b3a2a4bd968dc9db4270b105f
2013-03-09 00:07:59 +00:00
|
|
|
/**
|
|
|
|
* Reset state before each top-level parse -- this lets us share a pipeline
|
|
|
|
* to parse unrelated pages.
|
|
|
|
*/
|
2013-04-24 19:09:08 +00:00
|
|
|
Ref.prototype.reset = function() { };
|
2012-11-16 18:03:01 +00:00
|
|
|
|
2014-08-21 23:16:32 +00:00
|
|
|
function hasRef(node) {
|
|
|
|
var c = node.firstChild;
|
|
|
|
while (c) {
|
|
|
|
if (DU.isElt(c)) {
|
|
|
|
var typeOf = c.getAttribute('typeof');
|
|
|
|
if ((/(?:^|\s)mw:Extension\/ref\/Marker(?=$|\s)/).test(typeOf)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (hasRef(c)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
c = c.nextSibling;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-12-13 18:45:09 +00:00
|
|
|
/**
|
Extension handling rewrite + cite extension refactoring.
Tokenization
------------
* Fixed tokenizer to correctly parse extension tags in different
contexts: with start and end tags, in self-closing tag mode,
and to correctly handle scenarios when the exension end-tag is
followed by a '#' (the special char used to skip over extension
content).
* Removed the distinction in the tokenizer between installed
extensions and natively supported extension tags (<ref> and
<references> for ex.). They all tokenize and get processed
identically and get handled by different paths in the extension
handler.
* Template and TemplateArg tokens now carry tpl. transclusion
source alongwith them since tsr information will not be
accurate when they show up in extension contexts that in turn
showed up in template context that were expanded by the php
preprocessor.
Ex: {{echo|<ref>{{echo|foo}}</ref>}}
The tsr for the ref-tag will correspond to the
template-source of the echo-template, NOT the original top-level
page. So, env.page.src.substring(..) will return incorrect
source for the innermost {{echo|foo}}. This fix of carrying
along tpl transclusion source in the token itself eliminates
this problem.
Knowledge of native extensions
------------------------------
* Natively implemented extension tags (<ref> and <references>)
are hardcoded in env.conf.parsoid. At some point, it would
be good to have a registration mechanism for parsoid-native
extensions.
Extension handling
------------------
* Extracted extension handling out of the template handler into
its own handler class. Right now, this class inherits from the
template handler in order to be able to reuse a lot of the
expansion and encapsulation functionality currently in the
Template Handler.
* This handler now handles extensions that are:
(a) natively implemented and registered with Parsoid.
(b) implemented as a PHP extension and expanded by relying on
the PHP preprocessor.
For (a), it uses information from env.conf.parsoid to find
ext-handlers for natively implemented ext-tags. However, this
can be cleaned up at some point by making available a registration
mechanism.
Cite/Ref/References
-------------------
* Reworked the cite handler to split up ref-token processing
and references token processing.
* The handler now processes ref-tokens, parses content all
the way to html output and encapsulates the html in an
attribute of a meta-token that serves as a placeholder for
where the ref-token occured.
* References are handled as a DOM post-pass where these meta
placeholder tokens are collected, content extracted from
the attribute and spit out at the site of a references tag.
The DOM walking is in DOMPostProcessor.js, but the actual
processing is part of the Cite.js to keep all cite extension
handling code in one place.
Parser pipeline
---------------
* Restructured parser pipeline recipes based on changes to Cite,
TemplateHandler, and ExtensionHandler.
* Added a couple functions to the parser pipeline:
1. resetState to reset state before starting a new top-level parse
when pipelines are reused across top-level parses (ex: parser
tests)
2. setSourceOffsets to set start/end offsets of the source being
handled by the pipeline. This is required to correctly set tsr
values when extension content (which is a substring of original
top-level text) is parsed in its own pipeline.
Other fixes
-----------
* Removed env parameter from the Params object since it was not
being used and seemed like unnecessary state propagation.
* Removed a FIXME in DOMUtils.buildTokensFromDOM by reusing code
in the tokenizer that converts "\n" in text to NlTks.
* Cleanup of Util.shiftTokenTSR.
* ext.util.TokenCollection is now no longer used by anything.
Added a FIXME and left around in case we are able to improve
tokenizing and handling of *include* tags that can eliminate the
need for the messy TokenAndAttrCollector.
Test results
------------
* No change in parser tests results.
* Tested with a few different files.
- en:BO page seems to be parsed about 10% faster than before
(needs verification).
- Referencs on the en:BO page seem to be more accurate than
before.
Change-Id: I8a095fa9fa976c7b3a2a4bd968dc9db4270b105f
2013-03-09 00:07:59 +00:00
|
|
|
* Handle ref tokens
|
2011-12-13 18:45:09 +00:00
|
|
|
*/
|
2013-03-26 00:40:20 +00:00
|
|
|
Ref.prototype.handleRef = function ( manager, pipelineOpts, refTok, cb ) {
|
2013-07-15 22:31:20 +00:00
|
|
|
// Nested <ref> tags at the top level are considered errors
|
|
|
|
// But, inside templates, they are supported
|
|
|
|
if (!pipelineOpts.inTemplate && pipelineOpts.extTag === "ref") {
|
2013-06-13 16:27:27 +00:00
|
|
|
cb({ tokens: [refTok.getAttribute("source")] });
|
|
|
|
return;
|
|
|
|
}
|
2013-03-26 00:40:20 +00:00
|
|
|
|
2014-07-01 18:04:31 +00:00
|
|
|
var refOpts = Object.assign({
|
2014-04-14 23:04:31 +00:00
|
|
|
name: null, group: null
|
|
|
|
}, Util.KVtoHash(refTok.getAttribute("options"), true)),
|
2013-07-24 00:15:45 +00:00
|
|
|
about = manager.env.newAboutId(),
|
2014-08-21 23:16:32 +00:00
|
|
|
finalCB = function(toks, contentBody) {
|
2013-04-24 19:09:08 +00:00
|
|
|
// Marker meta with ref content
|
|
|
|
var da = Util.clone(refTok.dataAttribs);
|
|
|
|
// Clear stx='html' so that sanitizer doesn't barf
|
|
|
|
da.stx = undefined;
|
2014-07-01 18:04:31 +00:00
|
|
|
da.group = refOpts.group || '';
|
|
|
|
da.name = refOpts.name || '';
|
2014-08-21 23:16:32 +00:00
|
|
|
da.content = contentBody ? DU.serializeChildren(contentBody) : '';
|
|
|
|
da.hasRefInRef = contentBody ? hasRef(contentBody) : false;
|
2012-09-17 19:46:44 +00:00
|
|
|
|
2013-03-26 00:40:20 +00:00
|
|
|
toks.push(new SelfclosingTagTk( 'meta', [
|
Add capability for DOM-based template expansion, and use DOM fragments for extensions
This patch adds the capability to expand individual transclusions all the way
to DOM, which enforces properly nested templates. This is also needed for
DOM-based template re-expansion, which the VE folks would like to use for
template editing.
In normal parsing, DOM-based expansion is currently disabled by default for
transclusions, and enabled by default for extensions. The decision whether to
balance a particular transclusion can be based on a statistics-based
classification of templates into balanced and unbalanced ones. The advantage
of this approach is consistency in behavior for old revisions. Another
alternative is to wrap unbalanced transclusions into <domparse> tags which
disable DOM-based parsing for all transclusions in its content. This has the
advantage that all special cases can be handled after tag insertion, and that
balancing could also be enforced in the PHP parser using an extension.
Other major changes:
* Renamed transclusion content typeof from mw:Object/Template to
mw:Transclusion
* Renamed extension typeof from mw:Object/Extensions/foo to mw:Extension/foo
and switched Cite to use lower-case ref/references too
Other minor changes:
* Only apply template encapsulation algorithm on DOM to mw:Transclusion and
mw:Param objects, and no longer to all mw:Object/* elements. We should
probably switch to a more explicit encapsulation type instead. Maybe
something like mw:EncapStart/Transclusion and mw:EncapEnd/Transclusion
instead of the current mw:Transclusion and mw:Transclusion/End, so that
stripping those metas out selectively is easy?
* Changed the DOMTraverser logic to let handlers explicitly return the next
element to handle. Useful when several siblings are handled, as is the case
for the fragment unwrapper for example, and avoids some cases where deleted
nodes were still being processed.
* Changed Cite to use mw:Extension/Ref{,erences} as all other extensions.
* Make sure we round-trip gallery when the PHP preprocessor is not used
Five parsoid-specific wt2html tests are failing due to the typeof change.
They will be fine once those tests are adjusted. For now, adding them
to parser tests blacklist.
TODO:
* Switch the Cite extension to the generic DOMFragment mechanism instead of
marker tokens.
Change-Id: I64b560a12695256915d2196d0646347381400e80
2013-05-16 22:23:05 +00:00
|
|
|
new KV('typeof', 'mw:Extension/ref/Marker'),
|
2013-10-17 22:30:04 +00:00
|
|
|
new KV('about', about)
|
Add capability for DOM-based template expansion, and use DOM fragments for extensions
This patch adds the capability to expand individual transclusions all the way
to DOM, which enforces properly nested templates. This is also needed for
DOM-based template re-expansion, which the VE folks would like to use for
template editing.
In normal parsing, DOM-based expansion is currently disabled by default for
transclusions, and enabled by default for extensions. The decision whether to
balance a particular transclusion can be based on a statistics-based
classification of templates into balanced and unbalanced ones. The advantage
of this approach is consistency in behavior for old revisions. Another
alternative is to wrap unbalanced transclusions into <domparse> tags which
disable DOM-based parsing for all transclusions in its content. This has the
advantage that all special cases can be handled after tag insertion, and that
balancing could also be enforced in the PHP parser using an extension.
Other major changes:
* Renamed transclusion content typeof from mw:Object/Template to
mw:Transclusion
* Renamed extension typeof from mw:Object/Extensions/foo to mw:Extension/foo
and switched Cite to use lower-case ref/references too
Other minor changes:
* Only apply template encapsulation algorithm on DOM to mw:Transclusion and
mw:Param objects, and no longer to all mw:Object/* elements. We should
probably switch to a more explicit encapsulation type instead. Maybe
something like mw:EncapStart/Transclusion and mw:EncapEnd/Transclusion
instead of the current mw:Transclusion and mw:Transclusion/End, so that
stripping those metas out selectively is easy?
* Changed the DOMTraverser logic to let handlers explicitly return the next
element to handle. Useful when several siblings are handled, as is the case
for the fragment unwrapper for example, and avoids some cases where deleted
nodes were still being processed.
* Changed Cite to use mw:Extension/Ref{,erences} as all other extensions.
* Make sure we round-trip gallery when the PHP preprocessor is not used
Five parsoid-specific wt2html tests are failing due to the typeof change.
They will be fine once those tests are adjusted. For now, adding them
to parser tests blacklist.
TODO:
* Switch the Cite extension to the generic DOMFragment mechanism instead of
marker tokens.
Change-Id: I64b560a12695256915d2196d0646347381400e80
2013-05-16 22:23:05 +00:00
|
|
|
], da));
|
2012-11-16 23:36:07 +00:00
|
|
|
|
2013-03-26 00:40:20 +00:00
|
|
|
// All done!
|
|
|
|
cb({tokens: toks, async: false});
|
|
|
|
};
|
2012-11-16 23:36:07 +00:00
|
|
|
|
2013-03-26 00:40:20 +00:00
|
|
|
processExtSource(manager, refTok, {
|
Extension handling rewrite + cite extension refactoring.
Tokenization
------------
* Fixed tokenizer to correctly parse extension tags in different
contexts: with start and end tags, in self-closing tag mode,
and to correctly handle scenarios when the exension end-tag is
followed by a '#' (the special char used to skip over extension
content).
* Removed the distinction in the tokenizer between installed
extensions and natively supported extension tags (<ref> and
<references> for ex.). They all tokenize and get processed
identically and get handled by different paths in the extension
handler.
* Template and TemplateArg tokens now carry tpl. transclusion
source alongwith them since tsr information will not be
accurate when they show up in extension contexts that in turn
showed up in template context that were expanded by the php
preprocessor.
Ex: {{echo|<ref>{{echo|foo}}</ref>}}
The tsr for the ref-tag will correspond to the
template-source of the echo-template, NOT the original top-level
page. So, env.page.src.substring(..) will return incorrect
source for the innermost {{echo|foo}}. This fix of carrying
along tpl transclusion source in the token itself eliminates
this problem.
Knowledge of native extensions
------------------------------
* Natively implemented extension tags (<ref> and <references>)
are hardcoded in env.conf.parsoid. At some point, it would
be good to have a registration mechanism for parsoid-native
extensions.
Extension handling
------------------
* Extracted extension handling out of the template handler into
its own handler class. Right now, this class inherits from the
template handler in order to be able to reuse a lot of the
expansion and encapsulation functionality currently in the
Template Handler.
* This handler now handles extensions that are:
(a) natively implemented and registered with Parsoid.
(b) implemented as a PHP extension and expanded by relying on
the PHP preprocessor.
For (a), it uses information from env.conf.parsoid to find
ext-handlers for natively implemented ext-tags. However, this
can be cleaned up at some point by making available a registration
mechanism.
Cite/Ref/References
-------------------
* Reworked the cite handler to split up ref-token processing
and references token processing.
* The handler now processes ref-tokens, parses content all
the way to html output and encapsulates the html in an
attribute of a meta-token that serves as a placeholder for
where the ref-token occured.
* References are handled as a DOM post-pass where these meta
placeholder tokens are collected, content extracted from
the attribute and spit out at the site of a references tag.
The DOM walking is in DOMPostProcessor.js, but the actual
processing is part of the Cite.js to keep all cite extension
handling code in one place.
Parser pipeline
---------------
* Restructured parser pipeline recipes based on changes to Cite,
TemplateHandler, and ExtensionHandler.
* Added a couple functions to the parser pipeline:
1. resetState to reset state before starting a new top-level parse
when pipelines are reused across top-level parses (ex: parser
tests)
2. setSourceOffsets to set start/end offsets of the source being
handled by the pipeline. This is required to correctly set tsr
values when extension content (which is a substring of original
top-level text) is parsed in its own pipeline.
Other fixes
-----------
* Removed env parameter from the Params object since it was not
being used and seemed like unnecessary state propagation.
* Removed a FIXME in DOMUtils.buildTokensFromDOM by reusing code
in the tokenizer that converts "\n" in text to NlTks.
* Cleanup of Util.shiftTokenTSR.
* ext.util.TokenCollection is now no longer used by anything.
Added a FIXME and left around in case we are able to improve
tokenizing and handling of *include* tags that can eliminate the
need for the messy TokenAndAttrCollector.
Test results
------------
* No change in parser tests results.
* Tested with a few different files.
- en:BO page seems to be parsed about 10% faster than before
(needs verification).
- Referencs on the en:BO page seem to be more accurate than
before.
Change-Id: I8a095fa9fa976c7b3a2a4bd968dc9db4270b105f
2013-03-09 00:07:59 +00:00
|
|
|
// Full pipeline for processing ref-content
|
2013-03-26 00:40:20 +00:00
|
|
|
pipelineType: 'text/x-mediawiki/full',
|
|
|
|
pipelineOpts: {
|
(Bug 64901) Fix paragraph-wrapping to match PHP parser + Tidy combo
General changes
---------------
* Replaced the hacky 'inBlockNode' parser pipeline option with
a cleaner 'noPWrapping' option that suppresses paragraph wrapping
in sub-pipelines (ex: recursive link content, ref tags, attribute
content, etc.).
Changes to wt2html pipeline
---------------------------
* Fixed paragraph-wrapping code to ensure that there are no bare
text nodes left behind, but without removing the line-based block-tag
influences on p-wrapping. Some simplifications as well.
TODO: There are still some discrepancies around <blockquote>
p-wrapping behavior. These will be investigated and addressed
in a future patch.
* Fixed foster parenting code to ensure that fostered content is
added in p-tags where necessary rather than span-tags.
Changes to html2wt/selser pipeline
----------------------------------
* Fixed DOMDiff to tag mw:DiffMarker nodes with a is-block-node
attribute when the deleted node is a block node. This is used
during selective serialization to discard original separators
between adjacent p-nodes if either of their neighbors is a
deleted block node.
* Fixed serialization to account for changes to p-wrapping.
- Updated tag handlers for the <p> tag.
- Updated separator handling to deal with deleted block tags
and their influence on separators around adjacent p-tags.
- Updated selser output code to test whether a deleted block
tag forces nowiki escaping on unedited content from adjacent
p-tags.
Changes to parser tests / test setup
------------------------------------
* Tweaked selser test generation to ensure that text nodes are always
inserted in p-wrappers where necessary.
* Updated parser test output for several tests to introduce p-tags
instead of span-tags or missing p-tags, add html/parsoid section,
or in one case, add missing HTML output.
Parser Test Result changes
--------------------------
Newly passing
- 12 wt2html
- 1 wt2wt
- 3 html2html
- 3 html2wt
Newly failing
- 1 html2wt
"3. Leading whitespace in indent-pre suppressing contexts should not be escaped"
This is just normalization of output where multiple HTML forms
serialize to the same wikitext with a newline difference. It is not
worth the complexity to fix this.
- 1 wt2wt
""Trailing newlines in a deep dom-subtree that ends a wikitext line"
This is again normalization during serialization where an extra
unnecessary newline is introduced.
- A bunch of selser test changes.
182 +add, 188 -add => 6 fewer selser failures
- That is a lot of changes to sift through, and I didn't look at every
one of those, but a number of changes seem to be harmless, and just
a change to previously "failing" tests.
- "Media link with nasty text" test seems to have a lot of selser
changes, but the HTML generated by Parsoid seems to be "buggy" with
interesting DSR values as well. That needs investigation separately.
- "HTML nested bullet list, closed tags (bug 5497) [[3,3,4,[0,1,4],3]]"
has seen a degradation where a dirty diff got introduced.
Haven't investigated carefully why that is so.
Change-Id: Ia9c9950717120fbcd03abfe4e09168e787669ac4
2014-08-29 05:59:20 +00:00
|
|
|
extTag: "ref",
|
2013-07-15 22:31:20 +00:00
|
|
|
inTemplate: pipelineOpts.inTemplate,
|
2013-09-24 01:07:29 +00:00
|
|
|
noPre: true,
|
(Bug 64901) Fix paragraph-wrapping to match PHP parser + Tidy combo
General changes
---------------
* Replaced the hacky 'inBlockNode' parser pipeline option with
a cleaner 'noPWrapping' option that suppresses paragraph wrapping
in sub-pipelines (ex: recursive link content, ref tags, attribute
content, etc.).
Changes to wt2html pipeline
---------------------------
* Fixed paragraph-wrapping code to ensure that there are no bare
text nodes left behind, but without removing the line-based block-tag
influences on p-wrapping. Some simplifications as well.
TODO: There are still some discrepancies around <blockquote>
p-wrapping behavior. These will be investigated and addressed
in a future patch.
* Fixed foster parenting code to ensure that fostered content is
added in p-tags where necessary rather than span-tags.
Changes to html2wt/selser pipeline
----------------------------------
* Fixed DOMDiff to tag mw:DiffMarker nodes with a is-block-node
attribute when the deleted node is a block node. This is used
during selective serialization to discard original separators
between adjacent p-nodes if either of their neighbors is a
deleted block node.
* Fixed serialization to account for changes to p-wrapping.
- Updated tag handlers for the <p> tag.
- Updated separator handling to deal with deleted block tags
and their influence on separators around adjacent p-tags.
- Updated selser output code to test whether a deleted block
tag forces nowiki escaping on unedited content from adjacent
p-tags.
Changes to parser tests / test setup
------------------------------------
* Tweaked selser test generation to ensure that text nodes are always
inserted in p-wrappers where necessary.
* Updated parser test output for several tests to introduce p-tags
instead of span-tags or missing p-tags, add html/parsoid section,
or in one case, add missing HTML output.
Parser Test Result changes
--------------------------
Newly passing
- 12 wt2html
- 1 wt2wt
- 3 html2html
- 3 html2wt
Newly failing
- 1 html2wt
"3. Leading whitespace in indent-pre suppressing contexts should not be escaped"
This is just normalization of output where multiple HTML forms
serialize to the same wikitext with a newline difference. It is not
worth the complexity to fix this.
- 1 wt2wt
""Trailing newlines in a deep dom-subtree that ends a wikitext line"
This is again normalization during serialization where an extra
unnecessary newline is introduced.
- A bunch of selser test changes.
182 +add, 188 -add => 6 fewer selser failures
- That is a lot of changes to sift through, and I didn't look at every
one of those, but a number of changes seem to be harmless, and just
a change to previously "failing" tests.
- "Media link with nasty text" test seems to have a lot of selser
changes, but the HTML generated by Parsoid seems to be "buggy" with
interesting DSR values as well. That needs investigation separately.
- "HTML nested bullet list, closed tags (bug 5497) [[3,3,4,[0,1,4],3]]"
has seen a degradation where a dirty diff got introduced.
Haven't investigated carefully why that is so.
Change-Id: Ia9c9950717120fbcd03abfe4e09168e787669ac4
2014-08-29 05:59:20 +00:00
|
|
|
noPWrapping: true
|
2013-03-26 00:40:20 +00:00
|
|
|
},
|
2013-04-24 19:09:08 +00:00
|
|
|
res: [],
|
2013-03-26 00:40:20 +00:00
|
|
|
parentCB: cb,
|
|
|
|
emptyContentCB: finalCB,
|
|
|
|
documentCB: function(refContentDoc) {
|
2014-08-21 23:16:32 +00:00
|
|
|
finalCB([], refContentDoc.body);
|
2013-03-26 00:40:20 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
2012-11-29 20:09:06 +00:00
|
|
|
|
2013-04-24 19:09:08 +00:00
|
|
|
/**
|
|
|
|
* Helper class used by <references> implementation
|
|
|
|
*/
|
|
|
|
function RefGroup(group) {
|
|
|
|
this.name = group || '';
|
|
|
|
this.refs = [];
|
2014-01-10 03:33:57 +00:00
|
|
|
this.indexByName = new Map();
|
2013-04-24 19:09:08 +00:00
|
|
|
}
|
|
|
|
|
2014-01-03 23:21:46 +00:00
|
|
|
function makeValidIdAttr(val) {
|
|
|
|
// Looks like Cite.php doesn't try to fix ids that already have
|
|
|
|
// a "_" in them. Ex: name="a b" and name="a_b" are considered
|
|
|
|
// identical. Not sure if this is a feature or a bug.
|
2014-12-20 12:49:12 +00:00
|
|
|
// It also considers entities equal to their encoding (i.e. '&' === '&')
|
|
|
|
// and then substitutes % with .
|
|
|
|
var v = entities.decodeHTML(val).replace(/\s/g, '_');
|
|
|
|
return encodeURIComponent(v).replace(/%/g,".");
|
2014-01-03 23:21:46 +00:00
|
|
|
}
|
|
|
|
|
2013-04-24 19:09:08 +00:00
|
|
|
RefGroup.prototype.renderLine = function(refsList, ref) {
|
|
|
|
var ownerDoc = refsList.ownerDocument,
|
|
|
|
arrow = ownerDoc.createTextNode('↑'),
|
2015-02-19 18:06:29 +00:00
|
|
|
li, a, textSpan;
|
2013-04-24 19:09:08 +00:00
|
|
|
|
2013-05-02 16:17:08 +00:00
|
|
|
// Generate the li and set ref content first, so the HTML gets parsed.
|
2013-04-24 19:09:08 +00:00
|
|
|
// We then append the rest of the ref nodes before the first node
|
2013-05-02 16:17:08 +00:00
|
|
|
li = ownerDoc.createElement('li');
|
|
|
|
DU.addAttributes(li, {
|
|
|
|
'about': "#" + ref.target,
|
|
|
|
'id': ref.target
|
|
|
|
});
|
2015-02-19 18:06:29 +00:00
|
|
|
textSpan = ownerDoc.createElement('span');
|
|
|
|
DU.addAttributes(textSpan, {
|
|
|
|
'id': "mw-reference-text-" + ref.target,
|
|
|
|
'class': "mw-reference-text"
|
|
|
|
});
|
|
|
|
textSpan.innerHTML = ref.content;
|
|
|
|
li.appendChild(textSpan);
|
2013-05-02 16:17:08 +00:00
|
|
|
|
|
|
|
// 'mw:referencedBy' span wrapper
|
|
|
|
var span = ownerDoc.createElement('span');
|
|
|
|
span.setAttribute('rel', 'mw:referencedBy');
|
2015-02-19 18:06:29 +00:00
|
|
|
li.insertBefore(span, textSpan);
|
2013-04-24 19:09:08 +00:00
|
|
|
|
|
|
|
// Generate leading linkbacks
|
|
|
|
if (ref.linkbacks.length === 1) {
|
|
|
|
a = ownerDoc.createElement('a');
|
2013-05-02 16:17:08 +00:00
|
|
|
DU.addAttributes(a, {
|
2014-12-20 12:49:12 +00:00
|
|
|
'href': '#' + ref.id
|
2013-05-02 16:17:08 +00:00
|
|
|
});
|
2013-04-24 19:09:08 +00:00
|
|
|
a.appendChild(arrow);
|
2013-05-02 16:17:08 +00:00
|
|
|
span.appendChild(a);
|
2013-04-24 19:09:08 +00:00
|
|
|
} else {
|
2013-05-02 16:17:08 +00:00
|
|
|
span.appendChild(arrow);
|
2014-01-22 20:24:23 +00:00
|
|
|
ref.linkbacks.forEach(function(linkback, i) {
|
2013-04-24 19:09:08 +00:00
|
|
|
a = ownerDoc.createElement('a');
|
2013-05-02 16:17:08 +00:00
|
|
|
DU.addAttributes(a, {
|
|
|
|
'href': '#' + ref.linkbacks[i]
|
|
|
|
});
|
2013-04-24 19:09:08 +00:00
|
|
|
a.appendChild(ownerDoc.createTextNode(ref.groupIndex + '.' + i));
|
|
|
|
// Separate linkbacks with a space
|
2013-05-02 16:17:08 +00:00
|
|
|
span.appendChild(ownerDoc.createTextNode(' '));
|
|
|
|
span.appendChild(a);
|
2013-04-24 19:09:08 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2013-06-12 21:07:01 +00:00
|
|
|
// Space before content node
|
2015-02-19 18:06:29 +00:00
|
|
|
li.insertBefore(ownerDoc.createTextNode(' '), textSpan);
|
2013-06-12 21:07:01 +00:00
|
|
|
|
2013-04-24 19:09:08 +00:00
|
|
|
// Add it to the ref list
|
|
|
|
refsList.appendChild(li);
|
|
|
|
};
|
|
|
|
|
2015-03-31 16:52:01 +00:00
|
|
|
function ReferencesData() {
|
|
|
|
this.index = 0;
|
|
|
|
this.refGroups = new Map();
|
2013-06-12 21:01:27 +00:00
|
|
|
}
|
|
|
|
|
2015-03-31 16:52:01 +00:00
|
|
|
ReferencesData.prototype.getRefGroup = function (groupName, allocIfMissing) {
|
|
|
|
groupName = groupName || '';
|
|
|
|
if ( !this.refGroups.has( groupName ) && allocIfMissing ) {
|
|
|
|
this.refGroups.set( groupName, new RefGroup( groupName ) );
|
|
|
|
}
|
|
|
|
return this.refGroups.get( groupName );
|
|
|
|
};
|
2013-03-26 00:40:20 +00:00
|
|
|
|
2015-03-31 16:52:01 +00:00
|
|
|
ReferencesData.prototype.removeRefGroup = function (groupName) {
|
|
|
|
if (groupName !== null && groupName !== undefined) {
|
2014-03-04 23:13:43 +00:00
|
|
|
// '' is a valid group (the default group)
|
2015-03-31 16:52:01 +00:00
|
|
|
this.refGroups.delete(groupName);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
ReferencesData.prototype.add = function(groupName, refName, about, skipLinkback) {
|
|
|
|
var group = this.getRefGroup(groupName, true),
|
|
|
|
ref;
|
|
|
|
refName = makeValidIdAttr(refName);
|
|
|
|
if ( refName && group.indexByName.has( refName ) ) {
|
|
|
|
ref = group.indexByName.get( refName );
|
|
|
|
if (ref.content) {
|
|
|
|
ref.hasMultiples = true;
|
|
|
|
}
|
2013-04-24 19:09:08 +00:00
|
|
|
} else {
|
2015-03-31 16:52:01 +00:00
|
|
|
// The ids produced Cite.php have some particulars:
|
|
|
|
// Simple refs get 'cite_ref-' + index
|
|
|
|
// Refs with names get 'cite_ref-' + name + '_' + index + (backlink num || 0)
|
|
|
|
// Notes (references) whose ref doesn't have a name are 'cite_note-' + index
|
|
|
|
// Notes whose ref has a name are 'cite_note-' + name + '-' + index
|
|
|
|
var n = this.index,
|
2015-04-06 21:07:04 +00:00
|
|
|
refKey = (1 +n) + '',
|
2015-03-31 16:52:01 +00:00
|
|
|
refIdBase = 'cite_ref-' + (refName ? refName + '_' + refKey : refKey),
|
|
|
|
noteId = 'cite_note-' + (refName ? refName + '-' + refKey : refKey);
|
|
|
|
|
|
|
|
// bump index
|
|
|
|
this.index += 1;
|
|
|
|
|
|
|
|
ref = {
|
|
|
|
about: about,
|
|
|
|
content: null,
|
|
|
|
group: group.name,
|
|
|
|
groupIndex: group.refs.length + 1,
|
|
|
|
index: n,
|
|
|
|
key: refIdBase,
|
|
|
|
id: (refName ? refIdBase + '-0' : refIdBase),
|
|
|
|
linkbacks: [],
|
|
|
|
name: refName,
|
|
|
|
target: noteId
|
|
|
|
};
|
|
|
|
group.refs.push( ref );
|
|
|
|
if (refName) {
|
|
|
|
group.indexByName.set( refName, ref );
|
|
|
|
}
|
2013-04-24 19:09:08 +00:00
|
|
|
}
|
2014-01-10 21:13:20 +00:00
|
|
|
|
2015-03-31 16:52:01 +00:00
|
|
|
if (!skipLinkback) {
|
|
|
|
ref.linkbacks.push(ref.key + '-' + ref.linkbacks.length);
|
2014-01-10 21:13:20 +00:00
|
|
|
}
|
2015-03-31 16:52:01 +00:00
|
|
|
|
|
|
|
return ref;
|
Extension handling rewrite + cite extension refactoring.
Tokenization
------------
* Fixed tokenizer to correctly parse extension tags in different
contexts: with start and end tags, in self-closing tag mode,
and to correctly handle scenarios when the exension end-tag is
followed by a '#' (the special char used to skip over extension
content).
* Removed the distinction in the tokenizer between installed
extensions and natively supported extension tags (<ref> and
<references> for ex.). They all tokenize and get processed
identically and get handled by different paths in the extension
handler.
* Template and TemplateArg tokens now carry tpl. transclusion
source alongwith them since tsr information will not be
accurate when they show up in extension contexts that in turn
showed up in template context that were expanded by the php
preprocessor.
Ex: {{echo|<ref>{{echo|foo}}</ref>}}
The tsr for the ref-tag will correspond to the
template-source of the echo-template, NOT the original top-level
page. So, env.page.src.substring(..) will return incorrect
source for the innermost {{echo|foo}}. This fix of carrying
along tpl transclusion source in the token itself eliminates
this problem.
Knowledge of native extensions
------------------------------
* Natively implemented extension tags (<ref> and <references>)
are hardcoded in env.conf.parsoid. At some point, it would
be good to have a registration mechanism for parsoid-native
extensions.
Extension handling
------------------
* Extracted extension handling out of the template handler into
its own handler class. Right now, this class inherits from the
template handler in order to be able to reuse a lot of the
expansion and encapsulation functionality currently in the
Template Handler.
* This handler now handles extensions that are:
(a) natively implemented and registered with Parsoid.
(b) implemented as a PHP extension and expanded by relying on
the PHP preprocessor.
For (a), it uses information from env.conf.parsoid to find
ext-handlers for natively implemented ext-tags. However, this
can be cleaned up at some point by making available a registration
mechanism.
Cite/Ref/References
-------------------
* Reworked the cite handler to split up ref-token processing
and references token processing.
* The handler now processes ref-tokens, parses content all
the way to html output and encapsulates the html in an
attribute of a meta-token that serves as a placeholder for
where the ref-token occured.
* References are handled as a DOM post-pass where these meta
placeholder tokens are collected, content extracted from
the attribute and spit out at the site of a references tag.
The DOM walking is in DOMPostProcessor.js, but the actual
processing is part of the Cite.js to keep all cite extension
handling code in one place.
Parser pipeline
---------------
* Restructured parser pipeline recipes based on changes to Cite,
TemplateHandler, and ExtensionHandler.
* Added a couple functions to the parser pipeline:
1. resetState to reset state before starting a new top-level parse
when pipelines are reused across top-level parses (ex: parser
tests)
2. setSourceOffsets to set start/end offsets of the source being
handled by the pipeline. This is required to correctly set tsr
values when extension content (which is a substring of original
top-level text) is parsed in its own pipeline.
Other fixes
-----------
* Removed env parameter from the Params object since it was not
being used and seemed like unnecessary state propagation.
* Removed a FIXME in DOMUtils.buildTokensFromDOM by reusing code
in the tokenizer that converts "\n" in text to NlTks.
* Cleanup of Util.shiftTokenTSR.
* ext.util.TokenCollection is now no longer used by anything.
Added a FIXME and left around in case we are able to improve
tokenizing and handling of *include* tags that can eliminate the
need for the messy TokenAndAttrCollector.
Test results
------------
* No change in parser tests results.
* Tested with a few different files.
- en:BO page seems to be parsed about 10% faster than before
(needs verification).
- Referencs on the en:BO page seem to be more accurate than
before.
Change-Id: I8a095fa9fa976c7b3a2a4bd968dc9db4270b105f
2013-03-09 00:07:59 +00:00
|
|
|
};
|
2012-09-17 19:46:44 +00:00
|
|
|
|
2015-03-31 16:52:01 +00:00
|
|
|
function References(cite) {
|
|
|
|
this.cite = cite;
|
|
|
|
this.reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
References.prototype.reset = function() {};
|
|
|
|
|
Extension handling rewrite + cite extension refactoring.
Tokenization
------------
* Fixed tokenizer to correctly parse extension tags in different
contexts: with start and end tags, in self-closing tag mode,
and to correctly handle scenarios when the exension end-tag is
followed by a '#' (the special char used to skip over extension
content).
* Removed the distinction in the tokenizer between installed
extensions and natively supported extension tags (<ref> and
<references> for ex.). They all tokenize and get processed
identically and get handled by different paths in the extension
handler.
* Template and TemplateArg tokens now carry tpl. transclusion
source alongwith them since tsr information will not be
accurate when they show up in extension contexts that in turn
showed up in template context that were expanded by the php
preprocessor.
Ex: {{echo|<ref>{{echo|foo}}</ref>}}
The tsr for the ref-tag will correspond to the
template-source of the echo-template, NOT the original top-level
page. So, env.page.src.substring(..) will return incorrect
source for the innermost {{echo|foo}}. This fix of carrying
along tpl transclusion source in the token itself eliminates
this problem.
Knowledge of native extensions
------------------------------
* Natively implemented extension tags (<ref> and <references>)
are hardcoded in env.conf.parsoid. At some point, it would
be good to have a registration mechanism for parsoid-native
extensions.
Extension handling
------------------
* Extracted extension handling out of the template handler into
its own handler class. Right now, this class inherits from the
template handler in order to be able to reuse a lot of the
expansion and encapsulation functionality currently in the
Template Handler.
* This handler now handles extensions that are:
(a) natively implemented and registered with Parsoid.
(b) implemented as a PHP extension and expanded by relying on
the PHP preprocessor.
For (a), it uses information from env.conf.parsoid to find
ext-handlers for natively implemented ext-tags. However, this
can be cleaned up at some point by making available a registration
mechanism.
Cite/Ref/References
-------------------
* Reworked the cite handler to split up ref-token processing
and references token processing.
* The handler now processes ref-tokens, parses content all
the way to html output and encapsulates the html in an
attribute of a meta-token that serves as a placeholder for
where the ref-token occured.
* References are handled as a DOM post-pass where these meta
placeholder tokens are collected, content extracted from
the attribute and spit out at the site of a references tag.
The DOM walking is in DOMPostProcessor.js, but the actual
processing is part of the Cite.js to keep all cite extension
handling code in one place.
Parser pipeline
---------------
* Restructured parser pipeline recipes based on changes to Cite,
TemplateHandler, and ExtensionHandler.
* Added a couple functions to the parser pipeline:
1. resetState to reset state before starting a new top-level parse
when pipelines are reused across top-level parses (ex: parser
tests)
2. setSourceOffsets to set start/end offsets of the source being
handled by the pipeline. This is required to correctly set tsr
values when extension content (which is a substring of original
top-level text) is parsed in its own pipeline.
Other fixes
-----------
* Removed env parameter from the Params object since it was not
being used and seemed like unnecessary state propagation.
* Removed a FIXME in DOMUtils.buildTokensFromDOM by reusing code
in the tokenizer that converts "\n" in text to NlTks.
* Cleanup of Util.shiftTokenTSR.
* ext.util.TokenCollection is now no longer used by anything.
Added a FIXME and left around in case we are able to improve
tokenizing and handling of *include* tags that can eliminate the
need for the messy TokenAndAttrCollector.
Test results
------------
* No change in parser tests results.
* Tested with a few different files.
- en:BO page seems to be parsed about 10% faster than before
(needs verification).
- Referencs on the en:BO page seem to be more accurate than
before.
Change-Id: I8a095fa9fa976c7b3a2a4bd968dc9db4270b105f
2013-03-09 00:07:59 +00:00
|
|
|
/**
|
|
|
|
* Sanitize the references tag and convert it into a meta-token
|
|
|
|
*/
|
2013-03-26 00:40:20 +00:00
|
|
|
References.prototype.handleReferences = function ( manager, pipelineOpts, refsTok, cb ) {
|
2014-03-14 19:39:00 +00:00
|
|
|
var env = manager.env;
|
2013-02-20 23:50:52 +00:00
|
|
|
|
Extension handling rewrite + cite extension refactoring.
Tokenization
------------
* Fixed tokenizer to correctly parse extension tags in different
contexts: with start and end tags, in self-closing tag mode,
and to correctly handle scenarios when the exension end-tag is
followed by a '#' (the special char used to skip over extension
content).
* Removed the distinction in the tokenizer between installed
extensions and natively supported extension tags (<ref> and
<references> for ex.). They all tokenize and get processed
identically and get handled by different paths in the extension
handler.
* Template and TemplateArg tokens now carry tpl. transclusion
source alongwith them since tsr information will not be
accurate when they show up in extension contexts that in turn
showed up in template context that were expanded by the php
preprocessor.
Ex: {{echo|<ref>{{echo|foo}}</ref>}}
The tsr for the ref-tag will correspond to the
template-source of the echo-template, NOT the original top-level
page. So, env.page.src.substring(..) will return incorrect
source for the innermost {{echo|foo}}. This fix of carrying
along tpl transclusion source in the token itself eliminates
this problem.
Knowledge of native extensions
------------------------------
* Natively implemented extension tags (<ref> and <references>)
are hardcoded in env.conf.parsoid. At some point, it would
be good to have a registration mechanism for parsoid-native
extensions.
Extension handling
------------------
* Extracted extension handling out of the template handler into
its own handler class. Right now, this class inherits from the
template handler in order to be able to reuse a lot of the
expansion and encapsulation functionality currently in the
Template Handler.
* This handler now handles extensions that are:
(a) natively implemented and registered with Parsoid.
(b) implemented as a PHP extension and expanded by relying on
the PHP preprocessor.
For (a), it uses information from env.conf.parsoid to find
ext-handlers for natively implemented ext-tags. However, this
can be cleaned up at some point by making available a registration
mechanism.
Cite/Ref/References
-------------------
* Reworked the cite handler to split up ref-token processing
and references token processing.
* The handler now processes ref-tokens, parses content all
the way to html output and encapsulates the html in an
attribute of a meta-token that serves as a placeholder for
where the ref-token occured.
* References are handled as a DOM post-pass where these meta
placeholder tokens are collected, content extracted from
the attribute and spit out at the site of a references tag.
The DOM walking is in DOMPostProcessor.js, but the actual
processing is part of the Cite.js to keep all cite extension
handling code in one place.
Parser pipeline
---------------
* Restructured parser pipeline recipes based on changes to Cite,
TemplateHandler, and ExtensionHandler.
* Added a couple functions to the parser pipeline:
1. resetState to reset state before starting a new top-level parse
when pipelines are reused across top-level parses (ex: parser
tests)
2. setSourceOffsets to set start/end offsets of the source being
handled by the pipeline. This is required to correctly set tsr
values when extension content (which is a substring of original
top-level text) is parsed in its own pipeline.
Other fixes
-----------
* Removed env parameter from the Params object since it was not
being used and seemed like unnecessary state propagation.
* Removed a FIXME in DOMUtils.buildTokensFromDOM by reusing code
in the tokenizer that converts "\n" in text to NlTks.
* Cleanup of Util.shiftTokenTSR.
* ext.util.TokenCollection is now no longer used by anything.
Added a FIXME and left around in case we are able to improve
tokenizing and handling of *include* tags that can eliminate the
need for the messy TokenAndAttrCollector.
Test results
------------
* No change in parser tests results.
* Tested with a few different files.
- en:BO page seems to be parsed about 10% faster than before
(needs verification).
- Referencs on the en:BO page seem to be more accurate than
before.
Change-Id: I8a095fa9fa976c7b3a2a4bd968dc9db4270b105f
2013-03-09 00:07:59 +00:00
|
|
|
// group is the only recognized option?
|
2014-04-14 23:04:31 +00:00
|
|
|
var refsOpts = Object.assign({
|
|
|
|
group: null
|
|
|
|
}, Util.KVtoHash(refsTok.getAttribute("options"), true));
|
2012-11-27 23:13:32 +00:00
|
|
|
|
2013-07-24 00:15:45 +00:00
|
|
|
// Assign an about id and intialize the nested refs html
|
2014-03-14 19:39:00 +00:00
|
|
|
var referencesId = env.newAboutId();
|
2013-07-24 00:15:45 +00:00
|
|
|
|
2013-06-26 17:35:08 +00:00
|
|
|
// Emit a marker mw:DOMFragment for the references
|
|
|
|
// token so that the dom post processor can generate
|
|
|
|
// and emit references at this point in the DOM.
|
2014-03-04 23:13:43 +00:00
|
|
|
var emitReferencesFragment = function(toks, refsBody) {
|
2014-01-21 22:03:26 +00:00
|
|
|
var type = refsTok.getAttribute('typeof');
|
|
|
|
var olHTML = "<ol class='references'" +
|
|
|
|
" typeof='mw:Extension/references'" +
|
2014-03-04 23:13:43 +00:00
|
|
|
" about='" + referencesId + "'" + ">" + (refsBody || "") + "</ol>";
|
2014-01-21 22:03:26 +00:00
|
|
|
var olProcessor = function(ol) {
|
|
|
|
var dp = DU.getDataParsoid( ol );
|
|
|
|
dp.src = refsTok.getAttribute('source');
|
2014-04-14 23:04:31 +00:00
|
|
|
if ( refsOpts.group ) {
|
|
|
|
dp.group = refsOpts.group;
|
2014-01-21 22:03:26 +00:00
|
|
|
}
|
2014-09-08 20:10:25 +00:00
|
|
|
DU.storeDataParsoid( ol, dp );
|
2013-06-26 17:35:08 +00:00
|
|
|
};
|
|
|
|
|
2014-01-21 22:03:26 +00:00
|
|
|
cb({
|
|
|
|
async: false,
|
2014-02-20 23:03:09 +00:00
|
|
|
tokens: DU.buildDOMFragmentTokens(
|
|
|
|
manager.env,
|
2014-01-21 22:03:26 +00:00
|
|
|
refsTok,
|
|
|
|
olHTML,
|
|
|
|
olProcessor,
|
2014-03-04 23:13:43 +00:00
|
|
|
// The <ol> HTML above is wrapper HTML added on and doesn't
|
|
|
|
// have any DSR on it. We want DSR added to it.
|
2014-01-21 22:03:26 +00:00
|
|
|
{ aboutId: referencesId, setDSR: true, isForeignContent: true }
|
|
|
|
)
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2013-03-26 00:40:20 +00:00
|
|
|
processExtSource(manager, refsTok, {
|
|
|
|
// Partial pipeline for processing ref-content
|
|
|
|
// Expand till stage 2 so that all embedded
|
|
|
|
// ref tags get processed
|
2014-03-04 23:13:43 +00:00
|
|
|
pipelineType: 'text/x-mediawiki/full',
|
2013-03-26 00:40:20 +00:00
|
|
|
pipelineOpts: {
|
2014-03-04 23:13:43 +00:00
|
|
|
// In order to associated ref-tags nested here with this references
|
|
|
|
// object, we have to pass along the references id.
|
2013-03-26 00:40:20 +00:00
|
|
|
extTag: "references",
|
2014-03-04 23:13:43 +00:00
|
|
|
extTagId: referencesId,
|
2014-03-07 17:35:58 +00:00
|
|
|
wrapTemplates: pipelineOpts.wrapTemplates,
|
|
|
|
inTemplate: pipelineOpts.inTemplate
|
2013-03-26 00:40:20 +00:00
|
|
|
},
|
|
|
|
res: [],
|
|
|
|
parentCB: cb,
|
2013-06-26 17:35:08 +00:00
|
|
|
emptyContentCB: emitReferencesFragment,
|
2014-03-04 23:13:43 +00:00
|
|
|
endCB: emitReferencesFragment,
|
|
|
|
documentCB: function(refsDoc) {
|
2014-09-08 20:10:25 +00:00
|
|
|
emitReferencesFragment([], DU.serializeChildren(refsDoc.body));
|
2014-03-04 23:13:43 +00:00
|
|
|
}
|
2013-03-26 00:40:20 +00:00
|
|
|
});
|
Extension handling rewrite + cite extension refactoring.
Tokenization
------------
* Fixed tokenizer to correctly parse extension tags in different
contexts: with start and end tags, in self-closing tag mode,
and to correctly handle scenarios when the exension end-tag is
followed by a '#' (the special char used to skip over extension
content).
* Removed the distinction in the tokenizer between installed
extensions and natively supported extension tags (<ref> and
<references> for ex.). They all tokenize and get processed
identically and get handled by different paths in the extension
handler.
* Template and TemplateArg tokens now carry tpl. transclusion
source alongwith them since tsr information will not be
accurate when they show up in extension contexts that in turn
showed up in template context that were expanded by the php
preprocessor.
Ex: {{echo|<ref>{{echo|foo}}</ref>}}
The tsr for the ref-tag will correspond to the
template-source of the echo-template, NOT the original top-level
page. So, env.page.src.substring(..) will return incorrect
source for the innermost {{echo|foo}}. This fix of carrying
along tpl transclusion source in the token itself eliminates
this problem.
Knowledge of native extensions
------------------------------
* Natively implemented extension tags (<ref> and <references>)
are hardcoded in env.conf.parsoid. At some point, it would
be good to have a registration mechanism for parsoid-native
extensions.
Extension handling
------------------
* Extracted extension handling out of the template handler into
its own handler class. Right now, this class inherits from the
template handler in order to be able to reuse a lot of the
expansion and encapsulation functionality currently in the
Template Handler.
* This handler now handles extensions that are:
(a) natively implemented and registered with Parsoid.
(b) implemented as a PHP extension and expanded by relying on
the PHP preprocessor.
For (a), it uses information from env.conf.parsoid to find
ext-handlers for natively implemented ext-tags. However, this
can be cleaned up at some point by making available a registration
mechanism.
Cite/Ref/References
-------------------
* Reworked the cite handler to split up ref-token processing
and references token processing.
* The handler now processes ref-tokens, parses content all
the way to html output and encapsulates the html in an
attribute of a meta-token that serves as a placeholder for
where the ref-token occured.
* References are handled as a DOM post-pass where these meta
placeholder tokens are collected, content extracted from
the attribute and spit out at the site of a references tag.
The DOM walking is in DOMPostProcessor.js, but the actual
processing is part of the Cite.js to keep all cite extension
handling code in one place.
Parser pipeline
---------------
* Restructured parser pipeline recipes based on changes to Cite,
TemplateHandler, and ExtensionHandler.
* Added a couple functions to the parser pipeline:
1. resetState to reset state before starting a new top-level parse
when pipelines are reused across top-level parses (ex: parser
tests)
2. setSourceOffsets to set start/end offsets of the source being
handled by the pipeline. This is required to correctly set tsr
values when extension content (which is a substring of original
top-level text) is parsed in its own pipeline.
Other fixes
-----------
* Removed env parameter from the Params object since it was not
being used and seemed like unnecessary state propagation.
* Removed a FIXME in DOMUtils.buildTokensFromDOM by reusing code
in the tokenizer that converts "\n" in text to NlTks.
* Cleanup of Util.shiftTokenTSR.
* ext.util.TokenCollection is now no longer used by anything.
Added a FIXME and left around in case we are able to improve
tokenizing and handling of *include* tags that can eliminate the
need for the messy TokenAndAttrCollector.
Test results
------------
* No change in parser tests results.
* Tested with a few different files.
- en:BO page seems to be parsed about 10% faster than before
(needs verification).
- Referencs on the en:BO page seem to be more accurate than
before.
Change-Id: I8a095fa9fa976c7b3a2a4bd968dc9db4270b105f
2013-03-09 00:07:59 +00:00
|
|
|
};
|
|
|
|
|
2015-03-31 16:52:01 +00:00
|
|
|
References.prototype.extractRefFromNode = function(node, refsData,
|
|
|
|
refInRefProcessor, referencesAboutId, referencesGroup, refsInReferencesHTML) {
|
2014-08-21 23:16:32 +00:00
|
|
|
var nestedInReferences = referencesAboutId !== undefined,
|
2014-07-01 18:04:31 +00:00
|
|
|
dp = DU.getDataParsoid( node ),
|
|
|
|
// SSS FIXME: Need to clarify semantics here.
|
|
|
|
// If both the containing <references> elt as well as the nested <ref> elt has
|
|
|
|
// a group attribute, what takes precedence?
|
|
|
|
group = dp.group || referencesGroup || '',
|
|
|
|
refName = dp.name,
|
2013-04-24 19:09:08 +00:00
|
|
|
about = node.getAttribute("about"),
|
2015-03-31 16:52:01 +00:00
|
|
|
ref = refsData.add(group, refName, about, nestedInReferences),
|
2013-06-16 22:14:25 +00:00
|
|
|
nodeType = (node.getAttribute("typeof") || '').replace(/mw:Extension\/ref\/Marker/, '');
|
2013-04-24 19:09:08 +00:00
|
|
|
|
|
|
|
// Add ref-index linkback
|
2013-07-24 00:15:45 +00:00
|
|
|
var doc = node.ownerDocument,
|
|
|
|
span = doc.createElement('span'),
|
2014-07-01 18:04:31 +00:00
|
|
|
content = dp.content,
|
2015-02-27 19:11:37 +00:00
|
|
|
dataMW = Util.clone(DU.getDataMw(node)),
|
|
|
|
body;
|
2013-06-16 22:14:25 +00:00
|
|
|
|
2014-08-21 23:16:32 +00:00
|
|
|
if (dp.hasRefInRef) {
|
|
|
|
var html = DU.parseHTML(content).body;
|
2015-03-26 16:47:59 +00:00
|
|
|
refInRefProcessor(html);
|
2014-08-21 23:16:32 +00:00
|
|
|
content = DU.serializeChildren(html);
|
|
|
|
}
|
|
|
|
|
2015-02-27 19:11:37 +00:00
|
|
|
if (content) {
|
|
|
|
// If there are multiple <ref>s with the same name, but different
|
|
|
|
// content, we need to record this one's content instead of
|
|
|
|
// linking to <references>.
|
|
|
|
if (ref.hasMultiples && content !== ref.content) {
|
|
|
|
body = {'html': content};
|
|
|
|
} else {
|
|
|
|
body = {'id': "mw-reference-text-" + ref.target};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-08 20:10:25 +00:00
|
|
|
if (!Object.keys(dataMW).length) {
|
|
|
|
dataMW = {
|
2013-07-24 00:15:45 +00:00
|
|
|
'name': 'ref',
|
|
|
|
// Dont set body if this is a reused reference
|
|
|
|
// like <ref name='..' /> with empty content.
|
2015-02-27 19:11:37 +00:00
|
|
|
'body': body,
|
2013-07-24 00:15:45 +00:00
|
|
|
'attrs': {
|
2014-07-01 18:04:31 +00:00
|
|
|
// 1. Use 'dp.group' (which is the group attribute that the ref node had)
|
|
|
|
// rather than use 'group' (which could be the group from an enclosing
|
|
|
|
// <references> tag).
|
|
|
|
// 2. Dont emit empty keys
|
|
|
|
'group': dp.group || undefined,
|
2013-07-24 00:15:45 +00:00
|
|
|
'name': refName || undefined
|
Add capability for DOM-based template expansion, and use DOM fragments for extensions
This patch adds the capability to expand individual transclusions all the way
to DOM, which enforces properly nested templates. This is also needed for
DOM-based template re-expansion, which the VE folks would like to use for
template editing.
In normal parsing, DOM-based expansion is currently disabled by default for
transclusions, and enabled by default for extensions. The decision whether to
balance a particular transclusion can be based on a statistics-based
classification of templates into balanced and unbalanced ones. The advantage
of this approach is consistency in behavior for old revisions. Another
alternative is to wrap unbalanced transclusions into <domparse> tags which
disable DOM-based parsing for all transclusions in its content. This has the
advantage that all special cases can be handled after tag insertion, and that
balancing could also be enforced in the PHP parser using an extension.
Other major changes:
* Renamed transclusion content typeof from mw:Object/Template to
mw:Transclusion
* Renamed extension typeof from mw:Object/Extensions/foo to mw:Extension/foo
and switched Cite to use lower-case ref/references too
Other minor changes:
* Only apply template encapsulation algorithm on DOM to mw:Transclusion and
mw:Param objects, and no longer to all mw:Object/* elements. We should
probably switch to a more explicit encapsulation type instead. Maybe
something like mw:EncapStart/Transclusion and mw:EncapEnd/Transclusion
instead of the current mw:Transclusion and mw:Transclusion/End, so that
stripping those metas out selectively is easy?
* Changed the DOMTraverser logic to let handlers explicitly return the next
element to handle. Useful when several siblings are handled, as is the case
for the fragment unwrapper for example, and avoids some cases where deleted
nodes were still being processed.
* Changed Cite to use mw:Extension/Ref{,erences} as all other extensions.
* Make sure we round-trip gallery when the PHP preprocessor is not used
Five parsoid-specific wt2html tests are failing due to the typeof change.
They will be fine once those tests are adjusted. For now, adding them
to parser tests blacklist.
TODO:
* Switch the Cite extension to the generic DOMFragment mechanism instead of
marker tokens.
Change-Id: I64b560a12695256915d2196d0646347381400e80
2013-05-16 22:23:05 +00:00
|
|
|
}
|
2014-09-08 20:10:25 +00:00
|
|
|
};
|
2013-07-24 00:15:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
DU.addAttributes(span, {
|
|
|
|
'about': about,
|
|
|
|
'class': 'reference',
|
2014-12-20 12:49:12 +00:00
|
|
|
'id': nestedInReferences ? undefined :
|
|
|
|
(ref.name ? ref.linkbacks[ref.linkbacks.length - 1] : ref.id),
|
2013-07-24 00:15:45 +00:00
|
|
|
'rel': 'dc:references',
|
|
|
|
'typeof': nodeType
|
|
|
|
});
|
|
|
|
DU.addTypeOf(span, "mw:Extension/ref");
|
2014-09-08 20:10:25 +00:00
|
|
|
var dataParsoid = {
|
|
|
|
src: dp.src,
|
|
|
|
dsr: dp.dsr
|
|
|
|
};
|
|
|
|
DU.setDataParsoid( span, dataParsoid );
|
|
|
|
DU.setDataMw( span, dataMW );
|
2013-04-24 19:09:08 +00:00
|
|
|
|
2013-07-24 00:15:45 +00:00
|
|
|
// refIndex-a
|
|
|
|
var refIndex = doc.createElement('a');
|
|
|
|
refIndex.setAttribute('href', '#' + ref.target);
|
|
|
|
refIndex.appendChild(doc.createTextNode(
|
|
|
|
'[' + ((group === '') ? '' : group + ' ') + ref.groupIndex + ']'
|
|
|
|
));
|
|
|
|
span.appendChild(refIndex);
|
|
|
|
|
2014-08-21 23:16:32 +00:00
|
|
|
if (!nestedInReferences) {
|
2013-04-24 19:09:08 +00:00
|
|
|
node.parentNode.insertBefore(span, node);
|
2013-07-24 00:15:45 +00:00
|
|
|
} else {
|
2014-09-08 20:10:25 +00:00
|
|
|
DU.storeDataParsoid( span, dataParsoid );
|
|
|
|
DU.storeDataMw( span, dataMW );
|
|
|
|
refsInReferencesHTML.push( DU.serializeNode(span), "\n" );
|
2013-04-24 19:09:08 +00:00
|
|
|
}
|
Extension handling rewrite + cite extension refactoring.
Tokenization
------------
* Fixed tokenizer to correctly parse extension tags in different
contexts: with start and end tags, in self-closing tag mode,
and to correctly handle scenarios when the exension end-tag is
followed by a '#' (the special char used to skip over extension
content).
* Removed the distinction in the tokenizer between installed
extensions and natively supported extension tags (<ref> and
<references> for ex.). They all tokenize and get processed
identically and get handled by different paths in the extension
handler.
* Template and TemplateArg tokens now carry tpl. transclusion
source alongwith them since tsr information will not be
accurate when they show up in extension contexts that in turn
showed up in template context that were expanded by the php
preprocessor.
Ex: {{echo|<ref>{{echo|foo}}</ref>}}
The tsr for the ref-tag will correspond to the
template-source of the echo-template, NOT the original top-level
page. So, env.page.src.substring(..) will return incorrect
source for the innermost {{echo|foo}}. This fix of carrying
along tpl transclusion source in the token itself eliminates
this problem.
Knowledge of native extensions
------------------------------
* Natively implemented extension tags (<ref> and <references>)
are hardcoded in env.conf.parsoid. At some point, it would
be good to have a registration mechanism for parsoid-native
extensions.
Extension handling
------------------
* Extracted extension handling out of the template handler into
its own handler class. Right now, this class inherits from the
template handler in order to be able to reuse a lot of the
expansion and encapsulation functionality currently in the
Template Handler.
* This handler now handles extensions that are:
(a) natively implemented and registered with Parsoid.
(b) implemented as a PHP extension and expanded by relying on
the PHP preprocessor.
For (a), it uses information from env.conf.parsoid to find
ext-handlers for natively implemented ext-tags. However, this
can be cleaned up at some point by making available a registration
mechanism.
Cite/Ref/References
-------------------
* Reworked the cite handler to split up ref-token processing
and references token processing.
* The handler now processes ref-tokens, parses content all
the way to html output and encapsulates the html in an
attribute of a meta-token that serves as a placeholder for
where the ref-token occured.
* References are handled as a DOM post-pass where these meta
placeholder tokens are collected, content extracted from
the attribute and spit out at the site of a references tag.
The DOM walking is in DOMPostProcessor.js, but the actual
processing is part of the Cite.js to keep all cite extension
handling code in one place.
Parser pipeline
---------------
* Restructured parser pipeline recipes based on changes to Cite,
TemplateHandler, and ExtensionHandler.
* Added a couple functions to the parser pipeline:
1. resetState to reset state before starting a new top-level parse
when pipelines are reused across top-level parses (ex: parser
tests)
2. setSourceOffsets to set start/end offsets of the source being
handled by the pipeline. This is required to correctly set tsr
values when extension content (which is a substring of original
top-level text) is parsed in its own pipeline.
Other fixes
-----------
* Removed env parameter from the Params object since it was not
being used and seemed like unnecessary state propagation.
* Removed a FIXME in DOMUtils.buildTokensFromDOM by reusing code
in the tokenizer that converts "\n" in text to NlTks.
* Cleanup of Util.shiftTokenTSR.
* ext.util.TokenCollection is now no longer used by anything.
Added a FIXME and left around in case we are able to improve
tokenizing and handling of *include* tags that can eliminate the
need for the messy TokenAndAttrCollector.
Test results
------------
* No change in parser tests results.
* Tested with a few different files.
- en:BO page seems to be parsed about 10% faster than before
(needs verification).
- Referencs on the en:BO page seem to be more accurate than
before.
Change-Id: I8a095fa9fa976c7b3a2a4bd968dc9db4270b105f
2013-03-09 00:07:59 +00:00
|
|
|
|
2015-02-27 19:11:37 +00:00
|
|
|
// Keep the first content to compare multiple <ref>s with the same name.
|
Extension handling rewrite + cite extension refactoring.
Tokenization
------------
* Fixed tokenizer to correctly parse extension tags in different
contexts: with start and end tags, in self-closing tag mode,
and to correctly handle scenarios when the exension end-tag is
followed by a '#' (the special char used to skip over extension
content).
* Removed the distinction in the tokenizer between installed
extensions and natively supported extension tags (<ref> and
<references> for ex.). They all tokenize and get processed
identically and get handled by different paths in the extension
handler.
* Template and TemplateArg tokens now carry tpl. transclusion
source alongwith them since tsr information will not be
accurate when they show up in extension contexts that in turn
showed up in template context that were expanded by the php
preprocessor.
Ex: {{echo|<ref>{{echo|foo}}</ref>}}
The tsr for the ref-tag will correspond to the
template-source of the echo-template, NOT the original top-level
page. So, env.page.src.substring(..) will return incorrect
source for the innermost {{echo|foo}}. This fix of carrying
along tpl transclusion source in the token itself eliminates
this problem.
Knowledge of native extensions
------------------------------
* Natively implemented extension tags (<ref> and <references>)
are hardcoded in env.conf.parsoid. At some point, it would
be good to have a registration mechanism for parsoid-native
extensions.
Extension handling
------------------
* Extracted extension handling out of the template handler into
its own handler class. Right now, this class inherits from the
template handler in order to be able to reuse a lot of the
expansion and encapsulation functionality currently in the
Template Handler.
* This handler now handles extensions that are:
(a) natively implemented and registered with Parsoid.
(b) implemented as a PHP extension and expanded by relying on
the PHP preprocessor.
For (a), it uses information from env.conf.parsoid to find
ext-handlers for natively implemented ext-tags. However, this
can be cleaned up at some point by making available a registration
mechanism.
Cite/Ref/References
-------------------
* Reworked the cite handler to split up ref-token processing
and references token processing.
* The handler now processes ref-tokens, parses content all
the way to html output and encapsulates the html in an
attribute of a meta-token that serves as a placeholder for
where the ref-token occured.
* References are handled as a DOM post-pass where these meta
placeholder tokens are collected, content extracted from
the attribute and spit out at the site of a references tag.
The DOM walking is in DOMPostProcessor.js, but the actual
processing is part of the Cite.js to keep all cite extension
handling code in one place.
Parser pipeline
---------------
* Restructured parser pipeline recipes based on changes to Cite,
TemplateHandler, and ExtensionHandler.
* Added a couple functions to the parser pipeline:
1. resetState to reset state before starting a new top-level parse
when pipelines are reused across top-level parses (ex: parser
tests)
2. setSourceOffsets to set start/end offsets of the source being
handled by the pipeline. This is required to correctly set tsr
values when extension content (which is a substring of original
top-level text) is parsed in its own pipeline.
Other fixes
-----------
* Removed env parameter from the Params object since it was not
being used and seemed like unnecessary state propagation.
* Removed a FIXME in DOMUtils.buildTokensFromDOM by reusing code
in the tokenizer that converts "\n" in text to NlTks.
* Cleanup of Util.shiftTokenTSR.
* ext.util.TokenCollection is now no longer used by anything.
Added a FIXME and left around in case we are able to improve
tokenizing and handling of *include* tags that can eliminate the
need for the messy TokenAndAttrCollector.
Test results
------------
* No change in parser tests results.
* Tested with a few different files.
- en:BO page seems to be parsed about 10% faster than before
(needs verification).
- Referencs on the en:BO page seem to be more accurate than
before.
Change-Id: I8a095fa9fa976c7b3a2a4bd968dc9db4270b105f
2013-03-09 00:07:59 +00:00
|
|
|
if (!ref.content) {
|
2014-08-21 23:16:32 +00:00
|
|
|
ref.content = content;
|
2012-05-03 11:05:28 +00:00
|
|
|
}
|
Extension handling rewrite + cite extension refactoring.
Tokenization
------------
* Fixed tokenizer to correctly parse extension tags in different
contexts: with start and end tags, in self-closing tag mode,
and to correctly handle scenarios when the exension end-tag is
followed by a '#' (the special char used to skip over extension
content).
* Removed the distinction in the tokenizer between installed
extensions and natively supported extension tags (<ref> and
<references> for ex.). They all tokenize and get processed
identically and get handled by different paths in the extension
handler.
* Template and TemplateArg tokens now carry tpl. transclusion
source alongwith them since tsr information will not be
accurate when they show up in extension contexts that in turn
showed up in template context that were expanded by the php
preprocessor.
Ex: {{echo|<ref>{{echo|foo}}</ref>}}
The tsr for the ref-tag will correspond to the
template-source of the echo-template, NOT the original top-level
page. So, env.page.src.substring(..) will return incorrect
source for the innermost {{echo|foo}}. This fix of carrying
along tpl transclusion source in the token itself eliminates
this problem.
Knowledge of native extensions
------------------------------
* Natively implemented extension tags (<ref> and <references>)
are hardcoded in env.conf.parsoid. At some point, it would
be good to have a registration mechanism for parsoid-native
extensions.
Extension handling
------------------
* Extracted extension handling out of the template handler into
its own handler class. Right now, this class inherits from the
template handler in order to be able to reuse a lot of the
expansion and encapsulation functionality currently in the
Template Handler.
* This handler now handles extensions that are:
(a) natively implemented and registered with Parsoid.
(b) implemented as a PHP extension and expanded by relying on
the PHP preprocessor.
For (a), it uses information from env.conf.parsoid to find
ext-handlers for natively implemented ext-tags. However, this
can be cleaned up at some point by making available a registration
mechanism.
Cite/Ref/References
-------------------
* Reworked the cite handler to split up ref-token processing
and references token processing.
* The handler now processes ref-tokens, parses content all
the way to html output and encapsulates the html in an
attribute of a meta-token that serves as a placeholder for
where the ref-token occured.
* References are handled as a DOM post-pass where these meta
placeholder tokens are collected, content extracted from
the attribute and spit out at the site of a references tag.
The DOM walking is in DOMPostProcessor.js, but the actual
processing is part of the Cite.js to keep all cite extension
handling code in one place.
Parser pipeline
---------------
* Restructured parser pipeline recipes based on changes to Cite,
TemplateHandler, and ExtensionHandler.
* Added a couple functions to the parser pipeline:
1. resetState to reset state before starting a new top-level parse
when pipelines are reused across top-level parses (ex: parser
tests)
2. setSourceOffsets to set start/end offsets of the source being
handled by the pipeline. This is required to correctly set tsr
values when extension content (which is a substring of original
top-level text) is parsed in its own pipeline.
Other fixes
-----------
* Removed env parameter from the Params object since it was not
being used and seemed like unnecessary state propagation.
* Removed a FIXME in DOMUtils.buildTokensFromDOM by reusing code
in the tokenizer that converts "\n" in text to NlTks.
* Cleanup of Util.shiftTokenTSR.
* ext.util.TokenCollection is now no longer used by anything.
Added a FIXME and left around in case we are able to improve
tokenizing and handling of *include* tags that can eliminate the
need for the messy TokenAndAttrCollector.
Test results
------------
* No change in parser tests results.
* Tested with a few different files.
- en:BO page seems to be parsed about 10% faster than before
(needs verification).
- Referencs on the en:BO page seem to be more accurate than
before.
Change-Id: I8a095fa9fa976c7b3a2a4bd968dc9db4270b105f
2013-03-09 00:07:59 +00:00
|
|
|
};
|
|
|
|
|
2015-03-31 16:52:01 +00:00
|
|
|
References.prototype.insertReferencesIntoDOM = function(refsNode, refsData, refsInReferencesHTML) {
|
2013-06-27 00:56:44 +00:00
|
|
|
var about = refsNode.getAttribute('about'),
|
2014-01-08 21:18:44 +00:00
|
|
|
dp = DU.getDataParsoid( refsNode ),
|
|
|
|
group = dp.group || '',
|
|
|
|
src = dp.src || '<references/>', // fall back so we don't crash
|
2013-06-05 16:06:10 +00:00
|
|
|
// Extract ext-source for <references>..</references> usage
|
Enable wrapped extensions to parse and RT correctly
* Temporarily hacked sanitizer to pass through typeof attribute
so that mw:DOMFragment wrapper for extension tags can get to
the DOM post processor and get unwrapped.
* Implemented getArgDict for the extension handler since data-mw
for extensions has a different form than that for templates.
* Extracted common functionality into Util.js and used it in Cite.js
and ExtensionHandler.js
* Tested with timeline extension (test snippet below) and verified
that it parses and RTs both with editMode true and false.
TODO: Long overdue. Extension testing.
--------
<timeline>
ImageSize = width:250 height:200
PlotArea = left:40 right:10 top:10 bottom:20
TimeAxis = orientation:horizontal
AlignBars = justify
Colors =
id:gray1 value:gray(0.9)
DateFormat = yyyy
Period = from:1960 till:2010
ScaleMajor = unit:year increment:10 start:1960
PlotData =
bar:3000 color:gray1 width:1
from:start till:end
bar:2000 color:gray1
from:start till:end
bar:1000 color:gray1
from:start till:end
bar:0 color:gray1
LineData =
layer:front
points:(48,96)(84,111) color:blue width:2 #1962 tot 1968. Inwonertal 1962: 1348 1968: 1610
points:(84,111)(100,112) color:blue width:2 #1975: 1627
points:(100,112)(128,116) color:blue width:2 #1982: 1699
points:(128,116)(160,135) color:blue width:2 #1990: 2036
points:(160,135)(196,146) color:blue width:2 #1999: 2217
points:(196,146)(228,158) color:blue width:2 #2004/5
</timeline>
--------
Change-Id: Ia8d2f82e893047e2447cf809e04cc7f508f5899b
2013-06-06 00:00:41 +00:00
|
|
|
body = Util.extractExtBody("references", src).trim(),
|
2015-03-31 16:52:01 +00:00
|
|
|
refGroup = refsData.getRefGroup(group);
|
2013-06-05 16:06:10 +00:00
|
|
|
|
2014-09-08 20:10:25 +00:00
|
|
|
var dataMW = DU.getDataMw(refsNode);
|
|
|
|
if (!Object.keys(dataMW).length) {
|
2013-07-24 00:15:45 +00:00
|
|
|
var datamwBody;
|
|
|
|
// We'll have to output data-mw.body.extsrc in
|
|
|
|
// scenarios where original wikitext was of the form:
|
|
|
|
// "<references> lot of refs here </references>"
|
|
|
|
// Ex: See [[en:Barack Obama]]
|
|
|
|
if (body.length > 0) {
|
|
|
|
datamwBody = {
|
|
|
|
'extsrc': body,
|
2014-08-21 23:16:32 +00:00
|
|
|
'html': refsInReferencesHTML.join('')
|
2013-07-24 00:15:45 +00:00
|
|
|
};
|
|
|
|
}
|
2014-09-08 20:10:25 +00:00
|
|
|
dataMW = {
|
2013-06-05 16:06:10 +00:00
|
|
|
'name': 'references',
|
2013-07-24 00:15:45 +00:00
|
|
|
'body': datamwBody,
|
2013-06-05 16:06:10 +00:00
|
|
|
'attrs': {
|
|
|
|
// Dont emit empty keys
|
|
|
|
'group': group || undefined
|
|
|
|
}
|
2014-09-08 20:10:25 +00:00
|
|
|
};
|
|
|
|
DU.setDataMw(refsNode, dataMW);
|
2013-06-16 22:14:25 +00:00
|
|
|
}
|
|
|
|
|
2013-07-01 21:17:07 +00:00
|
|
|
// Remove all children from the references node
|
2013-10-24 01:57:17 +00:00
|
|
|
//
|
|
|
|
// Ex: When {{Reflist}} is reused from the cache, it comes with
|
|
|
|
// a bunch of references as well. We have to remove all those cached
|
|
|
|
// references before generating fresh references.
|
2013-07-01 21:17:07 +00:00
|
|
|
while (refsNode.firstChild) {
|
|
|
|
refsNode.removeChild(refsNode.firstChild);
|
|
|
|
}
|
|
|
|
|
2013-06-05 16:06:10 +00:00
|
|
|
if (refGroup) {
|
2014-03-26 19:08:03 +00:00
|
|
|
refGroup.refs.forEach(refGroup.renderLine.bind(refGroup, refsNode));
|
Extension handling rewrite + cite extension refactoring.
Tokenization
------------
* Fixed tokenizer to correctly parse extension tags in different
contexts: with start and end tags, in self-closing tag mode,
and to correctly handle scenarios when the exension end-tag is
followed by a '#' (the special char used to skip over extension
content).
* Removed the distinction in the tokenizer between installed
extensions and natively supported extension tags (<ref> and
<references> for ex.). They all tokenize and get processed
identically and get handled by different paths in the extension
handler.
* Template and TemplateArg tokens now carry tpl. transclusion
source alongwith them since tsr information will not be
accurate when they show up in extension contexts that in turn
showed up in template context that were expanded by the php
preprocessor.
Ex: {{echo|<ref>{{echo|foo}}</ref>}}
The tsr for the ref-tag will correspond to the
template-source of the echo-template, NOT the original top-level
page. So, env.page.src.substring(..) will return incorrect
source for the innermost {{echo|foo}}. This fix of carrying
along tpl transclusion source in the token itself eliminates
this problem.
Knowledge of native extensions
------------------------------
* Natively implemented extension tags (<ref> and <references>)
are hardcoded in env.conf.parsoid. At some point, it would
be good to have a registration mechanism for parsoid-native
extensions.
Extension handling
------------------
* Extracted extension handling out of the template handler into
its own handler class. Right now, this class inherits from the
template handler in order to be able to reuse a lot of the
expansion and encapsulation functionality currently in the
Template Handler.
* This handler now handles extensions that are:
(a) natively implemented and registered with Parsoid.
(b) implemented as a PHP extension and expanded by relying on
the PHP preprocessor.
For (a), it uses information from env.conf.parsoid to find
ext-handlers for natively implemented ext-tags. However, this
can be cleaned up at some point by making available a registration
mechanism.
Cite/Ref/References
-------------------
* Reworked the cite handler to split up ref-token processing
and references token processing.
* The handler now processes ref-tokens, parses content all
the way to html output and encapsulates the html in an
attribute of a meta-token that serves as a placeholder for
where the ref-token occured.
* References are handled as a DOM post-pass where these meta
placeholder tokens are collected, content extracted from
the attribute and spit out at the site of a references tag.
The DOM walking is in DOMPostProcessor.js, but the actual
processing is part of the Cite.js to keep all cite extension
handling code in one place.
Parser pipeline
---------------
* Restructured parser pipeline recipes based on changes to Cite,
TemplateHandler, and ExtensionHandler.
* Added a couple functions to the parser pipeline:
1. resetState to reset state before starting a new top-level parse
when pipelines are reused across top-level parses (ex: parser
tests)
2. setSourceOffsets to set start/end offsets of the source being
handled by the pipeline. This is required to correctly set tsr
values when extension content (which is a substring of original
top-level text) is parsed in its own pipeline.
Other fixes
-----------
* Removed env parameter from the Params object since it was not
being used and seemed like unnecessary state propagation.
* Removed a FIXME in DOMUtils.buildTokensFromDOM by reusing code
in the tokenizer that converts "\n" in text to NlTks.
* Cleanup of Util.shiftTokenTSR.
* ext.util.TokenCollection is now no longer used by anything.
Added a FIXME and left around in case we are able to improve
tokenizing and handling of *include* tags that can eliminate the
need for the messy TokenAndAttrCollector.
Test results
------------
* No change in parser tests results.
* Tested with a few different files.
- en:BO page seems to be parsed about 10% faster than before
(needs verification).
- Referencs on the en:BO page seem to be more accurate than
before.
Change-Id: I8a095fa9fa976c7b3a2a4bd968dc9db4270b105f
2013-03-09 00:07:59 +00:00
|
|
|
}
|
|
|
|
|
2015-03-31 16:52:01 +00:00
|
|
|
// Remove the group from refsData
|
|
|
|
refsData.removeRefGroup(group);
|
2011-12-14 23:38:46 +00:00
|
|
|
};
|
2011-12-13 14:48:47 +00:00
|
|
|
|
2015-03-31 16:52:01 +00:00
|
|
|
References.prototype.insertMissingReferencesIntoDOM = function (env, refsData, node) {
|
2015-02-11 15:32:57 +00:00
|
|
|
var doc = node.ownerDocument,
|
|
|
|
self = this;
|
|
|
|
|
2015-03-31 16:52:01 +00:00
|
|
|
refsData.refGroups.forEach(function (refsValue, refsGroup) {
|
2015-02-11 15:32:57 +00:00
|
|
|
var ol = doc.createElement('ol'),
|
|
|
|
dp = DU.getDataParsoid(ol);
|
|
|
|
DU.addAttributes(ol, {
|
|
|
|
'class': 'references',
|
|
|
|
typeof: 'mw:Extension/references',
|
2015-02-21 01:02:45 +00:00
|
|
|
about: env.newAboutId()
|
2015-02-11 15:32:57 +00:00
|
|
|
});
|
|
|
|
// The new references come out of "nowhere", so to make selser work
|
|
|
|
// propertly, add a zero-sized DSR pointing to the end of the document.
|
|
|
|
dp.dsr = [env.page.src.length, env.page.src.length, 0, 0];
|
|
|
|
if (refsGroup) {
|
|
|
|
dp.group = refsGroup;
|
|
|
|
}
|
|
|
|
DU.storeDataParsoid(ol, dp);
|
2015-02-17 17:48:06 +00:00
|
|
|
|
|
|
|
// Add a \n before the <ol> so that when serialized to wikitext,
|
|
|
|
// each <references /> tag appears on its own line.
|
2015-02-11 15:32:57 +00:00
|
|
|
node.appendChild(doc.createTextNode("\n"));
|
2015-02-17 17:48:06 +00:00
|
|
|
node.appendChild(ol);
|
2015-03-31 16:52:01 +00:00
|
|
|
self.insertReferencesIntoDOM(ol, refsData, [""]);
|
2015-02-11 15:32:57 +00:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2013-04-22 19:51:09 +00:00
|
|
|
/**
|
|
|
|
* Native Parsoid implementation of the Cite extension
|
|
|
|
* that ties together <ref> and <references>
|
|
|
|
*/
|
|
|
|
var Cite = function() {
|
|
|
|
this.ref = new Ref(this);
|
|
|
|
this.references = new References(this);
|
|
|
|
};
|
|
|
|
|
2014-06-16 17:30:25 +00:00
|
|
|
Cite.prototype.resetState = function(opts) {
|
|
|
|
if (opts && opts.toplevel) {
|
2014-04-30 17:02:39 +00:00
|
|
|
this.ref.reset();
|
2015-03-31 16:52:01 +00:00
|
|
|
this.references.reset();
|
2014-04-30 17:02:39 +00:00
|
|
|
}
|
2013-04-22 19:51:09 +00:00
|
|
|
};
|
|
|
|
|
2012-09-17 19:46:44 +00:00
|
|
|
if (typeof module === "object") {
|
2011-12-13 14:48:47 +00:00
|
|
|
module.exports.Cite = Cite;
|
2015-03-31 16:52:01 +00:00
|
|
|
module.exports.ReferencesData = ReferencesData;
|
2011-12-13 14:48:47 +00:00
|
|
|
}
|