Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

h5o

Package Overview
Dependencies
Maintainers
1
Versions
23
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

h5o - npm Package Compare versions

Comparing version 0.9.3 to 0.10.0

.nvmrc

194

dist/debug/bookmarklet.debug.js

@@ -63,4 +63,4 @@ /**

Outline.prototype.asHTML = function (createLinks) {
return asHTML(this.sections, createLinks);
Outline.prototype.asHTML = function (options) {
return asHTML(this.sections, options);
};

@@ -85,26 +85,54 @@

},{}],5:[function(require,module,exports){
var asHTML = require("./asHTML"),
utils = require("./utils");
function Section(startingNode) {
this.sections = [];
this.startingNode = startingNode;
}
function sectionHeadingText(sectionHeading) {
if (utils.getTagName(sectionHeading) == 'HGROUP') {
// @todo: share code with getHeadingElementRank() to return the heading itself and that would be it
var headings = sectionHeading.getElementsByTagName('h' + (-utils.getHeadingElementRank(sectionHeading)));
if (!headings.length) {
return "<i>Error: no H1-H6 inside HGROUP</i>";
}
sectionHeading = headings[0];
Section.prototype.append = function (what) {
what.container = this;
this.sections.push(what);
};
module.exports = Section;
},{}],6:[function(require,module,exports){
var utils = require("./utils");
function sectionHeadingText(section) {
if (section.heading.implied) {
return "<i>Untitled " + utils.getTagName(section.startingNode) + "</i>";
}
// @todo: try to resolve text content from img[alt] or *[title]
return utils.escapeHtml(sectionHeading.textContent) || "<i>No text content inside " + sectionHeading.nodeName + "</i>";
var elHeading = utils.getRankingHeadingElement(section.heading);
if (!elHeading) {
return "<i>Error: no H1-H6 inside HGROUP</i>";
}
var textContent = elHeading.textContent;
if (!textContent) {
return "<i>No text content inside " + utils.getTagName(elHeading) + "</i>";
}
return utils.escapeHtml(textContent);
}
function generateId(node) {
var linkCounter = 0; // @todo: move this out somewhere else, as this is not exactly performant (but makes old tests pass)
var id = node.getAttribute('id');
if (id) return id;
function getId(section, options) {
var sectionId = section.startingNode.getAttribute('id');
if (sectionId) {
return sectionId;
}
if (!section.heading.implied) {
var headingId = section.heading.getAttribute('id');
if (headingId) {
return headingId;
}
}
var node = section.startingNode;
do {
id = 'h5o-' + (++linkCounter);
} while (node.ownerDocument.getElementById(id)); // @todo: there's probably no document when outlining a detached fragment... is there?
var id = 'h5o-' + (++options.linkCounter);
} while (node.ownerDocument.getElementById(id));
node.setAttribute('id', id);

@@ -114,44 +142,52 @@ return id;

function Section(startingNode) {
this.sections = [];
this.startingNode = startingNode;
}
function asHTML(sections, options) {
Section.prototype.append = function (what) {
what.container = this;
this.sections.push(what);
};
if (typeof(options) !== "object") {
// if second argument is not an object - it must be the boolean for `createLinks` (backwards compat)
options = {
createLinks: !!options
}
}
if (!sections.length) {
return '';
}
Section.prototype.asHTML = function (createLinks) {
// @todo: this really belongs in a separate formatter type thing
if (options.skipTopHeader) {
return asHTML(sections[0].sections, {
skipToHeader: false,
createLinks: options.createLinks
})
}
if (!this.heading) {
// @todo: find formal proof if this is possible/not-possible
throw new Error("An implied heading should have been created at some point, but wasn't.");
if (typeof(options.linkCounter) === "undefined") {
options.linkCounter = 0;
}
var headingText = this.heading.implied
? "<i>Untitled " + utils.getTagName(this.startingNode) + "</i>"
: sectionHeadingText(this.heading);
var createLinks = !!options.createLinks;
var result = [];
if (createLinks) {
headingText = '<a href="#' + generateId(this.startingNode) + '">'
+ headingText
+ '</a>';
}
return headingText + asHTML(this.sections, createLinks);
};
result.push("<ol>");
module.exports = Section;
for (var i = 0; i < sections.length; i++) {
var section = sections[i];
result.push("<li>");
},{"./asHTML":6,"./utils":8}],6:[function(require,module,exports){
function asHTML(sections, createLinks) {
var retval = '';
if (createLinks) {
result.push('<a href="#' + getId(section, options) + '">');
}
for (var i = 0; i < sections.length; i++) {
retval += '<li>' + sections[i].asHTML(createLinks) + '</li>';
result.push(sectionHeadingText(section));
if (createLinks) {
result.push("</a>");
}
result.push(asHTML(section.sections, options));
result.push("</li>");
}
return (retval == '' ? retval : '<ol>' + retval + '</ol>');
result.push("</ol>");
return result.join("");
}

@@ -161,3 +197,3 @@

},{}],7:[function(require,module,exports){
},{"./utils":8}],7:[function(require,module,exports){
var Section = require("./Section"),

@@ -176,2 +212,13 @@ Outline = require("./Outline"),

function getRank(heading) {
var rankingElement = utils.getRankingHeadingElement(heading);
if (!rankingElement) {
// The rank of an hgroup element is the rank of the highest-ranked h1–h6 element descendant of the hgroup
// element, if there are any such elements, or otherwise the same as for an h1 element (the highest rank).
// ref: https://html.spec.whatwg.org/#the-hgroup-element
return -1; // rank of H1
}
return -parseInt(utils.getTagName(rankingElement).substr(1));
}
function onEnterNode(node) {

@@ -213,4 +260,3 @@

// Let current section be a newly created section for the current outline target element.
// Associate current outline target with current section.
// @todo: should the above two steps really be done in one step?
// @todo: Associate current outline target with current section.
currentSection = new Section(node);

@@ -239,3 +285,2 @@

// Let current section be a newly created section for the current outline target element.
// @todo: why not "associate", like when entering a sectioning content element? Is the "parentSection" the association? Is Outline a Section?
currentSection = new Section(node);

@@ -259,3 +304,3 @@

// outline target is an implied heading, then
} else if (currentOutlineTarget.outline.getLastSection().heading.implied || utils.getHeadingElementRank(node) >= utils.getHeadingElementRank(currentOutlineTarget.outline.getLastSection().heading)) {
} else if (currentOutlineTarget.outline.getLastSection().heading.implied || getRank(node) >= getRank(currentOutlineTarget.outline.getLastSection().heading)) {

@@ -300,3 +345,3 @@ // create a new section and

// If the element being entered has a rank lower than the rank of the heading of the candidate section, then
if (utils.getHeadingElementRank(node) < utils.getHeadingElementRank(candidateSection.heading)) {
if (getRank(node) < getRank(candidateSection.heading)) {

@@ -373,3 +418,2 @@ // create a new section,

// (This does not change which section is the last section in the outline.)
// @todo: what does "appending the outline" really mean?
for (var i = 0; i < targetBeingExited.outline.sections.length; i++) {

@@ -402,2 +446,3 @@ currentSection.append(targetBeingExited.outline.sections[i]);

if (utils.isSecContent(node) || utils.isSecRoot(node)) {
// If the current section has no heading, create an implied heading and let that be the heading for the current section.

@@ -465,15 +510,24 @@ if (!currentSection.heading) {

function getHeadingElementRank(el) {
var elTagName = getTagName(el);
if (elTagName == 'HGROUP') {
/* The rank of an hgroup element is the rank of the highest-ranked h1-h6 element descendant of the hgroup element, if there are any such elements, or otherwise the same as for an h1 element (the highest rank). */
for (var i = 1; i <= 6; i++) {
if (el.getElementsByTagName('H' + i).length > 0) {
return -i;
}
var isHeading = tagChecker('^H[1-6]|HGROUP$');
function getRankingHeadingElement(heading) {
if (!isHeading(heading)) {
throw new Error("Not a heading element");
}
var elTagName = getTagName(heading);
if (elTagName !== "HGROUP") {
return heading;
}
// find highest ranking heading inside HGROUP
for (var i = 1; i <= 6; i++) {
var headings = heading.getElementsByTagName("H" + i);
if (headings.length) {
return headings[0];
}
return -1;
} else {
return -parseInt(elTagName.substr(1));
}
// HGROUP has no headings...
return null;
}

@@ -494,4 +548,4 @@

exports.isSecContent = tagChecker('^ARTICLE|ASIDE|NAV|SECTION$');
exports.isHeading = tagChecker('^H[1-6]|HGROUP$');
exports.getHeadingElementRank = getHeadingElementRank;
exports.isHeading = isHeading;
exports.getRankingHeadingElement = getRankingHeadingElement;

@@ -498,0 +552,0 @@ exports.escapeHtml = escapeHtml;

@@ -11,2 +11,2 @@ /**

*/
!function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g<d.length;g++)e(d[g]);return e}({1:[function(a){var b=a("./index"),c=function(a,b){for(var c=0;c<a.length;c++)a[c].setAttribute("style",b)},d="font-size:11px;font-family:Verdana, sans-serif;",e="position:fixed;top:10px;right:10px;border:2px solid #000;background:rgba(255,255,255,.9);padding:15px;z-index:999;max-height:400px;overflow:auto;",f="list-style:decimal outside;margin-left:20px;",g="margin: 0;padding:0;",h="color:#008;text-decoration:underline;",i="float: right; margin: 0 0 5px 5px; padding: 5px; border: 1px #008 solid;color:#00f;background-color:#ccf;",j=b(document.body).asHTML(!0),k=document.createElement("div");c([k],e+d),k.innerHTML=j,c(k.getElementsByTagName("li"),f+d),c(k.getElementsByTagName("ol"),g+d),c(k.getElementsByTagName("a"),h+d);var l=k.insertBefore(document.createElement("a"),k.firstChild);c([l],i),l.innerHTML="Close",l.href="#",l.onclick=function(a){document.body.removeChild(k),k=l=null,a.preventDefault()},document.body.appendChild(k)},{"./index":2}],2:[function(a,b){b.exports=a("./src/createOutline")},{"./src/createOutline":7}],3:[function(a,b){function c(a,b){this.startingNode=a.node,this.sections=[b]}var d=a("./asHTML");c.prototype.getLastSection=function(){return this.sections[this.sections.length-1]},c.prototype.asHTML=function(a){return d(this.sections,a)},b.exports=c},{"./asHTML":6}],4:[function(a,b){function c(a){this.node=a}b.exports=c},{}],5:[function(a,b){function c(a){if("HGROUP"==g.getTagName(a)){var b=a.getElementsByTagName("h"+-g.getHeadingElementRank(a));if(!b.length)return"<i>Error: no H1-H6 inside HGROUP</i>";a=b[0]}return g.escapeHtml(a.textContent)||"<i>No text content inside "+a.nodeName+"</i>"}function d(a){var b=0,c=a.getAttribute("id");if(c)return c;do c="h5o-"+ ++b;while(a.ownerDocument.getElementById(c));return a.setAttribute("id",c),c}function e(a){this.sections=[],this.startingNode=a}var f=a("./asHTML"),g=a("./utils");e.prototype.append=function(a){a.container=this,this.sections.push(a)},e.prototype.asHTML=function(a){if(!this.heading)throw new Error("An implied heading should have been created at some point, but wasn't.");var b=this.heading.implied?"<i>Untitled "+g.getTagName(this.startingNode)+"</i>":c(this.heading);return a&&(b='<a href="#'+d(this.startingNode)+'">'+b+"</a>"),b+f(this.sections,a)},b.exports=e},{"./asHTML":6,"./utils":8}],6:[function(a,b){function c(a,b){for(var c="",d=0;d<a.length;d++)c+="<li>"+a[d].asHTML(b)+"</li>";return""==c?c:"<ol>"+c+"</ol>"}b.exports=c},{}],7:[function(a,b){function c(){return i.length?i[i.length-1].node:void 0}function d(a){var b=c();if(!n.isHeading(b)&&!n.hasHiddenAttribute(b)){if(n.hasHiddenAttribute(a))return void i.push({node:a});if(n.isSecContent(a))return null!=g&&(h.heading||(h.heading={implied:!0}),i.push(g)),g=new l(a),h=new j(a),void(g.outline=new k(g.node,h));if(n.isSecRoot(a))return null!=g&&i.push(g),g=new l(a),g.parentSection=h,h=new j(a),void(g.outline=new k(g.node,h));if(n.isHeading(a)){if(h.heading)if(g.outline.getLastSection().heading.implied||n.getHeadingElementRank(a)>=n.getHeadingElementRank(g.outline.getLastSection().heading)){var d=new j(a);g.outline.sections.push(d),h=d,h.heading=a}else{var e=!1,f=h;do{if(n.getHeadingElementRank(a)<n.getHeadingElementRank(f.heading)){var d=new j(a);f.append(d),h=d,h.heading=a,e=!0}var m=f.container;f=m}while(!e)}else h.heading=a;return void i.push({node:a})}}}function e(a){var b=c();if(b===a&&i.pop(),!n.isHeading(b)&&!n.hasHiddenAttribute(b)){if(!(n.isSecContent(a)&&i.length>0))return n.isSecRoot(a)&&i.length>0?(h.heading||(h.heading={implied:!0}),h=g.parentSection,void(g=i.pop())):n.isSecContent(a)||n.isSecRoot(a)?void(h.heading||(h.heading={implied:!0})):void 0;h.heading||(h.heading={implied:!0});var d=g;g=i.pop(),h=g.outline.getLastSection();for(var e=0;e<d.outline.sections.length;e++)h.append(d.outline.sections[e])}}function f(a){if(!n.isSecContent(a)&&!n.isSecRoot(a))throw new TypeError("Invalid argument: start element must either be sectioning root or sectioning content.");return g=null,h=null,i=[],m(a,d,e),g.outline}var g,h,i,j=a("./Section"),k=a("./Outline"),l=a("./OutlineTarget"),m=a("./walk"),n=a("./utils");b.exports=f},{"./Outline":3,"./OutlineTarget":4,"./Section":5,"./utils":8,"./walk":9}],8:[function(a,b,c){function d(a){return a.tagName.toUpperCase()}function e(a){return function(b){return f(b)&&new RegExp(a,"i").test(d(b))}}function f(a){return a&&a.tagName}function g(a){var b=d(a);if("HGROUP"==b){for(var c=1;6>=c;c++)if(a.getElementsByTagName("H"+c).length>0)return-c;return-1}return-parseInt(b.substr(1))}function h(a){return(""+a).replace(/&/g,"&amp;").replace(/</g,"&lt;")}function i(a){return f(a)&&a.hasAttribute("hidden")}c.getTagName=d,c.hasHiddenAttribute=i,c.isSecRoot=e("^BLOCKQUOTE|BODY|DETAILS|FIELDSET|FIGURE|TD$"),c.isSecContent=e("^ARTICLE|ASIDE|NAV|SECTION$"),c.isHeading=e("^H[1-6]|HGROUP$"),c.getHeadingElementRank=g,c.escapeHtml=h},{}],9:[function(a,b){b.exports=function(a,b,c){var d=a;a:for(;d;)if(b(d),d.firstChild)d=d.firstChild;else for(;d;){if(c(d),d.nextSibling){d=d.nextSibling;continue a}d=d==a?null:d.parentNode}}},{}]},{},[1]);
!function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g<d.length;g++)e(d[g]);return e}({1:[function(a){var b=a("./index"),c=function(a,b){for(var c=0;c<a.length;c++)a[c].setAttribute("style",b)},d="font-size:11px;font-family:Verdana, sans-serif;",e="position:fixed;top:10px;right:10px;border:2px solid #000;background:rgba(255,255,255,.9);padding:15px;z-index:999;max-height:400px;overflow:auto;",f="list-style:decimal outside;margin-left:20px;",g="margin: 0;padding:0;",h="color:#008;text-decoration:underline;",i="float: right; margin: 0 0 5px 5px; padding: 5px; border: 1px #008 solid;color:#00f;background-color:#ccf;",j=b(document.body).asHTML(!0),k=document.createElement("div");c([k],e+d),k.innerHTML=j,c(k.getElementsByTagName("li"),f+d),c(k.getElementsByTagName("ol"),g+d),c(k.getElementsByTagName("a"),h+d);var l=k.insertBefore(document.createElement("a"),k.firstChild);c([l],i),l.innerHTML="Close",l.href="#",l.onclick=function(a){document.body.removeChild(k),k=l=null,a.preventDefault()},document.body.appendChild(k)},{"./index":2}],2:[function(a,b){b.exports=a("./src/createOutline")},{"./src/createOutline":7}],3:[function(a,b){function c(a,b){this.startingNode=a.node,this.sections=[b]}var d=a("./asHTML");c.prototype.getLastSection=function(){return this.sections[this.sections.length-1]},c.prototype.asHTML=function(a){return d(this.sections,a)},b.exports=c},{"./asHTML":6}],4:[function(a,b){function c(a){this.node=a}b.exports=c},{}],5:[function(a,b){function c(a){this.sections=[],this.startingNode=a}c.prototype.append=function(a){a.container=this,this.sections.push(a)},b.exports=c},{}],6:[function(a,b){function c(a){if(a.heading.implied)return"<i>Untitled "+f.getTagName(a.startingNode)+"</i>";var b=f.getRankingHeadingElement(a.heading);if(!b)return"<i>Error: no H1-H6 inside HGROUP</i>";var c=b.textContent;return c?f.escapeHtml(c):"<i>No text content inside "+f.getTagName(b)+"</i>"}function d(a,b){var c=a.startingNode.getAttribute("id");if(c)return c;if(!a.heading.implied){var d=a.heading.getAttribute("id");if(d)return d}var e=a.startingNode;do var f="h5o-"+ ++b.linkCounter;while(e.ownerDocument.getElementById(f));return e.setAttribute("id",f),f}function e(a,b){if("object"!=typeof b&&(b={createLinks:!!b}),!a.length)return"";if(b.skipTopHeader)return e(a[0].sections,{skipToHeader:!1,createLinks:b.createLinks});"undefined"==typeof b.linkCounter&&(b.linkCounter=0);var f=!!b.createLinks,g=[];g.push("<ol>");for(var h=0;h<a.length;h++){var i=a[h];g.push("<li>"),f&&g.push('<a href="#'+d(i,b)+'">'),g.push(c(i)),f&&g.push("</a>"),g.push(e(i.sections,b)),g.push("</li>")}return g.push("</ol>"),g.join("")}var f=a("./utils");b.exports=e},{"./utils":8}],7:[function(a,b){function c(){return j.length?j[j.length-1].node:void 0}function d(a){var b=o.getRankingHeadingElement(a);return b?-parseInt(o.getTagName(b).substr(1)):-1}function e(a){var b=c();if(!o.isHeading(b)&&!o.hasHiddenAttribute(b)){if(o.hasHiddenAttribute(a))return void j.push({node:a});if(o.isSecContent(a))return null!=h&&(i.heading||(i.heading={implied:!0}),j.push(h)),h=new m(a),i=new k(a),void(h.outline=new l(h.node,i));if(o.isSecRoot(a))return null!=h&&j.push(h),h=new m(a),h.parentSection=i,i=new k(a),void(h.outline=new l(h.node,i));if(o.isHeading(a)){if(i.heading)if(h.outline.getLastSection().heading.implied||d(a)>=d(h.outline.getLastSection().heading)){var e=new k(a);h.outline.sections.push(e),i=e,i.heading=a}else{var f=!1,g=i;do{if(d(a)<d(g.heading)){var e=new k(a);g.append(e),i=e,i.heading=a,f=!0}var n=g.container;g=n}while(!f)}else i.heading=a;return void j.push({node:a})}}}function f(a){var b=c();if(b===a&&j.pop(),!o.isHeading(b)&&!o.hasHiddenAttribute(b)){if(!(o.isSecContent(a)&&j.length>0))return o.isSecRoot(a)&&j.length>0?(i.heading||(i.heading={implied:!0}),i=h.parentSection,void(h=j.pop())):o.isSecContent(a)||o.isSecRoot(a)?void(i.heading||(i.heading={implied:!0})):void 0;i.heading||(i.heading={implied:!0});var d=h;h=j.pop(),i=h.outline.getLastSection();for(var e=0;e<d.outline.sections.length;e++)i.append(d.outline.sections[e])}}function g(a){if(!o.isSecContent(a)&&!o.isSecRoot(a))throw new TypeError("Invalid argument: start element must either be sectioning root or sectioning content.");return h=null,i=null,j=[],n(a,e,f),h.outline}var h,i,j,k=a("./Section"),l=a("./Outline"),m=a("./OutlineTarget"),n=a("./walk"),o=a("./utils");b.exports=g},{"./Outline":3,"./OutlineTarget":4,"./Section":5,"./utils":8,"./walk":9}],8:[function(a,b,c){function d(a){return a.tagName.toUpperCase()}function e(a){return function(b){return f(b)&&new RegExp(a,"i").test(d(b))}}function f(a){return a&&a.tagName}function g(a){if(!j(a))throw new Error("Not a heading element");var b=d(a);if("HGROUP"!==b)return a;for(var c=1;6>=c;c++){var e=a.getElementsByTagName("H"+c);if(e.length)return e[0]}return null}function h(a){return(""+a).replace(/&/g,"&amp;").replace(/</g,"&lt;")}function i(a){return f(a)&&a.hasAttribute("hidden")}var j=e("^H[1-6]|HGROUP$");c.getTagName=d,c.hasHiddenAttribute=i,c.isSecRoot=e("^BLOCKQUOTE|BODY|DETAILS|FIELDSET|FIGURE|TD$"),c.isSecContent=e("^ARTICLE|ASIDE|NAV|SECTION$"),c.isHeading=j,c.getRankingHeadingElement=g,c.escapeHtml=h},{}],9:[function(a,b){b.exports=function(a,b,c){var d=a;a:for(;d;)if(b(d),d.firstChild)d=d.firstChild;else for(;d;){if(c(d),d.nextSibling){d=d.nextSibling;continue a}d=d==a?null:d.parentNode}}},{}]},{},[1]);

