Skip to content

Commit 88c79f7

Browse files
committed
[WIP] Implement the URL Pattern WHATWG specification
See: https://urlpattern.spec.whatwg.org Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
1 parent 19376c5 commit 88c79f7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+16629
-0
lines changed

.github/workflows/website-build.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ jobs:
3030
-DSOURCEMETA_CORE_JSONSCHEMA:BOOL=OFF
3131
-DSOURCEMETA_CORE_JSONPOINTER:BOOL=OFF
3232
-DSOURCEMETA_CORE_YAML:BOOL=OFF
33+
-DSOURCEMETA_CORE_URLPATTERN:BOOL=OFF
3334
-DSOURCEMETA_CORE_EXTENSION_ALTERSCHEMA:BOOL=OFF
3435
-DSOURCEMETA_CORE_EXTENSION_EDITORSCHEMA:BOOL=OFF
3536
-DSOURCEMETA_CORE_EXTENSION_SCHEMACONFIG:BOOL=OFF

.github/workflows/website-deploy.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ jobs:
4040
-DSOURCEMETA_CORE_JSONSCHEMA:BOOL=OFF
4141
-DSOURCEMETA_CORE_JSONPOINTER:BOOL=OFF
4242
-DSOURCEMETA_CORE_YAML:BOOL=OFF
43+
-DSOURCEMETA_CORE_URLPATTERN:BOOL=OFF
4344
-DSOURCEMETA_CORE_EXTENSION_ALTERSCHEMA:BOOL=OFF
4445
-DSOURCEMETA_CORE_EXTENSION_EDITORSCHEMA:BOOL=OFF
4546
-DSOURCEMETA_CORE_EXTENSION_SCHEMACONFIG:BOOL=OFF

CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ option(SOURCEMETA_CORE_JSONSCHEMA "Build the Sourcemeta Core JSON Schema library
1818
option(SOURCEMETA_CORE_JSONPOINTER "Build the Sourcemeta Core JSON Pointer library" ON)
1919
option(SOURCEMETA_CORE_JSONL "Build the Sourcemeta Core JSONL library" ON)
2020
option(SOURCEMETA_CORE_YAML "Build the Sourcemeta Core YAML library" ON)
21+
option(SOURCEMETA_CORE_URLPATTERN "Build the Sourcemeta Core URL Pattern library" ON)
2122
option(SOURCEMETA_CORE_EXTENSION_ALTERSCHEMA "Build the Sourcemeta Core AlterSchema library" ON)
2223
option(SOURCEMETA_CORE_EXTENSION_EDITORSCHEMA "Build the Sourcemeta Core EditorSchema library" ON)
2324
option(SOURCEMETA_CORE_EXTENSION_SCHEMACONFIG "Build the Sourcemeta Core SchemaConfig library" ON)
@@ -121,6 +122,10 @@ if(SOURCEMETA_CORE_YAML)
121122
add_subdirectory(src/core/yaml)
122123
endif()
123124

125+
if(SOURCEMETA_CORE_URLPATTERN)
126+
add_subdirectory(src/core/urlpattern)
127+
endif()
128+
124129
if(SOURCEMETA_CORE_EXTENSION_ALTERSCHEMA)
125130
add_subdirectory(src/extension/alterschema)
126131
endif()
@@ -232,6 +237,10 @@ if(SOURCEMETA_CORE_TESTS)
232237
add_subdirectory(test/yaml)
233238
endif()
234239

240+
if(SOURCEMETA_CORE_URLPATTERN)
241+
add_subdirectory(test/urlpattern)
242+
endif()
243+
235244
if(SOURCEMETA_CORE_EXTENSION_ALTERSCHEMA)
236245
add_subdirectory(test/alterschema)
237246
endif()

DEPENDENCIES

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ yaml https://github.com/yaml/libyaml 0.2.5
1515
pcre2 https://github.com/PCRE2Project/pcre2 pcre2-10.47
1616
googletest https://github.com/google/googletest a7f443b80b105f940225332ed3c31f2790092f47
1717
googlebenchmark https://github.com/google/benchmark 378fe693a1ef51500db21b11ff05a8018c5f0e55
18+
wpt https://github.com/web-platform-tests/wpt 71154f49e6cdda82c43e11bb74cfe3ad7b3f9368

config.cmake.in

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ if(NOT SOURCEMETA_CORE_COMPONENTS)
1919
list(APPEND SOURCEMETA_CORE_COMPONENTS jsonpointer)
2020
list(APPEND SOURCEMETA_CORE_COMPONENTS jsonschema)
2121
list(APPEND SOURCEMETA_CORE_COMPONENTS yaml)
22+
list(APPEND SOURCEMETA_CORE_COMPONENTS urlpattern)
2223
list(APPEND SOURCEMETA_CORE_COMPONENTS alterschema)
2324
list(APPEND SOURCEMETA_CORE_COMPONENTS editorschema)
2425
list(APPEND SOURCEMETA_CORE_COMPONENTS schemaconfig)
@@ -87,6 +88,11 @@ foreach(component ${SOURCEMETA_CORE_COMPONENTS})
8788
find_dependency(yaml CONFIG)
8889
include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_io.cmake")
8990
include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_yaml.cmake")
91+
elseif(component STREQUAL "urlpattern")
92+
include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_json.cmake")
93+
include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_regex.cmake")
94+
include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_punycode.cmake")
95+
include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_urlpattern.cmake")
9096
elseif(component STREQUAL "alterschema")
9197
include("${CMAKE_CURRENT_LIST_DIR}/sourcemeta_core_uri.cmake")
9298
find_dependency(mpdecimal CONFIG)
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
From ec3c41d5eb68cf24e86ef67b1067fc43df859ab0 Mon Sep 17 00:00:00 2001
2+
From: Juan Cruz Viotti <jv@jviotti.com>
3+
Date: Fri, 28 Nov 2025 15:42:16 -0400
4+
Subject: [PATCH] Remove invalid surrogate pairs tests
5+
6+
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
7+
---
8+
urlpattern/resources/urlpatterntestdata.json | 20 --------------------
9+
1 file changed, 20 deletions(-)
10+
11+
diff --git a/urlpattern/resources/urlpatterntestdata.json b/urlpattern/resources/urlpatterntestdata.json
12+
index 4b1b9ee5f6..ae10c412ad 100644
13+
--- a/urlpattern/resources/urlpatterntestdata.json
14+
+++ b/urlpattern/resources/urlpatterntestdata.json
15+
@@ -1136,26 +1136,6 @@
16+
"pathname": { "input": "/", "groups": {}}
17+
}
18+
},
19+
- {
20+
- "pattern": ["http://\uD83D \uDEB2"],
21+
- "expected_obj": "error"
22+
- },
23+
- {
24+
- "pattern": [{"hostname":"\uD83D \uDEB2"}],
25+
- "expected_obj": "error"
26+
- },
27+
- {
28+
- "pattern": [{"pathname":"\uD83D \uDEB2"}],
29+
- "inputs": [],
30+
- "expected_obj": {
31+
- "pathname": "%EF%BF%BD%20%EF%BF%BD"
32+
- },
33+
- "expected_match": null
34+
- },
35+
- {
36+
- "pattern": [{"pathname":":\uD83D \uDEB2"}],
37+
- "expected_obj": "error"
38+
- },
39+
{
40+
"pattern": [{"pathname":":a\uDB40\uDD00b"}],
41+
"inputs": [],
42+
--
43+
2.52.0
44+

src/core/urlpattern/CMakeLists.txt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
sourcemeta_library(NAMESPACE sourcemeta PROJECT core NAME urlpattern
2+
PRIVATE_HEADERS error.h part.h component.h
3+
SOURCES urlpattern.cc urlpattern_part.cc urlpattern_component.cc)
4+
5+
if(SOURCEMETA_CORE_INSTALL)
6+
sourcemeta_library_install(NAMESPACE sourcemeta PROJECT core NAME urlpattern)
7+
endif()
8+
9+
target_link_libraries(sourcemeta_core_urlpattern PUBLIC
10+
sourcemeta::core::json)
11+
target_link_libraries(sourcemeta_core_urlpattern PUBLIC
12+
sourcemeta::core::regex)
13+
target_link_libraries(sourcemeta_core_urlpattern PRIVATE
14+
sourcemeta::core::punycode)
15+
16+
# TODO: Find a way to get rid of this?
17+
target_link_libraries(sourcemeta_core_urlpattern PRIVATE PCRE2::pcre2)
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
#ifndef SOURCEMETA_CORE_URLPATTERN_H_
2+
#define SOURCEMETA_CORE_URLPATTERN_H_
3+
4+
#ifndef SOURCEMETA_CORE_URLPATTERN_EXPORT
5+
#include <sourcemeta/core/urlpattern_export.h>
6+
#endif
7+
8+
// NOLINTBEGIN(misc-include-cleaner)
9+
#include <sourcemeta/core/urlpattern_component.h>
10+
#include <sourcemeta/core/urlpattern_error.h>
11+
#include <sourcemeta/core/urlpattern_part.h>
12+
// NOLINTEND(misc-include-cleaner)
13+
14+
#include <sourcemeta/core/json.h>
15+
16+
#include <compare> // std::strong_ordering
17+
#include <optional> // std::optional
18+
#include <string> // std::string
19+
#include <string_view> // std::string_view
20+
21+
/// @defgroup urlpattern URL Pattern
22+
/// @brief A WHATWG URL Pattern implementation.
23+
///
24+
/// This functionality is included as follows:
25+
///
26+
/// ```cpp
27+
/// #include <sourcemeta/core/urlpattern.h>
28+
/// ```
29+
30+
namespace sourcemeta::core {
31+
32+
/// @ingroup urlpattern
33+
struct URLPatternResult {
34+
std::optional<URLPatternComponentResult> protocol;
35+
std::optional<URLPatternComponentResult> username;
36+
std::optional<URLPatternComponentResult> password;
37+
std::optional<URLPatternComponentResult> hostname;
38+
std::optional<URLPatternComponentResult> port;
39+
std::optional<URLPatternComponentResult> pathname;
40+
std::optional<URLPatternComponentResult> search;
41+
std::optional<URLPatternComponentResult> hash;
42+
};
43+
44+
/// @ingroup urlpattern
45+
struct SOURCEMETA_CORE_URLPATTERN_EXPORT URLPatternInput {
46+
std::string protocol;
47+
std::string username;
48+
std::string password;
49+
std::string hostname;
50+
std::string port;
51+
std::string pathname;
52+
std::string search;
53+
std::string hash;
54+
55+
[[nodiscard]] static auto parse(const JSON &input)
56+
-> std::optional<URLPatternInput>;
57+
[[nodiscard]] static auto parse(const std::string_view input)
58+
-> std::optional<URLPatternInput>;
59+
};
60+
61+
/// @ingroup urlpattern
62+
/// See https://urlpattern.spec.whatwg.org/#url-pattern-struct
63+
struct SOURCEMETA_CORE_URLPATTERN_EXPORT URLPattern {
64+
URLPatternProtocol protocol;
65+
URLPatternUsername username;
66+
URLPatternPassword password;
67+
URLPatternHostname hostname;
68+
URLPatternPort port;
69+
URLPatternPathname pathname;
70+
URLPatternSearch search;
71+
URLPatternHash hash;
72+
73+
auto operator==(const URLPattern &other) const -> bool = default;
74+
auto operator<=>(const URLPattern &other) const -> std::strong_ordering;
75+
76+
[[nodiscard]] static auto parse(const std::string_view input) -> URLPattern;
77+
[[nodiscard]] static auto parse(const JSON &input)
78+
-> std::optional<URLPattern>;
79+
80+
[[nodiscard]] auto match(const URLPatternInput &input) const
81+
-> URLPatternResult;
82+
};
83+
84+
} // namespace sourcemeta::core
85+
86+
#endif

0 commit comments

Comments
 (0)