Arlolra has uploaded a new change for review.
https://gerrit.wikimedia.org/r/252886
Change subject: Use async serializeDOM in jsapi
......................................................................
Use async serializeDOM in jsapi
* Replace uses of `toString` with a `toWt` method.
* Follow up to Id68d24007229dcfa0bf6fb16c6ed3ecdaad0c2e5 where these
tests were skipped.
Change-Id: I33717f9261885bd121aef27360602fe8ebbc8ccb
---
M guides/jsapi/README.md
M lib/jsapi.js
M tests/mocha/jsapi.js
3 files changed, 151 insertions(+), 80 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/services/parsoid
refs/changes/86/252886/1
diff --git a/guides/jsapi/README.md b/guides/jsapi/README.md
index 5ff6dcf..23f166a 100644
--- a/guides/jsapi/README.md
+++ b/guides/jsapi/README.md
@@ -46,29 +46,29 @@
> var text = "I has a template! {{foo|bar|baz|eggs=spam}} See it?\n";
> var pdoc = yield Parsoid.parse(text, { pdoc: true });
- > console.log(String(pdoc));
+ > console.log(yield pdoc.toWt());
I has a template! {{foo|bar|baz|eggs=spam}} See it?
> var templates = pdoc.filterTemplates();
- > console.log(templates.map(String));
+ > console.log(templates.map(t => yield t.toWt()));
[ '{{foo|bar|baz|eggs=spam}}' ]
> var template = templates[0];
> console.log(template.name);
foo
> template.name = 'notfoo';
- > console.log(String(template));
+ > console.log(yield template.toWt());
{{notfoo|bar|baz|eggs=spam}}
- > console.log(template.params.map(function(p) { return p.name; }));
+ > console.log(template.params.map(p => p.name));
[ '1', '2', 'eggs' ]
- > console.log(template.get(1).value);
+ > console.log(yield template.get(1).value.toWt());
bar
- > console.log(template.get("eggs").value);
+ > console.log(yield template.get("eggs").value.toWt());
spam
Getting nested templates is trivial:
> var text = "{{foo|bar={{baz|{{spam}}}}}}";
> var pdoc = yield Parsoid.parse(text, { pdoc: true });
- > console.log(pdoc.filterTemplates().map(String));
+ > console.log(pdoc.filterTemplates().map(t => yield t.toWt()));
[ '{{foo|bar={{baz|{{spam}}}}}}',
'{{baz|{{spam}}}}',
'{{spam}}' ]
@@ -108,13 +108,13 @@
... template.name = 'bar-stub';
... }
... });
- > console.log(String(pdoc));
+ > console.log(yield pdoc.toWt());
{{cleanup|date = July 2012}} '''Foo''' is a [[bar]]. {{bar-stub}}
At any time you can convert the `pdoc` into HTML conforming to the
[MediaWiki DOM spec] (by referencing the
[`document`](#!/api/PDoc-property-document) property) or into wikitext (by
-invoking [`toString()`](#!/api/PNodeList-method-toString)). This allows you
+invoking [`toWt()`](#!/api/PNodeList-method-toWt)). This allows you
to save the page using either standard API methods or the RESTBase API
(once [T101501](https://phabricator.wikimedia.org/T101501) is resolved).
diff --git a/lib/jsapi.js b/lib/jsapi.js
index b802961..8bef1b7 100644
--- a/lib/jsapi.js
+++ b/lib/jsapi.js
@@ -19,11 +19,6 @@
// WTS helper
var wts = function(env, nodes) {
- // XXX: Serializing to wikitext is very user-friendly, but it depends on
- // WTS.serializeDOMSync which we might not want to keep around forever.
- // An alternative would be:
- // return DU.normalizeOut(node, 'parsoidOnly');
- // which might be almost as friendly.
var body;
if (nodes.length === 0) {
return '';
@@ -35,8 +30,7 @@
body.appendChild(nodes[i].cloneNode(true));
}
}
- // FXIME: serializeDOMSync is dead.
- return (new WikitextSerializer({ env: env })).serializeDOMSync(body);
+ return (new WikitextSerializer({ env: env })).serializeDOM(body);
};
// noop helper
@@ -428,12 +422,12 @@
}, },
/**
- * Return a string representing the contents of this object as wikitext.
- * @return {String}
+ * Return a promise for a string representing the contents of this
object as wikitext.
+ * @return {Promise}
*/
- toString: { value: function() {
+ toWt: { value: Promise.method(function() {
return wts(this.pdoc.env, this.nodes);
- }, },
+ }), },
});
/**
* Create a {@link PNodeList} from a string containing HTML.
@@ -475,7 +469,7 @@
* A function which will be invoked when {@link #update} is called.
* @param {Function} [opts.wtsNodes]
* A function returning an array of {@link Node}s which can tweak the
- * portion of the document serialized by {@link #toString}.
+ * portion of the document serialized by {@link #toWt}.
*/
PNode = function PNode(pdoc, parent, node, opts) {
/** @property {PDoc} pdoc The parent document for this {@link PNode}. */
@@ -534,13 +528,13 @@
return nodes.map(function(n) { return n.outerHTML; }).join('');
}, },
/**
- * @inheritdoc PNodeList#toString
+ * @inheritdoc PNodeList#toWt
* @method
*/
- toString: { value: function() {
+ toWt: { value: Promise.method(function() {
var nodes = this._wtsNodes ? this._wtsNodes() : [ this.node ];
return wts(this.pdoc.env, nodes);
- }, },
+ }), },
});
// Helper: getter and setter for the inner contents of a node.
@@ -1167,10 +1161,10 @@
this._value.update();
},
},
- toString: { value: function() {
+ toWt: { value: Promise.method(function() {
var k = this.key;
return (k ? String(k) : this.name) + '=' + String(this.value);
- }, },
+ }), },
});
/**
@@ -1272,7 +1266,7 @@
* instance of {@link PNodeList}, you can filter it, mutate it, etc.
* But it also provides means to serialize the document as either
* HTML (via {@link #document} or {@link #toHtml}) or wikitext
- * (via {@link #toString}).
+ * (via {@link #toWt}).
* @class
* @extends PNodeList
* @alternateClassName Parsoid.PDoc
diff --git a/tests/mocha/jsapi.js b/tests/mocha/jsapi.js
index 9243c24..f352c4f 100644
--- a/tests/mocha/jsapi.js
+++ b/tests/mocha/jsapi.js
@@ -22,7 +22,7 @@
});
});
-describe.skip('Examples from guides/jsapi', function() {
+describe('Examples from guides/jsapi', function() {
it('converts empty wikitext to HTML', function() {
return Parsoid.parse('', { pdoc: true}).then(function(pdoc) {
pdoc.should.have.property('document');
@@ -38,21 +38,33 @@
});
it('filters out templates', function() {
var text = "I has a template! {{foo|bar|baz|eggs=spam}} See
it?\n";
- return Parsoid.parse(text, { pdoc: true }).then(function(pdoc) {
- String(pdoc).should.equal(text);
- var templates = pdoc.filterTemplates();
+ var pdoc, templates, template;
+ return Parsoid.parse(text, { pdoc: true }).then(function(_pdoc)
{
+ pdoc = _pdoc;
+ return pdoc.toWt();
+ }).then(function(wt) {
+ wt.should.equal(text);
+ templates = pdoc.filterTemplates();
templates.length.should.equal(1);
-
String(templates[0]).should.equal('{{foo|bar|baz|eggs=spam}}');
- var template = templates[0];
+ return templates[0].toWt();
+ }).then(function(wt) {
+ wt.should.equal('{{foo|bar|baz|eggs=spam}}');
+ template = templates[0];
template.name.should.equal('foo');
template.name = 'notfoo';
-
String(template).should.equal('{{notfoo|bar|baz|eggs=spam}}');
+ return template.toWt();
+ }).then(function(wt) {
+ wt.should.equal('{{notfoo|bar|baz|eggs=spam}}');
template.params.length.should.equal(3);
template.params[0].name.should.equal('1');
template.params[1].name.should.equal('2');
template.params[2].name.should.equal('eggs');
- String(template.get(1).value).should.equal('bar');
- String(template.get('eggs').value).should.equal('spam');
+ return template.get(1).value.toWt();
+ }).then(function(wt) {
+ wt.should.equal('bar');
+ return template.get('eggs').value.toWt();
+ }).then(function(wt) {
+ wt.should.equal('spam');
});
});
it('filters templates, recursively', function() {
@@ -66,14 +78,19 @@
});
it('filters templates, non-recursively', function() {
var text = "{{foo|this {{includes a|template}}}}";
+ var foo;
return Parsoid.parse(text, { pdoc: true }).then(function(pdoc) {
var templates = pdoc.filterTemplates({ recursive: false
});
templates.length.should.equal(1);
- var foo = templates[0];
- String(foo.get(1).value).should.equal('this {{includes
a|template}}');
+ foo = templates[0];
+ return foo.get(1).value.toWt();
+ }).then(function(wt) {
+ wt.should.equal('this {{includes a|template}}');
var more = foo.get(1).value.filterTemplates();
more.length.should.equal(1);
- String(more[0].get(1).value).should.equal('template');
+ return more[0].get(1).value.toWt();
+ }).then(function(wt) {
+ wt.should.equal('template');
});
});
it('is easy to mutate templates', function() {
@@ -87,12 +104,14 @@
template.name = 'bar-stub';
}
});
- String(pdoc).should.equal("{{cleanup|date = July 2012}}
'''Foo''' is a [[bar]]. {{bar-stub}}");
+ return pdoc.toWt();
+ }).then(function(wt) {
+ wt.should.equal("{{cleanup|date = July 2012}} '''Foo'''
is a [[bar]]. {{bar-stub}}");
});
});
});
-describe.skip('Further examples of PDoc API', function() {
+describe('Further examples of PDoc API', function() {
it('is easy to mutate templates (2)', function() {
// Works even on nested templates!
var text = "{{echo|{{cleanup}} '''Foo''' is a [[bar]].}}
{{uncategorized}}";
@@ -105,7 +124,9 @@
template.add('test2',
Parsoid.PNodeList.fromHTML(pdoc, "I'm so <b>bold</b>!"));
}
});
- String(pdoc).should.equal("{{echo|{{cleanup|date = July
2012|test1 = <nowiki>{{foo}}</nowiki>&bar{{!}}bat<nowiki><p></nowiki>|test2 =
I'm so '''bold'''!}} '''Foo''' is a [[bar]].}} {{uncategorized}}");
+ return pdoc.toWt();
+ }).then(function(wt) {
+ wt.should.equal("{{echo|{{cleanup|date = July
2012|test1 = <nowiki>{{foo}}</nowiki>&bar{{!}}bat<nowiki><p></nowiki>|test2 =
I'm so '''bold'''!}} '''Foo''' is a [[bar]].}} {{uncategorized}}");
});
});
it('is safe to mutate template arguments', function() {
@@ -113,7 +134,9 @@
return Parsoid.parse(text, { pdoc: true }).then(function(pdoc) {
var t = pdoc.filterTemplates()[0];
t.remove(1);
- String(pdoc).should.equal('{{echo||bar}}');
+ return pdoc.toWt();
+ }).then(function(wt) {
+ wt.should.equal('{{echo||bar}}');
});
});
it('is safe to mutate template arguments (2)', function() {
@@ -124,7 +147,9 @@
var param2 = t.get(2);
param2.value = param1.value;
param1.value = '|';
- String(pdoc).should.equal('{{echo|{{!}}|foo}}');
+ return pdoc.toWt();
+ }).then(function(wt) {
+ wt.should.equal('{{echo|{{!}}|foo}}');
});
});
it('filters and mutates headings', function() {
@@ -143,47 +168,77 @@
headings[0].title = '=0=';
headings[1].title = headings[2].title;
headings[3].level = 3;
- String(pdoc).should.equal('=<nowiki>=0=</nowiki>=\n==
three ==\n=== three ===\n\n=== four ===\nbody\n');
+ return pdoc.toWt();
+ }).then(function(wt) {
+ wt.should.equal('=<nowiki>=0=</nowiki>=\n== three
==\n=== three ===\n\n=== four ===\nbody\n');
});
});
it('filters and mutates headings inside templates', function() {
var text = "{{echo|1=\n= one =\n}}";
- return Parsoid.parse(text, { pdoc: true }).then(function(pdoc) {
- var headings = pdoc.filterHeadings();
+ var pdoc, headings;
+ return Parsoid.parse(text, { pdoc: true }).then(function(_pdoc)
{
+ pdoc = _pdoc;
+ headings = pdoc.filterHeadings();
headings.length.should.equal(1);
headings[0].level = 2;
- String(headings[0]).should.equal('== one ==\n');
- String(pdoc).should.equal('{{echo|1=\n== one ==\n}}');
+ return headings[0].toWt();
+ }).then(function(wt) {
+ wt.should.equal('== one ==\n');
+ return pdoc.toWt();
+ }).then(function(wt) {
+ wt.should.equal('{{echo|1=\n== one ==\n}}');
headings[0].title = 'two';
- String(headings[0]).should.equal('== two ==\n');
- String(pdoc).should.equal('{{echo|1=\n== two ==\n}}');
+ return headings[0].toWt();
+ }).then(function(wt) {
+ wt.should.equal('== two ==\n');
+ return pdoc.toWt();
+ }).then(function(wt) {
+ wt.should.equal('{{echo|1=\n== two ==\n}}');
});
});
it('filters and mutates external links', function() {
var text = "[http://example.com {{echo|link content}}]";
- return Parsoid.parse(text, { pdoc: true }).then(function(pdoc) {
- var extlinks = pdoc.filterExtLinks();
+ var pdoc, extlinks;
+ return Parsoid.parse(text, { pdoc: true }).then(function(_pdoc)
{
+ pdoc = _pdoc;
+ extlinks = pdoc.filterExtLinks();
extlinks.length.should.equal(1);
String(extlinks[0].url).should.equal('http://example.com');
- String(extlinks[0].title).should.equal('{{echo|link
content}}');
+ return extlinks[0].title.toWt();
+ }).then(function(wt) {
+ wt.should.equal('{{echo|link content}}');
extlinks[0].title = ']';
- String(pdoc).should.equal('[http://example.com
<nowiki>]</nowiki>]\n');
+ return pdoc.toWt();
+ }).then(function(wt) {
+ wt.should.equal('[http://example.com
<nowiki>]</nowiki>]\n');
});
});
it('filters and mutates wiki links', function() {
var text = "[[foo|1]] {{echo|[[bar|2]]}} [[{{echo|bat}}|3]]";
- return Parsoid.parse(text, { pdoc: true }).then(function(pdoc) {
- var extlinks = pdoc.filterWikiLinks();
+ var pdoc, extlinks;
+ return Parsoid.parse(text, { pdoc: true }).then(function(_pdoc)
{
+ pdoc = _pdoc;
+ extlinks = pdoc.filterWikiLinks();
extlinks.length.should.equal(3);
- String(extlinks[0].title).should.equal('Foo');
- String(extlinks[0].text).should.equal('1');
- String(extlinks[1].title).should.equal('Bar');
- String(extlinks[1].text).should.equal('2');
- String(extlinks[2].text).should.equal('3');
+ return Promise.all([
+ extlinks[0].title,
+ extlinks[0].text.toWt(),
+ extlinks[1].title,
+ extlinks[1].text.toWt(),
+ extlinks[2].text.toWt(),
+ ]);
+ }).then(function(all) {
+ all[0].should.equal('Foo');
+ all[1].should.equal('1');
+ all[2].should.equal('Bar');
+ all[3].should.equal('2');
+ all[4].should.equal('3');
extlinks[0].title = extlinks[0].text = 'foobar';
extlinks[1].text = 'A';
extlinks[2].text = 'B';
- String(pdoc).should.equal('[[foobar]]
{{echo|[[bar|A]]}} [[{{echo|bat}}|B]]\n');
+ return pdoc.toWt();
+ }).then(function(wt) {
+ wt.should.equal('[[foobar]] {{echo|[[bar|A]]}}
[[{{echo|bat}}|B]]\n');
});
});
it('filters and mutates html entities', function() {
@@ -195,7 +250,9 @@
entities[1].normalized.should.equal('"');
entities[0].normalized = '<';
entities[1].normalized = '>';
- String(pdoc).should.equal('<{{echo|>}}\n');
+ return pdoc.toWt();
+ }).then(function(wt) {
+ wt.should.equal('<{{echo|>}}\n');
});
});
it('filters and mutates comments', function() {
@@ -207,37 +264,53 @@
comments[1].contents.should.equal('bar');
comments[0].contents = '<!-- ha! -->';
comments[1].contents = '--';
- String(pdoc).should.equal('<!--<!-- ha! -->-->
{{echo|<!------>}}');
+ return pdoc.toWt();
+ }).then(function(wt) {
+ wt.should.equal('<!--<!-- ha! -->-->
{{echo|<!------>}}');
});
});
it('filters and mutates images', function() {
var text = '[[File:SomeFile1.jpg]]
[[File:SomeFile2.jpg|thumb|caption]]';
- return Parsoid.parse(text, { pdoc: true }).then(function(pdoc) {
- var media = pdoc.filterMedia();
+ var pdoc, media;
+ return Parsoid.parse(text, { pdoc: true }).then(function(_pdoc)
{
+ pdoc = _pdoc;
+ media = pdoc.filterMedia();
media.length.should.equal(2);
media[0].should.have.property('caption', null);
- String(media[1].caption).should.equal('caption');
+ return media[1].caption.toWt();
+ }).then(function(wt) {
+ wt.should.equal('caption');
media[0].caption = '|';
media[1].caption = null;
-
String(pdoc).should.equal('[[File:SomeFile1.jpg|<nowiki>|</nowiki>]]
[[File:SomeFile2.jpg|thumb]]');
+ return pdoc.toWt();
+ }).then(function(wt) {
+
wt.should.equal('[[File:SomeFile1.jpg|<nowiki>|</nowiki>]]
[[File:SomeFile2.jpg|thumb]]');
media[0].caption = null;
media[1].caption = '|';
- String(pdoc).should.equal('[[File:SomeFile1.jpg]]
[[File:SomeFile2.jpg|thumb|<nowiki>|</nowiki>]]');
+ return pdoc.toWt();
+ }).then(function(wt) {
+ wt.should.equal('[[File:SomeFile1.jpg]]
[[File:SomeFile2.jpg|thumb|<nowiki>|</nowiki>]]');
});
});
it('filters and mutates text', function() {
var text = 'foo {{echo|bar}}';
- return Parsoid.parse(text, { pdoc: true }).then(function(pdoc) {
- var texts = pdoc.filterText({ recursive: false });
+ var pdoc, texts;
+ return Parsoid.parse(text, { pdoc: true }).then(function(_pdoc)
{
+ pdoc = _pdoc;
+ texts = pdoc.filterText({ recursive: false });
texts.length.should.equal(1);
texts = pdoc.filterText({ recursive: true });
texts.length.should.equal(2);
texts[0].value.should.equal('foo ');
texts[1].value.should.equal('bar');
texts[0].value = 'FOO ';
- String(pdoc).should.equal('FOO {{echo|bar}}\n');
+ return pdoc.toWt();
+ }).then(function(wt) {
+ wt.should.equal('FOO {{echo|bar}}\n');
texts[1].value = 'BAR';
- String(pdoc).should.equal('FOO {{echo|BAR}}\n');
+ return pdoc.toWt();
+ }).then(function(wt) {
+ wt.should.equal('FOO {{echo|BAR}}\n');
});
});
it.skip('filters and mutates text (2)', function() {
@@ -253,15 +326,19 @@
});
it('allows mutation using wikitext', function() {
var text = '== heading ==';
- return Parsoid.parse(text, { pdoc: true }).then(function(pdoc) {
- var headings = pdoc.filterHeadings();
+ var pdoc, headings;
+ return Parsoid.parse(text, { pdoc: true }).then(function(_pdoc)
{
+ pdoc = _pdoc;
+ headings = pdoc.filterHeadings();
headings.length.should.equal(1);
// Note that even if the wikitext is unbalanced, the
result
// will be balanced. The bold face doesn't escape the
heading!
- return Parsoid.PNodeList.fromWikitext(pdoc,
"'''bold").then(function(pnl) {
- headings[0].title = pnl;
- String(pdoc).should.equal("== '''bold''' ==\n");
- });
+ return Parsoid.PNodeList.fromWikitext(pdoc, "'''bold");
+ }).then(function(pnl) {
+ headings[0].title = pnl;
+ return pdoc.toWt();
+ }).then(function(wt) {
+ wt.should.equal("== '''bold''' ==\n");
});
});
it('allows iteration using length and get()', function() {
--
To view, visit https://gerrit.wikimedia.org/r/252886
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I33717f9261885bd121aef27360602fe8ebbc8ccb
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/services/parsoid
Gerrit-Branch: master
Gerrit-Owner: Arlolra <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits