Skip to content

Commit

Permalink
Fix #2786 (links in HTML files in sub directories)
Browse files Browse the repository at this point in the history
  • Loading branch information
Philip Lonsing committed Mar 14, 2019
1 parent 2edae26 commit f73912d
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 1 deletion.
130 changes: 130 additions & 0 deletions packages/core/integration-tests/test/html.js
Original file line number Diff line number Diff line change
Expand Up @@ -836,4 +836,134 @@ describe('html', function() {
'Imports and requires are not supported inside inline <script> tags yet.'
);
});

it('should write correct relative urls in html file in sub directory when relative public url is specified', async function() {
const b = await bundle(
path.join(__dirname, '/integration/html-js-in-subdir/index.html'),
{
publicURL: './'
}
);

await assertBundleTree(b, {
name: 'index.html',
assets: ['index.html'],
childBundles: [
{
type: 'html',
assets: ['page1-in-subdir.html'],
childBundles: [
{
type: 'html',
assets: ['page2-in-subdir.html']
}
]
}
]
});

let html = await fs.readFile(
path.join(__dirname, '/dist/index.html'),
'utf8'
);

// link to html page in sub dir
assert(
html.includes(
'<a href="subdir/page1-in-subdir.html">./subdir/page1-in-subdir.html</a>'
)
);

let htmlInSubDir1 = await fs.readFile(
path.join(__dirname, '/dist/subdir/page1-in-subdir.html'),
'utf8'
);

const href = htmlInSubDir1.match(/href="(.*)"/);
assert(href, 'href contained in page1-in-subdir.html');
assert.equal(href[1], 'page2-in-subdir.html');

const src = htmlInSubDir1.match(/<script src="(.+)"/);
assert(src, '<script src="..."> contained in page1-in-subdir.html');
const jsLink = src[1];
const jsFileLinkStart = '../in-subdir';
assert(
jsLink.startsWith(jsFileLinkStart),
`JavaScript file link should start with '${jsFileLinkStart}' but is '${jsLink}'`
);

let htmlInSubDir2 = await fs.readFile(
path.join(__dirname, '/dist/subdir/page2-in-subdir.html'),
'utf8'
);

const href2 = htmlInSubDir2.match(/href="(.*)"/);
assert(href2, 'href contained in page1-in-subdir.html');
assert.equal(href2[1], 'page1-in-subdir.html');
});

it('should write correct absolute urls in html file in sub directory when absolute public url is specified', async function() {
const b = await bundle(
path.join(__dirname, '/integration/html-js-in-subdir/index.html'),
{
publicURL: '/'
}
);

await assertBundleTree(b, {
name: 'index.html',
assets: ['index.html'],
childBundles: [
{
type: 'html',
assets: ['page1-in-subdir.html'],
childBundles: [
{
type: 'html',
assets: ['page2-in-subdir.html']
}
]
}
]
});

let html = await fs.readFile(
path.join(__dirname, '/dist/index.html'),
'utf8'
);

// link to html page in sub dir
assert(
html.includes(
'<a href="/subdir/page1-in-subdir.html">./subdir/page1-in-subdir.html</a>'
)
);

let htmlInSubDir1 = await fs.readFile(
path.join(__dirname, '/dist/subdir/page1-in-subdir.html'),
'utf8'
);

const href = htmlInSubDir1.match(/href="(.*)"/);
assert(href, 'href contained in page1-in-subdir.html');
assert.equal(href[1], '/subdir/page2-in-subdir.html');

const src = htmlInSubDir1.match(/<script src="(.+)"/);
assert(src, '<script src="..."> contained in page1-in-subdir.html');
const jsLink = src[1];
const jsFileLinkStart = '/in-subdir';
assert(
jsLink.startsWith(jsFileLinkStart),
`JavaScript file link should start with '${jsFileLinkStart}' but is '${jsLink}'`
);

let htmlInSubDir2 = await fs.readFile(
path.join(__dirname, '/dist/subdir/page2-in-subdir.html'),
'utf8'
);

const href2 = htmlInSubDir2.match(/href="(.*)"/);
assert(href2, 'href contained in page1-in-subdir.html');
assert.equal(href2[1], '/subdir/page1-in-subdir.html');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<!DOCTYPE html>
<body>
<h1>Root</h1>
<a href="./subdir/page1-in-subdir.html">./subdir/page1-in-subdir.html</a>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
var elem = document.createElement("div");
elem.innerText = "Hello World!";
document.body.appendChild(elem);
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<!DOCTYPE html>
<body>
<h1>page 1 in sub directory</h1>
<a href="./page2-in-subdir.html">./page2-in-subdir.html</a>
<script src="./in-subdir.js"></script>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<!DOCTYPE html>
<body>
<h1>page 1 in sub directory</h1>
<a href="./page1-in-subdir.html">./page1-in-subdir.html</a>
<script src="./in-subdir.js"></script>
</body>
</html>
27 changes: 26 additions & 1 deletion packages/core/parcel-bundler/src/Asset.js
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,9 @@ class Asset {
// Replace temporary bundle names in the output with the final content-hashed names.
let newValue = value;
for (let [name, map] of bundleNameMap) {
newValue = newValue.split(name).join(map);
newValue = newValue
.split(name)
.join(this.makeBundlePathRelativeToParentBundle(map));
}

// Copy `this.generated` on write so we don't end up writing the final names to the cache.
Expand All @@ -271,6 +273,29 @@ class Asset {
}
}

makeBundlePathRelativeToParentBundle(bundlePath) {
if (path.isAbsolute(bundlePath)) {
return bundlePath;
}
if (!this.options || !this.options.publicURL) {
return bundlePath;
}
const urlPath = URL.parse(this.options.publicURL).path;
if (path.isAbsolute(urlPath)) {
return bundlePath;
}

// contentHash true or false does not matter because
// we only use the directory part of the path.
const parentBundleRelativePath = this.parentBundle.getHashedBundleName();
const parentBundleRelativeDir =
path.dirname(parentBundleRelativePath) || '.';
const relativeBundlePath = path
.relative(parentBundleRelativeDir, bundlePath)
.replace('\\', '/');
return relativeBundlePath;
}

generateErrorMessage(err) {
return err;
}
Expand Down

0 comments on commit f73912d

Please sign in to comment.