Skip to content

feat!: support parseable URL values#158

Open
charliecreates[bot] wants to merge 2 commits intomasterfrom
feat/157-is-parseable-url
Open

feat!: support parseable URL values#158
charliecreates[bot] wants to merge 2 commits intomasterfrom
feat/157-is-parseable-url

Conversation

@charliecreates
Copy link
Copy Markdown
Contributor

@charliecreates charliecreates Bot commented Apr 22, 2026

This PR contains:

  • bugfix
  • feature
  • refactor
  • tests
  • documentation
  • metadata

Breaking Changes?

  • yes
  • no

If yes, please describe the breakage.

The value of isUrl is now determined by different conditions, which could break consumers downstream if relying on older behavior and value of isUrl.

Please Describe Your Changes

  • Add support for parseable URL values.

Resolves #157

@shellscape
Copy link
Copy Markdown
Owner

@CharlieHelps use the pull request template

@charliecreates
Copy link
Copy Markdown
Contributor Author

Done — I updated the PR body to use the repository pull request template and kept the Resolves #157 linkage.

Copy link
Copy Markdown
Owner

@shellscape shellscape left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see no tests for the myriad of url('...') variants. And since url is producing a Word, the tests should go into the word tests.

Comment thread test/func.test.ts Outdated
Comment thread test/func.test.ts Outdated
Comment thread src/nodes/Node.ts Outdated
Comment thread docs/Parser.md Outdated
Comment thread docs/Parser.md
Comment thread src/nodes/Word.ts Outdated
Comment thread src/nodes/Word.ts Outdated
@shellscape
Copy link
Copy Markdown
Owner

shellscape commented Apr 22, 2026

@gwynne I was able to get a review in before I had to step away. please review this when able

@shellscape shellscape changed the title feat: support parseable URL values feat!: support parseable URL values Apr 22, 2026
Copy link
Copy Markdown

@gwynne gwynne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other than the incomplete test coverage, the rest looks correct to me, and a quick local test shows that it fully covers my use case.

Comment thread test/word.test.ts
Comment on lines +33 to +40
{ fixture: 'url(https://example.com/image.png)', label: 'unquoted absolute URL' },
{ fixture: "url('https://example.com/image.png')", label: 'single-quoted absolute URL' },
{ fixture: 'url("https://example.com/image.png")', label: 'double-quoted absolute URL' },
{ fixture: 'url(/images/image.png)', label: 'unquoted relative URL' },
{ fixture: "url('/images/image.png')", label: 'single-quoted relative URL' },
{ fixture: 'url("/images/image.png")', label: 'double-quoted relative URL' },
{ fixture: 'url(//cdn.example.com/image.png)', label: 'protocol-relative URL' },
{ fixture: 'url()', label: 'empty URL value' }
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are both mislabeled and incomplete. There are three types of meaningful URL—protocol-absolute, file-absolute, and file-relative—and valid inputs can include both query strings (e.g. ?a=b) and fragment identifiers (e.g. #foo). Procotol-relative URLs, while they did historically exist, are not considered valid by modern browsers, and thus should not be considered IMO. Here is a more comprehensive test matrix:

Suggested change
{ fixture: 'url(https://example.com/image.png)', label: 'unquoted absolute URL' },
{ fixture: "url('https://example.com/image.png')", label: 'single-quoted absolute URL' },
{ fixture: 'url("https://example.com/image.png")', label: 'double-quoted absolute URL' },
{ fixture: 'url(/images/image.png)', label: 'unquoted relative URL' },
{ fixture: "url('/images/image.png')", label: 'single-quoted relative URL' },
{ fixture: 'url("/images/image.png")', label: 'double-quoted relative URL' },
{ fixture: 'url(//cdn.example.com/image.png)', label: 'protocol-relative URL' },
{ fixture: 'url()', label: 'empty URL value' }
{ fixture: 'url(https://example.com/image.png)', label: 'unquoted full URL' },
{ fixture: 'url(/images/image.png)', label: 'unquoted absolute file path' },
{ fixture: 'url(images/image.png)', label: 'unquoted relative file path' },
{ fixture: 'url(./images/image.png)', label: 'unquoted relative file path with leading ./' },
{ fixture: "url('https://example.com/image.png')", label: 'single-quoted full URL' },
{ fixture: "url('/images/image.png')", label: 'single-quoted absolute file path' },
{ fixture: "url('images/image.png')", label: 'single-quoted relative file path' },
{ fixture: "url('./images/image.png')", label: 'single-quoted relative file path with leading ./' },
{ fixture: 'url("https://example.com/image.png")', label: 'double-quoted full URL' },
{ fixture: 'url("/images/image.png")', label: 'double-quoted absolute file path' },
{ fixture: 'url("images/image.png")', label: 'double-quoted relative file path' },
{ fixture: 'url("./images/image.png")', label: 'double-quoted relative file path with leading ./' },
{ fixture: "url('https://example.com/image.png?1234567890#abcdef')", label: 'single-quoted full URL with query and fragment' },
{ fixture: "url('/images/image.png?1234567890#abcdef')", label: 'single-quoted absolute file path with query and fragment' },
{ fixture: "url('images/image.png?1234567890#abcdef')", label: 'single-quoted relative file path with query and fragment' },
{ fixture: "url('./images/image.png?1234567890#abcdef')", label: 'single-quoted relative file path with leading ./, query, and fragment' },
{ fixture: 'url("https://example.com/image.png?1234567890#abcdef")', label: 'double-quoted full URL with query and fragment' },
{ fixture: 'url("/images/image.png?1234567890#abcdef")', label: 'double-quoted absolute file path with query and fragment' },
{ fixture: 'url("images/image.png?1234567890#abcdef")', label: 'double-quoted relative file path with query and fragment' },
{ fixture: 'url("./images/image.png?1234567890#abcdef")', label: 'double-quoted relative file path with leading ./, query, and fragment' },
{ fixture: 'url()', label: 'empty URL value' },
{ fixture: "url('')", label: 'empty single-quoted URL value' },
{ fixture: 'url("")', label: 'empty double-quoted URL value' }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

url()s containing file paths are not distinguishable from other arbitrary Word nodes

3 participants