Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,14 @@ Configuration in `netlify.toml`.

```
src/
├── components/ # Svelte components
├── layouts/ # Astro layouts
├── lib/ # Utilities, UI components
├── pages/ # Astro routes (*.astro)
├── services/ # Business logic
└── types/ # TypeScript types
tests/ # Playwright e2e specs
netlify/functions/ # Netlify serverless functions
├── components/ # Svelte components, each in [Name]/[Name].svelte
├── layouts/ # Astro layouts (MainLayout.astro)
├── lib/ # Utilities, UI components
├── pages/ # Astro routes (*.astro)
├── services/ # Business logic
└── types/ # TypeScript types
tests/ # Playwright e2e specs
netlify/functions/ # Netlify serverless functions
```

## State Management
Expand All @@ -123,7 +123,7 @@ Uses Svelte 5's `$state` runes with context-based sharing.

### Architecture Pattern

1. **Root component** (`transliterate/index.svelte`) creates state with `$state()` and exposes it via Svelte context using `setContext<Context<T>>("state_key", ...)`
1. **Root component** (e.g. `Transliterate/Transliterate.svelte`) creates state with `$state()` and exposes it via Svelte context using `setContext<Context<T>>("state_key", ...)`

2. **Consumer components** access state via `getContext<Context<T>>("state_key")` and mutate directly via `.value` property

Expand Down
11 changes: 11 additions & 0 deletions netlify.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,14 @@
for = "/schemas/*"
[headers.values]
Cache-Control = "public, max-age=31536000, immutable"

[[headers]]
for = "/*"
[headers.values]
Accept-CH = "Sec-CH-Prefers-Color-Scheme"
Critical-CH = "Sec-CH-Prefers-Color-Scheme"
Vary = "Sec-CH-Prefers-Color-Scheme"

[[edge_functions]]
function = "check-theme"
path = "/*"
24 changes: 24 additions & 0 deletions netlify/edge-functions/check-theme.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import type { Config, Context } from "@netlify/edge-functions";

export default async (request: Request, context: Context) => {
const response = await context.next();

const contentType = response.headers.get("content-type");
if (!contentType || !contentType.includes("text/html")) {
return response;
}

let html = await response.text();

const theme = context.cookies.get("theme") || "system";
html = html.replace("{{ USER_THEME }}", theme);

return new Response(html, {
status: response.status,
headers: response.headers,
});
};

