Skip to content

Commit

Permalink
Extract and adjust relative URL handling
Browse files Browse the repository at this point in the history
The code for generating relative URLs is extracted into a public method,
making it easier to reuse. In addition, the last component of the
current URL is now treated as a file instead of a directory, meaning
that linking to ../foo.css from /foo/bar/baz results in /foo/foo.css,
instead of /foo/bar/foo.css.

Changelog: changed
  • Loading branch information
yorickpeterse committed Jan 27, 2024
1 parent 82bec29 commit 83edb51
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 15 deletions.
16 changes: 2 additions & 14 deletions src/wobsite.inko
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import std.sys.(exit)
import std.time.DateTime
import wobsite.fnmatch
import wobsite.time.(parse_date)
import wobsite.url.(file_url)
import wobsite.url.(file_url, relative_to_absolute)

let INDEX_FILE = 'index.md'

Expand Down Expand Up @@ -371,19 +371,7 @@ class UpdateAssetLinks {

fn hashed_url(url: String) -> String {
let key = if url.starts_with?('..') {
let steps = url.split('/').take_while fn (v) { v == '..' }.count
let mut pending = steps
let chunks = @url.split('/').to_array

while pending > 0 {
chunks.pop
pending -= 1
}

let base = String.join(chunks.into_iter, '/')
let rel = String.join(url.split('/').skip(steps), '/')

"{base}/{rel}"
relative_to_absolute(@url, url)
} else {
url
}
Expand Down
21 changes: 21 additions & 0 deletions src/wobsite/url.inko
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,24 @@ fn pub file_url(directory: ref Path, path: ref Path) -> String {
"/{rel.with_extension('')}/"
}
}

fn pub relative_to_absolute(current: String, url: String) -> String {
let steps = url.split('/').take_while fn (v) { v == '..' }.count

# We add 1 here such that if the current URL is /foo/bar and we link to
# foo.css, the returned URL is /foo/foo.css, not /foo/bar/foo.css. In other
# words, the final component is treated as if it were a file instead of a
# directory.
let mut pending = steps + 1
let chunks = current.split('/').to_array

while pending > 0 {
chunks.pop
pending -= 1
}

let base = String.join(chunks.into_iter, '/')
let rel = String.join(url.split('/').skip(steps), '/')

"{base}/{rel}"
}
7 changes: 6 additions & 1 deletion test/test_wobsite.inko
Original file line number Diff line number Diff line change
Expand Up @@ -333,11 +333,16 @@ fn pub tests(t: mut Tests) {

assets.url = '/foo/bar'
t.equal(assets.hashed_url('/style.css'), '/style.css?hash=123')
t.equal(assets.hashed_url('../style.css'), '../style.css')
t.equal(assets.hashed_url('../style.css'), '../style.css?hash=123')
t.equal(assets.hashed_url('../../style.css'), '../../style.css?hash=123')

assets.url = '/foo/bar/'
t.equal(assets.hashed_url('/style.css'), '/style.css?hash=123')
t.equal(assets.hashed_url('../style.css'), '../style.css?hash=123')
t.equal(assets.hashed_url('../../style.css'), '../../style.css?hash=123')

assets.url = '/foo/bar/baz'
t.equal(assets.hashed_url('/style.css'), '/style.css?hash=123')
t.equal(assets.hashed_url('../style.css'), '../style.css')
t.equal(assets.hashed_url('../../style.css'), '../../style.css?hash=123')
}
Expand Down
14 changes: 14 additions & 0 deletions test/wobsite/test_url.inko
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,18 @@ fn pub tests(t: mut Tests) {
'/foo/'
)
}

t.test('url.relative_to_absolute') fn (t) {
t.equal(url.relative_to_absolute('/', '../style.css'), '/style.css')
t.equal(url.relative_to_absolute('/foo/', '../style.css'), '/style.css')
t.equal(url.relative_to_absolute('/foo/', 'style.css'), '/style.css')
t.equal(
url.relative_to_absolute('/foo/bar', '../style.css'),
'/style.css'
)
t.equal(
url.relative_to_absolute('/foo/bar/baz', '../style.css'),
'/foo/style.css'
)
}
}

0 comments on commit 83edb51

Please sign in to comment.