Skip to content

Commit

Permalink
feat(webidl-contiguous): link method() and enum "" (#1023)
Browse files Browse the repository at this point in the history
 * link simple method() names (closes #1000)
 * fix(webidl-contiguous): Link enum when empty string (closes #981)
 * test(webidl-contiguous-spec): link simple method() names
  • Loading branch information
Marcos Cáceres committed Jan 10, 2017
1 parent 2dd622d commit 9ea65c5
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 17 deletions.
2 changes: 1 addition & 1 deletion js/core/jquery-enhanced.js
Expand Up @@ -77,7 +77,7 @@ define([
} else if (this.contents().length == 1 && this.children("abbr, acronym").length == 1 && this.find(":first-child").attr("title")) {
titleString = this.find(":first-child").attr("title");
} else {
titleString = this.text();
titleString = this.text() === "\"\"" ? "the-empty-string" : this.text();
}
// now we have a string of one or more titles
titleString = utils.norm(titleString).toLowerCase();
Expand Down
6 changes: 3 additions & 3 deletions js/core/templates/webidl-contiguous/compiled.js
Expand Up @@ -137,13 +137,13 @@ templates['enum-item.html'] = template({"1":function(container,depth0,helpers,pa
var stack1, helper, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing, alias3=container.escapeExpression, alias4="function";

return alias3((helpers.idn || (depth0 && depth0.idn) || alias2).call(alias1,(depth0 != null ? depth0.indent : depth0),{"name":"idn","hash":{},"data":data}))
+ "\"<a href=\"#dom-"
+ "<a href=\"#dom-"
+ alias3(((helper = (helper = helpers.parentID || (depth0 != null ? depth0.parentID : depth0)) != null ? helper : alias2),(typeof helper === alias4 ? helper.call(alias1,{"name":"parentID","hash":{},"data":data}) : helper)))
+ "-"
+ alias3(((helper = (helper = helpers.lname || (depth0 != null ? depth0.lname : depth0)) != null ? helper : alias2),(typeof helper === alias4 ? helper.call(alias1,{"name":"lname","hash":{},"data":data}) : helper)))
+ "\" class=\"idlEnumItem\">"
+ "\" class=\"idlEnumItem\">\""
+ alias3(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : alias2),(typeof helper === alias4 ? helper.call(alias1,{"name":"name","hash":{},"data":data}) : helper)))
+ "</a>\""
+ "\"</a>"
+ ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.needsComma : depth0),{"name":"if","hash":{},"fn":container.program(1, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
+ "\n";
},"useData":true});
Expand Down
2 changes: 1 addition & 1 deletion js/core/templates/webidl-contiguous/enum-item.html
@@ -1 +1 @@
{{idn indent}}"<a href="#dom-{{parentID}}-{{lname}}" class="idlEnumItem">{{name}}</a>"{{#if needsComma}},{{/if}}
{{idn indent}}<a href="#dom-{{parentID}}-{{lname}}" class="idlEnumItem">"{{name}}"</a>{{#if needsComma}},{{/if}}
68 changes: 57 additions & 11 deletions js/core/webidl-contiguous.js
Expand Up @@ -130,8 +130,11 @@ define(
var content = options.fn(this);
if (obj.dfn) {
var result = "<a for='" + hb.Utils.escapeExpression(obj.linkFor || "") + "'";
if (obj.name) {
if (obj.name === obj.dfn.text().trim()) {
result += " data-lt='" + hb.Utils.escapeExpression(obj.name) + (obj.overload ? "!overload-" + obj.overload + "' data-lt-noDefault" : "'");
} else {
const lt = hb.Utils.escapeExpression(obj.dfn.text().trim()) + "|" + obj.dfn[0].dataset.lt;
result += " data-lt='" + lt + "' data-lt-noDefault";
}
result += ">" + content + "</a>";
return result;
Expand Down Expand Up @@ -472,7 +475,7 @@ define(
}
}
children += idlEnumItemTmpl({
lname: item.toString().toLowerCase(),
lname: item.toString() ? item.toString() : "the-empty-string",
name: item.toString(),
parentID: obj.name.toLowerCase(),
indent: indent + 1,
Expand Down Expand Up @@ -745,13 +748,14 @@ define(

case "enum":
name = defn.name;

defn.values.forEach(function(v, i) {
if (v.type === undefined) {
defn.values[i] = {
toString: function() {
return v;
},
dfn: findDfn(name, v, definitionMap)
dfn: findDfn(name, v, definitionMap, defn.type)
};
}
});
Expand Down Expand Up @@ -826,7 +830,7 @@ define(
if (parent) {
defn.linkFor = parent;
}
defn.dfn = findDfn(parent, name, definitionMap);
defn.dfn = findDfn(parent, name, definitionMap, defn.type);
});
}

Expand All @@ -837,14 +841,54 @@ define(
// counted as matching.
//
// When a matching <dfn> is found, it's given <code> formatting,
// marked as an IDL definition, and returned. If no <dfn> is found,
// marked as an IDL definition, and returned. If no <dfn> is found,
// the function returns 'undefined'.
function findDfn(parent, name, definitionMap) {
function findDfn(parent, name, definitionMap, type) {
var originalParent = parent;
var originalName = name;
parent = parent.toLowerCase();
name = name.toLowerCase();
if (unlinkable.has(name)){
switch (type) {
case "operation":
// ignore overloads
if (name.search("!overload") !== -1) {
break;
}
// Allow linking to both "method()" and "method" name.
const asMethodName = name.toLowerCase() + "()";

if (definitionMap[asMethodName]) {
const dfn = findDfn(parent, asMethodName, definitionMap);
if (!dfn) {
break; // try finding dfn using name, using normal search path...
}
const lt = (dfn[0].dataset.lt) ? dfn[0].dataset.lt.split("|") : [];
lt.push(asMethodName, name);
dfn[0].dataset.lt = lt.join("|");
if (!definitionMap[name]) {
definitionMap[name] = [];
}
definitionMap[name].push(dfn);
return dfn;
};
// no method alias, so let's find the dfn and add it
const dfn = findDfn(parent, name, definitionMap);
if (!dfn) {
break;
}
const lt = (dfn[0].dataset.lt) ? dfn[0].dataset.lt.split("|") : [];
lt.push(asMethodName, name);
dfn[0].dataset.lt = lt.join("|");
definitionMap[asMethodName] = [dfn];
return dfn;
case "enum":
if (name === "") {
name = "the-empty-string";
break;
}
default:
name = name.toLowerCase();
}
if (unlinkable.has(name)) {
return;
}
var dfnForArray = definitionMap[name];
Expand Down Expand Up @@ -882,9 +926,11 @@ define(
pubsubhub.pub("error", "Multiple <dfn>s for " + originalName + (originalParent ? " in " + originalParent : ""));
}
if (dfns.length === 0) {
const msg = "No <dfn> for " + originalName + (originalParent ? " in " + originalParent : "") + ".";
pubsubhub.pub("warn", msg);
return undefined;
if (type) {
const msg = "No <dfn> for " + originalName + (originalParent ? " in " + originalParent : "") + ".";
pubsubhub.pub("warn", msg);
}
return;
}
var dfn = dfns[0];
// Mark the definition as code.
Expand Down
52 changes: 51 additions & 1 deletion tests/spec/core/webidl-contiguous-spec.js
Expand Up @@ -11,6 +11,46 @@ describe("Core - Contiguous WebIDL", function() {
doc = idlDoc;
}, "spec/core/webidl-contiguous.html").then(done);
});

it("links simple method names and types", done => {
const section = doc.querySelector("#sec-parenthesis-method");
[
"basic",
"ext",
"ull",
"paramed",
"withName",
"named",
]
.map(
methodName => [methodName, methodName.toLowerCase()]
)
.map(
([methodName, id]) => [id, methodName, doc.getElementById(`dom-parenthesistest-${id}()`)]
)
.forEach(([id, methodName, elem]) => {
expect(elem).toBeTruthy();
expect(elem.firstElementChild.localName).toEqual("code");
expect(elem.textContent).toEqual(`${methodName}()`);
expect(elem.id).toEqual(`dom-parenthesistest-${id}()`);
expect(elem.dataset.dfnType).toEqual("dfn");
expect(elem.dataset.dfnFor).toEqual("parenthesistest");
expect(elem.dataset.idl).toEqual("");
// corresponding link
const aElem = section.querySelector(`pre a[href="#dom-parenthesistest-${id}()"]`);
expect(aElem).toBeTruthy();
expect(aElem.textContent).toEqual(methodName);
});
const smokeTest = doc.getElementById("dom-parenthesistest-noparens");
expect(smokeTest).toBeTruthy();
expect(smokeTest.firstElementChild.localName).toEqual("code");
expect(smokeTest.textContent).toEqual("noParens");
// corresponding link
const aElem = section.querySelector(`pre a[href="#dom-parenthesistest-noparens"]`);
expect(aElem).toBeTruthy();
expect(aElem.textContent).toEqual("noParens");
done();
});
it("should handle interfaces", function(done) {
var $target = $("#if-basic", doc);
var text = "interface SuperStar {\n};";
Expand Down Expand Up @@ -530,7 +570,7 @@ describe("Core - Contiguous WebIDL", function() {
expect($target.find(".idlEnumItem").length)
.toEqual(4);
expect($target.find(".idlEnumItem").first().text())
.toEqual("one");
.toEqual("\"one\"");

// Links and IDs.
expect($target.find(":contains('EnumBasic')").filter("a").attr("href"))
Expand All @@ -551,6 +591,16 @@ describe("Core - Contiguous WebIDL", function() {
done();
});

it("links empty-string enumeration value", done => {
const links = doc.querySelector(`#enum-empty-sec a[href="#dom-emptyenum-the-empty-string"]`);
const dfn = doc.querySelector("#dom-emptyenum-the-empty-string");
const smokeDfn = doc.querySelector(`#enum-empty-sec a[href="#dom-emptyenum-not empty"]`);
expect(links).toBeTruthy();
expect(dfn).toBeTruthy();
expect(smokeDfn).toBeTruthy();
done();
});

it("should handle callbacks", function(done) {
var $target = $("#cb-basic", doc);
var text = "callback SuperStar = void ();";
Expand Down
50 changes: 50 additions & 0 deletions tests/spec/core/webidl-contiguous.html
Expand Up @@ -37,6 +37,45 @@
CUSTOM PARAGRAPH
</p>
</section>
<section id="sec-parenthesis-method" data-dfn-for="ParenthesisTest" data-link-for="ParenthesisTest">
<pre class="idl">
interface ParenthesisTest {
void basic();
void noParens();
[Something] void ext();
unsigned long long ull(short s);
unsigned long long ull(long s);
SuperStar[][][][] paramed(SuperStar[][]?[] one, [ExtAttrs] ByteString? ext, optional short maybe, short[] shorts, short[][][][] hypercubes, optional short defaulted = 3.5, optional DOMString defaulted2 = "one", short... variable);
getter float withName ();
setter void named ();
void dataLtOverride();
};
</pre>
<p id="meth-basic-doc" data-dfn-for="ParenthesisTest">
<dfn>ull</dfn> is a method. Its <dfn data-lt="ull!overload-1">overloaded form</dfn> returns a <code>SuperStar/</code>
</p>
<p><dfn data-lt="this also links">dataLtOverride()</dfn></p>
<p><dfn>ParenthesisTest</dfn></p>
<p><dfn>basic()</dfn>...</p>
<p><dfn>ext()</dfn>...</p>
<p><dfn>ull()</dfn>...</p>
<p><dfn>paramed()</dfn>...</p>
<p><dfn>withName()</dfn>...</p>
<p><dfn>named()</dfn>...</p>
<p><dfn>dfnDoesNotLinkToAnything()</dfn>...</p>
<p><dfn>noParens</dfn>...</p>
<p>1 <a>basic</a></p>
<p>2 <a>basic()</a></p>
<p>3 <a data-lt="basic">basic</a></p>
<p>4 <a data-lt="basic()">basic</a></p>
<p><a>noParens</a></p>
<p><a>noParens()</a></p>
<p><a data-lt="noParens">noParens</a></p>
<p><a data-lt="noParens()">noParens</a></p>
<p><a>noParens()</a></p>
<p><a data-lt="this also links">this also links</a></p>
</section>
<p><a data-lt="ParenthesisTest.basic">test qualified</a></p>
<section>
<h2>Unsupported</h2>
<p>
Expand Down Expand Up @@ -410,6 +449,17 @@ <h2>Enumerations</h2>
<p dfn-for="EnumBasic"><dfn>one</dfn> is first.</p>
<p link-for="EnumBasic"><a>one</a> is referenced with a <code>[link-for]</code> attribute.</p>
<p id="enum-ref-without-link-for"><a>EnumBasic.one</a> may also be referenced with fully-qualified name.</p>
<section id="enum-empty-sec" data-dfn-for="EmptyEnum">
<pre class="idl">
enum EmptyEnum {
"",
"not empty"
};
</pre>
<p><dfn>EmptyEnum</dfn></p>
<p><dfn>""</dfn></p>...
<p><dfn>not empty</dfn>...</p>
</section>
</section>
<section>
<h2>Callbacks</h2>
Expand Down

0 comments on commit 9ea65c5

Please sign in to comment.