export const config: Config = {
path: "/*",
};
111 changes: 39 additions & 72 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"@astrojs/netlify": "^8.0.0",
"@astrojs/svelte": "^9.0.0",
"@codemirror/lang-javascript": "^6.2.5",
"@tabler/icons-astro": "^3.46.0",
"@tabler/icons-svelte": "^3.44.0",
"@tailwindcss/vite": "^4.3.1",
"astro": "^7.0.0",
Expand All @@ -42,16 +43,16 @@
"devDependencies": {
"@eslint/js": "^10.0.1",
"@internationalized/date": "^3.12.2",
"@lucide/svelte": "^1.21.0",
"@lucide/svelte": "^1.27.0",
"@netlify/functions": "^5.3.0",
"@playwright/test": "^1.61.0",
"@types/node": "^26.0.0",
"@types/serialize-javascript": "^5.0.4",
"bits-ui": "^2.18.1",
"clsx": "^2.1.1",
"eslint": "^10.5.0",
"eslint-plugin-svelte": "^3.19.0",
"globals": "^17.7.0",
"mode-watcher": "^1.1.0",
"npm-check-updates": "^22.2.7",
"prettier": "^3.8.4",
"prettier-plugin-astro": "^0.14.1",
Expand Down
2 changes: 1 addition & 1 deletion playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export default defineConfig({
timeout: 10000,
},
webServer: {
command: "npm run dev",
command: "NETLIFY_DEV=1 npm run dev",
port: 4321,
reuseExistingServer: false,
timeout: 120 * 1000,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { Separator } from "$lib/components/ui/separator/index.js";
import { version } from "hebrew-transliteration/package.json";
import type { Snippet } from "svelte";
import FeedbackModal from "./FeedbackModal.svelte";
import FeedbackModal from "../FeedbackModal/FeedbackModal.svelte";

interface Props {
aria_busy: boolean;
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
import NavigationLink from "./NavigationLink.astro";
import NavigationLink from "../NavigationLink/NavigationLink.astro";

const links = [
{ label: "Transliterate", href: "/" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
import { performRemoval } from "../../services/removalService";
import type { AppStatus, Context, RemoveState } from "../../types/index";
import { default_remove_options } from "../../utils/defaults";
import Card from "../shared/Card.svelte";
import Input from "../shared/Input.svelte";
import Output from "../shared/Output.svelte";
import Card from "../Card/Card.svelte";
import Input from "../Input/Input.svelte";
import Output from "../Output/Output.svelte";
import Settings from "./Settings.svelte";

const saved_options = deserialize_object(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import CodeMirror from "svelte-codemirror-editor";
import type { Context, RemoveState } from "../../types/index";
import { format_doc_url } from "../../utils/documentation";
import Dialog from "../shared/Dialog.svelte";
import Dialog from "../Dialog/Dialog.svelte";

const remove_state = getContext<Context<RemoveState>>("remove_state");

Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import { getContext } from "svelte";
import type { WhitespaceOption } from "../../services/structureService";
import type { Context, StructureState } from "../../types/index";
import Dialog from "../shared/Dialog.svelte";
import Dialog from "../Dialog/Dialog.svelte";

const structure_state = getContext<Context<StructureState>>("structure_state");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
import { performStructure } from "../../services/structureService";
import type { AppStatus, Context, StructureState } from "../../types/index";
import { default_structure_options } from "../../utils/defaults";
import Card from "../shared/Card.svelte";
import Input from "../shared/Input.svelte";
import Output from "../shared/Output.svelte";
import Card from "../Card/Card.svelte";
import Input from "../Input/Input.svelte";
import Output from "../Output/Output.svelte";
import Settings from "./Settings.svelte";

const saved_options = load_settings(STORAGE_KEYS.structure, default_structure_options);
Expand Down
28 changes: 28 additions & 0 deletions src/components/ThemeSelector/ThemeSelector.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<script lang="ts">
import { buttonVariants } from "$lib/components/ui/button/index.js";
import * as DropdownMenu from "$lib/components/ui/dropdown-menu/index.js";
import MoonIcon from "@lucide/svelte/icons/moon";
import SunIcon from "@lucide/svelte/icons/sun";
import SunMoonIcon from "@lucide/svelte/icons/sun-moon";

type Theme = "light" | "dark" | "system";

function set_display(theme: Theme) {
document.documentElement.setAttribute("data-theme", theme);
document.cookie = `theme=${theme}; path=/`;
}
</script>

<DropdownMenu.Root>
<DropdownMenu.Trigger class={buttonVariants({ variant: "outline", size: "sm" })}>
<SunMoonIcon class="size-4 hidden [html[data-theme='system']_&]:block" />
<SunIcon class="size-4 hidden [html[data-theme='light']_&]:block" />
<MoonIcon class="size-4 hidden [html[data-theme='dark']_&]:block" />
<span class="sr-only">Toggle theme</span>
</DropdownMenu.Trigger>
<DropdownMenu.Content align="end">
<DropdownMenu.Item onclick={() => set_display("light")}>Light</DropdownMenu.Item>
<DropdownMenu.Item onclick={() => set_display("dark")}>Dark</DropdownMenu.Item>
<DropdownMenu.Item onclick={() => set_display("system")}>System</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu.Root>
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
import type { Context, TransliterationState, VisibilityState } from "../../types/index";
import { format_doc_url, format_label } from "../../utils/documentation";
import { get_default_SBL_schema } from "../../utils/schemaDefaults";
import Dialog from "../shared/Dialog.svelte";
import Dialog from "../Dialog/Dialog.svelte";
import FeatureEditor from "./FeatureEditor.svelte";
import KetivQereEditor from "./KetivQereEditor.svelte";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
import { performTransliteration as perform_transliteration } from "../../services/transliterationService";
import type { AppStatus, Context, TransliterationState } from "../../types/index";
import { get_default_SBL_schema } from "../../utils/schemaDefaults";
import Card from "../shared/Card.svelte";
import ErrorBoundary from "../shared/ErrorBoundary.svelte";
import Input from "../shared/Input.svelte";
import Output from "../shared/Output.svelte";
import Card from "../Card/Card.svelte";
import ErrorBoundary from "../ErrorBoundary/ErrorBoundary.svelte";
import Input from "../Input/Input.svelte";
import Output from "../Output/Output.svelte";
import NiqqudModal from "./NiqqudModal.svelte";
import Settings from "./SettingsDialog.svelte";

Expand Down
Loading