@@ -27,4 +27,4 @@ /**

Outline.prototype.asHTML = function (createLinks) {
return asHTML(this.sections, createLinks);
Outline.prototype.asHTML = function (options) {
return asHTML(this.sections, options);
};

@@ -49,26 +49,54 @@

},{}],4:[function(require,module,exports){
var asHTML = require("./asHTML"),
utils = require("./utils");
function Section(startingNode) {
this.sections = [];
this.startingNode = startingNode;
}
function sectionHeadingText(sectionHeading) {
if (utils.getTagName(sectionHeading) == 'HGROUP') {
// @todo: share code with getHeadingElementRank() to return the heading itself and that would be it
var headings = sectionHeading.getElementsByTagName('h' + (-utils.getHeadingElementRank(sectionHeading)));
if (!headings.length) {
return "<i>Error: no H1-H6 inside HGROUP</i>";
}
sectionHeading = headings[0];
Section.prototype.append = function (what) {
what.container = this;
this.sections.push(what);
};
module.exports = Section;
},{}],5:[function(require,module,exports){
var utils = require("./utils");
function sectionHeadingText(section) {
if (section.heading.implied) {
return "<i>Untitled " + utils.getTagName(section.startingNode) + "</i>";
}
// @todo: try to resolve text content from img[alt] or *[title]
return utils.escapeHtml(sectionHeading.textContent) || "<i>No text content inside " + sectionHeading.nodeName + "</i>";
var elHeading = utils.getRankingHeadingElement(section.heading);
if (!elHeading) {
return "<i>Error: no H1-H6 inside HGROUP</i>";
}
var textContent = elHeading.textContent;
if (!textContent) {
return "<i>No text content inside " + utils.getTagName(elHeading) + "</i>";
}
return utils.escapeHtml(textContent);
}
function generateId(node) {
var linkCounter = 0; // @todo: move this out somewhere else, as this is not exactly performant (but makes old tests pass)
var id = node.getAttribute('id');
if (id) return id;
function getId(section, options) {
var sectionId = section.startingNode.getAttribute('id');
if (sectionId) {
return sectionId;
}
if (!section.heading.implied) {
var headingId = section.heading.getAttribute('id');
if (headingId) {
return headingId;
}
}
var node = section.startingNode;
do {
id = 'h5o-' + (++linkCounter);
} while (node.ownerDocument.getElementById(id)); // @todo: there's probably no document when outlining a detached fragment... is there?
var id = 'h5o-' + (++options.linkCounter);
} while (node.ownerDocument.getElementById(id));
node.setAttribute('id', id);

@@ -78,44 +106,52 @@ return id;

function Section(startingNode) {
this.sections = [];
this.startingNode = startingNode;
}
function asHTML(sections, options) {
Section.prototype.append = function (what) {
what.container = this;
this.sections.push(what);
};
if (typeof(options) !== "object") {
// if second argument is not an object - it must be the boolean for `createLinks` (backwards compat)
options = {
createLinks: !!options
}
}
if (!sections.length) {
return '';
}
Section.prototype.asHTML = function (createLinks) {
// @todo: this really belongs in a separate formatter type thing
if (options.skipTopHeader) {
return asHTML(sections[0].sections, {
skipToHeader: false,
createLinks: options.createLinks
})
}
if (!this.heading) {
// @todo: find formal proof if this is possible/not-possible
throw new Error("An implied heading should have been created at some point, but wasn't.");
if (typeof(options.linkCounter) === "undefined") {
options.linkCounter = 0;
}
var headingText = this.heading.implied
? "<i>Untitled " + utils.getTagName(this.startingNode) + "</i>"
: sectionHeadingText(this.heading);
var createLinks = !!options.createLinks;
var result = [];
if (createLinks) {
headingText = '<a href="#' + generateId(this.startingNode) + '">'
+ headingText
+ '</a>';
}
return headingText + asHTML(this.sections, createLinks);
};
result.push("<ol>");
module.exports = Section;
for (var i = 0; i < sections.length; i++) {
var section = sections[i];
result.push("<li>");
},{"./asHTML":5,"./utils":7}],5:[function(require,module,exports){
function asHTML(sections, createLinks) {
var retval = '';
if (createLinks) {
result.push('<a href="#' + getId(section, options) + '">');
}
for (var i = 0; i < sections.length; i++) {
retval += '<li>' + sections[i].asHTML(createLinks) + '</li>';
result.push(sectionHeadingText(section));
if (createLinks) {
result.push("</a>");
}
result.push(asHTML(section.sections, options));
result.push("</li>");
}
return (retval == '' ? retval : '<ol>' + retval + '</ol>');
result.push("</ol>");
return result.join("");
}

@@ -125,3 +161,3 @@

},{}],6:[function(require,module,exports){
},{"./utils":7}],6:[function(require,module,exports){
var Section = require("./Section"),

@@ -140,2 +176,13 @@ Outline = require("./Outline"),

function getRank(heading) {
var rankingElement = utils.getRankingHeadingElement(heading);
if (!rankingElement) {
// The rank of an hgroup element is the rank of the highest-ranked h1–h6 element descendant of the hgroup
// element, if there are any such elements, or otherwise the same as for an h1 element (the highest rank).
// ref: https://html.spec.whatwg.org/#the-hgroup-element
return -1; // rank of H1
}
return -parseInt(utils.getTagName(rankingElement).substr(1));
}
function onEnterNode(node) {

@@ -177,4 +224,3 @@

// Let current section be a newly created section for the current outline target element.
// Associate current outline target with current section.
// @todo: should the above two steps really be done in one step?
// @todo: Associate current outline target with current section.
currentSection = new Section(node);

@@ -203,3 +249,2 @@

// Let current section be a newly created section for the current outline target element.
// @todo: why not "associate", like when entering a sectioning content element? Is the "parentSection" the association? Is Outline a Section?
currentSection = new Section(node);

@@ -223,3 +268,3 @@

// outline target is an implied heading, then
} else if (currentOutlineTarget.outline.getLastSection().heading.implied || utils.getHeadingElementRank(node) >= utils.getHeadingElementRank(currentOutlineTarget.outline.getLastSection().heading)) {
} else if (currentOutlineTarget.outline.getLastSection().heading.implied || getRank(node) >= getRank(currentOutlineTarget.outline.getLastSection().heading)) {

@@ -264,3 +309,3 @@ // create a new section and

// If the element being entered has a rank lower than the rank of the heading of the candidate section, then
if (utils.getHeadingElementRank(node) < utils.getHeadingElementRank(candidateSection.heading)) {
if (getRank(node) < getRank(candidateSection.heading)) {

@@ -337,3 +382,2 @@ // create a new section,

// (This does not change which section is the last section in the outline.)
// @todo: what does "appending the outline" really mean?
for (var i = 0; i < targetBeingExited.outline.sections.length; i++) {

@@ -366,2 +410,3 @@ currentSection.append(targetBeingExited.outline.sections[i]);

if (utils.isSecContent(node) || utils.isSecRoot(node)) {
// If the current section has no heading, create an implied heading and let that be the heading for the current section.

@@ -429,15 +474,24 @@ if (!currentSection.heading) {

function getHeadingElementRank(el) {
var elTagName = getTagName(el);
if (elTagName == 'HGROUP') {
/* The rank of an hgroup element is the rank of the highest-ranked h1-h6 element descendant of the hgroup element, if there are any such elements, or otherwise the same as for an h1 element (the highest rank). */
for (var i = 1; i <= 6; i++) {
if (el.getElementsByTagName('H' + i).length > 0) {
return -i;
}
var isHeading = tagChecker('^H[1-6]|HGROUP$');
function getRankingHeadingElement(heading) {
if (!isHeading(heading)) {
throw new Error("Not a heading element");
}
var elTagName = getTagName(heading);
if (elTagName !== "HGROUP") {
return heading;
}
// find highest ranking heading inside HGROUP
for (var i = 1; i <= 6; i++) {
var headings = heading.getElementsByTagName("H" + i);
if (headings.length) {
return headings[0];
}
return -1;
} else {
return -parseInt(elTagName.substr(1));
}
// HGROUP has no headings...
return null;
}

@@ -458,4 +512,4 @@

exports.isSecContent = tagChecker('^ARTICLE|ASIDE|NAV|SECTION$');
exports.isHeading = tagChecker('^H[1-6]|HGROUP$');
exports.getHeadingElementRank = getHeadingElementRank;
exports.isHeading = isHeading;
exports.getRankingHeadingElement = getRankingHeadingElement;

@@ -462,0 +516,0 @@ exports.escapeHtml = escapeHtml;

@@ -11,2 +11,2 @@ /**

*/
!function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;b="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,b.HTML5Outline=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g<d.length;g++)e(d[g]);return e}({1:[function(a,b){b.exports=a("./src/createOutline")},{"./src/createOutline":6}],2:[function(a,b){function c(a,b){this.startingNode=a.node,this.sections=[b]}var d=a("./asHTML");c.prototype.getLastSection=function(){return this.sections[this.sections.length-1]},c.prototype.asHTML=function(a){return d(this.sections,a)},b.exports=c},{"./asHTML":5}],3:[function(a,b){function c(a){this.node=a}b.exports=c},{}],4:[function(a,b){function c(a){if("HGROUP"==g.getTagName(a)){var b=a.getElementsByTagName("h"+-g.getHeadingElementRank(a));if(!b.length)return"<i>Error: no H1-H6 inside HGROUP</i>";a=b[0]}return g.escapeHtml(a.textContent)||"<i>No text content inside "+a.nodeName+"</i>"}function d(a){var b=0,c=a.getAttribute("id");if(c)return c;do c="h5o-"+ ++b;while(a.ownerDocument.getElementById(c));return a.setAttribute("id",c),c}function e(a){this.sections=[],this.startingNode=a}var f=a("./asHTML"),g=a("./utils");e.prototype.append=function(a){a.container=this,this.sections.push(a)},e.prototype.asHTML=function(a){if(!this.heading)throw new Error("An implied heading should have been created at some point, but wasn't.");var b=this.heading.implied?"<i>Untitled "+g.getTagName(this.startingNode)+"</i>":c(this.heading);return a&&(b='<a href="#'+d(this.startingNode)+'">'+b+"</a>"),b+f(this.sections,a)},b.exports=e},{"./asHTML":5,"./utils":7}],5:[function(a,b){function c(a,b){for(var c="",d=0;d<a.length;d++)c+="<li>"+a[d].asHTML(b)+"</li>";return""==c?c:"<ol>"+c+"</ol>"}b.exports=c},{}],6:[function(a,b){function c(){return i.length?i[i.length-1].node:void 0}function d(a){var b=c();if(!n.isHeading(b)&&!n.hasHiddenAttribute(b)){if(n.hasHiddenAttribute(a))return void i.push({node:a});if(n.isSecContent(a))return null!=g&&(h.heading||(h.heading={implied:!0}),i.push(g)),g=new l(a),h=new j(a),void(g.outline=new k(g.node,h));if(n.isSecRoot(a))return null!=g&&i.push(g),g=new l(a),g.parentSection=h,h=new j(a),void(g.outline=new k(g.node,h));if(n.isHeading(a)){if(h.heading)if(g.outline.getLastSection().heading.implied||n.getHeadingElementRank(a)>=n.getHeadingElementRank(g.outline.getLastSection().heading)){var d=new j(a);g.outline.sections.push(d),h=d,h.heading=a}else{var e=!1,f=h;do{if(n.getHeadingElementRank(a)<n.getHeadingElementRank(f.heading)){var d=new j(a);f.append(d),h=d,h.heading=a,e=!0}var m=f.container;f=m}while(!e)}else h.heading=a;return void i.push({node:a})}}}function e(a){var b=c();if(b===a&&i.pop(),!n.isHeading(b)&&!n.hasHiddenAttribute(b)){if(!(n.isSecContent(a)&&i.length>0))return n.isSecRoot(a)&&i.length>0?(h.heading||(h.heading={implied:!0}),h=g.parentSection,void(g=i.pop())):n.isSecContent(a)||n.isSecRoot(a)?void(h.heading||(h.heading={implied:!0})):void 0;h.heading||(h.heading={implied:!0});var d=g;g=i.pop(),h=g.outline.getLastSection();for(var e=0;e<d.outline.sections.length;e++)h.append(d.outline.sections[e])}}function f(a){if(!n.isSecContent(a)&&!n.isSecRoot(a))throw new TypeError("Invalid argument: start element must either be sectioning root or sectioning content.");return g=null,h=null,i=[],m(a,d,e),g.outline}var g,h,i,j=a("./Section"),k=a("./Outline"),l=a("./OutlineTarget"),m=a("./walk"),n=a("./utils");b.exports=f},{"./Outline":2,"./OutlineTarget":3,"./Section":4,"./utils":7,"./walk":8}],7:[function(a,b,c){function d(a){return a.tagName.toUpperCase()}function e(a){return function(b){return f(b)&&new RegExp(a,"i").test(d(b))}}function f(a){return a&&a.tagName}function g(a){var b=d(a);if("HGROUP"==b){for(var c=1;6>=c;c++)if(a.getElementsByTagName("H"+c).length>0)return-c;return-1}return-parseInt(b.substr(1))}function h(a){return(""+a).replace(/&/g,"&amp;").replace(/</g,"&lt;")}function i(a){return f(a)&&a.hasAttribute("hidden")}c.getTagName=d,c.hasHiddenAttribute=i,c.isSecRoot=e("^BLOCKQUOTE|BODY|DETAILS|FIELDSET|FIGURE|TD$"),c.isSecContent=e("^ARTICLE|ASIDE|NAV|SECTION$"),c.isHeading=e("^H[1-6]|HGROUP$"),c.getHeadingElementRank=g,c.escapeHtml=h},{}],8:[function(a,b){b.exports=function(a,b,c){var d=a;a:for(;d;)if(b(d),d.firstChild)d=d.firstChild;else for(;d;){if(c(d),d.nextSibling){d=d.nextSibling;continue a}d=d==a?null:d.parentNode}}},{}]},{},[1])(1)});
!function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;b="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,b.HTML5Outline=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g<d.length;g++)e(d[g]);return e}({1:[function(a,b){b.exports=a("./src/createOutline")},{"./src/createOutline":6}],2:[function(a,b){function c(a,b){this.startingNode=a.node,this.sections=[b]}var d=a("./asHTML");c.prototype.getLastSection=function(){return this.sections[this.sections.length-1]},c.prototype.asHTML=function(a){return d(this.sections,a)},b.exports=c},{"./asHTML":5}],3:[function(a,b){function c(a){this.node=a}b.exports=c},{}],4:[function(a,b){function c(a){this.sections=[],this.startingNode=a}c.prototype.append=function(a){a.container=this,this.sections.push(a)},b.exports=c},{}],5:[function(a,b){function c(a){if(a.heading.implied)return"<i>Untitled "+f.getTagName(a.startingNode)+"</i>";var b=f.getRankingHeadingElement(a.heading);if(!b)return"<i>Error: no H1-H6 inside HGROUP</i>";var c=b.textContent;return c?f.escapeHtml(c):"<i>No text content inside "+f.getTagName(b)+"</i>"}function d(a,b){var c=a.startingNode.getAttribute("id");if(c)return c;if(!a.heading.implied){var d=a.heading.getAttribute("id");if(d)return d}var e=a.startingNode;do var f="h5o-"+ ++b.linkCounter;while(e.ownerDocument.getElementById(f));return e.setAttribute("id",f),f}function e(a,b){if("object"!=typeof b&&(b={createLinks:!!b}),!a.length)return"";if(b.skipTopHeader)return e(a[0].sections,{skipToHeader:!1,createLinks:b.createLinks});"undefined"==typeof b.linkCounter&&(b.linkCounter=0);var f=!!b.createLinks,g=[];g.push("<ol>");for(var h=0;h<a.length;h++){var i=a[h];g.push("<li>"),f&&g.push('<a href="#'+d(i,b)+'">'),g.push(c(i)),f&&g.push("</a>"),g.push(e(i.sections,b)),g.push("</li>")}return g.push("</ol>"),g.join("")}var f=a("./utils");b.exports=e},{"./utils":7}],6:[function(a,b){function c(){return j.length?j[j.length-1].node:void 0}function d(a){var b=o.getRankingHeadingElement(a);return b?-parseInt(o.getTagName(b).substr(1)):-1}function e(a){var b=c();if(!o.isHeading(b)&&!o.hasHiddenAttribute(b)){if(o.hasHiddenAttribute(a))return void j.push({node:a});if(o.isSecContent(a))return null!=h&&(i.heading||(i.heading={implied:!0}),j.push(h)),h=new m(a),i=new k(a),void(h.outline=new l(h.node,i));if(o.isSecRoot(a))return null!=h&&j.push(h),h=new m(a),h.parentSection=i,i=new k(a),void(h.outline=new l(h.node,i));if(o.isHeading(a)){if(i.heading)if(h.outline.getLastSection().heading.implied||d(a)>=d(h.outline.getLastSection().heading)){var e=new k(a);h.outline.sections.push(e),i=e,i.heading=a}else{var f=!1,g=i;do{if(d(a)<d(g.heading)){var e=new k(a);g.append(e),i=e,i.heading=a,f=!0}var n=g.container;g=n}while(!f)}else i.heading=a;return void j.push({node:a})}}}function f(a){var b=c();if(b===a&&j.pop(),!o.isHeading(b)&&!o.hasHiddenAttribute(b)){if(!(o.isSecContent(a)&&j.length>0))return o.isSecRoot(a)&&j.length>0?(i.heading||(i.heading={implied:!0}),i=h.parentSection,void(h=j.pop())):o.isSecContent(a)||o.isSecRoot(a)?void(i.heading||(i.heading={implied:!0})):void 0;i.heading||(i.heading={implied:!0});var d=h;h=j.pop(),i=h.outline.getLastSection();for(var e=0;e<d.outline.sections.length;e++)i.append(d.outline.sections[e])}}function g(a){if(!o.isSecContent(a)&&!o.isSecRoot(a))throw new TypeError("Invalid argument: start element must either be sectioning root or sectioning content.");return h=null,i=null,j=[],n(a,e,f),h.outline}var h,i,j,k=a("./Section"),l=a("./Outline"),m=a("./OutlineTarget"),n=a("./walk"),o=a("./utils");b.exports=g},{"./Outline":2,"./OutlineTarget":3,"./Section":4,"./utils":7,"./walk":8}],7:[function(a,b,c){function d(a){return a.tagName.toUpperCase()}function e(a){return function(b){return f(b)&&new RegExp(a,"i").test(d(b))}}function f(a){return a&&a.tagName}function g(a){if(!j(a))throw new Error("Not a heading element");var b=d(a);if("HGROUP"!==b)return a;for(var c=1;6>=c;c++){var e=a.getElementsByTagName("H"+c);if(e.length)return e[0]}return null}function h(a){return(""+a).replace(/&/g,"&amp;").replace(/</g,"&lt;")}function i(a){return f(a)&&a.hasAttribute("hidden")}var j=e("^H[1-6]|HGROUP$");c.getTagName=d,c.hasHiddenAttribute=i,c.isSecRoot=e("^BLOCKQUOTE|BODY|DETAILS|FIELDSET|FIGURE|TD$"),c.isSecContent=e("^ARTICLE|ASIDE|NAV|SECTION$"),c.isHeading=j,c.getRankingHeadingElement=g,c.escapeHtml=h},{}],8:[function(a,b){b.exports=function(a,b,c){var d=a;a:for(;d;)if(b(d),d.firstChild)d=d.firstChild;else for(;d;){if(c(d),d.nextSibling){d=d.nextSibling;continue a}d=d==a?null:d.parentNode}}},{}]},{},[1])(1)});
{
"name": "h5o",
"version": "0.9.3",
"version": "0.10.0",
"description": "HTML5 outliner",

@@ -19,2 +19,9 @@ "main": "index.js",

},
"contributors": [
{
"name": "Jeffrey Yasskin",
"email": "jyasskin@gmail.com",
"url": "https://github.com/jyasskin"
}
],
"license": "MIT",

@@ -21,0 +28,0 @@ "bugs": {

@@ -29,3 +29,7 @@ # HTML5 outliner #

- `HTML5Outline(startFrom)` (you likely want `startFrom` to be `document.body`). Returned value is an outline object, with sections.
- `outline.asHTML(createLinks)` to get HTML with an ordered list. If `createLinks` is `true`, the DOM will be amended with IDs and the list will contain links for navigation
- `outline.asHTML( [ options | createLinks ])` to get HTML with an ordered list.
- If `options.createLinks` (or `createLinks`) is `true`, the DOM will be amended with IDs and the list will contain links for navigation.
- If `options.skipToHeader` is true, the outline HTML will only include the sub-sections of the first section in
the outline (which is usually the `body`), i.e. it will only contain the sections of the documents, skipping
the title of the whole document.

@@ -62,2 +66,7 @@ ## Development ##

### v0.10.0 (2015-03-15) ###
* Implemented #18: Add an option to skip the top-level header when generating a ToC (thanks @jyasskin)
* Split up `getHeadingElementRank` into `getRankingHeadingElement` and `getRank`
* `Section` no longer has `asHTML` (out of scope)
### v0.9.3 (2015-03-11) ###

@@ -133,1 +142,6 @@ * `Outline` is not a separate object of its own

Originally [lived on Google Code](https://code.google.com/p/h5o), if you like archeology
## Contributors ##
* [Dominykas Blyžė](http://www.dominykas.com/)
* [Jeffrey Yasskin](https://github.com/jyasskin)

@@ -1,11 +0,96 @@

function asHTML(sections, createLinks) {
var retval = '';
var utils = require("./utils");
function sectionHeadingText(section) {
if (section.heading.implied) {
return "<i>Untitled " + utils.getTagName(section.startingNode) + "</i>";
}
var elHeading = utils.getRankingHeadingElement(section.heading);
if (!elHeading) {
return "<i>Error: no H1-H6 inside HGROUP</i>";
}
var textContent = elHeading.textContent;
if (!textContent) {
return "<i>No text content inside " + utils.getTagName(elHeading) + "</i>";
}
return utils.escapeHtml(textContent);
}
function getId(section, options) {
var sectionId = section.startingNode.getAttribute('id');
if (sectionId) {
return sectionId;
}
if (!section.heading.implied) {
var headingId = section.heading.getAttribute('id');
if (headingId) {
return headingId;
}
}
var node = section.startingNode;
do {
var id = 'h5o-' + (++options.linkCounter);
} while (node.ownerDocument.getElementById(id));
node.setAttribute('id', id);
return id;
}
function asHTML(sections, options) {
if (typeof(options) !== "object") {
// if second argument is not an object - it must be the boolean for `createLinks` (backwards compat)
options = {
createLinks: !!options
}
}
if (!sections.length) {
return '';
}
if (options.skipTopHeader) {
return asHTML(sections[0].sections, {
skipToHeader: false,
createLinks: options.createLinks
})
}
if (typeof(options.linkCounter) === "undefined") {
options.linkCounter = 0;
}
var createLinks = !!options.createLinks;
var result = [];
result.push("<ol>");
for (var i = 0; i < sections.length; i++) {
retval += '<li>' + sections[i].asHTML(createLinks) + '</li>';
var section = sections[i];
result.push("<li>");
if (createLinks) {
result.push('<a href="#' + getId(section, options) + '">');
}
result.push(sectionHeadingText(section));
if (createLinks) {
result.push("</a>");
}
result.push(asHTML(section.sections, options));
result.push("</li>");
}
return (retval == '' ? retval : '<ol>' + retval + '</ol>');
result.push("</ol>");
return result.join("");
}
module.exports = asHTML;

@@ -14,2 +14,13 @@ var Section = require("./Section"),

function getRank(heading) {
var rankingElement = utils.getRankingHeadingElement(heading);
if (!rankingElement) {
// The rank of an hgroup element is the rank of the highest-ranked h1–h6 element descendant of the hgroup
// element, if there are any such elements, or otherwise the same as for an h1 element (the highest rank).
// ref: https://html.spec.whatwg.org/#the-hgroup-element
return -1; // rank of H1
}
return -parseInt(utils.getTagName(rankingElement).substr(1));
}
function onEnterNode(node) {

@@ -51,4 +62,3 @@

// Let current section be a newly created section for the current outline target element.
// Associate current outline target with current section.
// @todo: should the above two steps really be done in one step?
// @todo: Associate current outline target with current section.
currentSection = new Section(node);

@@ -77,3 +87,2 @@

// Let current section be a newly created section for the current outline target element.
// @todo: why not "associate", like when entering a sectioning content element? Is the "parentSection" the association? Is Outline a Section?
currentSection = new Section(node);

@@ -97,3 +106,3 @@

// outline target is an implied heading, then
} else if (currentOutlineTarget.outline.getLastSection().heading.implied || utils.getHeadingElementRank(node) >= utils.getHeadingElementRank(currentOutlineTarget.outline.getLastSection().heading)) {
} else if (currentOutlineTarget.outline.getLastSection().heading.implied || getRank(node) >= getRank(currentOutlineTarget.outline.getLastSection().heading)) {

@@ -138,3 +147,3 @@ // create a new section and

// If the element being entered has a rank lower than the rank of the heading of the candidate section, then
if (utils.getHeadingElementRank(node) < utils.getHeadingElementRank(candidateSection.heading)) {
if (getRank(node) < getRank(candidateSection.heading)) {

@@ -211,3 +220,2 @@ // create a new section,

// (This does not change which section is the last section in the outline.)
// @todo: what does "appending the outline" really mean?
for (var i = 0; i < targetBeingExited.outline.sections.length; i++) {

@@ -240,2 +248,3 @@ currentSection.append(targetBeingExited.outline.sections[i]);

if (utils.isSecContent(node) || utils.isSecRoot(node)) {
// If the current section has no heading, create an implied heading and let that be the heading for the current section.

@@ -242,0 +251,0 @@ if (!currentSection.heading) {

@@ -12,6 +12,6 @@ var asHTML = require("./asHTML");

Outline.prototype.asHTML = function (createLinks) {
return asHTML(this.sections, createLinks);
Outline.prototype.asHTML = function (options) {
return asHTML(this.sections, options);
};
module.exports = Outline;

@@ -1,29 +0,1 @@

var asHTML = require("./asHTML"),
utils = require("./utils");
function sectionHeadingText(sectionHeading) {
if (utils.getTagName(sectionHeading) == 'HGROUP') {
// @todo: share code with getHeadingElementRank() to return the heading itself and that would be it
var headings = sectionHeading.getElementsByTagName('h' + (-utils.getHeadingElementRank(sectionHeading)));
if (!headings.length) {
return "<i>Error: no H1-H6 inside HGROUP</i>";
}
sectionHeading = headings[0];
}
// @todo: try to resolve text content from img[alt] or *[title]
return utils.escapeHtml(sectionHeading.textContent) || "<i>No text content inside " + sectionHeading.nodeName + "</i>";
}
function generateId(node) {
var linkCounter = 0; // @todo: move this out somewhere else, as this is not exactly performant (but makes old tests pass)
var id = node.getAttribute('id');
if (id) return id;
do {
id = 'h5o-' + (++linkCounter);
} while (node.ownerDocument.getElementById(id)); // @todo: there's probably no document when outlining a detached fragment... is there?
node.setAttribute('id', id);
return id;
}
function Section(startingNode) {

@@ -39,23 +11,2 @@ this.sections = [];

Section.prototype.asHTML = function (createLinks) {
// @todo: this really belongs in a separate formatter type thing
if (!this.heading) {
// @todo: find formal proof if this is possible/not-possible
throw new Error("An implied heading should have been created at some point, but wasn't.");
}
var headingText = this.heading.implied
? "<i>Untitled " + utils.getTagName(this.startingNode) + "</i>"
: sectionHeadingText(this.heading);
if (createLinks) {
headingText = '<a href="#' + generateId(this.startingNode) + '">'
+ headingText
+ '</a>';
}
return headingText + asHTML(this.sections, createLinks);
};
module.exports = Section;

@@ -15,15 +15,24 @@ function getTagName(el) {

function getHeadingElementRank(el) {
var elTagName = getTagName(el);
if (elTagName == 'HGROUP') {
/* The rank of an hgroup element is the rank of the highest-ranked h1-h6 element descendant of the hgroup element, if there are any such elements, or otherwise the same as for an h1 element (the highest rank). */
for (var i = 1; i <= 6; i++) {
if (el.getElementsByTagName('H' + i).length > 0) {
return -i;
}
var isHeading = tagChecker('^H[1-6]|HGROUP$');
function getRankingHeadingElement(heading) {
if (!isHeading(heading)) {
throw new Error("Not a heading element");
}
var elTagName = getTagName(heading);
if (elTagName !== "HGROUP") {
return heading;
}
// find highest ranking heading inside HGROUP
for (var i = 1; i <= 6; i++) {
var headings = heading.getElementsByTagName("H" + i);
if (headings.length) {
return headings[0];
}
return -1;
} else {
return -parseInt(elTagName.substr(1));
}
// HGROUP has no headings...
return null;
}

@@ -44,5 +53,5 @@

exports.isSecContent = tagChecker('^ARTICLE|ASIDE|NAV|SECTION$');
exports.isHeading = tagChecker('^H[1-6]|HGROUP$');
exports.getHeadingElementRank = getHeadingElementRank;
exports.isHeading = isHeading;
exports.getRankingHeadingElement = getRankingHeadingElement;
exports.escapeHtml = escapeHtml;

@@ -33,14 +33,26 @@ function createTests(suffix, doc, contextPath, HTML5Outline) {

"links_simple", "links_idreuse", "links_idcollision",
["links_simple", true], ["links_idreuse", true], ["links_idcollision", true],
"hgroup", "hgroup-without-headings", "hgroup-with-h1",
"issue-11", "issue-13"
"issue-11", "issue-13",
["issue-19-look-harder-for-ids", true],
["issue-18-skip-top-level", { skipTopHeader: true }],
["issue-18-skip-top-level-with-links", { skipTopHeader: true, createLinks: true }]
];
for (var i = 0; i < iframeTestList.length; i++) {
it(iframeTestList[i], testOutline(iframeTestList[i]));
var options = undefined,
test = iframeTestList[i];
if (typeof(test) !== "string") {
options = test[1];
test = test[0];
}
it(test, testOutline(test, options));
}
function testOutline(testID) {
function testOutline(testID, options) {
return function (done) {

@@ -53,8 +65,5 @@

var createLinks = (testID.substring(0, 6) == 'links_');
var runTest = function () {
var expected = cleanWhiteSpace(outputBody.innerHTML);
var actual = cleanWhiteSpace(HTML5Outline(inputBody).asHTML(createLinks));
var actual = cleanWhiteSpace(HTML5Outline(inputBody).asHTML(options));

@@ -61,0 +70,0 @@ expect(actual).toEqual(expected, "Comparison for: " + testID);

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc