- From: SVG Working Group repository <cam@mcc.id.au>
- Date: Fri, 14 Sep 2012 03:02:02 -0700
- To: public-svg-wg@w3.org
details: https://svgwg.org/hg/svg2-tools/rev/c7d24fd2e63b branches: changeset: 62:c7d24fd2e63b user: Cameron McCormack <cam@mcc.id.au> date: Fri Sep 14 20:03:34 2012 +1000 description: Build the single page version of the spec with the new script. diffstat: build.py | 10 +- publish/publish.js | 105 +++++++++++++++++++++++++++++++++++- single-page.xsl | 155 ----------------------------------------------------- 3 files changed, 108 insertions(+), 162 deletions(-) diffs (356 lines): diff --git a/build.py b/build.py --- a/build.py +++ b/build.py @@ -173,21 +173,21 @@ if not isfile(single_page): else: singlePageTime = getmtime(single_page) for name in all: if getmtime(join(master_dir, name + ".html")) > singlePageTime: buildSinglePage = True; break if buildSinglePage: - chaptersNoIndex = " ".join(all[1:]) - run("xsltproc --novalid --stringparam publish '" + publish_dir + - "' --stringparam chapters '" + chaptersNoIndex + "' " + - join(tools_dir, "single-page.xsl") + " " + - join(publish_dir, "index.html") + " > " + single_page) + os.chdir(master_dir) + run("node \"" + + native_path(join(tools_dir, "publish/publish.js")) + + "\" --build-single-page") + os.chdir(repo_dir) # chdir back # Copy over anything else that needs to be copied to 'publish': tocopypaths = [] for f in tocopy: tocopypath = join(master_dir, f) if os.path.exists(tocopypath): tocopypaths.append(tocopypath) diff --git a/publish/publish.js b/publish/publish.js --- a/publish/publish.js +++ b/publish/publish.js @@ -1,37 +1,42 @@ var config = require('./config.js'), namespaces = require('./namespaces.js'), utils = require('./utils.js'), processing = require('./processing.js'), - fs = require('fs'); + fs = require('fs'), + DOMParser = require('xmldom').DOMParser; var conf; function syntax() { console.error('Usage: node publish.js options'); console.error(''); console.error('Options:'); console.error(' --list-pages Print the names of all pages of the specification.'); console.error(' --build [PAGE ...] Builds the specified pages, or all pages if'); console.error(' none specified.'); + console.error(' --build-single-page Builds the single page version of the specification.'); console.error(' --local-style Link to local W3C style sheets rather than w3.org.'); console.error(' --help Show this message.'); } function parseOptions() { var opts = { rest: [] }; for (var i = 2; i < process.argv.length; i++) { switch (process.argv[i]) { case '--list-pages': opts.listPages = true; break; case '--build': opts.build = true; break; + case '--build-single-page': + opts.buildSinglePage = true; + break; case '--local-style': opts.localStyle = true; break; case '--help': opts.help = true; break; default: if (process.argv[i][0] == '-') { @@ -86,21 +91,117 @@ function buildPage(page) { processing.addSectionNumbers, processing.formatQuotes, // processing.formatIDL, processing.formatMarkup].forEach(function(fn) { fn(conf, page, doc); }); fs.writeFileSync(outputFilename, doc.toString()); } +function buildSinglePage() { + var outputFilename = conf.outputDirectory + 'single-page.html'; + var parser = new DOMParser(); + parser.recordPositions = true; + + // New document. + var doc = parser.parseFromString('<html><head></head><body></body></html>'); + var head = doc.documentElement.firstChild; + var body = doc.documentElement.lastChild; + + // Add HTML doctype. + doc.insertBefore(doc.implementation.createDocumentType("html", "", ""), doc.firstChild); + + var foundMathjax = false; + + // Add the contents of each published chapter. + for (var i = 0; i < conf.pageOrder.length; i++) { + var page = conf.pageOrder[i]; + var pageDocument = utils.parseXHTML(conf.outputDirectory + page + '.html'); + var pageHead = utils.child(pageDocument.documentElement, 'head'); + var pageBody = utils.child(pageDocument.documentElement, 'body'); + if (i == 0) { + // The <head> contents of the index are used for the single page document. + head.appendChild(utils.cloneChildren(pageHead)); + } else { + // Separate each page. + body.appendChild(utils.parse('<hr class="chapter-divider"/>')); + } + + utils.forEachNode(pageHead, function(n) { + // Copy a <style> in any chapter's <head> into the single page <head>. + if (n.nodeName == 'style') { + head.appendChild(n.cloneNode(true)); + } + // Note if Mathjax was used anywhere. + if (n.nodeName == 'script' && + n.getAttribute('src') == 'style/load-mathjax.js') { + foundMathjax = true; + } + }); + + // Clone the body of the chapter. + var clonedPageBody = utils.cloneChildren(pageBody); + + // Fix up IDs so that they don't clash between chapters. + utils.forEachNode(clonedPageBody, function(n) { + if (n.nodeType == n.ELEMENT_NODE) { + if (n.hasAttribute('id')) { + n.setAttribute('id', page + '-' + n.getAttribute('id')); + } + if (n.nodeName == 'a') { + if (n.hasAttribute('name')) { + n.setAttribute('name', page + '-' + n.getAttribute('name')); + } + if (n.hasAttribute('href')) { + var href = n.getAttribute('href'); + if (href[0] == '#') { + n.setAttribute('href', '#' + page + '-' + href.substring(1)); + } else if (href.match(/^([^\/]+)\.html#(.*)$/)) { + n.setAttribute('href', '#' + RegExp.$1 + '-' + RegExp.$2); + } else if (href.match(/^([^\/]+)\.html$/)) { + n.setAttribute('href', '#chapter-' + RegExp.$1); + } + } + } + } + }); + + // Copy the chapter in. + body.appendChild(utils.parse('<div id="chapter-{{page}}" class="{{classes}}">{{pagebody}}</div>', + { page: page, + classes: pageBody.getAttribute('class'), + pagebody: clonedPageBody })); + } + + // Remove all references to expanders.js. + utils.forEachNode(doc, function(n) { + if (n.nodeName == 'script' && + n.getAttribute('src') == 'style/expanders.js') { + n.parentNode.removeChild(n); + } + }); + + // Add one reference to expanders.js at the end of the document. + body.appendChild(utils.parse('<script src="style/expanders.js"></script>')); + + // Add reference to load-mathjax.js if we found one in any chapter. + if (foundMathjax) { + head.appendChild(utils.parse('<script src="style/load-mathjax.js"></script>')); + } + + fs.writeFileSync(outputFilename, doc.toString()); +} + var opts = parseOptions(); -if (opts.help || (!!opts.listPages + !!opts.build) != 1) { +if (opts.help || (!!opts.listPages + !!opts.build + !!opts.buildSinglePage) != 1) { syntax(); process.exit(opts.help ? 0 : 1); } else { conf = config.load('publish.xml'); conf.localStyleSheets = opts.localStyle; if (opts.listPages) { listPages(); } else if (opts.build) { buildPages(opts.rest); + } else if (opts.buildSinglePage) { + buildSinglePage(); } } diff --git a/single-page.xsl b/single-page.xsl deleted file mode 100644 --- a/single-page.xsl +++ /dev/null @@ -1,155 +0,0 @@ -<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' - xmlns:h='http://www.w3.org/1999/xhtml' - xmlns='http://www.w3.org/1999/xhtml' - version='1.0'> - - <xsl:output method='xml' encoding='UTF-8' - doctype-public='-//W3C//DTD XHTML 1.0 Transitional//EN' - doctype-system='http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'/> - - <xsl:param name='chapters'/> - <xsl:param name='publish'/> - - <xsl:template match='/h:html/h:body'> - <xsl:copy> - <xsl:apply-templates select="@*"/> - <xsl:apply-templates/> - <xsl:call-template name='do-chapters'> - <xsl:with-param name='cs' select='concat($chapters, " ")'/> - </xsl:call-template> - <script src='style/expanders.js'><xsl:text> </xsl:text></script> - </xsl:copy> - </xsl:template> - - <xsl:template match='h:div[@class="header" or @class="footer" or @class="header top" or @class="header bottom"]'/> - - <xsl:template match="h:head"> - <xsl:copy> - <xsl:apply-templates select="@*"/> - <xsl:apply-templates select="*[not(self::script)]"/> - <xsl:call-template name='do-chapters-style'> - <xsl:with-param name='cs' select='concat($chapters, " ")'/> - </xsl:call-template> - <script> - var n, local = location.protocol == "file:"; - if (local) { - for (n = document.head.firstChild; n; n = n.nextSibling) { - if (n.nodeName.toLowerCase() == "link") { - if (n.getAttribute("href").indexOf("//") == 0) { - n.href = "https:" + n.getAttribute("href"); - } - } - } - } - </script> - <xsl:call-template name='do-chapters-script'> - <xsl:with-param name='cs' select='concat($chapters, " ")'/> - </xsl:call-template> - </xsl:copy> - </xsl:template> - - <xsl:template match='@id'> - <xsl:param name='c'/> - <xsl:attribute name='id'> - <xsl:value-of select='concat($c, .)'/> - </xsl:attribute> - </xsl:template> - - <xsl:template match='h:a/@name'> - <xsl:param name='c'/> - <xsl:attribute name='name'> - <xsl:value-of select='concat($c, .)'/> - </xsl:attribute> - </xsl:template> - - <xsl:template match='h:a/@href'> - <xsl:param name='c'/> - <xsl:attribute name='href'> - <xsl:choose> - <xsl:when test='starts-with(., "#")'> - <xsl:value-of select='concat("#", $c, substring(., 2))'/> - </xsl:when> - <xsl:when test='substring-after(substring-before(., "#"), ".") = "html" and not(contains(., "/"))'> - <xsl:value-of select='concat("#", substring-before(., ".html"), "-", substring-after(., "#"))'/> - </xsl:when> - <xsl:when test='contains(concat(" ", $chapters, " "), concat(" ", substring-before(., ".html"), " "))'> - <xsl:value-of select='concat("#chapter-", substring-before(., ".html"))'/> - </xsl:when> - <xsl:when test='contains(concat(" ", $chapters, " "), concat(" ", ., " "))'> - <xsl:value-of select='concat("#chapter-", .)'/> - </xsl:when> - <xsl:otherwise> - <xsl:value-of select='.'/> - </xsl:otherwise> - </xsl:choose> - </xsl:attribute> - </xsl:template> - - <xsl:template match='@aria-describedby'> - <xsl:param name='c'/> - <xsl:attribute name='aria-describedby'> - <xsl:value-of select='concat($c, .)'/> - </xsl:attribute> - </xsl:template> - - <xsl:template match='h:script[@src="style/expanders.js"]'/> - <xsl:template match='h:script[@data-script-mathjax]'/> - - <xsl:template match='node()|@*'> - <xsl:param name='c'/> - <xsl:copy> - <xsl:apply-templates select="@*"> - <xsl:with-param name='c' select='$c'/> - </xsl:apply-templates> - <xsl:apply-templates> - <xsl:with-param name='c' select='$c'/> - </xsl:apply-templates> - </xsl:copy> - </xsl:template> - - <xsl:template name='do-chapters'> - <xsl:param name='cs'/> - <xsl:variable name='c' select='concat(substring-before($cs, " "), "-")'/> - <xsl:if test='$c != "" and $c != "-"'> - <hr class='chapter-divider'/> - <xsl:text>
</xsl:text> - <div id='chapter-{substring($c, 1, string-length($c) - 1)}'> - <xsl:apply-templates select='document(concat($publish, "/", substring($c, 1, string-length($c) - 1), ".html"))/h:html/h:body/node()'> - <xsl:with-param name='c' select='$c'/> - </xsl:apply-templates> - </div> - <xsl:call-template name='do-chapters'> - <xsl:with-param name='cs' select='substring-after($cs, " ")'/> - </xsl:call-template> - </xsl:if> - </xsl:template> - - <xsl:template name='do-chapters-style'> - <xsl:param name='cs'/> - <xsl:variable name='c' select='concat(substring-before($cs, " "), "-")'/> - <xsl:if test='$c != "" and $c != "-"'> - <xsl:apply-templates select='document(concat($publish, "/", substring($c, 1, string-length($c) - 1), ".html"))/h:html/h:head/h:style'/> - <xsl:call-template name='do-chapters-style'> - <xsl:with-param name='cs' select='substring-after($cs, " ")'/> - </xsl:call-template> - </xsl:if> - </xsl:template> - - <xsl:template name='do-chapters-script'> - <xsl:param name='cs'/> - <xsl:variable name='c' select='concat(substring-before($cs, " "), "-")'/> - <xsl:if test='$c != "" and $c != "-"'> - <xsl:variable name="mathjax" select='document(concat($publish, "/", substring($c, 1, string-length($c) - 1), ".html"))/h:html/h:head/h:script[@data-script-mathjax]'/> - <xsl:choose> - <xsl:when test="count($mathjax) != 0"> - <xsl:copy-of select="$mathjax[1]"/> - </xsl:when> - <xsl:otherwise> - <xsl:call-template name='do-chapters-script'> - <xsl:with-param name='cs' select='substring-after($cs, " ")'/> - </xsl:call-template> - </xsl:otherwise> - </xsl:choose> - </xsl:if> - </xsl:template> -</xsl:stylesheet>
Received on Friday, 14 September 2012 10:03:34 UTC