fix: link prefix supports absolute path, file:// and http://

Fixes #185
pull/231/head
Romain 3 years ago
parent f3571718ce
commit df1c6a7073

@ -1,5 +1,6 @@
const path = require('path')
const urljoin = require('url-join')
const url = require('./url')
const BROWSER_SUPPORTED_EXT = /(jpg|jpeg|png|gif)$/i
@ -51,8 +52,8 @@ function photoExtension (filepath) {
}
function join (prefix, filepath) {
if (prefix.match(/^https?:\/\//)) {
return urljoin(prefix, filepath)
if (prefix.match(/^(http|https|file):\/\//)) {
return urljoin(prefix, url.fromPath(filepath))
} else {
return path.join(prefix, filepath)
}

@ -1,9 +1,19 @@
const path = require('path')
const process = require('process')
exports.fromPath = function (filepath) {
// already a URL (typically provided as a CLI argument, e.g. link prefix)
if (filepath.match(/^(http|https|file):\/\//)) {
return filepath
}
// absolute paths should start with file://
const prefix = path.isAbsolute(filepath) ? 'file://' : ''
// convert \ to / but only on Windows
if (process.platform === 'win32') {
filepath = filepath.replace(/\\/g, '/')
}
const encoded = encodeURIComponent(filepath)
return encoded.replace(/%2F/g, '/')
// encode URLs, but decode overly-encoded slashes
filepath = encodeURIComponent(filepath).replace(/%2F/g, '/')
// prepend the prefix if needed
return prefix + filepath
}

@ -36,7 +36,9 @@ exports.create = function (files, opts, problems) {
const destDate = modifiedDate(dest)
const action = actionMap[f.output[out].rel]
// ignore output files that don't have an action (e.g. existing links)
debug(`Comparing ${f.path} (${f.date}) and ${f.output[out].path} (${destDate})`)
if (action) {
debug(`Comparing ${f.path} (${f.date}) and ${f.output[out].path} (${destDate})`)
}
if (action && f.date > destDate) {
sourceFiles.add(f.path)
tasks[dest] = {

@ -1,6 +1,10 @@
const path = require('path')
module.exports = (target, options) => {
// if already an absolute URL, do nothing
if (target.match(/^(http|https|file):\/\//)) {
return target
}
const albumPath = options.data.root.album.path
const relative = path.relative(path.dirname(albumPath), target)
const url = relative.replace(/\\/g, '/')

@ -71,11 +71,31 @@ describe('Structure', () => {
should(folders('holidays/IMG_0001.mp4', 'video:poster')).endWith(ospath('IMG_0001.jpg'))
})
it('can use a file system link', () => {
it('can use a relative file system link', () => {
const res = folders('holidays/IMG_0001.jpg', 'fs:link', { linkPrefix: '../..' })
should(res).eql(ospath('../../holidays/IMG_0001.jpg'))
})
itLinux('can use an absolute file system link', () => {
const res = folders('holidays/IMG_0001.jpg', 'fs:link', { linkPrefix: '/media' })
should(res).eql('/media/holidays/IMG_0001.jpg')
})
itLinux('can use a file:// system link', () => {
const res = folders('holidays/IMG_0001.jpg', 'fs:link', { linkPrefix: 'file:///media' })
should(res).eql('file:///media/holidays/IMG_0001.jpg')
})
itWindows('can use an absolute file system link', () => {
const res = folders('holidays/IMG_0001.jpg', 'fs:link', { linkPrefix: 'C:\\media' })
should(res).eql('C:\\media\\holidays\\IMG_0001.jpg')
})
itWindows('can use a file:// system link', () => {
const res = folders('holidays/IMG_0001.jpg', 'fs:link', { linkPrefix: 'file://C:/media' })
should(res).eql('file://C:/media/holidays/IMG_0001.jpg')
})
it('can use a remote HTTP link', () => {
const res = folders('holidays/IMG_0001.jpg', 'fs:link', { linkPrefix: 'http://test.com' })
should(res).eql('http://test.com/holidays/IMG_0001.jpg')

@ -15,21 +15,36 @@ describe('URLs', () => {
})
})
itLinux('converts standard Linux paths', function () {
it('doesnt escape a file:// prefix', function () {
const res = url.fromPath('file:///media/photos/IMG_001.jpg')
should(res).eql('file:///media/photos/IMG_001.jpg')
})
itLinux('converts relative Linux paths', function () {
const res = url.fromPath('photos/holidays/IMG_001.jpg')
should(res).eql('photos/holidays/IMG_001.jpg')
})
itLinux('converts absolute Linux paths', function () {
const res = url.fromPath('/photos/holidays/IMG_001.jpg')
should(res).eql('file:///photos/holidays/IMG_001.jpg')
})
itLinux('encodes backslash in Linux paths', function () {
const res = url.fromPath('photos/my\\holidays.jpg')
should(res).eql('photos/my%5Cholidays.jpg')
})
itWindows('converts standard Windows paths', function () {
itWindows('converts relative Windows paths', function () {
const res = url.fromPath('photos\\holidays\\IMG_001.jpg')
should(res).eql('photos/holidays/IMG_001.jpg')
})
itWindows('converts absolute Windows paths', function () {
const res = url.fromPath('C:\\photos\\holidays\\IMG_001.jpg')
should(res).eql('file://C:/photos/holidays/IMG_001.jpg')
})
itWindows('slashes are also valid path separators on Windows', function () {
const res = url.fromPath('photos/holidays/IMG_001.jpg')
should(res).eql('photos/holidays/IMG_001.jpg')

@ -25,6 +25,14 @@ describe('Handlebars helpers: relative', () => {
should(res).eql('<link rel="stylesheet" href="../public/theme.css" />')
})
it('does not do anything if the path is an absolute URL', () => {
// This can happen when using --link-prefix
const url = 'http://example.com/photo.jpg'
const template = handlebars.compile(`<img src="{{relative '${url}'}}" />`)
const res = template({})
should(res).eql(`<img src="${url}" />`)
})
// TODO: this should not be needed anymore because all URLs are already escaped
it('escapes single quotes so they can be used in CSS background-image', () => {
const template = handlebars.compile(`background-image('{{relative url}}')`)

Loading…
Cancel
Save