├── .github
├── dependabot.yml
└── workflows
│ └── ci.yml
├── .gitignore
├── .npmrc
├── README.md
├── astro.config.mts
├── astro
├── assets
│ ├── logo-dark.svg
│ └── logo-light.svg
├── components
│ ├── Benchmarks.astro
│ ├── SiteTitle.astro
│ └── playground
│ │ ├── Playground.astro
│ │ ├── form.tsx
│ │ ├── result.tsx
│ │ ├── styles
│ │ ├── form.module.css
│ │ ├── result.module.css
│ │ └── toast.module.css
│ │ └── ui
│ │ ├── toast.tsx
│ │ ├── toaster.tsx
│ │ └── use-toast.ts
├── content
│ ├── config.ts
│ └── docs
│ │ ├── cli
│ │ ├── index.md
│ │ └── performance.md
│ │ ├── clients
│ │ ├── cpp.mdx
│ │ ├── d.md
│ │ ├── go.mdx
│ │ ├── luajit.md
│ │ ├── python.mdx
│ │ └── rust.md
│ │ ├── index.mdx
│ │ ├── installation.mdx
│ │ ├── introduction.md
│ │ ├── performance.mdx
│ │ └── playground.mdx
├── custom.css
└── env.d.ts
├── biome.jsonc
├── lib
└── wasm
│ ├── wasm.js
│ └── wasm.wasm
├── package.json
├── pnpm-lock.yaml
├── public
├── ada.png
├── ada.svg
├── android-chrome-192x192.png
├── apple-touch-icon.png
├── browserconfig.xml
├── favicon-16x16.png
├── favicon-32x32.png
├── fonts
│ └── Inter-SemiBold.woff
├── mstile-150x150.png
├── safari-pinned-tab.svg
└── site.webmanifest
├── tailwind.config.js
└── tsconfig.json
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | enable-beta-ecosystems: true
3 | updates:
4 | - package-ecosystem: npm
5 | directory: "/"
6 | open-pull-requests-limit: 10
7 | schedule:
8 | interval: monthly
9 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: linter
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 | pull_request:
8 | branches:
9 | - main
10 |
11 | # This allows a subsequently queued workflow run to interrupt previous runs
12 | concurrency:
13 | group: "${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}"
14 | cancel-in-progress: true
15 |
16 | jobs:
17 | build:
18 | runs-on: ubuntu-latest
19 | permissions:
20 | contents: read
21 | steps:
22 | - uses: actions/checkout@v4
23 | with:
24 | persist-credentials: false
25 |
26 | - name: Setup Biome
27 | uses: biomejs/setup-biome@v2
28 |
29 | - name: Lint
30 | run: biome ci .
31 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # next.js
12 | /.next/
13 | /out/
14 |
15 | # production
16 | /build
17 |
18 | # misc
19 | .DS_Store
20 | *.pem
21 |
22 | # debug
23 | npm-debug.log*
24 | yarn-debug.log*
25 | yarn-error.log*
26 |
27 | # local env files
28 | .env*.local
29 |
30 | # vercel
31 | .vercel
32 |
33 | # typescript
34 | *.tsbuildinfo
35 | next-env.d.ts
36 |
37 | .contentlayer
38 |
39 | # Astro
40 | /.astro
41 | /dist
42 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | # Ref: https://pnpm.io/npmrc#manage-package-manager-versions
2 | # When enabled, pnpm will automatically download and run the version of pnpm
3 | # specified in the packageManager field of package.json.
4 | manage-package-manager-versions = true
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Getting started
2 |
3 | `ada-url.com` requires Node.js 20 with [pnpm](https://pnpm.io) to install dependencies.
4 |
5 | - To install `pnpm` follow the steps in https://pnpm.io/installation.
6 | - To build locally, run `pnpm install` in the root repository and navigate to `http://localhost:3000`
7 | - To run the linter, run `pnpm run lint-fix`
8 |
9 | ## Documentation
10 |
11 | All documentation lives inside `contents/docs` folder
12 |
13 | ## Credits
14 |
15 | - Components of this website is developed by `ui.shadcn.com`
16 |
--------------------------------------------------------------------------------
/astro.config.mts:
--------------------------------------------------------------------------------
1 | import starlight from '@astrojs/starlight'
2 | import { defineConfig } from 'astro/config'
3 |
4 | import react from '@astrojs/react'
5 |
6 | import tailwind from '@astrojs/tailwind'
7 |
8 | // https://astro.build/config
9 | export default defineConfig({
10 | srcDir: './astro',
11 | site: 'https://www.ada-url.com',
12 | vite: {
13 | build: {
14 | rollupOptions: {
15 | // For some reason, the build crashes without this
16 | external: ['sharp'],
17 | },
18 | },
19 | },
20 | integrations: [
21 | starlight({
22 | // https://starlight.astro.build/reference/configuration
23 | title: 'Ada URL',
24 | social: {
25 | github: 'https://github.com/ada-url/ada',
26 | },
27 | sidebar: [
28 | {
29 | label: 'Getting Started',
30 | items: ['introduction', 'installation'],
31 | },
32 | {
33 | label: 'CLI',
34 | items: [
35 | {
36 | label: 'Introduction',
37 | slug: 'cli',
38 | },
39 | {
40 | label: 'Performance',
41 | slug: 'cli/performance',
42 | },
43 | ],
44 | },
45 | {
46 | label: 'Supported Languages',
47 | items: [
48 | {
49 | label: 'C++ client',
50 | slug: 'clients/cpp',
51 | },
52 | {
53 | label: 'Rust client',
54 | slug: 'clients/rust',
55 | },
56 | {
57 | label: 'Python client',
58 | slug: 'clients/python',
59 | },
60 | {
61 | label: 'Go client',
62 | slug: 'clients/go',
63 | },
64 | {
65 | label: 'LuaJIT client',
66 | slug: 'clients/luajit',
67 | },
68 | {
69 | label: 'D client',
70 | slug: 'clients/d',
71 | },
72 | ],
73 | },
74 | ],
75 | components: {
76 | SiteTitle: './astro/components/SiteTitle.astro',
77 | },
78 | favicon: './favicon-32x32.png',
79 | logo: {
80 | light: './astro/assets/logo-light.svg',
81 | dark: './astro/assets/logo-dark.svg',
82 | replacesTitle: true,
83 | },
84 | customCss: [
85 | // Relative path to your custom CSS file
86 | './astro/custom.css',
87 | ],
88 | editLink: {
89 | baseUrl: 'https://github.com/ada-url/website/edit/main',
90 | },
91 | titleDelimiter: '-',
92 | credits: false,
93 | }),
94 | react(),
95 | tailwind(),
96 | ],
97 | })
98 |
--------------------------------------------------------------------------------
/astro/assets/logo-dark.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/astro/assets/logo-light.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/astro/components/Benchmarks.astro:
--------------------------------------------------------------------------------
1 |
19 |
20 |
94 |
95 |
--------------------------------------------------------------------------------
/astro/components/SiteTitle.astro:
--------------------------------------------------------------------------------
1 | ---
2 | import AstrolightSiteTitle from '@astrojs/starlight/components/SiteTitle.astro'
3 | import type { Props } from '@astrojs/starlight/props'
4 |
5 | const menuItems = [
6 | { name: 'Docs', href: '/introduction' },
7 | { name: 'Performance', href: '/performance' },
8 | { name: 'Playground', href: '/playground' },
9 | ]
10 |
11 | function pathsMatch(lhs: string, rhs: string): boolean {
12 | return rhs.includes(lhs)
13 | }
14 | ---
15 |
16 |
17 |
18 |
19 |
20 |
21 |
35 |
36 |
37 |
77 |
--------------------------------------------------------------------------------
/astro/components/playground/Playground.astro:
--------------------------------------------------------------------------------
1 | ---
2 | import PlaygroundForm from './form'
3 | import { Toaster } from './ui/toaster'
4 | ---
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/astro/components/playground/form.tsx:
--------------------------------------------------------------------------------
1 | import WASM from '@/lib/wasm/wasm.js'
2 | import { ChevronDown, Loader2 } from 'lucide-react'
3 | import { useCallback, useEffect, useState } from 'react'
4 | import { useForm } from 'react-hook-form'
5 | import ParsingResult, { type WASMResponse } from './result'
6 | import styles from './styles/form.module.css'
7 | import { useToast } from './ui/use-toast'
8 |
9 | let wasm: {
10 | parse: (url: string) => WASMResponse & { delete: VoidFunction }
11 | }
12 |
13 | const versions = ['2.9.2', '2.9.1', '2.9.0', '2.8.0']
14 |
15 | function toJS(obj: Record): any {
16 | const result: Record = {}
17 | for (const key in obj.__proto__) {
18 | result[key] = typeof obj[key] === 'object' ? toJS(obj[key]) : obj[key]
19 | }
20 | return result
21 | }
22 |
23 | export default function PlaygroundForm() {
24 | const { toast } = useToast()
25 | const { handleSubmit, register, formState } = useForm<{ url: string; version: string }>()
26 | const [output, setOutput] = useState()
27 |
28 | const [defaultValue, setDefaultValue] = useState()
29 | const onSubmit = useCallback(
30 | async (data: { url: string; version: string }) => {
31 | try {
32 | wasm ??= await WASM()
33 | const result = wasm.parse(data.url)
34 | setOutput(toJS(result))
35 | result.delete()
36 | history.replaceState({}, '', `/playground?url=${encodeURIComponent(data.url)}`)
37 | } catch (error) {
38 | if (error instanceof Error) {
39 | toast({
40 | title: 'An error occurred',
41 | description: error.message,
42 | })
43 | }
44 | setOutput(undefined)
45 | }
46 | },
47 | [toast],
48 | )
49 |
50 | // This function only runs on mounting/refresh to set initial default value
51 | useEffect(() => {
52 | const searchParams = new URLSearchParams(window.location.search)
53 | const search = searchParams.get('url')
54 | const value = search ? decodeURI(search) : window.location.href
55 | setDefaultValue(value)
56 | onSubmit({ url: value, version: versions.at(0) ?? '' })
57 | }, [onSubmit])
58 |
59 | return (
60 |
61 |
89 |
90 | {output !== undefined ?
: null}
91 |
92 | )
93 | }
94 |
--------------------------------------------------------------------------------
/astro/components/playground/result.tsx:
--------------------------------------------------------------------------------
1 | import * as Tabs from '@radix-ui/react-tabs'
2 | import { Terminal } from 'lucide-react'
3 | import styles from './styles/result.module.css'
4 |
5 | export type WASMResponse =
6 | | {
7 | components: {
8 | hash_start: number
9 | host_end: number
10 | host_start: number
11 | pathname_start: number
12 | port: number
13 | protocol_end: number
14 | search_start: number
15 | username_end: number
16 | }
17 | href: string
18 | result: 'success'
19 | type: number
20 | }
21 | | {
22 | result: 'fail'
23 | }
24 |
25 | function getDiagram(props: WASMResponse) {
26 | if (props.result === 'fail') {
27 | return null
28 | }
29 |
30 | const { components } = props
31 |
32 | const omitted = 4294967295
33 | const lines: string[][] = [props.href.split(''), new Array(props.href.length).fill(' ')]
34 |
35 | const omittable_values = [components.hash_start, components.search_start]
36 |
37 | for (const value of omittable_values) {
38 | if (value !== omitted) {
39 | lines[1][value] = '|'
40 | }
41 | }
42 |
43 | const non_omittable_values = [
44 | components.pathname_start,
45 | components.host_end,
46 | components.host_start,
47 | components.username_end,
48 | components.protocol_end,
49 | ]
50 |
51 | for (const value of non_omittable_values) {
52 | if (value !== props.href.length) {
53 | lines[1][value] = '|'
54 | }
55 | }
56 |
57 | const line2 = lines[1].slice()
58 | if (components.hash_start !== omitted) {
59 | line2[components.hash_start] = '`'
60 |
61 | for (let i = components.hash_start + 1; i < line2.length; i++) {
62 | line2[i] = '-'
63 | }
64 | line2.push(` hash_start ${components.hash_start}`)
65 | lines.push(line2)
66 | }
67 |
68 | const line3 = lines[1].slice()
69 | if (components.search_start !== omitted) {
70 | line3[components.search_start] = '`'
71 |
72 | for (let i = components.search_start + 1; i < line3.length; i++) {
73 | line3[i] = '-'
74 | }
75 | line3.push(` search_start ${components.search_start}`)
76 | lines.push(line3)
77 | }
78 |
79 | const line4 = lines[1].slice()
80 | if (components.pathname_start !== props.href.length) {
81 | line4[components.pathname_start] = '`'
82 | for (let i = components.pathname_start + 1; i < line4.length; i++) {
83 | line4[i] = '-'
84 | }
85 | line4.push(` pathname_start ${components.pathname_start}`)
86 | lines.push(line4)
87 | }
88 |
89 | const line5 = lines[1].slice()
90 | if (components.host_end !== props.href.length) {
91 | line5[components.host_end] = '`'
92 |
93 | for (let i = components.host_end + 1; i < line5.length; i++) {
94 | line5[i] = '-'
95 | }
96 | line5.push(` host_end ${components.host_end}`)
97 | lines.push(line5)
98 | }
99 |
100 | const line6 = lines[1].slice()
101 | if (components.host_start !== props.href.length) {
102 | line6[components.host_start] = '`'
103 |
104 | for (let i = components.host_start + 1; i < line6.length; i++) {
105 | line6[i] = '-'
106 | }
107 |
108 | line6.push(` host_start ${components.host_start}`)
109 | lines.push(line6)
110 | }
111 |
112 | const line7: string[] = lines[1].slice()
113 | if (components.username_end !== props.href.length) {
114 | line7[components.username_end] = '`'
115 |
116 | for (let i = components.username_end + 1; i < line7.length; i++) {
117 | line7[i] = '-'
118 | }
119 | line7.push(` username_end ${components.username_end}`)
120 | lines.push(line7)
121 | }
122 |
123 | const line8 = lines[1].slice()
124 | if (components.protocol_end !== props.href.length) {
125 | line8[components.protocol_end] = '`'
126 |
127 | for (let i = components.protocol_end + 1; i < line8.length; i++) {
128 | line8[i] = '-'
129 | }
130 | line8.push(` protocol_end ${components.protocol_end}`)
131 | lines.push(line8)
132 | }
133 | return lines.map((line) => line.join('')).join('\n')
134 | }
135 |
136 | export default function ParsingResult(props: WASMResponse) {
137 | const alert = (
138 |
139 |
140 |
141 | {props.result === 'success' ? 'Parsing successful!' : 'Parsing failed!'}
142 |
143 |
144 | {props.result === 'success'
145 | ? `Input resolved into "${props.href}"`
146 | : 'We could not parse this input. It is invalid.'}
147 |
148 |
149 | )
150 |
151 | if (props.result !== 'success') {
152 | return alert
153 | }
154 |
155 | return (
156 | <>
157 | {alert}
158 |
159 |
160 |
161 |
162 | Diagram
163 |
164 |
165 | Raw Output
166 |
167 |
168 |
169 | {getDiagram(props)}
170 |
171 |
172 | {JSON.stringify(props, null, 2)}
173 |
174 |
175 | >
176 | )
177 | }
178 |
--------------------------------------------------------------------------------
/astro/components/playground/styles/form.module.css:
--------------------------------------------------------------------------------
1 | .formContainer {
2 | display: flex;
3 | flex-direction: column;
4 | row-gap: 1rem;
5 | }
6 |
7 | form {
8 | display: flex;
9 | flex-direction: column;
10 | row-gap: 1rem;
11 | }
12 |
13 | form > div {
14 | display: flex;
15 | flex-direction: row;
16 | column-gap: 1rem;
17 | }
18 |
19 | .loader {
20 | margin-right: 0.5rem;
21 | width: 1rem;
22 | height: 1rem;
23 | animation: spin 1s linear infinite;
24 | }
25 |
26 | .Button {
27 | display: inline-flex;
28 | align-items: center;
29 | justify-content: center;
30 | border-radius: 0.5rem;
31 | font-size: var(--sl-text-sm);
32 | font-weight: 600;
33 | background-color: var(--sl-color-gray-1);
34 | color: var(--sl-color-black);
35 | height: 2.5rem;
36 | width: fit-content;
37 | padding-inline: 1rem;
38 | outline-offset: 0.25rem;
39 | border-width: 0;
40 | }
41 |
42 | .Button:hover {
43 | cursor: pointer;
44 | }
45 |
46 | .Button:disabled {
47 | pointer-events: none;
48 | opacity: 0.5;
49 | }
50 |
51 | .Input {
52 | display: flex;
53 | width: 100%;
54 | height: 2.5rem;
55 | border-radius: 0.5rem;
56 | border: 1px solid var(--sl-color-gray-5);
57 | background-color: var(--sl-color-black);
58 | padding-block: 0.5rem;
59 | font-size: var(--sl-text-base);
60 | color: var(--sl-color-gray-2);
61 | padding-left: 0.5rem;
62 | }
63 |
64 | .Input:hover {
65 | border: 1px solid var(--sl-color-white);
66 | }
67 |
68 | .Input:disabled {
69 | cursor: not-allowed;
70 | opacity: 0.5;
71 | }
72 |
73 | .Label {
74 | position: relative;
75 | display: flex;
76 | justify-content: flex-end;
77 | align-items: center;
78 | gap: 0.25rem;
79 | color: var(--sl-color-gray-1);
80 | }
81 |
82 | .Icon {
83 | position: absolute;
84 | top: 50%;
85 | transform: translateY(-50%);
86 | pointer-events: none;
87 | }
88 |
89 | .Caret {
90 | width: 1rem;
91 | height: 1rem;
92 | inset-inline-end: 0;
93 | }
94 |
95 | .Select {
96 | align-self: self-end;
97 | background-color: transparent;
98 | text-overflow: ellipsis;
99 | color: inherit;
100 | cursor: pointer;
101 | appearance: none;
102 | font-size: var(--sl-text-sm);
103 | border: 0;
104 | padding-inline: 1.25rem;
105 | }
106 |
107 | .Option {
108 | background-color: var(--sl-color-bg-nav);
109 | color: var(--sl-color-gray-1);
110 | }
111 |
112 | @media (min-width: 50rem) {
113 | .Button {
114 | width: 8rem;
115 | }
116 | }
117 | @keyframes spin {
118 | from {
119 | transform: rotate(0deg);
120 | }
121 | to {
122 | transform: rotate(360deg);
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/astro/components/playground/styles/result.module.css:
--------------------------------------------------------------------------------
1 | .Terminal {
2 | width: 1rem;
3 | height: 1rem;
4 | }
5 |
6 | .Alert {
7 | position: relative;
8 | padding: 1rem;
9 | border-radius: 0.5rem;
10 | width: 100%;
11 | font-size: var(--sl-text-base);
12 | border: 1px solid var(--sl-color-gray-5);
13 | background-color: var(--sl-color-black);
14 | }
15 |
16 | .Alert > svg {
17 | position: absolute;
18 | left: 1rem;
19 | top: 1rem;
20 | }
21 |
22 | .AlertTitle {
23 | font-size: var(--sl-text-h5);
24 | margin-bottom: 0.25rem;
25 | font-weight: 500;
26 | line-height: 1;
27 | padding-left: 1.75rem;
28 | }
29 |
30 | .AlertDescription {
31 | line-height: var(--sl-line-height);
32 | padding-left: 1.75rem;
33 | }
34 |
35 | .Root {
36 | width: 100%;
37 | padding: 0.25rem 0rem;
38 | }
39 |
40 | .TabsList {
41 | display: flex;
42 | height: 2.5rem;
43 | border-bottom: 2px solid var(--sl-color-gray-5);
44 | }
45 |
46 | .TabsTrigger {
47 | display: flex;
48 | appearance: none;
49 | align-items: center;
50 | margin-bottom: -2px;
51 | padding: 0 1.25rem;
52 | border-width: 0 0 2px 0;
53 | border-bottom: solid var(--sl-color-gray-5);
54 | color: var(--sl-color-gray-3);
55 | outline-offset: var(--sl-outline-offset-inside);
56 | background-color: var(--sl-color-bg);
57 | }
58 |
59 | .TabsTrigger:disabled {
60 | pointer-events: none;
61 | opacity: 0.5;
62 | }
63 |
64 | .TabsTrigger[data-state="active"] {
65 | color: var(--sl-color-white);
66 | border-color: var(--sl-color-text-accent);
67 | font-weight: 600;
68 | }
69 |
70 | .TabsContent {
71 | margin-top: 0.5rem;
72 | outline-offset: 0.25rem;
73 | border: 1px solid var(--sl-color-gray-5);
74 | background-color: var(--sl-color-bg-inline-code);
75 | }
76 |
77 | .TabsContent pre {
78 | border-radius: 0.5rem;
79 | padding: 1rem;
80 | color: var(--sl-color-white);
81 | font-family: var(--sl-font-system-mono);
82 | overflow-x: auto;
83 | }
84 |
--------------------------------------------------------------------------------
/astro/components/playground/styles/toast.module.css:
--------------------------------------------------------------------------------
1 | .Viewport {
2 | --viewport-padding: 25px;
3 | position: fixed;
4 | bottom: 0;
5 | right: 0;
6 | display: flex;
7 | flex-direction: column;
8 | padding: var(--viewport-padding);
9 | gap: 10px;
10 | width: 390px;
11 | max-width: 100vw;
12 | margin: 0;
13 | list-style: none;
14 | z-index: 2147483647;
15 | outline: none;
16 | }
17 |
18 | .Root {
19 | position: relative;
20 | color: white;
21 | font-size: var(--sl-text-sm);
22 | background-color: var(--sl-color-toast-red);
23 | border-radius: 0.5rem;
24 | padding: 15px;
25 | display: grid;
26 | grid-template-areas: "title action" "description action";
27 | grid-template-columns: auto max-content;
28 | column-gap: 15px;
29 | align-items: center;
30 | &[data-state="open"] {
31 | animation: slideIn 150ms cubic-bezier(0.16, 1, 0.3, 1);
32 | }
33 | &[data-state="closed"] {
34 | animation: hide 100ms ease-in;
35 | }
36 | &[data-swipe="move"] {
37 | transform: translateX(var(--radix-toast-swipe-move-x));
38 | }
39 | &[data-swipe="cancel"] {
40 | transform: translateX(0);
41 | transition: transform 200ms ease-out;
42 | }
43 | &[data-swipe="end"] {
44 | animation: swipeOut 100ms ease-out;
45 | }
46 | }
47 |
48 | @keyframes hide {
49 | from {
50 | opacity: 1;
51 | }
52 | to {
53 | opacity: 0;
54 | }
55 | }
56 |
57 | @keyframes slideIn {
58 | from {
59 | transform: translateX(calc(100% + var(--viewport-padding)));
60 | }
61 | to {
62 | transform: translateX(0);
63 | }
64 | }
65 |
66 | @keyframes swipeOut {
67 | from {
68 | transform: translateX(var(--radix-toast-swipe-end-x));
69 | }
70 | to {
71 | transform: translateX(calc(100% + var(--viewport-padding)));
72 | }
73 | }
74 |
75 | .Title {
76 | grid-area: title;
77 | font-weight: 500;
78 | }
79 |
80 | .Description {
81 | grid-area: description;
82 | margin: 0;
83 | opacity: 0.9;
84 | }
85 |
86 | .Action {
87 | grid-area: action;
88 | }
89 |
90 | .Close {
91 | position: absolute;
92 | top: 0.5rem;
93 | right: 0.5rem;
94 | background-color: var(--sl-color-toast-red);
95 | border: 0;
96 | padding: 0.25rem 0.5rem;
97 | }
98 |
99 | .X {
100 | height: 1rem;
101 | width: 1rem;
102 | }
103 |
--------------------------------------------------------------------------------
/astro/components/playground/ui/toast.tsx:
--------------------------------------------------------------------------------
1 | import * as ToastPrimitives from '@radix-ui/react-toast'
2 | import { X } from 'lucide-react'
3 | import * as React from 'react'
4 | import styles from '../styles/toast.module.css'
5 |
6 | const ToastProvider = ToastPrimitives.Provider
7 |
8 | const ToastViewport = React.forwardRef<
9 | React.ElementRef,
10 | React.ComponentPropsWithoutRef
11 | >(({ ...props }, ref) => (
12 |
13 | ))
14 | ToastViewport.displayName = ToastPrimitives.Viewport.displayName
15 |
16 | const Toast = React.forwardRef<
17 | React.ElementRef,
18 | React.ComponentPropsWithoutRef
19 | >(({ className, ...props }, ref) => {
20 | return
21 | })
22 | Toast.displayName = ToastPrimitives.Root.displayName
23 |
24 | const ToastAction = React.forwardRef<
25 | React.ElementRef,
26 | React.ComponentPropsWithoutRef
27 | >(({ ...props }, ref) => )
28 | ToastAction.displayName = ToastPrimitives.Action.displayName
29 |
30 | const ToastClose = React.forwardRef<
31 | React.ElementRef,
32 | React.ComponentPropsWithoutRef
33 | >(({ ...props }, ref) => (
34 |
35 |
36 |
37 | ))
38 | ToastClose.displayName = ToastPrimitives.Close.displayName
39 |
40 | const ToastTitle = React.forwardRef<
41 | React.ElementRef,
42 | React.ComponentPropsWithoutRef
43 | >(({ ...props }, ref) => )
44 | ToastTitle.displayName = ToastPrimitives.Title.displayName
45 |
46 | const ToastDescription = React.forwardRef<
47 | React.ElementRef,
48 | React.ComponentPropsWithoutRef
49 | >(({ ...props }, ref) => (
50 |
51 | ))
52 | ToastDescription.displayName = ToastPrimitives.Description.displayName
53 |
54 | type ToastProps = React.ComponentPropsWithoutRef
55 |
56 | type ToastActionElement = React.ReactElement
57 |
58 | export {
59 | type ToastProps,
60 | type ToastActionElement,
61 | ToastProvider,
62 | ToastViewport,
63 | Toast,
64 | ToastTitle,
65 | ToastDescription,
66 | ToastClose,
67 | ToastAction,
68 | }
69 |
--------------------------------------------------------------------------------
/astro/components/playground/ui/toaster.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Toast,
3 | ToastClose,
4 | ToastDescription,
5 | ToastProvider,
6 | ToastTitle,
7 | ToastViewport,
8 | } from './toast'
9 | import { useToast } from './use-toast'
10 |
11 | export function Toaster() {
12 | const { toasts } = useToast()
13 |
14 | return (
15 |
16 | {toasts.map(({ id, title, description, ...props }) => (
17 |
18 | {title && {title}}
19 | {description && {description}}
20 |
21 |
22 | ))}
23 |
24 |
25 | )
26 | }
27 |
--------------------------------------------------------------------------------
/astro/components/playground/ui/use-toast.ts:
--------------------------------------------------------------------------------
1 | // Inspired by react-hot-toast library
2 | import * as React from 'react'
3 |
4 | import type { ToastActionElement, ToastProps } from './toast'
5 |
6 | const TOAST_LIMIT = 1
7 | const TOAST_REMOVE_DELAY = 1000000
8 |
9 | type ToasterToast = ToastProps & {
10 | id: string
11 | title?: React.ReactNode
12 | description?: React.ReactNode
13 | action?: ToastActionElement
14 | }
15 |
16 | const actionTypes = {
17 | ADD_TOAST: 'ADD_TOAST',
18 | UPDATE_TOAST: 'UPDATE_TOAST',
19 | DISMISS_TOAST: 'DISMISS_TOAST',
20 | REMOVE_TOAST: 'REMOVE_TOAST',
21 | } as const
22 |
23 | let count = 0
24 |
25 | function genId() {
26 | count = (count + 1) % Number.MAX_VALUE
27 | return count.toString()
28 | }
29 |
30 | type ActionType = typeof actionTypes
31 |
32 | type Action =
33 | | {
34 | type: ActionType['ADD_TOAST']
35 | toast: ToasterToast
36 | }
37 | | {
38 | type: ActionType['UPDATE_TOAST']
39 | toast: Partial
40 | }
41 | | {
42 | type: ActionType['DISMISS_TOAST']
43 | toastId?: ToasterToast['id']
44 | }
45 | | {
46 | type: ActionType['REMOVE_TOAST']
47 | toastId?: ToasterToast['id']
48 | }
49 |
50 | interface State {
51 | toasts: ToasterToast[]
52 | }
53 |
54 | const toastTimeouts = new Map>()
55 |
56 | const addToRemoveQueue = (toastId: string) => {
57 | if (toastTimeouts.has(toastId)) {
58 | return
59 | }
60 |
61 | const timeout = setTimeout(() => {
62 | toastTimeouts.delete(toastId)
63 | dispatch({
64 | type: 'REMOVE_TOAST',
65 | toastId: toastId,
66 | })
67 | }, TOAST_REMOVE_DELAY)
68 |
69 | toastTimeouts.set(toastId, timeout)
70 | }
71 |
72 | export const reducer = (state: State, action: Action): State => {
73 | switch (action.type) {
74 | case 'ADD_TOAST':
75 | return {
76 | ...state,
77 | toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),
78 | }
79 |
80 | case 'UPDATE_TOAST':
81 | return {
82 | ...state,
83 | toasts: state.toasts.map((t) => (t.id === action.toast.id ? { ...t, ...action.toast } : t)),
84 | }
85 |
86 | case 'DISMISS_TOAST': {
87 | const { toastId } = action
88 |
89 | // ! Side effects ! - This could be extracted into a dismissToast() action,
90 | // but I'll keep it here for simplicity
91 | if (toastId) {
92 | addToRemoveQueue(toastId)
93 | } else {
94 | state.toasts.forEach((toast) => {
95 | addToRemoveQueue(toast.id)
96 | })
97 | }
98 |
99 | return {
100 | ...state,
101 | toasts: state.toasts.map((t) =>
102 | t.id === toastId || toastId === undefined
103 | ? {
104 | ...t,
105 | open: false,
106 | }
107 | : t,
108 | ),
109 | }
110 | }
111 | case 'REMOVE_TOAST':
112 | if (action.toastId === undefined) {
113 | return {
114 | ...state,
115 | toasts: [],
116 | }
117 | }
118 | return {
119 | ...state,
120 | toasts: state.toasts.filter((t) => t.id !== action.toastId),
121 | }
122 | }
123 | }
124 |
125 | const listeners: Array<(state: State) => void> = []
126 |
127 | let memoryState: State = { toasts: [] }
128 |
129 | function dispatch(action: Action) {
130 | memoryState = reducer(memoryState, action)
131 | listeners.forEach((listener) => {
132 | listener(memoryState)
133 | })
134 | }
135 |
136 | type Toast = Omit
137 |
138 | function toast({ ...props }: Toast) {
139 | const id = genId()
140 |
141 | const update = (props: ToasterToast) =>
142 | dispatch({
143 | type: 'UPDATE_TOAST',
144 | toast: { ...props, id },
145 | })
146 | const dismiss = () => dispatch({ type: 'DISMISS_TOAST', toastId: id })
147 |
148 | dispatch({
149 | type: 'ADD_TOAST',
150 | toast: {
151 | ...props,
152 | id,
153 | open: true,
154 | onOpenChange: (open) => {
155 | if (!open) dismiss()
156 | },
157 | },
158 | })
159 |
160 | return {
161 | id: id,
162 | dismiss,
163 | update,
164 | }
165 | }
166 |
167 | function useToast() {
168 | const [state, setState] = React.useState(memoryState)
169 |
170 | // biome-ignore lint/correctness/useExhaustiveDependencies: Ignore for now.
171 | React.useEffect(() => {
172 | listeners.push(setState)
173 | return () => {
174 | const index = listeners.indexOf(setState)
175 | if (index > -1) {
176 | listeners.splice(index, 1)
177 | }
178 | }
179 | }, [state])
180 |
181 | return {
182 | ...state,
183 | toast,
184 | dismiss: (toastId?: string) => dispatch({ type: 'DISMISS_TOAST', toastId }),
185 | }
186 | }
187 |
188 | export { useToast, toast }
189 |
--------------------------------------------------------------------------------
/astro/content/config.ts:
--------------------------------------------------------------------------------
1 | import { defineCollection } from 'astro:content'
2 | import { docsSchema } from '@astrojs/starlight/schema'
3 |
4 | export const collections = {
5 | docs: defineCollection({ schema: docsSchema() }),
6 | }
7 |
--------------------------------------------------------------------------------
/astro/content/docs/cli/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Command line interface
3 | description: How to use adaparse CLI
4 | ---
5 |
6 | The adaparse command tool takes URL strings (ASCII/UTF-8) and it validates, normalizes and queries them efficiently.
7 |
8 | ## Options
9 |
10 | - `-d`, `--diagram`: Print a diagram of the result
11 | - `-u`, `--url`: URL Parameter (required)
12 | - `-h`, `--help`: Print usage
13 | - `-g`, `--get`: Get a specific part of the URL (e.g., 'origin', 'host', etc. as mentioned in the examples above)
14 | - `-b`, `--benchmark`: Run benchmark for piped file functions
15 | - `-p`, `--path`: Process all the URLs in a given file
16 | - `-o`, `--output`: Output the results of the parsing to a file
17 |
18 | ## Usage/Examples
19 |
20 | ### Well-formatted URL
21 |
22 | ```bash
23 | adaparse "http://www.google.com"
24 | ```
25 |
26 | **Output:**
27 |
28 | ```text
29 | http://www.google.com
30 | ```
31 |
32 | ### Diagram
33 |
34 | ```bash
35 | adaparse -d http://www.google.com/bal\?a\=\=11\#fddfds
36 | ```
37 |
38 | **Output:**
39 |
40 | ```text
41 | http://www.google.com/bal?a==11#fddfds [38 bytes]
42 | | | | | |
43 | | | | | `------ hash_start
44 | | | | `------------ search_start 25
45 | | | `---------------- pathname_start 21
46 | | | `---------------- host_end 21
47 | | `------------------------------ host_start 7
48 | | `------------------------------ username_end 7
49 | `-------------------------------- protocol_end 5
50 | ```
51 |
52 | ### Pipe Operator
53 |
54 | Ada can process URLs from piped input, making it easy to integrate with other command-line tools
55 | that produce ASCII or UTF-8 outputs. Here's an example of how to pipe the output of another command into Ada.
56 | Given a list of URLs, one by line, we may query the normalized URL string (`href`) and detect any malformed URL:
57 |
58 | ```bash
59 | cat dragonball_url.txt | adaparse --get href
60 | ```
61 |
62 | **Output:**
63 |
64 | ```text
65 | http://www.goku.com
66 | http://www.vegeta.com
67 | http://www.gohan.com
68 | ```
69 |
70 | Our tool supports the passing of arguments to each URL in said file so
71 | that you can query for the hash, the host, the protocol, the port,
72 | the origin, the search, the password, the username, the pathname
73 | or the hostname:
74 |
75 | ```bash
76 | cat dragonball_url.txt | adaparse -g host
77 | ```
78 |
79 | **Output:**
80 |
81 | ```text
82 | www.goku.com
83 | www.vegeta.com
84 | www.gohan.com
85 | ```
86 |
87 | If you omit `-g`, it will only provide a list of invalid URLs. This might be
88 | useful if you want to valid quickly a list of URLs.
89 |
90 | ### Benchmark Runner
91 |
92 | The benchmark flag can be used to output the time it takes to process piped input:
93 |
94 | ```bash
95 | cat wikipedia_100k.txt | adaparse -b
96 | ```
97 |
98 | **Output:**
99 |
100 | ```text
101 | Invalid URL: 1968:_Die_Kinder_der_Diktatur
102 | Invalid URL: 58957:_The_Bluegrass_Guitar_Collection
103 | Invalid URL: 650luc:_Gangsta_Grillz
104 | Invalid URL: Q4%3A57
105 | Invalid URL: Q10%3A47
106 | Invalid URL: Q5%3A45
107 | Invalid URL: Q40%3A28
108 | Invalid URL: 1:1_scale
109 | Invalid URL: 1893:_A_World's_Fair_Mystery
110 | Invalid URL: 12:51_(Krissy_%26_Ericka_song)
111 | Invalid URL: 111:_A_Nelson_Number
112 | Invalid URL: 7:00AM-8%3A00AM_(24_season_5)
113 | Invalid URL: Q53%3A31
114 | read 5209265 bytes in 32819917 ns using 100000 lines, used 160 loads
115 | 0.1587226744053009 GB/s
116 | ```
117 |
118 | ### Saving result to file system
119 |
120 | There is an option to output to a file on disk:
121 |
122 | ```bash
123 | cat wikipedia_100k.txt | adaparse -o wiki_output.txt
124 | ```
125 |
126 | As well as read in from a file on disk without going through cat:
127 |
128 | ```bash
129 | adaparse -p wikipedia_top_100_txt
130 | ```
131 |
132 | #### Advanced Usage
133 |
134 | You may also combine different flags together. E.g. Say one wishes to extract only the host from URLs stored in wikipedia.txt and output it to the test_write.txt file:
135 |
136 | ```bash
137 | adaparse -p wikipedia_top100.txt -o test_write.txt -g host -b
138 | ```
139 |
140 | **Output:**
141 |
142 | ```text
143 | read 5209265 bytes in 26737131 ns using 100000 lines, total_bytes is 5209265 used 160 loads
144 | 0.19483260937757307 GB/s(base)
145 | ```
146 |
147 | Content of test_write.txt:
148 |
149 | ```text
150 | (---snip---)
151 | en.wikipedia.org
152 | en.wikipedia.org
153 | en.wikipedia.org
154 | en.wikipedia.org
155 | en.wikipedia.org
156 | en.wikipedia.org
157 | en.wikipedia.org
158 | en.wikipedia.org
159 | en.wikipedia.org
160 | en.wikipedia.org
161 | (---snip---)
162 | ```
--------------------------------------------------------------------------------
/astro/content/docs/cli/performance.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: CLI Performance
3 | description: How is the performance of Ada and adaparse CLI?
4 | ---
5 |
6 | Our `adaparse` tool may outperform other popular alternatives. We offer a [collection of
7 | sets of URLs](https://github.com/ada-url/url-various-datasets) for benchmarking purposes.
8 | The following results are on a MacBook Air 2022 (M2 processor) using LLVM 14. We
9 | compare against [trurl](https://github.com/curl/trurl) version 0.6 (libcurl/7.87.0).
10 |
11 | ### Benchmarks
12 |
13 |
14 |
15 | wikipedia_100k dataset, adaparse can parse URLs three times faster than trurl.
16 |
17 |
18 | ```bash
19 | time cat url-various-datasets/wikipedia/wikipedia_100k.txt| trurl --url-file - &> /dev/null 1
20 | cat url-various-datasets/wikipedia/wikipedia_100k.txt 0,00s user 0,01s system 3% cpu 0,179 total
21 | trurl --url-file - &> /dev/null 0,14s user 0,03s system 98% cpu 0,180 total
22 |
23 |
24 | time cat url-various-datasets/wikipedia/wikipedia_100k.txt| ./build/tools/cli/adaparse -g href &> /dev/null
25 | cat url-various-datasets/wikipedia/wikipedia_100k.txt 0,00s user 0,00s system 10% cpu 0,056 total
26 | ./build/tools/cli/adaparse -g href &> /dev/null 0,05s user 0,00s system 93% cpu 0,055 total
27 | ```
28 |
29 |
30 |
31 | Using top100 dataset, adaparse is twice as fast as the trurl.
32 |
33 |
34 | ```bash
35 | time cat url-various-datasets/top100/top100.txt| trurl --url-file - &> /dev/null 1
36 | cat url-various-datasets/top100/top100.txt 0,00s user 0,00s system 4% cpu 0,115 total
37 | trurl --url-file - &> /dev/null 0,09s user 0,02s system 97% cpu 0,113 total
38 |
39 | time cat url-various-datasets/top100/top100.txt| ./build/tools/cli/adaparse -g href &> /dev/null
40 | cat url-various-datasets/top100/top100.txt 0,00s user 0,01s system 11% cpu 0,062 total
41 | ./build/tools/cli/adaparse -g href &> /dev/null 0,05s user 0,00s system 94% cpu 0,061 total
42 | ```
43 |
44 |
45 | ### Results
46 |
47 | The results will vary depending on your system. We invite you to run your own benchmarks.
48 |
49 | #### Parsing 100,000 Wikipedia URLs
50 |
51 | ```bash
52 | ada ▏ 55 ms ███████▋
53 | trurl ▏ 180 ms █████████████████████████
54 | ```
55 |
56 | #### Parsing 100,000 URLs from TOP 100 websites
57 |
58 | ```bash
59 | ada ▏ 61 ms █████████████▍
60 | trurl ▏ 113 ms █████████████████████████
61 | ```
--------------------------------------------------------------------------------
/astro/content/docs/clients/cpp.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: C++
3 | description: How to install and use Ada in a C++ project
4 | ---
5 | import { Steps } from '@astrojs/starlight/components';
6 |
7 | More information about the API can be found from [C++ API Reference](https://cpp-api.ada-url.com).
8 |
9 | ## Requirements
10 |
11 | The project is self-contained and has no dependency.
12 | A recent C++ compiler supporting C++17. We test GCC 9 or better, LLVM 10 or better and Microsoft Visual Studio 2022.
13 |
14 | ## Building
15 |
16 | Ada uses **cmake** as a build system. It's recommended to have cmake available in your system.
17 | Run the following commands to compile and build Ada locally.
18 |
19 |
20 |
21 | 1. **Prepare**
22 |
23 | ```bash
24 | cmake -B build
25 | ```
26 |
27 | 2. **Build**
28 |
29 | ```bash
30 | cmake --build build
31 | ```
32 |
33 |
34 |
35 | ## Usage
36 |
37 | Use the following code to run and test Ada.
38 |
39 | ```cpp
40 | #include "ada.h"
41 | #include
42 |
43 | int main(int , char *[]) {
44 | ada::result url = ada::parse("https://www.google.com");
45 | url->set_protocol("http");
46 | std::cout << url->get_protocol() << std::endl;
47 | std::cout << url->get_host() << std::endl;
48 | return EXIT_SUCCESS;
49 | }
50 | ```
51 |
52 | ### Parsing & Validation
53 |
54 | Parse and validate a URL from an ASCII or UTF-8 string
55 |
56 | ```cpp
57 | ada::result url =
58 | ada::parse("https://www.google.com");
59 | if (url) { /* URL is valid */ }
60 | ```
61 |
62 | After calling **parse** function, you *must* check that the result is valid before
63 | accessing it when you are not sure that it will succeed. The following
64 | code is unsafe:
65 |
66 | ```cpp
67 | ada::result url =
68 | ada::parse("some bad url");
69 | url->get_href();
70 | ```
71 |
72 | You should do...
73 |
74 | ```cpp
75 | ada::result url =
76 | ada::parse("some bad url");
77 | if(url) {
78 | // next line is now safe:
79 | url->get_href();
80 | } else {
81 | // report a parsing failure
82 | }
83 | ```
84 |
85 | For simplicity, in the examples below, we skip the check because
86 | we know that parsing succeeds.
87 |
88 | ## Examples
89 |
90 | ### Credentials
91 |
92 | ```cpp
93 | auto url = ada::parse("https://www.google.com");
94 | url->set_username("username");
95 | url->set_password("password");
96 | // ada->get_href() will return "https://username:password@www.google.com/"
97 | ```
98 |
99 | ### Protocol
100 |
101 | ```cpp
102 | auto url = ada::parse("https://www.google.com");
103 | url->set_protocol("wss");
104 | // url->get_protocol() will return "wss:"
105 | // url->get_href() will return "wss://www.google.com/"
106 | ```
107 |
108 | ### Host
109 |
110 | ```cpp
111 | auto url = ada::parse("https://www.google.com");
112 | url->set_host("github.com");
113 | // url->get_host() will return "github.com"
114 | // you can use `url.set_hostname` depending on your usage.
115 | ```
116 |
117 | ### Port
118 |
119 | ```cpp
120 | auto url = ada::parse("https://www.google.com");
121 | url->set_port("8080");
122 | // url->get_port() will return "8080"
123 | ```
124 |
125 | ### Pathname
126 |
127 | ```cpp
128 | auto url = ada::parse("https://www.google.com");
129 | url->set_pathname("/my-super-long-path")
130 | // url->get_pathname() will return "/my-super-long-path"
131 | ```
132 |
133 | ### Search/Query
134 |
135 | ```cpp
136 | auto url = ada::parse("https://www.google.com");
137 | url->set_search("target=self");
138 | // url->get_search() will return "?target=self"
139 | ```
140 |
141 | ### Hash/Fragment
142 |
143 | ```cpp
144 | auto url = ada::parse("https://www.google.com");
145 | url->set_hash("is-this-the-real-life");
146 | // url->get_hash() will return "#is-this-the-real-life"
147 | ```
--------------------------------------------------------------------------------
/astro/content/docs/clients/d.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: D
3 | description: How to install and use Ada in a D project
4 | ---
5 |
6 | Ada has a D client available on [Github][source-code] and
7 | also on [dub.pm][dub-registry].
8 |
9 | ## Installation
10 |
11 | Add the following as a dependency to your project (`dub.json` or `dub.sdl`):
12 |
13 | ```bash
14 | # dub add ada-d from dub-registry
15 | $ dub add ada-d
16 | ```
17 |
18 | Modules hierarchy:
19 |
20 | ```bash
21 | .
22 | └── source
23 | └── ada
24 | ├── c
25 | │ ├── ada.d # low-level C bindings - @nogc, nothrow, @safe and betterC compatible
26 | │ └── wrapper.d # D (mangled) RAII - @nogc, nothrow, @safe and betterC compatible
27 | └── url
28 | └── package.d # by default set public wrapper.d in 'import ada.url'
29 | # (for low-level C bindings use 'import ada.c.ada')
30 | ```
31 |
32 | ## Usage
33 |
34 | Here is an example illustrating a common usage:
35 |
36 | ```d
37 | import ada.url : AdaUrl, ParseOptions; // @safe, nothrow and betterC compatible
38 | import std.stdio : writeln; // need GC and throw exception
39 |
40 | void main() @safe {
41 | auto u = AdaUrl(ParseOptions("http://www.google:8080/love#drug"));
42 | writeln("port: ", u.getPort);
43 | writeln("hash: ", u.getHash);
44 | writeln("pathname: ", u.getPathname);
45 | writeln("href: ", u.getHref());
46 | u.setPort("9999");
47 | writeln("href: ", u.getHref); // empty '()' is optional
48 | }
49 | ```
50 |
51 | full example: [here](https://github.com/kassane/ada-d/tree/main/example)
52 |
53 | ## Resources
54 |
55 | - [Source code][source-code]
56 | - [Dub - dub.pm][dub-registry]
57 | - [Documentation - dpldocs.info][documentation]
58 |
59 |
60 | [dub-registry]: http://ada-d.dub.pm
61 | [documentation]: https://ada-d.dpldocs.info
62 | [source-code]: https://github.com/kassane/ada-d
--------------------------------------------------------------------------------
/astro/content/docs/clients/go.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Go
3 | description: How to install and use Ada in a Go project
4 | ---
5 |
6 | Ada has a Go client available on [Github](https://github.com/ada-url/goada).
--------------------------------------------------------------------------------
/astro/content/docs/clients/luajit.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: LuaJIT
3 | description: How to install and use Ada in a LuaJIT or OpenResty project
4 | ---
5 |
6 | Ada has a LuaJIT / OpenResty client available on [Github][source-code],
7 | and also on [luarocks.org][rock] and [https://opm.openresty.org/][opm].
8 |
9 | ## Installation
10 |
11 | ### Using LuaRocks
12 |
13 | ```bash
14 | luarocks install lua-resty-ada
15 | ```
16 |
17 | LuaRocks repository for `lua-resty-ada` is located at
18 | [luarocks.org/modules/bungle/lua-resty-ada](https://luarocks.org/modules/bungle/lua-resty-session).
19 |
20 | ### Using OpenResty Package Manager
21 |
22 | ```bash
23 | opm get bungle/lua-resty-ada
24 | ```
25 |
26 | OPM repository for `lua-resty-ada` is located at
27 | [opm.openresty.org/package/bungle/lua-resty-ada](https://opm.openresty.org/package/bungle/lua-resty-ada/).
28 |
29 | ## Usage
30 |
31 | Please consult the [API documentation][documentation] for a more detailed information.
32 |
33 | ### URL class
34 |
35 | The `resty.ada` can parse URL and return an instance of URL:
36 |
37 | ```lua
38 | local ada_url = require("resty.ada")
39 | local url = ada_url.parse("https://example.org/path/file.txt")
40 | local protocol = url:get_protocol()
41 | url:free() -- explicit free (garbage collector would do it implicitly)
42 | print(protocol) -- "https:"
43 | ```
44 |
45 | ### Static functions
46 |
47 | The library can also be used without creating instances:
48 |
49 | ```lua
50 | local ada_url = require("resty.ada")
51 | local protocol = ada_url.get_protocol("https://example.org/path/file.txt")
52 | print(protocol) -- "https:"
53 | ```
54 |
55 | ## Resources
56 |
57 | - [Source code][source-code]
58 | - [LuaRocks][rock]
59 | - [OpenResty Package Manager][opm]
60 | - [Documentation][documentation]
61 |
62 | [rock]: https://luarocks.org/modules/bungle/lua-resty-ada
63 | [opm]: https://opm.openresty.org/package/bungle/lua-resty-ada/
64 | [documentation]: https://bungle.github.io/lua-resty-ada/
65 | [source-code]: https://github.com/bungle/lua-resty-ada
--------------------------------------------------------------------------------
/astro/content/docs/clients/python.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Python
3 | description: How to install and use Ada in a Python project
4 | ---
5 | import { Steps } from '@astrojs/starlight/components';
6 |
7 | Ada has a Python client available on [Github](https://github.com/ada-url/ada-python).
8 | For more details on the `ada_url` API, see the documentation at [Read the Docs](https://ada-url.readthedocs.io/en/latest/).
9 |
10 | ## Installation
11 |
12 | ### Installing pre-built binary wheels
13 |
14 | The easiest way to get started is to install `ada-url` from [PyPI](https://pypi.org/project/ada-url/).
15 |
16 | From within your virtual environment, run:
17 |
18 | ```bash
19 | python3 -m pip install ada-url
20 | ```
21 |
22 | ### Installing from source
23 |
24 | The `Makefile` in the [project root](https://github.com/ada-url/ada-python) will build a package for installation on your own machine.
25 |
26 | From within your virtual environment, run:
27 |
28 |
29 |
30 | 1. **Prepare**
31 |
32 | ```bash
33 | make requirements package
34 | ```
35 |
36 | 2. **Install**
37 |
38 | ```bash
39 | python3 -m install -e .
40 | ```
41 |
42 |
43 |
44 | ## Usage
45 |
46 | ### URL class
47 |
48 | The `ada_url` package defines a `URL` class that can parse URLs:
49 |
50 | ```py
51 | >>> import ada_url
52 | >>> urlobj = ada_url.URL('https://example.org/path/file.txt')
53 | >>> urlobj.protocol
54 | 'https:'
55 | >>> urlobj.pathname
56 | '/path/file.txt'
57 | ```
58 |
59 | ### High-level functions
60 |
61 | It also exposes some higher level functions for analyzing and manipulating URLs:
62 |
63 | #### parse_url
64 |
65 | ```py
66 | >>> import ada_url
67 | >>> ada_url.parse_url('https://user:pass@example.org:80/api?q=1#2')
68 | {
69 | 'href': 'https://user:pass@example.org:80/api?q=1#2',
70 | 'username': 'user',
71 | 'password': 'pass',
72 | 'protocol': 'https:',
73 | 'host': 'example.org:80',
74 | 'port': '80',
75 | 'hostname': 'example.org',
76 | 'pathname': '/api',
77 | 'search': '?q=1',
78 | 'hash': '#2'
79 | }
80 | ```
81 |
82 | #### join_url
83 |
84 | ```py
85 | >>> import ada_url
86 | >>> ada_url.join_url(
87 | 'https://example.org/dir/child.txt', '../parent.txt'
88 | )
89 | ```
--------------------------------------------------------------------------------
/astro/content/docs/clients/rust.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Rust
3 | description: How to install and use Ada in a Rust project
4 | ---
5 |
6 | Ada has a Rust client available on [Github][source-code] and
7 | also on [crates.io][crate].
8 |
9 | ## Installation
10 |
11 | Add the following as a dependency to your project (`Cargo.toml`):
12 |
13 | ```toml
14 | [dependencies]
15 | ada-url = "1"
16 | ```
17 |
18 | ## Usage
19 |
20 | Here is an example illustrating a common usage:
21 |
22 | ```rust
23 | use ada_url::Url;
24 | fn main() {
25 | let mut u = Url::parse("http://www.google:8080/love#drug", None)
26 | .expect("bad url");
27 | println!("port: {:?}", u.port());
28 | println!("hash: {:?}", u.hash());
29 | println!("pathname: {:?}", u.pathname());
30 | println!("href: {:?}", u.href());
31 | u.set_port("9999");
32 | println!("href: {:?}", u.href());
33 | }
34 | ```
35 |
36 | ## Resources
37 |
38 | - [Source code][source-code]
39 | - [Crate - crates.io][crate]
40 | - [Documentation - docs.rs][documentation]
41 |
42 |
43 | [crate]: https://crates.io/crates/ada-url
44 | [documentation]: https://docs.rs/ada-url/1.0.2/ada_url/
45 | [source-code]: https://github.com/ada-url/rust
--------------------------------------------------------------------------------
/astro/content/docs/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Fast WHATWG Compliant URL parser"
3 | description: WHATWG Compliant URL parser written with focus on compliance, performance and security across multiple platforms and languages.
4 | template: splash
5 | hero:
6 | tagline: Parse millions of URLs per second
7 | image:
8 | dark: ../../assets/logo-dark.svg
9 | light: ../../assets/logo-light.svg
10 | actions:
11 | - text: Get Started
12 | link: /introduction/
13 | icon: right-arrow
14 | variant: primary
15 | - text: GitHub
16 | link: https://github.com/ada-url/ada
17 | icon: external
18 | variant: secondary
19 | next: false
20 | ---
21 |
22 | import Benchmarks from '../../components/Benchmarks.astro'
23 |
24 |
25 |
--------------------------------------------------------------------------------
/astro/content/docs/installation.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Installation
3 | description: How to install Ada and add as a dependency
4 | ---
5 | import { Steps } from '@astrojs/starlight/components';
6 |
7 | :::note
8 | Ada is available on different programming languages such as **C++**, **Python**, **Go**, **Rust** or **LuaJIT**.
9 | :::
10 |
11 | ## Homebrew
12 |
13 | Ada is available through [Homebrew](https://formulae.brew.sh/formula/ada-url#default).
14 | Homebrew is kept up to date with the recent releases of Ada.
15 |
16 | Run the following command to install Ada to your macOS computer:
17 |
18 | ```bash
19 | brew install ada-url
20 | ```
21 |
22 | ## Build from source
23 |
24 | ### Requirements
25 |
26 | The project is self-contained and has no dependency.
27 | A recent C++ compiler supporting C++17. We test GCC 9 or better, LLVM 10 or better and Microsoft Visual Studio 2022.
28 |
29 | ### Compiling
30 |
31 | :::note
32 | Ada uses **cmake** as a build system. It's recommended to have cmake available in your system.
33 | :::
34 |
35 | Run the following commands to compile and build Ada locally.
36 |
37 |
38 |
39 | 1. **Prepare build**
40 |
41 | The following command prepares the build.
42 |
43 | ```bash
44 | cmake -B build
45 | ```
46 |
47 | 2. **Build**
48 |
49 | Run the following command to build Ada on your system.
50 |
51 | ```bash
52 | cmake --build build
53 | ```
54 |
55 | 3. **Run tests**
56 |
57 | Run the following `ctest` command to validate your build.
58 |
59 | ```bash
60 | ctest --output-on-failure --test-dir build
61 | ```
62 |
63 |
64 | ### Windows
65 |
66 | Windows users need additional flags to specify the build configuration, e.g. `--config Release`.
67 |
68 | ### Docker
69 |
70 | The project can also be built via docker using default docker file of repository with following commands.
71 |
72 |
73 |
74 | 1. **Build**
75 |
76 | Build and prepare the docker file
77 |
78 | ```bash
79 | docker build -t ada-builder
80 | ```
81 |
82 | 2. **Run**
83 |
84 | Run the tests
85 |
86 | ```bash
87 | docker run --rm -it -v ${PWD}:/repo ada-builder
88 | ```
89 |
90 |
91 |
92 | ### Amalgamation
93 |
94 | You may amalgamate all source files into only two files (`ada.h` and `ada.cpp`) by typing executing the Python
95 | 3 script `singleheader/amalgamate.py`. By default, the files are created in the `singleheader` directory.
96 |
97 | ```bash
98 | ./singleheader/amalgamate.py
99 | ```
--------------------------------------------------------------------------------
/astro/content/docs/introduction.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Introduction
3 | description: WHATWG specification compliant URL parser
4 | ---
5 |
6 | Ada is a fast and spec-compliant URL parser written in C++.
7 |
8 | * It's widely tested by both Web Platform Tests and Google OSS Fuzzer.
9 | * It is **extremely fast**.
10 | * It's the default URL parser of Node.js since Node 18.16.0.
11 | * It supports Unicode Technical Standard.
12 |
13 | The Ada library passes the full range of tests from the specification, across a wide range of platforms (e.g., Windows, Linux, macOS).
14 |
15 | ## FAQ
16 |
17 |
18 | What is WHATWG?
19 |
20 | The term WHATWG stands for **Web Hypertext Application Technology Working Group**.
21 |
22 | It is a community-driven organization that focuses on developing and maintaining web standards.
23 | The WHATWG was initially formed in response to the divergence between the World Wide Web Consortium (W3C) and the browser vendors at the time, who felt that the W3C process was too slow to address the evolving needs of web developers.
24 |
25 |
26 | Who uses Ada? It is battle-tested?
27 |
28 | Ada is adopted by Node.js and used by millions of developers since Node.js 18.16.0.
29 |
30 |
31 | Can I use this in my project?
32 |
33 | Yes. Free to use for personal and commercial projects. Ada is available under MIT and Apache License 2.0.
34 |
35 |
36 | ## License
37 |
38 | This code is made available under the Apache License 2.0 as well as the MIT license.
39 |
40 | Our tests include third-party code and data. The benchmarking code includes third-party code: it is provided for research purposes only and not part of the library.
--------------------------------------------------------------------------------
/astro/content/docs/performance.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Performance
3 | description: How's the performance of Ada?
4 | ---
5 |
6 | On a benchmark where we need to validate and normalize [thousands URLs found
7 | on popular websites](https://github.com/ada-url/url-various-datasets/tree/main/top100),
8 | we find that ada can be several times faster than popular competitors (system: Apple MacBook 2022
9 | with LLVM 14).
10 |
11 | ```bash
12 | Ada ▏ 188 ns/URL ███▏
13 | servo-url ▏ 664 ns/URL ███████████▎
14 | cURL ▏ 1471 ns/URL █████████████████████████
15 | ```
16 |
17 | Ada has improved the performance of the popular JavaScript environment Node.js:
18 |
19 | :::note
20 | Since Node.js 18, a new URL parser dependency was added to Node.js — Ada. This addition bumped the Node.js performance when parsing URLs to a new level. Some results could reach up to an improvement of **400%**. ([State of Node.js Performance 2023](https://blog.rafaelgss.dev/state-of-nodejs-performance-2023))
21 | :::
22 | ## Available datasets
23 |
24 | ### [ada-url/url-various-datasets](https://github.com/ada-url/url-various-datasets)
25 |
26 | These are collections of URLs for benchmarking purposes. Disclaimer: This repository is developed and released for research purposes only.
27 |
28 | - `files/node_files.txt`:
29 | - Contains all source files from a given Node.js snapshot as URLs (43415 URLs).
30 | - `files/linux_files.txt`:
31 | - Contains all files from a Linux systems as URLs (169312 URLs).
32 | - `wikipedia/wikipedia_100k.txt`:
33 | - Contains 100k URLs from a snapshot of all Wikipedia articles as URLs (March 6th 2023)
34 | - `others/kasztp.txt`:
35 | - Contains test URLs from [URL_Shortener](https://github.com/kasztp/URL_Shortener) (MIT License) (48009 URLs).
36 | - `others/userbait.txt`:
37 | - Contains test URLs from [phishing_sites_detector](https://github.com/userbait/phishing_sites_detector) (unknown copyright) (11430 URLs).
38 | - `top100/top100.txt`
39 | - Contains crawl of the top visited 100 websites and extracts unique URLs (98000 URLs)
40 |
41 | ### [ada-url/url-dataset](https://github.com/ada-url/url-dataset)
42 |
43 | This repository crawls the top visited 100 websites and extracts unique URLs to be used for generating a dataset of unique real-world URL examples.
44 | The script creates a out.txt file with each line containing a different URL.
45 |
46 | ## Resources
47 |
48 | ### [ada_analysis](https://github.com/ada-url/ada_analysis)
49 |
50 | #### Introduction
51 |
52 | Repository to do data analysis
53 |
54 | The file follow the CSV format. For each URL in a set, on a given system, we include the number of cycles and instructions needed to process the URL as well as many other attributes of the URL, including its protocol type, length of the path and so forth. You can open CSV files in a spreadsheet tool.
55 |
56 | The big_url_set is our default (github//ada-url/url-dataset/out.txt).
57 |
58 | We process each URL 30 times, but not in sequence. We record the time needed to generate the normalized URL (href).
59 |
60 | The benchmark done using model_bench. It only works under Linux because only under Linux can we get the fine grained precision we need to benchmark individual URL.
61 |
62 | We do not need report the timings (ns) for precision reasons. Only the number of cycles and the number of instructions are reported.
63 |
64 | ### [js_url_benchmark](https://github.com/ada-url/js_url_benchmark)
65 |
66 | #### Introduction
67 |
68 | Runs the same benchmark in latest Bun, Deno as well as Node.js v16, v17, v18 and v20.
69 |
70 | ## Benchmarks
71 |
72 | ### JavaScript URLs
73 |
74 | Benchmarks and results are available through [js_url_benchmark](https://github.com/ada-url/js_url_benchmark)
75 | repository in `ada-url` organization.
76 |
77 | #### Deno 1.32.5
78 |
79 | ```bash
80 | cpu: AMD EPYC 7262 8-Core Processor
81 | runtime: deno 1.32.5 (x86_64-unknown-linux-gnu)
82 |
83 | benchmark time (avg) (min … max) p75 p99 p995
84 | ------------------------------------------------------------------- -----------------------------
85 | fixtures/linux_files.txt 184.46 ms/iter (183.7 ms … 185.67 ms) 184.54 ms 185.67 ms 185.67 ms
86 | fixtures/kasztp.txt 59.97 ms/iter (59.72 ms … 60.31 ms) 60.06 ms 60.31 ms 60.31 ms
87 | fixtures/userbait.txt 21.03 ms/iter (20.8 ms … 21.54 ms) 21.06 ms 21.54 ms 21.54 ms
88 | fixtures/top100.txt 158.16 ms/iter (157.51 ms … 158.72 ms) 158.62 ms 158.72 ms 158.72 ms
89 | fixtures/wikipedia_100k.txt 110.1 ms/iter (109.66 ms … 110.55 ms) 110.36 ms 110.55 ms 110.55 ms
90 | Average URL size: 62 bytes
91 | Ratio of bad URLs: 0.02%
92 | ```
93 |
94 | #### Bun 0.5.9
95 |
96 | ```bash
97 | cpu: AMD EPYC 7262 8-Core Processor
98 | runtime: bun 0.5.9 (x64-linux)
99 |
100 | benchmark time (avg) (min … max) p75 p99 p995
101 | ------------------------------------------------------------------- -----------------------------
102 | fixtures/linux_files.txt 101.06 ms/iter (93.72 ms … 112.09 ms) 103.01 ms 112.09 ms 112.09 ms
103 | fixtures/kasztp.txt 45.11 ms/iter (43.38 ms … 62.19 ms) 44.78 ms 62.19 ms 62.19 ms
104 | fixtures/userbait.txt 13.46 ms/iter (12.77 ms … 27.97 ms) 13.26 ms 27.97 ms 27.97 ms
105 | fixtures/top100.txt 122.87 ms/iter (120.98 ms … 134.54 ms) 122.85 ms 134.54 ms 134.54 ms
106 | fixtures/wikipedia_100k.txt 69.06 ms/iter (62.78 ms … 87 ms) 73.06 ms 87 ms 87 ms
107 | Average URL size: 61 bytes
108 | Ratio of bad URLs: 0.02%
109 | ```
110 |
111 | #### Node.js v20.0.0
112 |
113 |
114 | ```bash
115 | cpu: AMD EPYC 7262 8-Core Processor
116 | runtime: node v20.0.0 (x64-linux)
117 |
118 | benchmark time (avg) (min … max) p75 p99 p995
119 | ------------------------------------------------------------------- -----------------------------
120 | fixtures/linux_files.txt 92.01 ms/iter (91.27 ms … 92.66 ms) 92.35 ms 92.66 ms 92.66 ms
121 | fixtures/kasztp.txt 30 ms/iter (29.68 ms … 30.36 ms) 30.16 ms 30.36 ms 30.36 ms
122 | fixtures/userbait.txt 8.33 ms/iter (8.17 ms … 9.79 ms) 8.36 ms 9.79 ms 9.79 ms
123 | fixtures/top100.txt 67.44 ms/iter (67 ms … 68.93 ms) 67.54 ms 68.93 ms 68.93 ms
124 | fixtures/wikipedia_100k.txt 56.98 ms/iter (56.65 ms … 57.65 ms) 57.14 ms 57.65 ms 57.65 ms
125 | Average URL size: 62 bytes
126 | Ratio of bad URLs: 0.03%
127 | ```
--------------------------------------------------------------------------------
/astro/content/docs/playground.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: "Playground"
3 | description: 'A playground to test and run Ada URL parser: a WHATWG Compliant and fast URL parser'
4 | template: splash
5 | ---
6 |
7 | import Playground from '../../components/playground/Playground.astro'
8 |
9 |
10 |
--------------------------------------------------------------------------------
/astro/custom.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --sl-color-toast-red: #991b1b;
3 | }
4 |
5 | :root[data-theme="light"] {
6 | --sl-color-toast-red: #dc2626;
7 | }
8 |
--------------------------------------------------------------------------------
/astro/env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/biome.jsonc:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
3 | "organizeImports": {
4 | "enabled": true
5 | },
6 | "linter": {
7 | "enabled": true,
8 | "rules": {
9 | "recommended": true,
10 | "a11y": {
11 | "recommended": true
12 | },
13 | "performance": {
14 | "recommended": true
15 | },
16 | "suspicious": {
17 | "noExplicitAny": "off"
18 | },
19 | "complexity": {
20 | "noForEach": "off"
21 | },
22 | "correctness": {
23 | "useExhaustiveDependencies": "warn"
24 | }
25 | }
26 | },
27 | "formatter": {
28 | "enabled": true,
29 | "indentWidth": 2,
30 | "indentStyle": "space",
31 | "lineWidth": 100
32 | },
33 | "files": {
34 | "ignore": [
35 | "node_modules",
36 | "public",
37 | ".next",
38 | ".contentlayer",
39 | "lib/wasm",
40 | ".vercel",
41 | ".astro",
42 | "dist"
43 | ]
44 | },
45 | "javascript": {
46 | "formatter": {
47 | "quoteStyle": "single",
48 | "quoteProperties": "asNeeded",
49 | "jsxQuoteStyle": "single",
50 | "trailingCommas": "all",
51 | "semicolons": "asNeeded"
52 | }
53 | },
54 | "css": {
55 | "formatter": {
56 | "enabled": true
57 | }
58 | },
59 | "json": {
60 | "formatter": {
61 | "enabled": true
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/lib/wasm/wasm.js:
--------------------------------------------------------------------------------
1 |
2 | var loadWASM = (() => {
3 | var _scriptDir = import.meta.url;
4 |
5 | return (
6 | function(loadWASM = {}) {
7 |
8 | var Module=typeof loadWASM!="undefined"?loadWASM:{};var readyPromiseResolve,readyPromiseReject;Module["ready"]=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject});var moduleOverrides=Object.assign({},Module);var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var ENVIRONMENT_IS_WEB=true;var ENVIRONMENT_IS_WORKER=false;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(_scriptDir){scriptDirectory=_scriptDir}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1)}else{scriptDirectory=""}{read_=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=(url,onload,onerror)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()};xhr.onerror=onerror;xhr.send(null)}}setWindowTitle=title=>document.title=title}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.error.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime=Module["noExitRuntime"]||true;if(typeof WebAssembly!="object"){abort("no native wasm support detected")}var wasmMemory;var ABORT=false;var EXITSTATUS;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateMemoryViews(){var b=wasmMemory.buffer;Module["HEAP8"]=HEAP8=new Int8Array(b);Module["HEAP16"]=HEAP16=new Int16Array(b);Module["HEAP32"]=HEAP32=new Int32Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);Module["HEAPF64"]=HEAPF64=new Float64Array(b)}var wasmTable;var __ATPRERUN__=[];var __ATINIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnInit(cb){__ATINIT__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what="Aborted("+what+")";err(what);ABORT=true;EXITSTATUS=1;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject(e);throw e}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return filename.startsWith(dataURIPrefix)}var wasmBinaryFile;if(Module["locateFile"]){wasmBinaryFile="wasm.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}}else{wasmBinaryFile=new URL("wasm.wasm",import.meta.url).href}function getBinary(file){try{if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}catch(err){abort(err)}}function getBinaryPromise(binaryFile){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)){if(typeof fetch=="function"){return fetch(binaryFile,{credentials:"same-origin"}).then(response=>{if(!response["ok"]){throw"failed to load wasm binary file at '"+binaryFile+"'"}return response["arrayBuffer"]()}).catch(()=>getBinary(binaryFile))}}return Promise.resolve().then(()=>getBinary(binaryFile))}function instantiateArrayBuffer(binaryFile,imports,receiver){return getBinaryPromise(binaryFile).then(binary=>{return WebAssembly.instantiate(binary,imports)}).then(instance=>{return instance}).then(receiver,reason=>{err("failed to asynchronously prepare wasm: "+reason);abort(reason)})}function instantiateAsync(binary,binaryFile,imports,callback){if(!binary&&typeof WebAssembly.instantiateStreaming=="function"&&!isDataURI(binaryFile)&&typeof fetch=="function"){return fetch(binaryFile,{credentials:"same-origin"}).then(response=>{var result=WebAssembly.instantiateStreaming(response,imports);return result.then(callback,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(binaryFile,imports,callback)})})}else{return instantiateArrayBuffer(binaryFile,imports,callback)}}function createWasm(){var info={"a":wasmImports};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmMemory=Module["asm"]["q"];updateMemoryViews();wasmTable=Module["asm"]["t"];addOnInit(Module["asm"]["r"]);removeRunDependency("wasm-instantiate");return exports}addRunDependency("wasm-instantiate");function receiveInstantiationResult(result){receiveInstance(result["instance"])}if(Module["instantiateWasm"]){try{return Module["instantiateWasm"](info,receiveInstance)}catch(e){err("Module.instantiateWasm callback failed with error: "+e);readyPromiseReject(e)}}instantiateAsync(wasmBinary,wasmBinaryFile,info,receiveInstantiationResult).catch(readyPromiseReject);return{}}function callRuntimeCallbacks(callbacks){while(callbacks.length>0){callbacks.shift()(Module)}}function ExceptionInfo(excPtr){this.excPtr=excPtr;this.ptr=excPtr-24;this.set_type=function(type){HEAPU32[this.ptr+4>>2]=type};this.get_type=function(){return HEAPU32[this.ptr+4>>2]};this.set_destructor=function(destructor){HEAPU32[this.ptr+8>>2]=destructor};this.get_destructor=function(){return HEAPU32[this.ptr+8>>2]};this.set_caught=function(caught){caught=caught?1:0;HEAP8[this.ptr+12>>0]=caught};this.get_caught=function(){return HEAP8[this.ptr+12>>0]!=0};this.set_rethrown=function(rethrown){rethrown=rethrown?1:0;HEAP8[this.ptr+13>>0]=rethrown};this.get_rethrown=function(){return HEAP8[this.ptr+13>>0]!=0};this.init=function(type,destructor){this.set_adjusted_ptr(0);this.set_type(type);this.set_destructor(destructor)};this.set_adjusted_ptr=function(adjustedPtr){HEAPU32[this.ptr+16>>2]=adjustedPtr};this.get_adjusted_ptr=function(){return HEAPU32[this.ptr+16>>2]};this.get_exception_ptr=function(){var isPointer=___cxa_is_pointer_type(this.get_type());if(isPointer){return HEAPU32[this.excPtr>>2]}var adjusted=this.get_adjusted_ptr();if(adjusted!==0)return adjusted;return this.excPtr}}var exceptionLast=0;var uncaughtExceptionCount=0;function ___cxa_throw(ptr,type,destructor){var info=new ExceptionInfo(ptr);info.init(type,destructor);exceptionLast=ptr;uncaughtExceptionCount++;throw exceptionLast}function __embind_register_bigint(primitiveType,name,size,minRange,maxRange){}function getShiftFromSize(size){switch(size){case 1:return 0;case 2:return 1;case 4:return 2;case 8:return 3;default:throw new TypeError(`Unknown type size: ${size}`)}}function embind_init_charCodes(){var codes=new Array(256);for(var i=0;i<256;++i){codes[i]=String.fromCharCode(i)}embind_charCodes=codes}var embind_charCodes=undefined;function readLatin1String(ptr){var ret="";var c=ptr;while(HEAPU8[c]){ret+=embind_charCodes[HEAPU8[c++]]}return ret}var awaitingDependencies={};var registeredTypes={};var typeDependencies={};var char_0=48;var char_9=57;function makeLegalFunctionName(name){if(undefined===name){return"_unknown"}name=name.replace(/[^a-zA-Z0-9_]/g,"$");var f=name.charCodeAt(0);if(f>=char_0&&f<=char_9){return`_${name}`}return name}function createNamedFunction(name,body){name=makeLegalFunctionName(name);return{[name]:function(){return body.apply(this,arguments)}}[name]}function extendError(baseErrorType,errorName){var errorClass=createNamedFunction(errorName,function(message){this.name=errorName;this.message=message;var stack=new Error(message).stack;if(stack!==undefined){this.stack=this.toString()+"\n"+stack.replace(/^Error(:[^\n]*)?\n/,"")}});errorClass.prototype=Object.create(baseErrorType.prototype);errorClass.prototype.constructor=errorClass;errorClass.prototype.toString=function(){if(this.message===undefined){return this.name}else{return`${this.name}: ${this.message}`}};return errorClass}var BindingError=undefined;function throwBindingError(message){throw new BindingError(message)}var InternalError=undefined;function throwInternalError(message){throw new InternalError(message)}function whenDependentTypesAreResolved(myTypes,dependentTypes,getTypeConverters){myTypes.forEach(function(type){typeDependencies[type]=dependentTypes});function onComplete(typeConverters){var myTypeConverters=getTypeConverters(typeConverters);if(myTypeConverters.length!==myTypes.length){throwInternalError("Mismatched type converter count")}for(var i=0;i{if(registeredTypes.hasOwnProperty(dt)){typeConverters[i]=registeredTypes[dt]}else{unregisteredTypes.push(dt);if(!awaitingDependencies.hasOwnProperty(dt)){awaitingDependencies[dt]=[]}awaitingDependencies[dt].push(()=>{typeConverters[i]=registeredTypes[dt];++registered;if(registered===unregisteredTypes.length){onComplete(typeConverters)}})}});if(0===unregisteredTypes.length){onComplete(typeConverters)}}function registerType(rawType,registeredInstance,options={}){if(!("argPackAdvance"in registeredInstance)){throw new TypeError("registerType registeredInstance requires argPackAdvance")}var name=registeredInstance.name;if(!rawType){throwBindingError(`type "${name}" must have a positive integer typeid pointer`)}if(registeredTypes.hasOwnProperty(rawType)){if(options.ignoreDuplicateRegistrations){return}else{throwBindingError(`Cannot register type '${name}' twice`)}}registeredTypes[rawType]=registeredInstance;delete typeDependencies[rawType];if(awaitingDependencies.hasOwnProperty(rawType)){var callbacks=awaitingDependencies[rawType];delete awaitingDependencies[rawType];callbacks.forEach(cb=>cb())}}function __embind_register_bool(rawType,name,size,trueValue,falseValue){var shift=getShiftFromSize(size);name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":function(wt){return!!wt},"toWireType":function(destructors,o){return o?trueValue:falseValue},"argPackAdvance":8,"readValueFromPointer":function(pointer){var heap;if(size===1){heap=HEAP8}else if(size===2){heap=HEAP16}else if(size===4){heap=HEAP32}else{throw new TypeError("Unknown boolean type size: "+name)}return this["fromWireType"](heap[pointer>>shift])},destructorFunction:null})}function ClassHandle_isAliasOf(other){if(!(this instanceof ClassHandle)){return false}if(!(other instanceof ClassHandle)){return false}var leftClass=this.$$.ptrType.registeredClass;var left=this.$$.ptr;var rightClass=other.$$.ptrType.registeredClass;var right=other.$$.ptr;while(leftClass.baseClass){left=leftClass.upcast(left);leftClass=leftClass.baseClass}while(rightClass.baseClass){right=rightClass.upcast(right);rightClass=rightClass.baseClass}return leftClass===rightClass&&left===right}function shallowCopyInternalPointer(o){return{count:o.count,deleteScheduled:o.deleteScheduled,preservePointerOnDelete:o.preservePointerOnDelete,ptr:o.ptr,ptrType:o.ptrType,smartPtr:o.smartPtr,smartPtrType:o.smartPtrType}}function throwInstanceAlreadyDeleted(obj){function getInstanceTypeName(handle){return handle.$$.ptrType.registeredClass.name}throwBindingError(getInstanceTypeName(obj)+" instance already deleted")}var finalizationRegistry=false;function detachFinalizer(handle){}function runDestructor($$){if($$.smartPtr){$$.smartPtrType.rawDestructor($$.smartPtr)}else{$$.ptrType.registeredClass.rawDestructor($$.ptr)}}function releaseClassHandle($$){$$.count.value-=1;var toDelete=0===$$.count.value;if(toDelete){runDestructor($$)}}function downcastPointer(ptr,ptrClass,desiredClass){if(ptrClass===desiredClass){return ptr}if(undefined===desiredClass.baseClass){return null}var rv=downcastPointer(ptr,ptrClass,desiredClass.baseClass);if(rv===null){return null}return desiredClass.downcast(rv)}var registeredPointers={};function getInheritedInstanceCount(){return Object.keys(registeredInstances).length}function getLiveInheritedInstances(){var rv=[];for(var k in registeredInstances){if(registeredInstances.hasOwnProperty(k)){rv.push(registeredInstances[k])}}return rv}var deletionQueue=[];function flushPendingDeletes(){while(deletionQueue.length){var obj=deletionQueue.pop();obj.$$.deleteScheduled=false;obj["delete"]()}}var delayFunction=undefined;function setDelayFunction(fn){delayFunction=fn;if(deletionQueue.length&&delayFunction){delayFunction(flushPendingDeletes)}}function init_embind(){Module["getInheritedInstanceCount"]=getInheritedInstanceCount;Module["getLiveInheritedInstances"]=getLiveInheritedInstances;Module["flushPendingDeletes"]=flushPendingDeletes;Module["setDelayFunction"]=setDelayFunction}var registeredInstances={};function getBasestPointer(class_,ptr){if(ptr===undefined){throwBindingError("ptr should not be undefined")}while(class_.baseClass){ptr=class_.upcast(ptr);class_=class_.baseClass}return ptr}function getInheritedInstance(class_,ptr){ptr=getBasestPointer(class_,ptr);return registeredInstances[ptr]}function makeClassHandle(prototype,record){if(!record.ptrType||!record.ptr){throwInternalError("makeClassHandle requires ptr and ptrType")}var hasSmartPtrType=!!record.smartPtrType;var hasSmartPtr=!!record.smartPtr;if(hasSmartPtrType!==hasSmartPtr){throwInternalError("Both smartPtrType and smartPtr must be specified")}record.count={value:1};return attachFinalizer(Object.create(prototype,{$$:{value:record}}))}function RegisteredPointer_fromWireType(ptr){var rawPointer=this.getPointee(ptr);if(!rawPointer){this.destructor(ptr);return null}var registeredInstance=getInheritedInstance(this.registeredClass,rawPointer);if(undefined!==registeredInstance){if(0===registeredInstance.$$.count.value){registeredInstance.$$.ptr=rawPointer;registeredInstance.$$.smartPtr=ptr;return registeredInstance["clone"]()}else{var rv=registeredInstance["clone"]();this.destructor(ptr);return rv}}function makeDefaultHandle(){if(this.isSmartPointer){return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this.pointeeType,ptr:rawPointer,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this,ptr:ptr})}}var actualType=this.registeredClass.getActualType(rawPointer);var registeredPointerRecord=registeredPointers[actualType];if(!registeredPointerRecord){return makeDefaultHandle.call(this)}var toType;if(this.isConst){toType=registeredPointerRecord.constPointerType}else{toType=registeredPointerRecord.pointerType}var dp=downcastPointer(rawPointer,this.registeredClass,toType.registeredClass);if(dp===null){return makeDefaultHandle.call(this)}if(this.isSmartPointer){return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp})}}function attachFinalizer(handle){if("undefined"===typeof FinalizationRegistry){attachFinalizer=handle=>handle;return handle}finalizationRegistry=new FinalizationRegistry(info=>{releaseClassHandle(info.$$)});attachFinalizer=handle=>{var $$=handle.$$;var hasSmartPtr=!!$$.smartPtr;if(hasSmartPtr){var info={$$:$$};finalizationRegistry.register(handle,info,handle)}return handle};detachFinalizer=handle=>finalizationRegistry.unregister(handle);return attachFinalizer(handle)}function ClassHandle_clone(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.preservePointerOnDelete){this.$$.count.value+=1;return this}else{var clone=attachFinalizer(Object.create(Object.getPrototypeOf(this),{$$:{value:shallowCopyInternalPointer(this.$$)}}));clone.$$.count.value+=1;clone.$$.deleteScheduled=false;return clone}}function ClassHandle_delete(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}detachFinalizer(this);releaseClassHandle(this.$$);if(!this.$$.preservePointerOnDelete){this.$$.smartPtr=undefined;this.$$.ptr=undefined}}function ClassHandle_isDeleted(){return!this.$$.ptr}function ClassHandle_deleteLater(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}deletionQueue.push(this);if(deletionQueue.length===1&&delayFunction){delayFunction(flushPendingDeletes)}this.$$.deleteScheduled=true;return this}function init_ClassHandle(){ClassHandle.prototype["isAliasOf"]=ClassHandle_isAliasOf;ClassHandle.prototype["clone"]=ClassHandle_clone;ClassHandle.prototype["delete"]=ClassHandle_delete;ClassHandle.prototype["isDeleted"]=ClassHandle_isDeleted;ClassHandle.prototype["deleteLater"]=ClassHandle_deleteLater}function ClassHandle(){}function ensureOverloadTable(proto,methodName,humanName){if(undefined===proto[methodName].overloadTable){var prevFunc=proto[methodName];proto[methodName]=function(){if(!proto[methodName].overloadTable.hasOwnProperty(arguments.length)){throwBindingError(`Function '${humanName}' called with an invalid number of arguments (${arguments.length}) - expects one of (${proto[methodName].overloadTable})!`)}return proto[methodName].overloadTable[arguments.length].apply(this,arguments)};proto[methodName].overloadTable=[];proto[methodName].overloadTable[prevFunc.argCount]=prevFunc}}function exposePublicSymbol(name,value,numArguments){if(Module.hasOwnProperty(name)){if(undefined===numArguments||undefined!==Module[name].overloadTable&&undefined!==Module[name].overloadTable[numArguments]){throwBindingError(`Cannot register public name '${name}' twice`)}ensureOverloadTable(Module,name,name);if(Module.hasOwnProperty(numArguments)){throwBindingError(`Cannot register multiple overloads of a function with the same number of arguments (${numArguments})!`)}Module[name].overloadTable[numArguments]=value}else{Module[name]=value;if(undefined!==numArguments){Module[name].numArguments=numArguments}}}function RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast){this.name=name;this.constructor=constructor;this.instancePrototype=instancePrototype;this.rawDestructor=rawDestructor;this.baseClass=baseClass;this.getActualType=getActualType;this.upcast=upcast;this.downcast=downcast;this.pureVirtualFunctions=[]}function upcastPointer(ptr,ptrClass,desiredClass){while(ptrClass!==desiredClass){if(!ptrClass.upcast){throwBindingError(`Expected null or instance of ${desiredClass.name}, got an instance of ${ptrClass.name}`)}ptr=ptrClass.upcast(ptr);ptrClass=ptrClass.baseClass}return ptr}function constNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}return 0}if(!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}function genericPointerToWireType(destructors,handle){var ptr;if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}if(this.isSmartPointer){ptr=this.rawConstructor();if(destructors!==null){destructors.push(this.rawDestructor,ptr)}return ptr}else{return 0}}if(!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}if(!this.isConst&&handle.$$.ptrType.isConst){throwBindingError(`Cannot convert argument of type ${handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name} to parameter type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);if(this.isSmartPointer){if(undefined===handle.$$.smartPtr){throwBindingError("Passing raw pointer to smart pointer is illegal")}switch(this.sharingPolicy){case 0:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{throwBindingError(`Cannot convert argument of type ${handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name} to parameter type ${this.name}`)}break;case 1:ptr=handle.$$.smartPtr;break;case 2:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{var clonedHandle=handle["clone"]();ptr=this.rawShare(ptr,Emval.toHandle(function(){clonedHandle["delete"]()}));if(destructors!==null){destructors.push(this.rawDestructor,ptr)}}break;default:throwBindingError("Unsupporting sharing policy")}}return ptr}function nonConstNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}return 0}if(!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}if(handle.$$.ptrType.isConst){throwBindingError(`Cannot convert argument of type ${handle.$$.ptrType.name} to parameter type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}function simpleReadValueFromPointer(pointer){return this["fromWireType"](HEAP32[pointer>>2])}function RegisteredPointer_getPointee(ptr){if(this.rawGetPointee){ptr=this.rawGetPointee(ptr)}return ptr}function RegisteredPointer_destructor(ptr){if(this.rawDestructor){this.rawDestructor(ptr)}}function RegisteredPointer_deleteObject(handle){if(handle!==null){handle["delete"]()}}function init_RegisteredPointer(){RegisteredPointer.prototype.getPointee=RegisteredPointer_getPointee;RegisteredPointer.prototype.destructor=RegisteredPointer_destructor;RegisteredPointer.prototype["argPackAdvance"]=8;RegisteredPointer.prototype["readValueFromPointer"]=simpleReadValueFromPointer;RegisteredPointer.prototype["deleteObject"]=RegisteredPointer_deleteObject;RegisteredPointer.prototype["fromWireType"]=RegisteredPointer_fromWireType}function RegisteredPointer(name,registeredClass,isReference,isConst,isSmartPointer,pointeeType,sharingPolicy,rawGetPointee,rawConstructor,rawShare,rawDestructor){this.name=name;this.registeredClass=registeredClass;this.isReference=isReference;this.isConst=isConst;this.isSmartPointer=isSmartPointer;this.pointeeType=pointeeType;this.sharingPolicy=sharingPolicy;this.rawGetPointee=rawGetPointee;this.rawConstructor=rawConstructor;this.rawShare=rawShare;this.rawDestructor=rawDestructor;if(!isSmartPointer&®isteredClass.baseClass===undefined){if(isConst){this["toWireType"]=constNoSmartPtrRawPointerToWireType;this.destructorFunction=null}else{this["toWireType"]=nonConstNoSmartPtrRawPointerToWireType;this.destructorFunction=null}}else{this["toWireType"]=genericPointerToWireType}}function replacePublicSymbol(name,value,numArguments){if(!Module.hasOwnProperty(name)){throwInternalError("Replacing nonexistant public symbol")}if(undefined!==Module[name].overloadTable&&undefined!==numArguments){Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}}function dynCallLegacy(sig,ptr,args){var f=Module["dynCall_"+sig];return args&&args.length?f.apply(null,[ptr].concat(args)):f.call(null,ptr)}function getWasmTableEntry(funcPtr){return wasmTable.get(funcPtr)}function dynCall(sig,ptr,args){if(sig.includes("j")){return dynCallLegacy(sig,ptr,args)}var rtn=getWasmTableEntry(ptr).apply(null,args);return rtn}function getDynCaller(sig,ptr){var argCache=[];return function(){argCache.length=0;Object.assign(argCache,arguments);return dynCall(sig,ptr,argCache)}}function embind__requireFunction(signature,rawFunction){signature=readLatin1String(signature);function makeDynCaller(){if(signature.includes("j")){return getDynCaller(signature,rawFunction)}return getWasmTableEntry(rawFunction)}var fp=makeDynCaller();if(typeof fp!="function"){throwBindingError(`unknown function pointer with signature ${signature}: ${rawFunction}`)}return fp}var UnboundTypeError=undefined;function getTypeName(type){var ptr=___getTypeName(type);var rv=readLatin1String(ptr);_free(ptr);return rv}function throwUnboundTypeError(message,types){var unboundTypes=[];var seen={};function visit(type){if(seen[type]){return}if(registeredTypes[type]){return}if(typeDependencies[type]){typeDependencies[type].forEach(visit);return}unboundTypes.push(type);seen[type]=true}types.forEach(visit);throw new UnboundTypeError(`${message}: `+unboundTypes.map(getTypeName).join([", "]))}function __embind_register_class(rawType,rawPointerType,rawConstPointerType,baseClassRawType,getActualTypeSignature,getActualType,upcastSignature,upcast,downcastSignature,downcast,name,destructorSignature,rawDestructor){name=readLatin1String(name);getActualType=embind__requireFunction(getActualTypeSignature,getActualType);if(upcast){upcast=embind__requireFunction(upcastSignature,upcast)}if(downcast){downcast=embind__requireFunction(downcastSignature,downcast)}rawDestructor=embind__requireFunction(destructorSignature,rawDestructor);var legalFunctionName=makeLegalFunctionName(name);exposePublicSymbol(legalFunctionName,function(){throwUnboundTypeError(`Cannot construct ${name} due to unbound types`,[baseClassRawType])});whenDependentTypesAreResolved([rawType,rawPointerType,rawConstPointerType],baseClassRawType?[baseClassRawType]:[],function(base){base=base[0];var baseClass;var basePrototype;if(baseClassRawType){baseClass=base.registeredClass;basePrototype=baseClass.instancePrototype}else{basePrototype=ClassHandle.prototype}var constructor=createNamedFunction(legalFunctionName,function(){if(Object.getPrototypeOf(this)!==instancePrototype){throw new BindingError("Use 'new' to construct "+name)}if(undefined===registeredClass.constructor_body){throw new BindingError(name+" has no accessible constructor")}var body=registeredClass.constructor_body[arguments.length];if(undefined===body){throw new BindingError(`Tried to invoke ctor of ${name} with invalid number of parameters (${arguments.length}) - expected (${Object.keys(registeredClass.constructor_body).toString()}) parameters instead!`)}return body.apply(this,arguments)});var instancePrototype=Object.create(basePrototype,{constructor:{value:constructor}});constructor.prototype=instancePrototype;var registeredClass=new RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast);if(registeredClass.baseClass){if(registeredClass.baseClass.__derivedClasses===undefined){registeredClass.baseClass.__derivedClasses=[]}registeredClass.baseClass.__derivedClasses.push(registeredClass)}var referenceConverter=new RegisteredPointer(name,registeredClass,true,false,false);var pointerConverter=new RegisteredPointer(name+"*",registeredClass,false,false,false);var constPointerConverter=new RegisteredPointer(name+" const*",registeredClass,false,true,false);registeredPointers[rawType]={pointerType:pointerConverter,constPointerType:constPointerConverter};replacePublicSymbol(legalFunctionName,constructor);return[referenceConverter,pointerConverter,constPointerConverter]})}function runDestructors(destructors){while(destructors.length){var ptr=destructors.pop();var del=destructors.pop();del(ptr)}}function validateThis(this_,classType,humanName){if(!(this_ instanceof Object)){throwBindingError(`${humanName} with invalid "this": ${this_}`)}if(!(this_ instanceof classType.registeredClass.constructor)){throwBindingError(`${humanName} incompatible with "this" of type ${this_.constructor.name}`)}if(!this_.$$.ptr){throwBindingError(`cannot call emscripten binding method ${humanName} on deleted object`)}return upcastPointer(this_.$$.ptr,this_.$$.ptrType.registeredClass,classType.registeredClass)}function __embind_register_class_property(classType,fieldName,getterReturnType,getterSignature,getter,getterContext,setterArgumentType,setterSignature,setter,setterContext){fieldName=readLatin1String(fieldName);getter=embind__requireFunction(getterSignature,getter);whenDependentTypesAreResolved([],[classType],function(classType){classType=classType[0];var humanName=`${classType.name}.${fieldName}`;var desc={get:function(){throwUnboundTypeError(`Cannot access ${humanName} due to unbound types`,[getterReturnType,setterArgumentType])},enumerable:true,configurable:true};if(setter){desc.set=()=>{throwUnboundTypeError(`Cannot access ${humanName} due to unbound types`,[getterReturnType,setterArgumentType])}}else{desc.set=v=>{throwBindingError(humanName+" is a read-only property")}}Object.defineProperty(classType.registeredClass.instancePrototype,fieldName,desc);whenDependentTypesAreResolved([],setter?[getterReturnType,setterArgumentType]:[getterReturnType],function(types){var getterReturnType=types[0];var desc={get:function(){var ptr=validateThis(this,classType,humanName+" getter");return getterReturnType["fromWireType"](getter(getterContext,ptr))},enumerable:true};if(setter){setter=embind__requireFunction(setterSignature,setter);var setterArgumentType=types[1];desc.set=function(v){var ptr=validateThis(this,classType,humanName+" setter");var destructors=[];setter(setterContext,ptr,setterArgumentType["toWireType"](destructors,v));runDestructors(destructors)}}Object.defineProperty(classType.registeredClass.instancePrototype,fieldName,desc);return[]});return[]})}function HandleAllocator(){this.allocated=[undefined];this.freelist=[];this.get=function(id){return this.allocated[id]};this.has=function(id){return this.allocated[id]!==undefined};this.allocate=function(handle){var id=this.freelist.pop()||this.allocated.length;this.allocated[id]=handle;return id};this.free=function(id){this.allocated[id]=undefined;this.freelist.push(id)}}var emval_handles=new HandleAllocator;function __emval_decref(handle){if(handle>=emval_handles.reserved&&0===--emval_handles.get(handle).refcount){emval_handles.free(handle)}}function count_emval_handles(){var count=0;for(var i=emval_handles.reserved;i{if(!handle){throwBindingError("Cannot use deleted val. handle = "+handle)}return emval_handles.get(handle).value},toHandle:value=>{switch(value){case undefined:return 1;case null:return 2;case true:return 3;case false:return 4;default:{return emval_handles.allocate({refcount:1,value:value})}}}};function __embind_register_emval(rawType,name){name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":function(handle){var rv=Emval.toValue(handle);__emval_decref(handle);return rv},"toWireType":function(destructors,value){return Emval.toHandle(value)},"argPackAdvance":8,"readValueFromPointer":simpleReadValueFromPointer,destructorFunction:null})}function embindRepr(v){if(v===null){return"null"}var t=typeof v;if(t==="object"||t==="array"||t==="function"){return v.toString()}else{return""+v}}function floatReadValueFromPointer(name,shift){switch(shift){case 2:return function(pointer){return this["fromWireType"](HEAPF32[pointer>>2])};case 3:return function(pointer){return this["fromWireType"](HEAPF64[pointer>>3])};default:throw new TypeError("Unknown float type: "+name)}}function __embind_register_float(rawType,name,size){var shift=getShiftFromSize(size);name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":function(value){return value},"toWireType":function(destructors,value){return value},"argPackAdvance":8,"readValueFromPointer":floatReadValueFromPointer(name,shift),destructorFunction:null})}function newFunc(constructor,argumentList){if(!(constructor instanceof Function)){throw new TypeError(`new_ called with constructor type ${typeof constructor} which is not a function`)}var dummy=createNamedFunction(constructor.name||"unknownFunctionName",function(){});dummy.prototype=constructor.prototype;var obj=new dummy;var r=constructor.apply(obj,argumentList);return r instanceof Object?r:obj}function craftInvokerFunction(humanName,argTypes,classType,cppInvokerFunc,cppTargetFunc,isAsync){var argCount=argTypes.length;if(argCount<2){throwBindingError("argTypes array size mismatch! Must at least get return value and 'this' types!")}var isClassMethodFunc=argTypes[1]!==null&&classType!==null;var needsDestructorStack=false;for(var i=1;i0?", ":"")+argsListWired}invokerFnBody+=(returns||isAsync?"var rv = ":"")+"invoker(fn"+(argsListWired.length>0?", ":"")+argsListWired+");\n";if(needsDestructorStack){invokerFnBody+="runDestructors(destructors);\n"}else{for(var i=isClassMethodFunc?1:2;i>2])}return array}function __embind_register_function(name,argCount,rawArgTypesAddr,signature,rawInvoker,fn,isAsync){var argTypes=heap32VectorToArray(argCount,rawArgTypesAddr);name=readLatin1String(name);rawInvoker=embind__requireFunction(signature,rawInvoker);exposePublicSymbol(name,function(){throwUnboundTypeError(`Cannot call ${name} due to unbound types`,argTypes)},argCount-1);whenDependentTypesAreResolved([],argTypes,function(argTypes){var invokerArgsArray=[argTypes[0],null].concat(argTypes.slice(1));replacePublicSymbol(name,craftInvokerFunction(name,invokerArgsArray,null,rawInvoker,fn,isAsync),argCount-1);return[]})}function integerReadValueFromPointer(name,shift,signed){switch(shift){case 0:return signed?function readS8FromPointer(pointer){return HEAP8[pointer]}:function readU8FromPointer(pointer){return HEAPU8[pointer]};case 1:return signed?function readS16FromPointer(pointer){return HEAP16[pointer>>1]}:function readU16FromPointer(pointer){return HEAPU16[pointer>>1]};case 2:return signed?function readS32FromPointer(pointer){return HEAP32[pointer>>2]}:function readU32FromPointer(pointer){return HEAPU32[pointer>>2]};default:throw new TypeError("Unknown integer type: "+name)}}function __embind_register_integer(primitiveType,name,size,minRange,maxRange){name=readLatin1String(name);if(maxRange===-1){maxRange=4294967295}var shift=getShiftFromSize(size);var fromWireType=value=>value;if(minRange===0){var bitshift=32-8*size;fromWireType=value=>value<>>bitshift}var isUnsignedType=name.includes("unsigned");var checkAssertions=(value,toTypeName)=>{};var toWireType;if(isUnsignedType){toWireType=function(destructors,value){checkAssertions(value,this.name);return value>>>0}}else{toWireType=function(destructors,value){checkAssertions(value,this.name);return value}}registerType(primitiveType,{name:name,"fromWireType":fromWireType,"toWireType":toWireType,"argPackAdvance":8,"readValueFromPointer":integerReadValueFromPointer(name,shift,minRange!==0),destructorFunction:null})}function __embind_register_memory_view(rawType,dataTypeIndex,name){var typeMapping=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array];var TA=typeMapping[dataTypeIndex];function decodeMemoryView(handle){handle=handle>>2;var heap=HEAPU32;var size=heap[handle];var data=heap[handle+1];return new TA(heap.buffer,data,size)}name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":decodeMemoryView,"argPackAdvance":8,"readValueFromPointer":decodeMemoryView},{ignoreDuplicateRegistrations:true})}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len}var UTF8Decoder=typeof TextDecoder!="undefined"?new TextDecoder("utf8"):undefined;function UTF8ArrayToString(heapOrArray,idx,maxBytesToRead){var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heapOrArray[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function __embind_register_std_string(rawType,name){name=readLatin1String(name);var stdStringIsUTF8=name==="std::string";registerType(rawType,{name:name,"fromWireType":function(value){var length=HEAPU32[value>>2];var payload=value+4;var str;if(stdStringIsUTF8){var decodeStartPtr=payload;for(var i=0;i<=length;++i){var currentBytePtr=payload+i;if(i==length||HEAPU8[currentBytePtr]==0){var maxRead=currentBytePtr-decodeStartPtr;var stringSegment=UTF8ToString(decodeStartPtr,maxRead);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+1}}}else{var a=new Array(length);for(var i=0;i>2]=length;if(stdStringIsUTF8&&valueIsOfTypeString){stringToUTF8(value,ptr,length+1)}else{if(valueIsOfTypeString){for(var i=0;i255){_free(ptr);throwBindingError("String has UTF-16 code units that do not fit in 8 bits")}HEAPU8[ptr+i]=charCode}}else{for(var i=0;i>1;var maxIdx=idx+maxBytesToRead/2;while(!(idx>=maxIdx)&&HEAPU16[idx])++idx;endPtr=idx<<1;if(endPtr-ptr>32&&UTF16Decoder)return UTF16Decoder.decode(HEAPU8.subarray(ptr,endPtr));var str="";for(var i=0;!(i>=maxBytesToRead/2);++i){var codeUnit=HEAP16[ptr+i*2>>1];if(codeUnit==0)break;str+=String.fromCharCode(codeUnit)}return str}function stringToUTF16(str,outPtr,maxBytesToWrite){if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<2)return 0;maxBytesToWrite-=2;var startPtr=outPtr;var numCharsToWrite=maxBytesToWrite>1]=codeUnit;outPtr+=2}HEAP16[outPtr>>1]=0;return outPtr-startPtr}function lengthBytesUTF16(str){return str.length*2}function UTF32ToString(ptr,maxBytesToRead){var i=0;var str="";while(!(i>=maxBytesToRead/4)){var utf32=HEAP32[ptr+i*4>>2];if(utf32==0)break;++i;if(utf32>=65536){var ch=utf32-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}else{str+=String.fromCharCode(utf32)}}return str}function stringToUTF32(str,outPtr,maxBytesToWrite){if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<4)return 0;var startPtr=outPtr;var endPtr=startPtr+maxBytesToWrite-4;for(var i=0;i=55296&&codeUnit<=57343){var trailSurrogate=str.charCodeAt(++i);codeUnit=65536+((codeUnit&1023)<<10)|trailSurrogate&1023}HEAP32[outPtr>>2]=codeUnit;outPtr+=4;if(outPtr+4>endPtr)break}HEAP32[outPtr>>2]=0;return outPtr-startPtr}function lengthBytesUTF32(str){var len=0;for(var i=0;i=55296&&codeUnit<=57343)++i;len+=4}return len}function __embind_register_std_wstring(rawType,charSize,name){name=readLatin1String(name);var decodeString,encodeString,getHeap,lengthBytesUTF,shift;if(charSize===2){decodeString=UTF16ToString;encodeString=stringToUTF16;lengthBytesUTF=lengthBytesUTF16;getHeap=()=>HEAPU16;shift=1}else if(charSize===4){decodeString=UTF32ToString;encodeString=stringToUTF32;lengthBytesUTF=lengthBytesUTF32;getHeap=()=>HEAPU32;shift=2}registerType(rawType,{name:name,"fromWireType":function(value){var length=HEAPU32[value>>2];var HEAP=getHeap();var str;var decodeStartPtr=value+4;for(var i=0;i<=length;++i){var currentBytePtr=value+4+i*charSize;if(i==length||HEAP[currentBytePtr>>shift]==0){var maxReadBytes=currentBytePtr-decodeStartPtr;var stringSegment=decodeString(decodeStartPtr,maxReadBytes);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+charSize}}_free(value);return str},"toWireType":function(destructors,value){if(!(typeof value=="string")){throwBindingError(`Cannot pass non-string to C++ string type ${name}`)}var length=lengthBytesUTF(value);var ptr=_malloc(4+length+charSize);HEAPU32[ptr>>2]=length>>shift;encodeString(value,ptr+4,length+charSize);if(destructors!==null){destructors.push(_free,ptr)}return ptr},"argPackAdvance":8,"readValueFromPointer":simpleReadValueFromPointer,destructorFunction:function(ptr){_free(ptr)}})}function __embind_register_void(rawType,name){name=readLatin1String(name);registerType(rawType,{isVoid:true,name:name,"argPackAdvance":0,"fromWireType":function(){return undefined},"toWireType":function(destructors,o){return undefined}})}function _abort(){abort("")}function _emscripten_memcpy_big(dest,src,num){HEAPU8.copyWithin(dest,src,src+num)}function abortOnCannotGrowMemory(requestedSize){abort("OOM")}function _emscripten_resize_heap(requestedSize){var oldSize=HEAPU8.length;requestedSize=requestedSize>>>0;abortOnCannotGrowMemory(requestedSize)}embind_init_charCodes();BindingError=Module["BindingError"]=extendError(Error,"BindingError");InternalError=Module["InternalError"]=extendError(Error,"InternalError");init_ClassHandle();init_embind();init_RegisteredPointer();UnboundTypeError=Module["UnboundTypeError"]=extendError(Error,"UnboundTypeError");init_emval();var wasmImports={"d":___cxa_throw,"l":__embind_register_bigint,"i":__embind_register_bool,"h":__embind_register_class,"b":__embind_register_class_property,"p":__embind_register_emval,"g":__embind_register_float,"k":__embind_register_function,"c":__embind_register_integer,"a":__embind_register_memory_view,"f":__embind_register_std_string,"e":__embind_register_std_wstring,"j":__embind_register_void,"m":_abort,"o":_emscripten_memcpy_big,"n":_emscripten_resize_heap};var asm=createWasm();var ___wasm_call_ctors=function(){return(___wasm_call_ctors=Module["asm"]["r"]).apply(null,arguments)};var _malloc=function(){return(_malloc=Module["asm"]["s"]).apply(null,arguments)};var ___getTypeName=function(){return(___getTypeName=Module["asm"]["u"]).apply(null,arguments)};var __embind_initialize_bindings=Module["__embind_initialize_bindings"]=function(){return(__embind_initialize_bindings=Module["__embind_initialize_bindings"]=Module["asm"]["v"]).apply(null,arguments)};var ___errno_location=function(){return(___errno_location=Module["asm"]["__errno_location"]).apply(null,arguments)};var _free=function(){return(_free=Module["asm"]["w"]).apply(null,arguments)};var ___cxa_is_pointer_type=function(){return(___cxa_is_pointer_type=Module["asm"]["x"]).apply(null,arguments)};var calledRun;dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(){if(runDependencies>0){return}preRun();if(runDependencies>0){return}function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();readyPromiseResolve(Module);if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}run();
9 |
10 |
11 | return loadWASM.ready
12 | }
13 |
14 | );
15 | })();
16 | export default loadWASM;
--------------------------------------------------------------------------------
/lib/wasm/wasm.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ada-url/website/ebbb16ad9de9b11d90918abd01d212de0ba9a3e9/lib/wasm/wasm.wasm
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ada-url.com",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "astro dev",
7 | "build": "astro sync && astro build",
8 | "start": "astro dev",
9 | "lint": "biome check .",
10 | "lint-fix": "biome check . --write"
11 | },
12 | "dependencies": {
13 | "@astrojs/react": "^3.6.2",
14 | "@astrojs/starlight": "^0.29.0",
15 | "@astrojs/tailwind": "^5.1.2",
16 | "@radix-ui/react-tabs": "^1.1.1",
17 | "@radix-ui/react-toast": "^1.2.2",
18 | "@tailwindcss/nesting": "0.0.0-insiders.565cd3e",
19 | "@types/react": "18.2.24",
20 | "@types/react-dom": "18.2.8",
21 | "astro": "^4.16.10",
22 | "autoprefixer": "10.4.20",
23 | "chart.js": "^4.4.3",
24 | "lucide-react": "0.279.0",
25 | "postcss": "8.4.49",
26 | "react": "18.2.0",
27 | "react-dom": "18.2.0",
28 | "react-hook-form": "^7.45.4",
29 | "sharp": "^0.33.5",
30 | "tailwindcss": "3.4.14",
31 | "tailwindcss-animate": "^1.0.7",
32 | "typescript": "5.6.3"
33 | },
34 | "devDependencies": {
35 | "@biomejs/biome": "^1.9.4"
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/public/ada.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ada-url/website/ebbb16ad9de9b11d90918abd01d212de0ba9a3e9/public/ada.png
--------------------------------------------------------------------------------
/public/ada.svg:
--------------------------------------------------------------------------------
1 |
94 |
--------------------------------------------------------------------------------
/public/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ada-url/website/ebbb16ad9de9b11d90918abd01d212de0ba9a3e9/public/android-chrome-192x192.png
--------------------------------------------------------------------------------
/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ada-url/website/ebbb16ad9de9b11d90918abd01d212de0ba9a3e9/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/public/browserconfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | #2b5797
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/public/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ada-url/website/ebbb16ad9de9b11d90918abd01d212de0ba9a3e9/public/favicon-16x16.png
--------------------------------------------------------------------------------
/public/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ada-url/website/ebbb16ad9de9b11d90918abd01d212de0ba9a3e9/public/favicon-32x32.png
--------------------------------------------------------------------------------
/public/fonts/Inter-SemiBold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ada-url/website/ebbb16ad9de9b11d90918abd01d212de0ba9a3e9/public/fonts/Inter-SemiBold.woff
--------------------------------------------------------------------------------
/public/mstile-150x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ada-url/website/ebbb16ad9de9b11d90918abd01d212de0ba9a3e9/public/mstile-150x150.png
--------------------------------------------------------------------------------
/public/safari-pinned-tab.svg:
--------------------------------------------------------------------------------
1 |
2 |
4 |
42 |
--------------------------------------------------------------------------------
/public/site.webmanifest:
--------------------------------------------------------------------------------
1 | {
2 | "name": "",
3 | "short_name": "",
4 | "icons": [
5 | {
6 | "src": "/android-chrome-192x192.png",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | }
10 | ],
11 | "theme_color": "#ffffff",
12 | "background_color": "#ffffff",
13 | "display": "standalone"
14 | }
15 |
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | module.exports = {
3 | darkMode: ['class'],
4 | content: ['./pages/**/*.{ts,tsx}', './components/**/*.{ts,tsx}', './app/**/*.{ts,tsx}'],
5 | theme: {
6 | container: {
7 | center: true,
8 | padding: '2rem',
9 | screens: {
10 | '2xl': '1400px',
11 | },
12 | },
13 | extend: {
14 | colors: {
15 | border: 'hsl(var(--border))',
16 | input: 'hsl(var(--input))',
17 | ring: 'hsl(var(--ring))',
18 | background: 'hsl(var(--background))',
19 | foreground: 'hsl(var(--foreground))',
20 | primary: {
21 | DEFAULT: 'hsl(var(--primary))',
22 | foreground: 'hsl(var(--primary-foreground))',
23 | },
24 | secondary: {
25 | DEFAULT: 'hsl(var(--secondary))',
26 | foreground: 'hsl(var(--secondary-foreground))',
27 | },
28 | destructive: {
29 | DEFAULT: 'hsl(var(--destructive))',
30 | foreground: 'hsl(var(--destructive-foreground))',
31 | },
32 | muted: {
33 | DEFAULT: 'hsl(var(--muted))',
34 | foreground: 'hsl(var(--muted-foreground))',
35 | },
36 | accent: {
37 | DEFAULT: 'hsl(var(--accent))',
38 | foreground: 'hsl(var(--accent-foreground))',
39 | },
40 | popover: {
41 | DEFAULT: 'hsl(var(--popover))',
42 | foreground: 'hsl(var(--popover-foreground))',
43 | },
44 | card: {
45 | DEFAULT: 'hsl(var(--card))',
46 | foreground: 'hsl(var(--card-foreground))',
47 | },
48 | },
49 | borderRadius: {
50 | lg: 'var(--radius)',
51 | md: 'calc(var(--radius) - 2px)',
52 | sm: 'calc(var(--radius) - 4px)',
53 | },
54 | keyframes: {
55 | 'accordion-down': {
56 | from: { height: 0 },
57 | to: { height: 'var(--radix-accordion-content-height)' },
58 | },
59 | 'accordion-up': {
60 | from: { height: 'var(--radix-accordion-content-height)' },
61 | to: { height: 0 },
62 | },
63 | },
64 | animation: {
65 | 'accordion-down': 'accordion-down 0.2s ease-out',
66 | 'accordion-up': 'accordion-up 0.2s ease-out',
67 | },
68 | },
69 | },
70 | plugins: [
71 | require('@tailwindcss/nesting'),
72 | require('tailwindcss-animate'),
73 | require('tailwindcss'),
74 | require('autoprefixer'),
75 | ],
76 | }
77 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es6",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "strict": true,
8 | "forceConsistentCasingInFileNames": true,
9 | "noEmit": true,
10 | "esModuleInterop": true,
11 | "module": "esnext",
12 | "moduleResolution": "Bundler", // allow following "exports" in package.json. This is also fine as the code isn't compiled by `tsc` but by Next / Astro
13 | "resolveJsonModule": true,
14 | "isolatedModules": true,
15 | "jsx": "preserve",
16 | "incremental": true,
17 | "baseUrl": ".",
18 | "plugins": [
19 | {
20 | "name": "next"
21 | }
22 | ],
23 | "paths": {
24 | "@/*": ["./*"],
25 | "contentlayer/generated": ["./.contentlayer/generated"]
26 | }
27 | },
28 | "include": [
29 | "next-env.d.ts",
30 | "**/*.ts",
31 | "**/*.tsx",
32 | ".next/types/**/*.ts",
33 | ".contentlayer/generated"
34 | ],
35 | "exclude": ["node_modules"]
36 | }
37 |
--------------------------------------------------------------------------------