diff options
author | Samy Pessé <samypesse@gmail.com> | 2016-02-18 14:47:53 +0100 |
---|---|---|
committer | Samy Pessé <samypesse@gmail.com> | 2016-02-18 14:47:53 +0100 |
commit | 709b388dfcc641fab25d297618b6ffe49f5cd677 (patch) | |
tree | 661973ac5d7de4bb32db33648ecb23e9bba6b00e | |
parent | 6e83240233e6168aa6567eb6fcac62508fe7fd0e (diff) | |
download | gitbook-709b388dfcc641fab25d297618b6ffe49f5cd677.zip gitbook-709b388dfcc641fab25d297618b6ffe49f5cd677.tar.gz gitbook-709b388dfcc641fab25d297618b6ffe49f5cd677.tar.bz2 |
Fix path calcul to be coherant
-rw-r--r-- | lib/output/assets-inliner.js | 2 | ||||
-rw-r--r-- | lib/output/base.js | 12 | ||||
-rw-r--r-- | lib/output/website.js | 2 | ||||
-rw-r--r-- | lib/page/html.js | 13 | ||||
-rw-r--r-- | lib/page/index.js | 22 | ||||
-rw-r--r-- | lib/utils/location.js | 3 | ||||
-rw-r--r-- | test/location.js | 16 | ||||
-rw-r--r-- | test/page.js | 102 |
8 files changed, 134 insertions, 38 deletions
diff --git a/lib/output/assets-inliner.js b/lib/output/assets-inliner.js index 8d7c48e..6768830 100644 --- a/lib/output/assets-inliner.js +++ b/lib/output/assets-inliner.js @@ -73,7 +73,7 @@ module.exports = function assetsInliner(Base) { // Return relative path from the page .then(function(filename) { - return page.relative('/' + filename); + return page.relative(filename); }); }; diff --git a/lib/output/base.js b/lib/output/base.js index d22fda1..6678bb0 100644 --- a/lib/output/base.js +++ b/lib/output/base.js @@ -130,10 +130,18 @@ Output.prototype.finish = function() { // Resolve an HTML link Output.prototype.onRelativeLink = function(currentPage, href) { - var to = this.book.getPage(href); + var to = currentPage.followPage(href); // Replace by an .html link - if (to) href = this.outputUrl(to.path); + if (to) { + href = to.path; + + // Recalcul as relative link + href = currentPage.relative(href); + + // Replace .md by .html + href = this.outputUrl(href); + } return href; }; diff --git a/lib/output/website.js b/lib/output/website.js index b595897..d856229 100644 --- a/lib/output/website.js +++ b/lib/output/website.js @@ -87,7 +87,7 @@ WebsiteOutput.prototype.prepare = function() { // Transform a '.md' into a '.html' (README -> index) that.env.addFilter('contentURL', function(s) { - return that.onRelativeLink(null, s); + return that.outputUrl(s); }); // Relase path to an asset diff --git a/lib/page/html.js b/lib/page/html.js index 45fae0d..bd9ec91 100644 --- a/lib/page/html.js +++ b/lib/page/html.js @@ -1,4 +1,5 @@ var _ = require('lodash'); +var url = require('url'); var cheerio = require('cheerio'); var domSerializer = require('dom-serializer'); var slug = require('github-slugid'); @@ -63,7 +64,11 @@ HTMLPipeline.prototype.transformLinks = function() { if (location.isAnchor(href)) { // Don't "change" anchor links } else if (location.isRelative(href)) { - $a.attr('href', this.opts.onRelativeLink(href)); + // Preserve anchor + var parsed = url.parse(href); + var filename = this.opts.onRelativeLink(parsed.pathname); + + $a.attr('href', filename + (parsed.hash || '')); } else { // External links $a.attr('target', '_blank'); @@ -178,12 +183,16 @@ HTMLPipeline.prototype.output = function() { var that = this; return Promise() - .then(this.transformLinks) .then(this.transformImages) .then(this.transformHeadings) .then(this.transformCodeBlocks) .then(this.transformSvgs) .then(this.applyAnnotations) + + // Transform of links should be applied after annotations + // because annotations are created as links + .then(this.transformLinks) + .then(function() { return renderDOM(that.$); }); diff --git a/lib/page/index.js b/lib/page/index.js index bdf3c81..bc12529 100644 --- a/lib/page/index.js +++ b/lib/page/index.js @@ -60,14 +60,23 @@ Page.prototype.resolve = function() { return this.book.resolve(this.resolveLocal.apply(this, arguments)); }; -// Convert an absolite path to a relative path from this page +// Convert an absolute path (in the book) to a relative path from this page Page.prototype.relative = function(name) { + // Convert /test.png -> test.png + name = location.toAbsolute(name, '', ''); + return location.relative( - this.resolve('.'), - this.resolve(name) + this.resolve('.') + '/', + this.book.resolve(name) ); }; +// Return a page result of a relative page from this page +Page.prototype.followPage = function(filename) { + var absPath = this.resolveLocal(filename); + return this.book.getPage(absPath); +}; + // Update content of the page Page.prototype.update = function(content) { this.content = content; @@ -148,10 +157,7 @@ Page.prototype.toHTML = function(output) { // Normalize HTML output .then(function() { var pipelineOpts = { - onRelativeLink: function (href) { - href = that.relative(href); - return output.onRelativeLink(that, href); - }, + onRelativeLink: _.partial(output.onRelativeLink, that), onImage: _.partial(output.onOutputImage, that), onOutputSVG: _.partial(output.onOutputSVG, that), @@ -166,7 +172,7 @@ Page.prototype.toHTML = function(output) { }, // Convert glossary entries to annotations - annotations: that.book.glosary.annotations() + annotations: that.book.glossary.annotations() }; var pipeline = new HTMLPipeline(that.content, pipelineOpts); diff --git a/lib/utils/location.js b/lib/utils/location.js index 09fa93a..d96cf85 100644 --- a/lib/utils/location.js +++ b/lib/utils/location.js @@ -51,7 +51,8 @@ function toAbsolute(_href, dir, outdir) { return _href; } -// Convert an absolute path to a relative patg +// Convert an absolute path to a relative path for a specific folder (dir) +// ('test/', 'hello.md') -> '../hello.md' function relative(dir, file) { return normalize(path.relative(dir, file)); } diff --git a/test/location.js b/test/location.js index 4d949fa..2f209e0 100644 --- a/test/location.js +++ b/test/location.js @@ -16,7 +16,21 @@ describe('Location', function() { location.isAnchor('test.md#test').should.be.exactly(false); }); - describe('toAbsolute', function() { + describe('.relative', function() { + it('should resolve to a relative path (same folder)', function() { + location.relative('links/', 'links/test.md').should.equal('test.md'); + }); + + it('should resolve to a relative path (parent folder)', function() { + location.relative('links/', 'test.md').should.equal('../test.md'); + }); + + it('should resolve to a relative path (child folder)', function() { + location.relative('links/', 'links/hello/test.md').should.equal('hello/test.md'); + }); + }); + + describe('.toAbsolute', function() { it('should correctly transform as absolute', function() { location.toAbsolute('http://google.fr').should.be.equal('http://google.fr'); location.toAbsolute('test.md', './', './').should.be.equal('test.md'); diff --git a/test/page.js b/test/page.js index b68e894..41a0893 100644 --- a/test/page.js +++ b/test/page.js @@ -7,7 +7,9 @@ describe('Page', function() { before(function() { return mock.setupDefaultBook({ 'heading.md': '# Hello\n\n## World', + 'links.md': '[link](hello.md) [link 2](variables/page/next.md) [readme](README.md)', + 'links/relative.md': '[link](../hello.md) [link 2](/variables/page/next.md) [readme](../README.md)', 'annotations/simple.md': 'A magicien say abracadabra!', 'annotations/code.md': 'A magicien say `abracadabra`!', @@ -71,12 +73,12 @@ describe('Page', function() { describe('.relative', function() { it('should correctly resolve absolute path in the book', function() { var page = book.addPage('heading.md'); - var page2 = book.addPage('folder/paths.md'); - page.relative('/test.png').should.equal('test.png'); page.relative('test.png').should.equal('test.png'); + + var page2 = book.addPage('folder/paths.md'); page2.relative('/test.png').should.equal('../test.png'); - page2.relative('test.png').should.equal('test.png'); + page2.relative('test.png').should.equal('../test.png'); }); }); @@ -126,35 +128,91 @@ describe('Page', function() { }); }); - describe('Links', function() { + describe('.resolve', function() { var page; before(function() { - page = book.addPage('links.md'); - return page.toHTML(output); + page = book.addPage('links/relative.md'); }); - it('should replace links to page to .html', function() { - page.content.should.be.html({ - 'a[href="./"]': { - count: 1 - } - }); + it('should resolve to a relative path (same folder)', function() { + page.relative('links/test.md').should.equal('test.md'); }); - it('should use directory urls when file is a README', function() { - page.content.should.be.html({ - 'a[href="./"]': { - count: 1 - } + it('should resolve to a relative path (parent folder)', function() { + page.relative('test.md').should.equal('../test.md'); + page.relative('hello/test.md').should.equal('../hello/test.md'); + }); + + it('should resolve to a relative path (child folder)', function() { + page.relative('links/hello/test.md').should.equal('hello/test.md'); + }); + }); + + describe('Links', function() { + describe('From base directory', function() { + var page; + + before(function() { + page = book.addPage('links.md'); + return page.toHTML(output); + }); + + it('should replace links to page to .html', function() { + page.content.should.be.html({ + 'a[href="variables/page/next.html"]': { + count: 1 + } + }); + }); + + it('should use directory urls when file is a README', function() { + page.content.should.be.html({ + 'a[href="./"]': { + count: 1 + } + }); + }); + + it('should not replace links to file not in SUMMARY', function() { + page.content.should.be.html({ + 'a[href="hello.md"]': { + count: 1 + } + }); }); }); - it('should not replace links to file not in SUMMARY', function() { - page.content.should.be.html({ - 'a[href="hello.md"]': { - count: 1 - } + describe('From sub-directory', function() { + var page; + + before(function() { + page = book.addPage('links/relative.md'); + return page.toHTML(output); + }); + + it('should replace links to page to .html', function() { + page.content.should.be.html({ + 'a[href="../variables/page/next.html"]': { + count: 1 + } + }); + }); + + it('should use directory urls when file is a README', function() { + page.content.should.be.html({ + 'a[href="../"]': { + count: 1 + } + }); + }); + + it('should not replace links to file not in SUMMARY', function() { + page.content.should.be.html({ + 'a[href="../hello.md"]': { + count: 1 + } + }); }); }); }); |