--- /dev/null
+*.beam
+*.ez
+/build
+erl_crash.dump
+
+#Added automatically by Lustre Dev Tools
+/.lustre
+/dist
--- /dev/null
+# client
+
+[](https://hex.pm/packages/client)
+[](https://client.hexdocs.pm/)
+
+```sh
+gleam add client@1
+```
+```gleam
+import client
+
+pub fn main() -> Nil {
+ // TODO: An example of the project in use
+}
+```
+
+Further documentation can be found at <https://client.hexdocs.pm/>.
+
+## Development
+
+```sh
+gleam run # Run the project
+gleam test # Run the tests
+```
--- /dev/null
+name = "client"
+version = "1.0.0"
+target = "javascript"
+
+# Fill out these fields if you intend to generate HTML documentation or publish
+# your project to the Hex package manager.
+#
+# description = ""
+# licences = ["Apache-2.0"]
+# repository = { type = "github", user = "", repo = "" }
+# links = [{ title = "Website", href = "" }]
+#
+# For a full reference of all the available options, you can have a look at
+# https://gleam.run/writing-gleam/gleam-toml/.
+
+[dependencies]
+gleam_stdlib = ">= 1.0.0 and < 2.0.0"
+lustre = ">= 5.7.1 and < 6.0.0"
+rsvp = ">= 2.0.0 and < 3.0.0"
+gleam_json = ">= 3.1.0 and < 4.0.0"
+gleam_http = ">= 4.3.0 and < 5.0.0"
+plinth = ">= 0.11.0 and < 1.0.0"
+shared = { path = "../shared" }
+gleam_erlang = ">= 1.3.0 and < 2.0.0"
+mist = ">= 6.0.3 and < 7.0.0"
+simplifile = ">= 2.7.0 and < 3.0.0"
+
+[dev_dependencies]
+gleeunit = ">= 1.0.0 and < 2.0.0"
+lustre_dev_tools = ">= 2.3.6 and < 3.0.0"
--- /dev/null
+# Do not manually edit this file, it is managed by Gleam.
+#
+# This file locks the dependency versions used, to make your build
+# deterministic and to prevent unexpected versions from being included
+# in your application.
+#
+# You should check this file into your source control repository.
+
+packages = [
+ { name = "argv", version = "1.1.0", build_tools = ["gleam"], requirements = [], otp_app = "argv", source = "hex", outer_checksum = "3277D100448BDB4A29B6D58C0F36F631CBC349E8BDD09766C6309DF202831140" },
+ { name = "booklet", version = "1.1.0", build_tools = ["gleam"], requirements = [], otp_app = "booklet", source = "hex", outer_checksum = "08E0FDB78DC4D8A5D3C80295B021505C7D2A2E7B6C6D5EAB7286C36F4A53C851" },
+ { name = "directories", version = "1.2.0", build_tools = ["gleam"], requirements = ["envoy", "gleam_stdlib", "platform", "simplifile"], otp_app = "directories", source = "hex", outer_checksum = "D13090CFCDF6759B87217E8DDD73A75903A700148A82C1D33799F333E249BF9E" },
+ { name = "envoy", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "envoy", source = "hex", outer_checksum = "9C6FBB6BFA02A52798BEEC5977A738CAD6E4A057F4B67FD0C8061AD2502C191A" },
+ { name = "exception", version = "2.1.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "exception", source = "hex", outer_checksum = "6BDEA95248093599391C3B5DF1835C5C6A86C353C2F99CE539B450E3432FE117" },
+ { name = "filepath", version = "1.1.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "B06A9AF0BF10E51401D64B98E4B627F1D2E48C154967DA7AF4D0914780A6D40A" },
+ { name = "gleam_community_ansi", version = "1.5.0", build_tools = ["gleam"], requirements = ["gleam_community_colour", "gleam_regexp", "gleam_stdlib"], otp_app = "gleam_community_ansi", source = "hex", outer_checksum = "B5AA433AF84313E23FDF90CCFF752B9380FE9FFCE02B2949D49B7AACCC77B16D" },
+ { name = "gleam_community_colour", version = "2.0.4", build_tools = ["gleam"], requirements = ["gleam_json", "gleam_stdlib"], otp_app = "gleam_community_colour", source = "hex", outer_checksum = "6DB4665555D7D2B27F0EA32EF47E8BEBC4303821765F9C73D483F38EE24894F0" },
+ { name = "gleam_crypto", version = "1.6.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_crypto", source = "hex", outer_checksum = "2DE9E4EF53CF6FEE049D4F765731F7178F7A11AEFAE00EEE63BF7536B354AD3F" },
+ { name = "gleam_erlang", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "1124AD3AA21143E5AF0FC5CF3D9529F6DB8CA03E43A55711B60B6B7B3874375C" },
+ { name = "gleam_fetch", version = "1.4.0", build_tools = ["gleam"], requirements = ["gleam_http", "gleam_javascript", "gleam_stdlib"], otp_app = "gleam_fetch", source = "hex", outer_checksum = "284CE88E37436699545F9F65D413E1DFB6C1EA3FE3824B6EA2018D0ECF088FFC" },
+ { name = "gleam_http", version = "4.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_http", source = "hex", outer_checksum = "82EA6A717C842456188C190AFB372665EA56CE13D8559BF3B1DD9E40F619EE0C" },
+ { name = "gleam_httpc", version = "5.0.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_http", "gleam_stdlib"], otp_app = "gleam_httpc", source = "hex", outer_checksum = "C545172618D07811494E97AAA4A0FB34DA6F6D0061FDC8041C2F8E3BE2B2E48F" },
+ { name = "gleam_javascript", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_javascript", source = "hex", outer_checksum = "D542C4B4F40E942F5D3372D524419FA521A7BB92D621AF696CC286E89D882D55" },
+ { name = "gleam_json", version = "3.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_json", source = "hex", outer_checksum = "44FDAA8847BE8FC48CA7A1C089706BD54BADCC4C45B237A992EDDF9F2CDB2836" },
+ { name = "gleam_otp", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "gleam_otp", source = "hex", outer_checksum = "DE4CA6850842F0266EE95317A25DD6A0A0F20CDFAB7C0ADC2E63251D7C3C72EC" },
+ { name = "gleam_regexp", version = "1.1.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_regexp", source = "hex", outer_checksum = "9C215C6CA84A5B35BB934A9B61A9A306EC743153BE2B0425A0D032E477B062A9" },
+ { name = "gleam_stdlib", version = "1.0.5", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "CEE5B6C076A85B45F60C585F4316C63EC8B7127C119D5738C3958A9C4D50404E" },
+ { name = "gleam_time", version = "1.10.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_time", source = "hex", outer_checksum = "56539216E4C4B1748714652AB38F0BD16B9101F61DB62769FDC7CD42A8E5E833" },
+ { name = "gleeunit", version = "1.11.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "EC31ABA74256AEA531EDF8169931D775BBB384FED0A8A1BDC4DD9354E3E21826" },
+ { name = "glint", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_community_ansi", "gleam_community_colour", "gleam_stdlib", "snag"], otp_app = "glint", source = "hex", outer_checksum = "26CCA9BC3ACB56CD9D754ACF598F49B4C281C4FDD81AE61FA21C8E92E9C8218E" },
+ { name = "glisten", version = "9.0.1", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_otp", "gleam_stdlib", "logging"], otp_app = "glisten", source = "hex", outer_checksum = "7795AA50830656F3A0316A6B26595F893C83272DA901B3405E31339CAA31A10B" },
+ { name = "gramps", version = "6.0.1", build_tools = ["gleam"], requirements = ["gleam_crypto", "gleam_erlang", "gleam_http", "gleam_stdlib"], otp_app = "gramps", source = "hex", outer_checksum = "D55636072DEE173F6586A5679D3C02EC7A0DE3F8646B78C351B72908FF223DF7" },
+ { name = "group_registry", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_otp", "gleam_stdlib"], otp_app = "group_registry", source = "hex", outer_checksum = "BC798A53D6F2406DB94E27CB45C57052CB56B32ACF7CC16EA20F6BAEC7E36B90" },
+ { name = "houdini", version = "1.2.1", build_tools = ["gleam"], requirements = [], otp_app = "houdini", source = "hex", outer_checksum = "6F8AC2F12974567FB744BEA66AC93CEB76AAEA19AD28564623F76CDA9BC26A85" },
+ { name = "hpack_erl", version = "0.3.0", build_tools = ["rebar3"], requirements = [], otp_app = "hpack", source = "hex", outer_checksum = "D6137D7079169D8C485C6962DFE261AF5B9EF60FBC557344511C1E65E3D95FB0" },
+ { name = "justin", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "justin", source = "hex", outer_checksum = "8B1C62269E8607D0A0ED698B7903984CE0BF7B6B3C0DEA3C6C8302B39402837B" },
+ { name = "logging", version = "1.5.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "logging", source = "hex", outer_checksum = "BC5F18CE5DD9686100229FE5409BDC3DD5C46D5A7DF2F804AD2D8F0DD6C5060E" },
+ { name = "lustre", version = "5.7.1", build_tools = ["gleam"], requirements = ["exception", "gleam_erlang", "gleam_json", "gleam_otp", "gleam_stdlib", "houdini"], otp_app = "lustre", source = "hex", outer_checksum = "663A2D1A3458914CA537A42AC07E601DD3FD85415EBDAF4717F2DFF6E86F90F9" },
+ { name = "lustre_dev_tools", version = "2.3.6", build_tools = ["gleam"], requirements = ["argv", "booklet", "filepath", "gleam_community_ansi", "gleam_crypto", "gleam_erlang", "gleam_http", "gleam_httpc", "gleam_json", "gleam_otp", "gleam_regexp", "gleam_stdlib", "glint", "group_registry", "justin", "lustre", "mist", "polly", "simplifile", "tom", "wisp"], otp_app = "lustre_dev_tools", source = "hex", outer_checksum = "7A650A107C7E767D902A8CB608460B927DE0CDD47D5BA04DED71F9F622FE6AD9" },
+ { name = "marceau", version = "1.3.0", build_tools = ["gleam"], requirements = [], otp_app = "marceau", source = "hex", outer_checksum = "2D1C27504BEF45005F5DFB18591F8610FB4BFA91744878210BDC464412EC44E9" },
+ { name = "mist", version = "6.0.3", build_tools = ["gleam"], requirements = ["exception", "gleam_erlang", "gleam_http", "gleam_otp", "gleam_stdlib", "glisten", "gramps", "hpack_erl", "logging"], otp_app = "mist", source = "hex", outer_checksum = "1B07F321D5FA0CB162D81496F2DE96AEB6EF8980F4F38230A4CC3F849497E020" },
+ { name = "platform", version = "1.0.0", build_tools = ["gleam"], requirements = [], otp_app = "platform", source = "hex", outer_checksum = "8339420A95AD89AAC0F82F4C3DB8DD401041742D6C3F46132A8739F6AEB75391" },
+ { name = "plinth", version = "0.11.0", build_tools = ["gleam"], requirements = ["gleam_javascript", "gleam_json", "gleam_stdlib"], otp_app = "plinth", source = "hex", outer_checksum = "D30FDE8FC11EB76538AB498ACFF5399D0AE27993C74D63BE05AFE8CE80C4C839" },
+ { name = "polly", version = "3.1.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_erlang", "gleam_otp", "gleam_stdlib", "simplifile"], otp_app = "polly", source = "hex", outer_checksum = "51FB565D81FF6212FDF3306D44419601F2A7C4EDD1F00FC9DA5C376A00AED4FE" },
+ { name = "rsvp", version = "2.0.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_fetch", "gleam_http", "gleam_httpc", "gleam_javascript", "gleam_json", "gleam_stdlib", "lustre"], otp_app = "rsvp", source = "hex", outer_checksum = "A38F2DB9657E84A584278DB50FD903693FF370C22C191753B773546FEB2465F0" },
+ { name = "shared", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_json", "gleam_stdlib"], source = "local", path = "../shared" },
+ { name = "simplifile", version = "2.7.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "A2727627B063E87351934C7F7F008F2D1FDB16F6DE0B8C79F9E46459CFC9C164" },
+ { name = "snag", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "snag", source = "hex", outer_checksum = "274F41D6C3ECF99F7686FDCE54183333E41D2C1CA5A3A673F9A8B2C7A4401077" },
+ { name = "tom", version = "2.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "gleam_time"], otp_app = "tom", source = "hex", outer_checksum = "DCF04CB7AB35D58CFC598C66EA2E1816D160759802C89B2BA6238780D59BC256" },
+ { name = "wisp", version = "2.2.2", build_tools = ["gleam"], requirements = ["directories", "exception", "filepath", "gleam_crypto", "gleam_erlang", "gleam_http", "gleam_json", "gleam_stdlib", "houdini", "logging", "marceau", "mist", "simplifile"], otp_app = "wisp", source = "hex", outer_checksum = "5FF5F1E288C3437252ABB93D8F9CF42FF652CE7AD54480CFE736038DC09C4F22" },
+]
+
+[requirements]
+gleam_erlang = { version = ">= 1.3.0 and < 2.0.0" }
+gleam_http = { version = ">= 4.3.0 and < 5.0.0" }
+gleam_json = { version = ">= 3.1.0 and < 4.0.0" }
+gleam_stdlib = { version = ">= 1.0.0 and < 2.0.0" }
+gleeunit = { version = ">= 1.0.0 and < 2.0.0" }
+lustre = { version = ">= 5.7.1 and < 6.0.0" }
+lustre_dev_tools = { version = ">= 2.3.6 and < 3.0.0" }
+mist = { version = ">= 6.0.3 and < 7.0.0" }
+plinth = { version = ">= 0.11.0 and < 1.0.0" }
+rsvp = { version = ">= 2.0.0 and < 3.0.0" }
+shared = { path = "../shared" }
+simplifile = { version = ">= 2.7.0 and < 3.0.0" }
--- /dev/null
+import gleam/int
+import gleam/list
+import gleam/option.{type Option, None, Some}
+import gleam/result
+import lustre
+import lustre/attribute
+import lustre/effect.{type Effect}
+import lustre/element.{type Element}
+import lustre/element/html
+import lustre/event
+import plinth/browser/location
+import plinth/browser/window
+import rsvp
+import shared
+
+pub fn main() -> Nil {
+ let app = lustre.application(init, update, view)
+ let assert Ok(_) = lustre.start(app, "#app", None)
+ Nil
+}
+
+type Model {
+ Model(
+ page: String,
+ dashboard: Option(shared.Dashboard),
+ error: Option(String),
+ username: String,
+ password: String,
+ project_name: String,
+ project_description: String,
+ task_title: String,
+ task_description: String,
+ task_assignee: String,
+ task_assignees: String,
+ task_due_date: String,
+ )
+}
+
+pub type Message {
+ DashboardLoaded(Result(shared.Dashboard, rsvp.Error(String)))
+ LoginSubmitted(List(#(String, String)))
+ RegisterSubmitted(List(#(String, String)))
+ ProjectSubmitted(List(#(String, String)))
+ TaskSubmitted(Int, List(#(String, String)))
+ StatusSubmitted(Int, List(#(String, String)))
+ Authenticated(Result(String, rsvp.Error(String)))
+ Saved(Result(String, rsvp.Error(String)))
+ UsernameChanged(String)
+ PasswordChanged(String)
+ ProjectNameChanged(String)
+ ProjectDescriptionChanged(String)
+ TaskTitleChanged(String)
+ TaskDescriptionChanged(String)
+ TaskAssigneeChanged(String)
+ TaskAssigneesChanged(String)
+ TaskDueDateChanged(String)
+ LogOut
+ Nothing
+}
+
+fn init(_flags: Option(Nil)) -> #(Model, Effect(Message)) {
+ let page = case current_path() {
+ "/login" -> "login"
+ "/register" -> "register"
+ _ -> "dashboard"
+ }
+
+ echo page
+ let model =
+ Model(
+ page:,
+ dashboard: None,
+ error: None,
+ username: "",
+ password: "",
+ project_name: "",
+ project_description: "",
+ task_title: "",
+ task_description: "",
+ task_assignee: "",
+ task_assignees: "",
+ task_due_date: "",
+ )
+
+ case page {
+ // "dashboard" ->
+ // #(
+ // model,
+ // rsvp.get(
+ // "/api/dashboard",
+ // rsvp.expect_json(shared.dashboard_decoder(), DashboardLoaded),
+ // ),
+ // )
+ _ ->
+ //#(model, effect.none())
+ auth_request(model, [], "/api/login", "/")
+ }
+}
+
+fn update(model: Model, message: Message) -> #(Model, Effect(Message)) {
+ case message {
+ DashboardLoaded(Ok(value)) -> {
+ echo "dashload good"
+ #(Model(..model, dashboard: Some(value), error: None), effect.none())
+ }
+ DashboardLoaded(Error(_)) -> {
+ echo "dashload err"
+ #(
+ Model(
+ ..model,
+ page: "login",
+ error: Some("Please sign in to continue."),
+ ),
+ effect.none(),
+ )
+ }
+ UsernameChanged(value) -> #(Model(..model, username: value), effect.none())
+ PasswordChanged(value) -> #(Model(..model, password: value), effect.none())
+ ProjectNameChanged(value) -> #(
+ Model(..model, project_name: value),
+ effect.none(),
+ )
+ ProjectDescriptionChanged(value) -> #(
+ Model(..model, project_description: value),
+ effect.none(),
+ )
+ TaskTitleChanged(value) -> #(
+ Model(..model, task_title: value),
+ effect.none(),
+ )
+ TaskDescriptionChanged(value) -> #(
+ Model(..model, task_description: value),
+ effect.none(),
+ )
+ TaskAssigneeChanged(value) -> #(
+ Model(..model, task_assignee: value),
+ effect.none(),
+ )
+ TaskAssigneesChanged(value) -> #(
+ Model(..model, task_assignees: value),
+ effect.none(),
+ )
+ TaskDueDateChanged(value) -> #(
+ Model(..model, task_due_date: value),
+ effect.none(),
+ )
+ LoginSubmitted(fields) -> auth_request(model, fields, "/api/login", "/")
+ RegisterSubmitted(fields) ->
+ auth_request(model, fields, "/api/register", "/")
+ ProjectSubmitted(fields) -> {
+ let body =
+ shared.NewProject(field(fields, "name"), field(fields, "description"))
+ |> shared.new_project_json
+ #(
+ model,
+ rsvp.post(
+ "/api/projects",
+ body,
+ rsvp.expect_any_response(fn(result) {
+ Saved(result |> result.map(fn(response) { response.body }))
+ }),
+ ),
+ )
+ }
+ TaskSubmitted(project_id, fields) -> {
+ let body =
+ shared.NewTask(
+ field(fields, "title"),
+ field(fields, "description"),
+ field(fields, "assignee"),
+ field(fields, "assignees"),
+ field(fields, "due_date"),
+ )
+ |> shared.new_task_json
+ #(
+ model,
+ rsvp.post(
+ "/api/projects/" <> int.to_string(project_id) <> "/tasks",
+ body,
+ rsvp.expect_any_response(fn(result) {
+ Saved(result |> result.map(fn(response) { response.body }))
+ }),
+ ),
+ )
+ }
+ StatusSubmitted(task_id, fields) -> {
+ let status = field(fields, "status")
+ let body = shared.StatusChange(status) |> shared.status_change_json
+ #(
+ model,
+ rsvp.post(
+ "/api/tasks/" <> int.to_string(task_id) <> "/status",
+ body,
+ rsvp.expect_any_response(fn(result) {
+ Saved(result |> result.map(fn(response) { response.body }))
+ }),
+ ),
+ )
+ }
+ Authenticated(Ok(_)) -> #(
+ Model(..model, page: "dashboard"),
+ rsvp.get(
+ "/api/dashboard",
+ rsvp.expect_json(shared.dashboard_decoder(), DashboardLoaded),
+ ),
+ )
+ Authenticated(Error(_)) -> #(
+ Model(..model, error: Some("Invalid username or password.")),
+ effect.none(),
+ )
+ Saved(Ok(_)) -> #(
+ Model(
+ ..model,
+ project_name: "",
+ project_description: "",
+ task_title: "",
+ task_description: "",
+ task_assignee: "",
+ task_assignees: "",
+ task_due_date: "",
+ ),
+ rsvp.get(
+ "/api/dashboard",
+ rsvp.expect_json(shared.dashboard_decoder(), DashboardLoaded),
+ ),
+ )
+ Saved(Error(_)) -> #(
+ Model(..model, error: Some("The request could not be saved.")),
+ effect.none(),
+ )
+ LogOut -> #(
+ Model(..model, page: "login"),
+ rsvp.get("/api/logout", rsvp.expect_ok_response(fn(_) { Nothing })),
+ )
+ Nothing -> #(model, effect.none())
+ }
+}
+
+fn auth_request(
+ model: Model,
+ fields: List(#(String, String)),
+ url: String,
+ _redirect: String,
+) -> #(Model, Effect(Message)) {
+ let body =
+ shared.Credentials(field(fields, "username"), field(fields, "password"))
+ |> shared.credentials_json
+ #(
+ model,
+ rsvp.post(
+ url,
+ body,
+ rsvp.expect_any_response(fn(result) {
+ Authenticated(result |> result.map(fn(response) { response.body }))
+ }),
+ ),
+ )
+}
+
+fn view(model: Model) -> Element(Message) {
+ case model.page {
+ "login" -> auth_view(model, "Welcome back", "Log in", LoginSubmitted)
+ "register" ->
+ auth_view(
+ model,
+ "Create your account",
+ "Create account",
+ RegisterSubmitted,
+ )
+ _ -> dashboard_view(model)
+ }
+}
+
+fn auth_view(
+ model: Model,
+ title: String,
+ submit: String,
+ on_submit: fn(List(#(String, String))) -> Message,
+) -> Element(Message) {
+ let link = case submit == "Log in" {
+ True -> "/register"
+ False -> "/login"
+ }
+ let link_text = case submit == "Log in" {
+ True -> "Need an account?"
+ False -> "Already registered?"
+ }
+ html.main([attribute.class("auth")], [
+ styles(),
+ html.text("FRC 972 · IRON CLAW"),
+ html.h1([], [html.text(title)]),
+ html.p([], [html.text("google sheets, more like shmoogle shits")]),
+ error_view(model.error),
+ html.form([event.on_submit(on_submit)], [
+ html.input([
+ attribute.name("username"),
+ attribute.placeholder("Username"),
+ event.on_input(UsernameChanged),
+ ]),
+ html.input([
+ attribute.name("password"),
+ attribute.type_("password"),
+ attribute.placeholder("Password"),
+ event.on_input(PasswordChanged),
+ ]),
+ html.button([], [html.text(submit)]),
+ ]),
+ html.a([attribute.href(link)], [html.text(link_text)]),
+ ])
+}
+
+fn dashboard_view(model: Model) -> Element(Message) {
+ case model.dashboard {
+ None ->
+ html.main([attribute.class("auth")], [
+ html.h1([], [html.text("Loading Iron Claw...")]),
+ error_view(model.error),
+ ])
+ Some(board) ->
+ html.main(
+ [attribute.class("page")],
+ list.append(
+ [
+ styles(),
+ html.header([], [
+ html.div([], [
+ html.text("FRC 972 · IRON CLAW"),
+ html.h1([], [html.text("Team board")]),
+ ]),
+ html.button([event.on_click(LogOut)], [
+ html.text("Sign out"),
+ ]),
+ ]),
+ html.section([attribute.class("hero")], [
+ html.text("wassup"),
+ ]),
+ html.section([attribute.class("panel")], [
+ html.h2([], [html.text("New project")]),
+ html.form([event.on_submit(ProjectSubmitted)], [
+ text_input("name", "Project name"),
+ text_input("description", "What does success look like?"),
+ html.button([], [html.text("Add project")]),
+ ]),
+ ]),
+ ],
+ list.map(board.projects, fn(project) { project_view(model, project) }),
+ ),
+ )
+ }
+}
+
+fn project_view(_model: Model, project: shared.Project) -> Element(Message) {
+ html.article(
+ [attribute.class("panel")],
+ list.append(
+ [
+ html.text("PROJECT"),
+ html.h2([], [html.text(project.name)]),
+ html.p([], [html.text(project.description)]),
+ ],
+ list.append(list.map(project.tasks, task_view), [
+ html.form(
+ [event.on_submit(fn(fields) { TaskSubmitted(project.id, fields) })],
+ [
+ text_input("title", "Task title"),
+ text_input("assignee", "Owner"),
+ text_input("assignees", "Assignees"),
+ text_input("due_date", "Due date"),
+ text_input("description", "Details"),
+ html.button([], [html.text("Add task")]),
+ ],
+ ),
+ ]),
+ ),
+ )
+}
+
+fn task_view(task: shared.Task) -> Element(Message) {
+ let next = case task.status {
+ "todo" -> "doing"
+ "doing" -> "done"
+ _ -> "todo"
+ }
+ html.div([attribute.class("task")], [
+ html.div([], [
+ html.strong([], [html.text(task.title)]),
+ html.p([], [html.text(task.description)]),
+ ]),
+ html.div([attribute.class("task-meta")], [
+ html.span([], [html.text(task.status)]),
+ html.text("Owner: " <> task.assignee),
+ html.text("Assignees: " <> task.assignees),
+ html.form(
+ [event.on_submit(fn(fields) { StatusSubmitted(task.id, fields) })],
+ [
+ html.input([
+ attribute.type_("hidden"),
+ attribute.name("status"),
+ attribute.value(next),
+ ]),
+ html.button([], [html.text("Move to " <> next)]),
+ ],
+ ),
+ ]),
+ ])
+}
+
+fn text_input(name: String, placeholder: String) -> Element(Message) {
+ html.input([
+ attribute.name(name),
+ attribute.placeholder(placeholder),
+ ])
+}
+
+fn styles() -> Element(Message) {
+ html.style(
+ [],
+ "body{margin:0;background:#f4f0e8;color:#28231e;font-family:Inter,ui-sans-serif,system-ui,sans-serif}.page{max-width:1120px;margin:auto;padding:28px 22px 72px}.auth{max-width:430px;margin:10vh auto;padding:42px;background:#fff;border:1px solid #e2d9cc;border-radius:22px;box-shadow:0 20px 60px #2d241414}.auth h1{font-size:clamp(2.4rem,8vw,4.8rem);line-height:.95;letter-spacing:-.06em;margin:14px 0}.auth form{display:grid;gap:12px;margin:26px 0 14px}.auth a{color:#b53b24;font-weight:700}.eyebrow{font-size:.72rem;letter-spacing:.16em;color:#b53b24;font-weight:800}header{display:flex;justify-content:space-between;gap:24px;align-items:start;margin-bottom:42px}header h1{font-size:clamp(2.7rem,7vw,5.5rem);line-height:.9;letter-spacing:-.07em;margin:12px 0}.hero{padding:42px;border-radius:22px;background:linear-gradient(120deg,#29241f,#594538);color:#fff;margin-bottom:20px;font-size:clamp(1.5rem,3vw,2.5rem);font-weight:800;letter-spacing:-.04em}.panel{background:#fff;border:1px solid #e2d9cc;border-radius:18px;padding:24px;margin:18px 0;box-shadow:0 12px 30px #2d24140b}.panel h2{margin:5px 0 8px;letter-spacing:-.03em}.panel>p{color:#796f64}.task{display:flex;justify-content:space-between;gap:20px;padding:17px 0;border-top:1px solid #eee8df}.task p{margin:5px 0 0;color:#796f64}.task-meta{display:flex;align-items:center;justify-content:flex-end;gap:9px;flex-wrap:wrap;color:#796f64;font-size:.82rem}.task-meta span{padding:5px 9px;border-radius:99px;background:#f0ebe3}.task-meta button{padding:7px 10px;font-size:.78rem}form{display:flex;gap:10px;flex-wrap:wrap;margin-top:22px}input{min-width:150px;flex:1;padding:12px 13px;border:1px solid #d9cfc2;border-radius:10px;background:#fffcf8;color:#28231e;font:inherit}button{border:0;border-radius:10px;background:#b53b24;color:#fff;padding:12px 17px;font:inherit;font-weight:800;cursor:pointer}button:hover{background:#902e1d}.error{color:#b53b24;font-weight:700}a{color:inherit;text-decoration:none}@media(max-width:650px){.task{display:block}.task-meta{justify-content:flex-start;margin-top:12px}header{display:block}.hero{padding:28px}}",
+ )
+}
+
+fn error_view(error: Option(String)) -> Element(Message) {
+ case error {
+ Some(message) -> html.p([attribute.class("error")], [html.text(message)])
+ None -> element.none()
+ }
+}
+
+fn field(fields: List(#(String, String)), name: String) -> String {
+ list.key_find(fields, name) |> result.unwrap("")
+}
+
+fn current_path() -> String {
+ window.self() |> window.location |> location.pathname
+}
--- /dev/null
+import gleeunit
+
+pub fn main() -> Nil {
+ gleeunit.main()
+}
+
+// gleeunit test functions end in `_test`
+pub fn hello_world_test() {
+ let name = "Joe"
+ let greeting = "Hello, " <> name <> "!"
+
+ assert greeting == "Hello, Joe!"
+}
--- /dev/null
+*.beam
+*.ez
+/build
+erl_crash.dump
--- /dev/null
+# css_to_lustre
+
+[](https://hex.pm/packages/css_to_lustre)
+[](https://css-to-lustre.hexdocs.pm/)
+
+```sh
+gleam add css_to_lustre@1
+```
+```gleam
+import css_to_lustre
+
+pub fn main() -> Nil {
+ // TODO: An example of the project in use
+}
+```
+
+Further documentation can be found at <https://css-to-lustre.hexdocs.pm/>.
+
+## Development
+
+```sh
+gleam run # Run the project
+gleam test # Run the tests
+```
--- /dev/null
+name = "css_to_lustre"
+version = "1.0.0"
+
+# Fill out these fields if you intend to generate HTML documentation or publish
+# your project to the Hex package manager.
+#
+# description = ""
+# licences = ["Apache-2.0"]
+# repository = { type = "github", user = "", repo = "" }
+# links = [{ title = "Website", href = "" }]
+#
+# For a full reference of all the available options, you can have a look at
+# https://gleam.run/writing-gleam/gleam-toml/.
+
+[dependencies]
+gleam_stdlib = ">= 1.0.0 and < 2.0.0"
+in = ">= 1.1.0 and < 2.0.0"
+
+[dev_dependencies]
+gleeunit = ">= 1.0.0 and < 2.0.0"
--- /dev/null
+# Do not manually edit this file, it is managed by Gleam.
+#
+# This file locks the dependency versions used, to make your build
+# deterministic and to prevent unexpected versions from being included
+# in your application.
+#
+# You should check this file into your source control repository.
+
+packages = [
+ { name = "gleam_stdlib", version = "1.0.5", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "CEE5B6C076A85B45F60C585F4316C63EC8B7127C119D5738C3958A9C4D50404E" },
+ { name = "gleeunit", version = "1.11.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "EC31ABA74256AEA531EDF8169931D775BBB384FED0A8A1BDC4DD9354E3E21826" },
+ { name = "in", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "in", source = "hex", outer_checksum = "5339494529936AF83EAA0B8368195DCA9505382836CDED4CD6B0F5F9FA93C2B8" },
+]
+
+[requirements]
+gleam_stdlib = { version = ">= 1.0.0 and < 2.0.0" }
+gleeunit = { version = ">= 1.0.0 and < 2.0.0" }
+in = { version = ">= 1.1.0 and < 2.0.0" }
--- /dev/null
+import gleam/list
+import gleam/option.{type Option, None, Some}
+import gleam/string
+import in
+
+pub fn main() -> Nil {
+ let lines = lines() |> list.map(string.drop_end(_, 1))
+ echo lines
+
+ let pairs = lines |> list.map(line_to_css_pair) |> option.values
+
+ let fmt = echo pairs |> list.map(lustre_format) |> string.concat
+
+ Nil
+}
+
+fn lustre_format(pair: #(String, String)) -> String {
+ "#(" <> pair.0 <> "," <> pair.1 <> "),"
+}
+
+fn line_to_css_pair(line: String) -> Option(#(String, String)) {
+ use #(key, value) <- option.map(
+ line |> string.trim |> string.split_once(":") |> option.from_result,
+ )
+
+ let key = string.trim(key)
+ let value = value |> string.trim |> string.remove_suffix(";")
+
+ #(key, value)
+}
+
+fn lines() -> List(String) {
+ read_lines([])
+}
+
+fn read_lines(acc: List(String)) -> List(String) {
+ case in.read_line() {
+ Ok(line) -> read_lines([line, ..acc])
+ Error(_) -> list.reverse(acc)
+ }
+}
--- /dev/null
+import gleeunit
+
+pub fn main() -> Nil {
+ gleeunit.main()
+}
+
+// gleeunit test functions end in `_test`
+pub fn hello_world_test() {
+ let name = "Joe"
+ let greeting = "Hello, " <> name <> "!"
+
+ assert greeting == "Hello, Joe!"
+}
--- /dev/null
+DATABASE_URL="postgresql://robotics:reallylongamazingpasswordbyyourstruly@taranathan.com:5432/robotics_task_manager"
--- /dev/null
+*.beam
+*.ez
+/build
+erl_crash.dump
--- /dev/null
+# Iron Claw task board
+
+The server is a small Gleam/Wisp JSON API for FRC team 972. The Lustre client
+in `../client` owns the UI and communicates with this server through the typed
+models in `../shared`. It stores users, projects, tasks, and signed sessions in
+PostgreSQL. SQL query modules live in `src/sql.gleam`; the corresponding SQL
+source files in `src/sql/` are kept ready for Squirrel generation.
+
+## Run locally
+
+Create a PostgreSQL database, then export a connection string:
+
+```sh
+export DATABASE_URL=postgresql://postgres:postgres@localhost:5432/iron_claw
+export SESSION_SECRET="replace-this-in-production"
+gleam run
+```
+
+The `db/init.sql` schema is applied automatically at startup. Build the client
+bundle before starting the server:
+
+```sh
+cd ../client
+gleam run -m lustre/dev build
+cp dist/client.js ../server/static/client.js
+```
+
+Then open <http://localhost:3000/register> to create the first account.
+
+Run the test suite with `gleam test`. If the database schema changes, run
+`gleam run -m squirrel` with the same `DATABASE_URL` to regenerate the typed
+query module.
--- /dev/null
+[{"secret_word":"'squire","clues":[{"next":"and the 'squire","previous":"preaching at the","count":4},{"next":"who live in","previous":"parson and the","count":4},{"next":"to be revenged","previous":"'squire and the","count":4},{"next":"shall make you","previous":"a polite country","count":3},{"next":"has not said","previous":"extremity that the","count":3},{"next":"with the parson","previous":"a hearty english","count":2},{"next":"and the whole","previous":"book against the","count":2},{"next":"lath a proper","previous":"other hand there's","count":2},{"next":"or a conjurer","previous":"coquet a country","count":2},{"next":"of shrubs who","previous":"of interrogating the","count":1},{"next":"has said it","previous":"not priest or","count":1},{"next":"of dames' in","previous":"have turned a","count":1},{"next":"said he you","previous":"i told you","count":1}]},{"secret_word":"'your","clues":[{"next":"most humble servant","previous":"'i am sir","count":21},{"next":"most humble servant","previous":"am dear sir","count":12},{"next":"most humble servant","previous":"and in particular","count":2},{"next":"money or your","previous":"the girl gloomily","count":1},{"next":"voice sounds as","previous":"the elder woman","count":1},{"next":"husband' or 'mr","previous":"suddenly call bruce","count":1},{"next":"royal highness is","previous":"replied without reflection","count":1},{"next":"telling me that","previous":"' he said","count":1},{"next":"face is the","previous":"' he observed","count":1},{"next":"leaving us at","previous":"' said wentworth","count":1},{"next":"ladyship i am","previous":"sarcastic smile saying","count":1},{"next":"chancellor judges like","previous":"treachery' wallenstein replies","count":1}]},{"secret_word":"action","clues":[{"next":"to the word","previous":"and suiting the","count":26},{"next":"always pressing then","previous":"the need for","count":1},{"next":"and that at","previous":"he must have","count":1},{"next":"pressed upon him","previous":"some great immediate","count":1},{"next":"all along the","previous":"anything like gettin'","count":1},{"next":"on my stuff","previous":"you to get","count":1},{"next":"those westerners are","previous":"brightest people to","count":1},{"next":"and there couldn't","previous":"reason for prompt","count":1},{"next":"is matured he","previous":"unusual plan of","count":1},{"next":"and i'm going","previous":"get things in","count":1},{"next":"resumed her tete","previous":"performed a kindly","count":1},{"next":"and set the","previous":"swing out get","count":1}]},{"secret_word":"aine","clues":[{"next":"had just gone","previous":"very early risler","count":3},{"next":"come in on","previous":"they see risler","count":3},{"next":"would ask nothing","previous":"sure monsieur risler","count":3},{"next":"by absenting herself","previous":"insult madame risler","count":3},{"next":"and the factory","previous":"talks about risler","count":3},{"next":"of rue des","previous":"jeune and risler","count":3},{"next":"was awakened with","previous":"jeune and risler","count":3},{"next":"sigismond planus is","previous":"jeune and risler","count":3},{"next":"has the appearance","previous":"fromont jeune risler","count":3},{"next":"whom she had","previous":"planus recognize risler","count":3},{"next":"marked the beginning","previous":"jeune et risler","count":1},{"next":"crowned by the","previous":"jeune et risler","count":1},{"next":"enjoyed a notable","previous":"jeune et risler","count":1}]},{"secret_word":"albertinelli","clues":[{"next":"at a time","previous":"by cardinal giulio","count":3},{"next":"a little of","previous":"and of prince","count":3},{"next":"prided himself on","previous":"and whom prince","count":3},{"next":"professor arrighi choulette","previous":"of the prince","count":3},{"next":"della spina she","previous":"to prince eusebio","count":3},{"next":"caressed his beard","previous":"over her prince","count":3},{"next":"and that gentle","previous":"too handsome prince","count":3},{"next":"palace said miss","previous":"come to the","count":3},{"next":"coming out of","previous":"bell and prince","count":3},{"next":"will read to","previous":"punish you prince","count":3},{"next":"gravely you are","previous":"choulette said prince","count":3},{"next":"how do you","previous":"dechartre asked prince","count":3}]},{"secret_word":"aldarondo","clues":[{"next":"charles franks and","previous":"produced by charles","count":10},{"next":"tiffany vergon william","previous":"produced by charles","count":2},{"next":"and the online","previous":"charles franks charles","count":2},{"next":"mary meehan and","previous":"produced by charles","count":1},{"next":"tiffany vergon and","previous":"produced by charles","count":1},{"next":"tiffany vergon robert","previous":"produced by charles","count":1},{"next":"tiffany vergon thomas","previous":"produced by charles","count":1},{"next":"tiffany vergon juliet","previous":"produced by charles","count":1},{"next":"tiffany vergon s","previous":"produced by charles","count":1},{"next":"tiffany vergon charles","previous":"produced by charles","count":1},{"next":"tiffany vergon david","previous":"produced by charles","count":1},{"next":"tiffany vergon jerry","previous":"produced by charles","count":1},{"next":"tiffany vergon eric","previous":"produced by charles","count":1},{"next":"tiffany vergon andy","previous":"produced by charles","count":1},{"next":"tiffany vergon michelle","previous":"produced by charles","count":1},{"next":"tiffany vergon thomas","previous":"prepared by charles","count":1},{"next":"charles franks and","previous":"van dael charles","count":1},{"next":"charles franks and","previous":"tom allen charles","count":1},{"next":"charles franks and","previous":"tonya allen charles","count":1}]},{"secret_word":"arbillot","clues":[{"next":"the notary announcing","previous":"second missive from","count":3},{"next":"replied the justice","previous":"your orders maitre","count":3},{"next":"we will not","previous":"you please maitre","count":3},{"next":"the notary passed","previous":"before their departure","count":3},{"next":"has been speaking","previous":"mother nor maitre","count":3},{"next":"the notary i","previous":"intention to monsieur","count":3},{"next":"and ask him","previous":"morrow to monsieur","count":3},{"next":"and it seems","previous":"confidence in maitre","count":3},{"next":"is drawn up","previous":"inventory explained maitre","count":3},{"next":"which was dignified","previous":"conferring with maitre","count":3},{"next":"and the tax","previous":"clerk seurrot maitre","count":3},{"next":"and a petulant","previous":"bailiff entered maitre","count":3},{"next":"drew up the","previous":"auberive where maitre","count":3}]},{"secret_word":"arcis","clues":[{"next":"beatrix a man","previous":"the member for","count":9},{"next":"cousin betty the","previous":"the member for","count":7},{"next":"a daughter of","previous":"the member for","count":4},{"next":"serizy comtesse de","previous":"the member for","count":4},{"next":"pamiers vidame de","previous":"the member for","count":3},{"next":"falcon jean the","previous":"the member for","count":2},{"next":"ridal fulgence a","previous":"the member for","count":2},{"next":"langeais duc de","previous":"the member for","count":2},{"next":"navarreins duc de","previous":"the member for","count":2},{"next":"milaud lost illusions","previous":"the member for","count":2},{"next":"michu francois the","previous":"the member for","count":2},{"next":"bruel jean francois","previous":"the member for","count":1}]},{"secret_word":"ardea","clues":[{"next":"amused himself by","previous":"and increasing vexation","count":3},{"next":"and on finding","previous":"the engagement of","count":3},{"next":"and in thus","previous":"in selling up","count":3},{"next":"and hafner rendered","previous":"his impatience toward","count":3},{"next":"and others circulated","previous":"her friends hafner","count":3},{"next":"had jested so","previous":"on which imprudent","count":3},{"next":"and he did","previous":"little dealing to","count":3},{"next":"and fanny hafner","previous":"honor of peppino","count":3},{"next":"for the emotion","previous":"fancied she loved","count":3},{"next":"alas i am","previous":"begins to judge","count":3},{"next":"try to see","previous":"cibo pietrapertosa hafner","count":3},{"next":"lanuvium and the","previous":"right stretching to","count":1}]},{"secret_word":"armholes","clues":[{"next":"of his waistcoat","previous":"thumbs in the","count":11},{"next":"of his vest","previous":"thumbs into the","count":6},{"next":"of his waistcoat","previous":"thumbs into the","count":5},{"next":"of his vest","previous":"thumbs in the","count":4},{"next":"of his waistcoat","previous":"by the two","count":1},{"next":"of his vest","previous":"were in the","count":1},{"next":"of his vest","previous":"hands in the","count":1},{"next":"of his vest","previous":"fingers in the","count":1},{"next":"of his waistcoat","previous":"fingers in the","count":1},{"next":"of the waistcoat","previous":"thumbs in the","count":1},{"next":"of his broad","previous":"thumbs in the","count":1},{"next":"of his execrable","previous":"thumbs in the","count":1},{"next":"watched the wife","previous":"thumbs in his","count":1},{"next":"regarding dunham quizzically","previous":"thumbs in his","count":1},{"next":"of his waistcoat","previous":"thumbs within the","count":1},{"next":"of his waistcoat","previous":"comfortably in the","count":1},{"next":"and showed at","previous":"tight about the","count":1},{"next":"of which his","previous":"waistcoat in the","count":1}]},{"secret_word":"astika","clues":[{"next":"parva of the","previous":"section in the","count":24},{"next":"after the snake","previous":"the words of","count":1},{"next":"who saved the","previous":"of jaratkaru that","count":1},{"next":"exactly as it","previous":"this history of","count":1},{"next":"plaudits expressive of","previous":"was granted to","count":1},{"next":"born of jaratkaru","previous":"mind the famous","count":1},{"next":"exceedingly gratified for","previous":"home the wise","count":1},{"next":"shall have his","previous":"such mention of","count":1},{"next":"and asked him","previous":"much pleased with","count":1},{"next":"that increaseth virtue","previous":"holy history of","count":1},{"next":"also be gratified","previous":"safe let this","count":1},{"next":"artiman and sunitha","previous":"call to mind","count":1}]},{"secret_word":"auberive","clues":[{"next":"there will be","previous":"the gentlemen of","count":3},{"next":"at the epoch","previous":"the monks of","count":3},{"next":"people with whom","previous":"the notables of","count":3},{"next":"through the woods","previous":"their way to","count":3},{"next":"to notify the","previous":"am going to","count":3},{"next":"gentry with whom","previous":"those of the","count":3},{"next":"and ask the","previous":"go over to","count":3},{"next":"where maitre arbillot","previous":"accompanied claudet to","count":3},{"next":"side along the","previous":"shortly on the","count":3},{"next":"and had deliberately","previous":"distinguished visitors from","count":3},{"next":"society is following","previous":"reine listening the","count":3},{"next":"road and the","previous":"praslay by the","count":3},{"next":"notary's first letter","previous":"contained in the","count":2}]},{"secret_word":"author's","clues":[{"next":"ideas before making","previous":"to sample the","count":57},{"next":"powers to be","previous":"proof of the","count":2},{"next":"nature but that","previous":"or at least","count":2},{"next":"having but you","previous":"much worth the","count":2},{"next":"life assail toil","previous":"what ills the","count":2},{"next":"visage is but","previous":"frontispiece of an","count":2},{"next":"jury to determine","previous":"one of the","count":1},{"next":"school exercises we","previous":"rest of the","count":1},{"next":"copy with his","previous":"pray accept this","count":1},{"next":"friendly esteem is","previous":"mark of the","count":1},{"next":"merits they are","previous":"con of an","count":1},{"next":"name and the","previous":"celebrity of the","count":1}]},{"secret_word":"bagg","clues":[{"next":"says it was","previous":"the man laughed","count":3},{"next":"rushing in with","previous":"a dart at","count":3},{"next":"got home alive","previous":"is well that","count":3},{"next":"i have no","previous":"should do without","count":3},{"next":"though without it","previous":"nor more does","count":3},{"next":"and left the","previous":"trouble ' said","count":3},{"next":"and staring him","previous":"close up to","count":3},{"next":"'and in that","previous":"sir ' said","count":3},{"next":"and drawing himself","previous":"sir ' says","count":3},{"next":"and forthwith seized","previous":"sir ' says","count":3},{"next":"thinks at least","previous":"immense tall fellow","count":3},{"next":"says he had","previous":"grappled each other","count":3},{"next":"is a left","previous":"fellow's right eye","count":2}]},{"secret_word":"balzajette","clues":[{"next":"uneasiness for his","previous":"of the lamps","count":3},{"next":"and his return","previous":"his departure with","count":3},{"next":"talk for if","previous":"only to let","count":3},{"next":"or to the","previous":"to phillis to","count":3},{"next":"spoke of the","previous":"that moment monsieur","count":3},{"next":"replied i am","previous":"that saniel said","count":3},{"next":"a few hours","previous":"came herewith monsieur","count":3},{"next":"he was in","previous":"been to monsieur","count":3},{"next":"said who never","previous":"we have decided","count":3},{"next":"said who took","previous":"let us return","count":3},{"next":"proposed asking for","previous":"setting sun faded","count":3},{"next":"hailed a passing","previous":"des petits champs","count":3}]},{"secret_word":"barratt","clues":[{"next":"the proprietor of","previous":"the fact of","count":3},{"next":"to a shocking","previous":"of this wretched","count":3},{"next":"had attempted to","previous":"in the prison","count":3},{"next":"had practised the","previous":"to arise that","count":3},{"next":"had met her","previous":"city the monster","count":3},{"next":"and seconded by","previous":"her made by","count":3},{"next":"into such written","previous":"means of entrapping","count":3},{"next":"though perhaps it","previous":"wicked collusion with","count":3},{"next":"and accordingly much","previous":"attempted by this","count":3},{"next":"but now its","previous":"run strongly against","count":3},{"next":"did not revive","previous":"sufficiently strange that","count":3},{"next":"came to suspect","previous":"disguise his purposes","count":3},{"next":"had that been","previous":"emanating from this","count":3}]},{"secret_word":"beatrix","clues":[{"next":"a man of","previous":"member for arcis","count":9},{"next":"lost illusions a","previous":"mademoiselle felicite des","count":5},{"next":"the peasantry chesnel","previous":"the old maid","count":2},{"next":"ronceret madame du","previous":"the old maid","count":2},{"next":"leroi pierre the","previous":"the gondreville mystery","count":2},{"next":"the unconscious humorists","previous":"a courtesan's life","count":2},{"next":"gaudissart ii scherbelloff","previous":"du or duronceret","count":2},{"next":"in which she","previous":"out his novel","count":1},{"next":"and the first","previous":"last part of","count":1},{"next":"trotter a daughter","previous":"mother's name was","count":1},{"next":"ronceret madame du","previous":"antiquities companion piece","count":1},{"next":"the gondreville mystery","previous":"simeuse admiral de","count":1},{"next":"and modeste mignon","previous":"etude de femme","count":1}]},{"secret_word":"bebee","clues":[{"next":"if you want","previous":"are going mad","count":3},{"next":"screamed the girl","previous":"a pretty affair","count":3},{"next":"say that she","previous":"had heard her","count":3},{"next":"'twas by that","previous":"it romanly already","count":3},{"next":"isn't he poisoned","previous":"if he doesn't","count":3},{"next":"leave the fellow","previous":"you are mad","count":3},{"next":"let's leave him","previous":"soon be gone","count":3},{"next":"as much or","previous":"say so again","count":3},{"next":"' says the","previous":"'come with me","count":3},{"next":"ha ha look","previous":"but look there","count":2},{"next":"here's the door","previous":"your here there","count":2},{"next":"and becoming alarmed","previous":"sleep missed her","count":2}]},{"secret_word":"bigelow","clues":[{"next":"paine mt bg","previous":"biography by albert","count":11},{"next":"paine mt lt","previous":"v by albert","count":10},{"next":"house bar was","previous":"and round the","count":1},{"next":"house on the","previous":"in at the","count":1},{"next":"house to the","previous":"way from the","count":1},{"next":"and nuttall are","previous":"as long as","count":1},{"next":"house the previous","previous":"me at the","count":1},{"next":"house to make","previous":"front of the","count":1},{"next":"house for choice","previous":"main street the","count":1},{"next":"house office that","previous":"walked into the","count":1},{"next":"house and frank","previous":"choose between the","count":1},{"next":"house are no","previous":"beds in the","count":1},{"next":"to see the","previous":"graham and will","count":1}]},{"secret_word":"bohemia","clues":[{"next":"a man of","previous":"a prince of","count":17},{"next":"letters of two","previous":"a prince of","count":12},{"next":"hungary and lombardy","previous":"the king of","count":1},{"next":"which is the","previous":"the odor of","count":1},{"next":"was an utterly","previous":"for whom this","count":1},{"next":"and o how","previous":"a peep into","count":1},{"next":"and a great","previous":"he was from","count":1},{"next":"and seen prague","previous":"had travelled into","count":1},{"next":"who married and","previous":"bridegroom of parisian","count":1},{"next":"and poisoning my","previous":"slang of parisian","count":1},{"next":"protestantism was stifled","previous":"austria bavaria and","count":1},{"next":"their mother country","previous":"tribes who call","count":1},{"next":"bolingbroke bonn boston","previous":"bismarck blackwood boehm","count":1}]},{"secret_word":"boleslas","clues":[{"next":"had scarcely touched","previous":"to the adventure","count":3},{"next":"gorka how would","previous":"her mother and","count":3},{"next":"to forget his","previous":"so striking caused","count":3},{"next":"taking her hand","previous":"my word replied","count":3},{"next":"and that will","previous":"promise too said","count":3},{"next":"with the bitterest","previous":"happy couple tortured","count":3},{"next":"would have been","previous":"left and undoubtedly","count":3},{"next":"marinski graboski i","previous":"something to drink","count":3},{"next":"distinguished an intention","previous":"eagerness in which","count":3},{"next":"was so proud","previous":"energy of which","count":3},{"next":"suffered one of","previous":"connected with him","count":3},{"next":"gorka's madness which","previous":"the story of","count":2}]},{"secret_word":"bonzes","clues":[{"next":"of the temple","previous":"of the head","count":4},{"next":"and above all","previous":"up by the","count":4},{"next":"through this long","previous":"while following the","count":4},{"next":"officiate to the","previous":"temple where the","count":4},{"next":"sit immovable embodiments","previous":"open temple the","count":4},{"next":"which is situated","previous":"our friends the","count":4},{"next":"notwithstanding an unctuousness","previous":"our friends the","count":4},{"next":"in yellow robes","previous":"only associates were","count":1},{"next":"who hide their","previous":"to the vilest","count":1},{"next":"talapoins and such","previous":"manner of buddhists","count":1},{"next":"talapoins and suchlike","previous":"manner of buddists","count":1},{"next":"too just joking","previous":"that's it and","count":1}]},{"secret_word":"bookmarks","clues":[{"next":"or pointers at","previous":"short list of","count":57},{"next":"is an attested","previous":"by way of","count":1},{"next":"from the entire","previous":"lair etext editor's","count":1},{"next":"from the complete","previous":"lair etext editor's","count":1},{"next":"a heart break","previous":"etext editor s","count":1}]},{"secret_word":"brigard","clues":[{"next":"that everything that","previous":"and respect for","count":3},{"next":"whose principles forbade","previous":"the count de","count":3},{"next":"who came to","previous":"he wished for","count":3},{"next":"said for i","previous":"to meet you","count":3},{"next":"turned to crozat","previous":"were both gone","count":3},{"next":"the same man","previous":"appearance of old","count":3},{"next":"who received him","previous":"shook hands with","count":3},{"next":"take seriously an","previous":"pained to see","count":3},{"next":"and saniel was","previous":"all gone but","count":2},{"next":"and saniel's old","previous":"men who accompanied","count":2},{"next":"concluded the discussion","previous":"at the end","count":2},{"next":"and advised saniel","previous":"crozat concurred with","count":2}]},{"secret_word":"buxieres","clues":[{"next":"thought she would","previous":"a moment de","count":3},{"next":"threw his arms","previous":"when julien de","count":3},{"next":"provoked at the","previous":"it insisted de","count":3},{"next":"i was just","previous":"you monsieur de","count":3},{"next":"observed with pain","previous":"alone julien de","count":3},{"next":"send for the","previous":"night monsieur de","count":3},{"next":"matters might in","previous":"perhaps monsieur de","count":3},{"next":"first of all","previous":"reasons monsieur de","count":3},{"next":"that reine wished","previous":"message to de","count":3},{"next":"do you know","previous":"resumed monsieur de","count":3},{"next":"walked beside reine","previous":"tacit permission de","count":3}]},{"secret_word":"caffie","clues":[{"next":"is pronounced madame","previous":"the name of","count":3},{"next":"he had not","previous":"the death of","count":3},{"next":"raised the lamp","previous":"the moment when","count":3},{"next":"and florentin and","previous":"the affair of","count":3},{"next":"exasperated her she","previous":"the assassination of","count":3},{"next":"and in the","previous":"to him of","count":3},{"next":"who until then","previous":"not curious that","count":3},{"next":"lying in his","previous":"if he saw","count":3},{"next":"and taking enough","previous":"idea of strangling","count":3},{"next":"by sending them","previous":"bills taken from","count":3},{"next":"was assassinated at","previous":"five o'clock that","count":2},{"next":"and balzajette's explanations","previous":"her questions regarding","count":2}]},{"secret_word":"camier","clues":[{"next":"whose ruddy face","previous":"was monsieur de","count":3},{"next":"drove with the","previous":"which monsieur de","count":3},{"next":"with the sagacity","previous":"said monsieur de","count":3},{"next":"whose caps flashed","previous":"from monsieur de","count":3},{"next":"attributed it to","previous":"like monsieur de","count":3},{"next":"said the baron","previous":"you remain here","count":3},{"next":"as he parted","previous":"exclaimed monsieur de","count":3},{"next":"suddenly as he","previous":"exclaimed monsieur de","count":3},{"next":"who has but","previous":"scandalized monsieur de","count":3},{"next":"who were cognisant","previous":"and madame r","count":1},{"next":"on the lacy","previous":"of a r","count":1},{"next":"and the duc","previous":"friends madame r","count":1}]},{"secret_word":"camors","clues":[{"next":"slightly moist rolling","previous":"the eyes of","count":3},{"next":"turned on the","previous":"the head of","count":3},{"next":"did not admit","previous":"the health of","count":3},{"next":"loudly raised then","previous":"the voice of","count":3},{"next":"yielding to considerations","previous":"the comtesse de","count":3},{"next":"refused hesitated made","previous":"men love them","count":3},{"next":"and renee mauperin","previous":"were madame de","count":3},{"next":"did not descend","previous":"end of september","count":3},{"next":"white with foam","previous":"favorite mare of","count":3},{"next":"by octave feuillet","previous":"widger monsieur de","count":2},{"next":"refused hesitated made","previous":"but in battalions","count":1}]},{"secret_word":"campvallon","clues":[{"next":"was strolling beside","previous":"the marquise de","count":3},{"next":"against the life","previous":"of madame de","count":3},{"next":"who soon came","previous":"for madame de","count":3},{"next":"and he attributed","previous":"to madame de","count":3},{"next":"the sweetest period","previous":"to madame de","count":3},{"next":"the goal of","previous":"to madame de","count":3},{"next":"on entering the","previous":"after madame de","count":3},{"next":"had herself furnished","previous":"provoke madame de","count":3},{"next":"experienced a serious","previous":"winter madame de","count":3},{"next":"which could be","previous":"twelve leagues from","count":3},{"next":"heard some one","previous":"o'clock madame de","count":2}]},{"secret_word":"canadian","clues":[{"next":"institute for historical","previous":"available by the","count":19},{"next":"enterprise thinks that","previous":"the russian and","count":1},{"next":"artist who occupied","previous":"name of the","count":1},{"next":"mica mining company","previous":"was headed 'the","count":1},{"next":"mica mine on","previous":"saw the name","count":1},{"next":"mica mine and","previous":"will call the","count":1},{"next":"mining company he","previous":"regard to the","count":1},{"next":"magnates who happened","previous":"got from some","count":1},{"next":"opening that might","previous":"notion of a","count":1},{"next":"mica mining company","previous":"referring to the","count":1},{"next":"horse that was","previous":"natty little french","count":1},{"next":"express pulled by","previous":"junction when the","count":1}]},{"secret_word":"castagna","clues":[{"next":"with his long","previous":"of the palais","count":3},{"next":"that he had","previous":"of the palais","count":3},{"next":"that historical garden","previous":"of the palais","count":3},{"next":"was to realize","previous":"at the palais","count":3},{"next":"she had been","previous":"to the palais","count":3},{"next":"family in its","previous":"came upon the","count":3},{"next":"playing on their","previous":"said to cardinal","count":3},{"next":"where they are","previous":"from the palais","count":3},{"next":"to a joint","previous":"just sold palais","count":3},{"next":"with her hafner","previous":"visited the palais","count":3},{"next":"apartments and they","previous":"magnificence of the","count":3},{"next":"paolo uccello and","previous":"pollajuoli andrea del","count":3}]},{"secret_word":"cayrol","clues":[{"next":"despite jeanne who","previous":"and advanced toward","count":3},{"next":"in a travelling","previous":"the same moment","count":3},{"next":"had done it","previous":"the idea that","count":3},{"next":"from the outside","previous":"the voice of","count":3},{"next":"falling into an","previous":"most miserable sobbed","count":3},{"next":"they went down","previous":"had received from","count":3},{"next":"serge thought he","previous":"had gone to","count":3},{"next":"a heavy step","previous":"had indeed evoked","count":3},{"next":"to prevent his","previous":"one word to","count":3},{"next":"when he comes","previous":"i say to","count":3},{"next":"entering his wife's","previous":"fancy she saw","count":2}]},{"secret_word":"center","clues":[{"next":"of the room","previous":"stood in the","count":20},{"next":"of the room","previous":"table in the","count":17},{"next":"aisle and look","previous":"in the house","count":1},{"next":"of festivities that","previous":"he was the","count":1},{"next":"of the vance","previous":"to be the","count":1},{"next":"of the room","previous":"enter from the","count":1},{"next":"any better'n he","previous":"have hit exact","count":1},{"next":"and a piano","previous":"table in the","count":1},{"next":"about which for","previous":"locust was the","count":1},{"next":"of the floor","previous":"upward from the","count":1},{"next":"of his forehead","previous":"veins in the","count":1},{"next":"of which a","previous":"desks in the","count":1},{"next":"of the flickering","previous":"leader in the","count":1},{"next":"bespeaking a new","previous":"balls in each","count":1}]},{"secret_word":"cercle","clues":[{"next":"has just had","previous":"of the grand","count":3},{"next":"gave serge a","previous":"to the grand","count":3},{"next":"where we go","previous":"we have the","count":3},{"next":"at the hour","previous":"voice at the","count":3},{"next":"with their glaring","previous":"club the grand","count":3},{"next":"which is not","previous":"shooting and the","count":3},{"next":"de la chasse","previous":"note to the","count":3},{"next":"de la chasse","previous":"hastened to the","count":3},{"next":"de la rue","previous":"altercation at the","count":3},{"next":"d or n","previous":"v nus aucun","count":1},{"next":"blanch tre autour","previous":"et porte un","count":1},{"next":"de famille applaudit","previous":"l'enfant parait le","count":1},{"next":"militaire in paris","previous":"vasselot at the","count":1}]},{"secret_word":"cernay","clues":[{"next":"became unsettled and","previous":"the weather at","count":3},{"next":"is a vast","previous":"the chateau of","count":3},{"next":"where the marriage","previous":"to morrow for","count":3},{"next":"gallop there to","previous":"made mademoiselle de","count":3},{"next":"that terrible night","previous":"had conceived at","count":3},{"next":"not as in","previous":"settled themselves at","count":3},{"next":"simply tendering him","previous":"said mademoiselle de","count":3},{"next":"was really happy","previous":"sovereign lord of","count":3},{"next":"seizing the hands","previous":"cried mademoiselle de","count":3},{"next":"clinging to him","previous":"cried mademoiselle de","count":3},{"next":"she was surprised","previous":"desvarennes arrived at","count":3}]},{"secret_word":"chapron","clues":[{"next":"fixed upon maitland","previous":"the eyes of","count":3},{"next":"with all the","previous":"time of aretin","count":3},{"next":"might have been","previous":"between gorka and","count":3},{"next":"of the two","previous":"certainly informed by","count":3},{"next":"apologize for his","previous":"words and monsieur","count":3},{"next":"stirred within her","previous":"blood of colonel","count":3},{"next":"prevented you from","previous":"those of florent","count":3},{"next":"and she quarrels","previous":"husband and florent","count":3},{"next":"than to arrange","previous":"render our brave","count":3},{"next":"always faithful was","previous":"bed while florent","count":3},{"next":"should not be","previous":"gorka to monsieur","count":3}]},{"secret_word":"chapter","clues":[{"next":"chapter chapter chapter","previous":"chapter chapter chapter","count":153},{"next":"covers for fourteen","previous":"of the preceding","count":1},{"next":"could have precisely","previous":"in the preceding","count":1},{"next":"his interpreter did","previous":"to write this","count":1},{"next":"ii metz with","previous":"part ii lorraine","count":1},{"next":"with these words","previous":"history begins this","count":1},{"next":"to an end","previous":"brought this short","count":1},{"next":"giving the adventures","previous":"coming to the","count":1},{"next":"of the second","previous":"us read another","count":1},{"next":"xii precy sur","previous":"forests of chantilly","count":1},{"next":"xvii the stuffed","previous":"spring in charleville","count":1},{"next":"i the traveller","previous":"hut at bar","count":1}]},{"secret_word":"charnot","clues":[{"next":"i think we","previous":"by saying monsieur","count":3},{"next":"how sorry i","previous":"to tell monsieur","count":3},{"next":"will never change","previous":"that mademoiselle jeanne","count":3},{"next":"said he i","previous":"my dear monsieur","count":3},{"next":"of the institute","previous":"i am monsieur","count":3},{"next":"bringing his pretty","previous":"ordinary to mademoiselle","count":3},{"next":"is aware of","previous":"confess that mademoiselle","count":3},{"next":"can go and","previous":"room where monsieur","count":3},{"next":"can you guess","previous":"talk my dear","count":3},{"next":"upset by the","previous":"add that mademoiselle","count":3},{"next":"have left paris","previous":"monsieur and mademoiselle","count":3},{"next":"i'm convinced of","previous":"dowry he's after","count":2}]},{"secret_word":"chebe","clues":[{"next":"appeared little monsieur","previous":"him and monsieur","count":3},{"next":"and delobelle his","previous":"two faithful borrowers","count":3},{"next":"and desiree delobelle","previous":"days of little","count":3},{"next":"the anger of","previous":"against his little","count":3},{"next":"a grudge because","previous":"they bear little","count":3},{"next":"sobbing in the","previous":"could hear madame","count":3},{"next":"i am selling","previous":"not moving monsieur","count":3},{"next":"flushed and breathless","previous":"appeared little monsieur","count":3},{"next":"sidonie risler had","previous":"dreams of little","count":3},{"next":"in his long","previous":"moments earlier monsieur","count":3},{"next":"of the old","previous":"girl the little","count":3},{"next":"was fully convinced","previous":"eloquent that monsieur","count":3}]},{"secret_word":"chorche","clues":[{"next":"is this true","previous":"this true madame","count":3},{"next":"would pass her","previous":"his dear madame","count":3},{"next":"bending over some","previous":"his dear madame","count":3},{"next":"risler advised her","previous":"his dear madame","count":3},{"next":"the wife of","previous":"he called madame","count":3},{"next":"you could not","previous":"but you madame","count":3},{"next":"was always there","previous":"thought of madame","count":3},{"next":"who was drawing","previous":"master of monsieur","count":3},{"next":"muttered poor sigismond","previous":"monsieur chorche monsieur","count":3},{"next":"the only two","previous":"frantz and madame","count":3},{"next":"walking in front","previous":"risler and madame","count":3}]},{"secret_word":"choulette","clues":[{"next":"is right too","previous":"and that brute","count":3},{"next":"lighting his pipe","previous":"in a box","count":3},{"next":"appeared with the","previous":"at table when","count":3},{"next":"if i were","previous":"be mine monsieur","count":3},{"next":"which he understood","previous":"ardent praises of","count":3},{"next":"may come without","previous":"possible too that","count":3},{"next":"is not a","previous":"insist that monsieur","count":3},{"next":"the flame of","previous":"bald cranium of","count":3},{"next":"has written me","previous":"martin darling monsieur","count":3},{"next":"for all our","previous":"marmet for monsieur","count":3}]},{"secret_word":"chrysantheme","clues":[{"next":"always eagerly attentive","previous":"the white mats","count":3},{"next":"has left them","previous":"the summer blooms","count":3},{"next":"oyouki and i","previous":"the town yves","count":3},{"next":"what will they","previous":"of yves and","count":3},{"next":"lights a lantern","previous":"for yves san","count":3},{"next":"yves is in","previous":"with regard to","count":3},{"next":"it is indeed","previous":"to yves about","count":3},{"next":"which though translating","previous":"her better than","count":3},{"next":"i listen with","previous":"between yves and","count":3},{"next":"was very charming","previous":"sweet and little","count":3},{"next":"madame prune her","previous":"helping hand yves","count":3},{"next":"with her japanese","previous":"vases arranged by","count":3}]},{"secret_word":"cibo","clues":[{"next":"the doctor declared","previous":"the care of","count":3},{"next":"who had brought","previous":"for us concluded","count":3},{"next":"answered for the","previous":"a stroll but","count":3},{"next":"pietrapertosa hafner ardea","previous":"in vain did","count":3},{"next":"and pietrapertosa who","previous":"he continued addressing","count":3},{"next":"with an eagerness","previous":"that time replied","count":3},{"next":"as a paddock","previous":"had formerly served","count":3},{"next":"i will guarantee","previous":"is well began","count":3},{"next":"had ceased since","previous":"if pietrapertosa and","count":3},{"next":"and pietrapertosa such","previous":"those of montfanon","count":3},{"next":"and of pietrapertosa","previous":"determine that of","count":3}]},{"secret_word":"cicalas","clues":[{"next":"accompanies them in","previous":"of crickets and","count":4},{"next":"are mute odors","previous":"old roof the","count":4},{"next":"that seems to","previous":"song of the","count":4},{"next":"ceaseless strident and","previous":"song of the","count":4},{"next":"on the roof","previous":"hour while the","count":4},{"next":"which filled the","previous":"sound of the","count":4},{"next":"make themselves heard","previous":"cocks and the","count":4},{"next":"continue their sonorous","previous":"the distance the","count":3},{"next":"around us keep","previous":"to say the","count":3},{"next":"i mount to","previous":"noise of the","count":3},{"next":"then be mute","previous":"and halcyons and","count":1},{"next":"was pleasant to","previous":"cry of the","count":1}]},{"secret_word":"claudet","clues":[{"next":"had undertaken for","previous":"the district which","count":3},{"next":"the ancient minister","previous":"of medicine and","count":3},{"next":"stoops to pick","previous":"at this moment","count":3},{"next":"and secondly to","previous":"to hear about","count":3},{"next":"his share in","previous":"not help envying","count":3},{"next":"who would at","previous":"have driven away","count":3},{"next":"had infused into","previous":"much living heat","count":3},{"next":"was cured opportunely","previous":"marriage the minister","count":3},{"next":"is on duty","previous":"approach of night","count":3},{"next":"since she is","previous":"must have loved","count":3},{"next":"is dead and","previous":"particularly oracular air","count":3},{"next":"she could not","previous":"afterthought in renouncing","count":3},{"next":"sejournant volunteer in","previous":"decease of germain","count":3}]},{"secret_word":"clifton","clues":[{"next":"london grosvenor street","previous":"ives to louisa","count":22},{"next":"of whom his","previous":"he would silence","count":1},{"next":"and i now","previous":"only of coke","count":1},{"next":"hill for the","previous":"were sent to","count":1},{"next":"to be a","previous":"now know coke","count":1},{"next":"be not there","previous":"direction 'if miss","count":1},{"next":"as to a","previous":"added by louisa","count":1},{"next":"to guy fairfax","previous":"letter cxxvii coke","count":1},{"next":"to guy fairfax","previous":"letter cxxv coke","count":1},{"next":"to guy fairfax","previous":"letter cxxix coke","count":1},{"next":"of consumption before","previous":"privation died at","count":1},{"next":"oh my friend","previous":"ives to louisa","count":1}]},{"secret_word":"contessina","clues":[{"next":"in her pretty","previous":"she called the","count":3},{"next":"busy at that","previous":"visit to the","count":3},{"next":"replied dorsenne if","previous":"you are here","count":3},{"next":"said he the","previous":"you are right","count":3},{"next":"said he when","previous":"you come opportunely","count":3},{"next":"still doubted and","previous":"signs that the","count":3},{"next":"with a glance","previous":"again toward the","count":3},{"next":"and you are","previous":"again vexed you","count":3},{"next":"he was singularly","previous":"mission to the","count":3},{"next":"was the victim","previous":"maud's husband the","count":2},{"next":"burst out laughing","previous":"chair and the","count":1},{"next":"emilia viviani who","previous":"noble lady the","count":1}]},{"secret_word":"context","clues":[{"next":"of any of","previous":"read the entire","count":17},{"next":"of the quotations","previous":"location and complete","count":5},{"next":"with a concentration","previous":"and assimilated their","count":1},{"next":"glowing with a","previous":"all the noble","count":1},{"next":"das man vom","previous":"ever had a","count":1},{"next":"i have no","previous":"occurred in the","count":1},{"next":"in society and","previous":"things from his","count":1},{"next":"suggests that he","previous":"did but the","count":1},{"next":"but full for","previous":"torn from their","count":1},{"next":"if they had","previous":"broken from their","count":1},{"next":"with a melancholy","previous":"expression in another","count":1},{"next":"with a given","previous":"social and political","count":1}]},{"secret_word":"coppee","clues":[{"next":"with a preface","previous":"youth by francois","count":3},{"next":"he woke up","previous":"the reputation of","count":3},{"next":"can be seen","previous":"of an artist","count":3},{"next":"francois edouard joachim","previous":"french academy francois","count":3},{"next":"is parisian by","previous":"to enjoy for","count":3},{"next":"sticks rigorously to","previous":"which is tedious","count":3},{"next":"belongs to the","previous":"we contemplate him","count":3},{"next":"most fully possesses","previous":"will deny that","count":3},{"next":"became as before","previous":"juvenile sarah bernhardt","count":3},{"next":"was born in","previous":"francois edouard joachim","count":3},{"next":"break in his","previous":"youth by francois","count":1},{"next":"but by the","previous":"contes by francois","count":1}]},{"secret_word":"corandeuil","clues":[{"next":"stretched out in","previous":"was mademoiselle de","count":3},{"next":"asked me for","previous":"which mademoiselle de","count":3},{"next":"as she laid","previous":"said mademoiselle de","count":3},{"next":"tried to raise","previous":"while mademoiselle de","count":3},{"next":"aroused from her","previous":"she mademoiselle de","count":3},{"next":"noticing for the","previous":"asked mademoiselle de","count":3},{"next":"a second time","previous":"exclaimed mademoiselle de","count":3},{"next":"in a falsetto","previous":"exclaimed mademoiselle de","count":3},{"next":"who thought that","previous":"exclaimed mademoiselle de","count":3},{"next":"into a second","previous":"metamorphosing mademoiselle de","count":3}]},{"secret_word":"cormier","clues":[{"next":"and nougarede and","previous":"of phillis madame","count":3},{"next":"against whom so","previous":"was not florentin","count":3},{"next":"fell into a","previous":"in prison madame","count":3},{"next":"opened the door","previous":"his ring madame","count":3},{"next":"said with emotion","previous":"her own madame","count":3},{"next":"spoke of it","previous":"than once madame","count":3},{"next":"and phillis would","previous":"emotion of madame","count":3},{"next":"was in her","previous":"proved that madame","count":3},{"next":"in whom at","previous":"do for madame","count":3},{"next":"interrupted by going","previous":"silences that madame","count":3},{"next":"with more decision","previous":"reproach said madame","count":3}]},{"secret_word":"corners","clues":[{"next":"of her eyes","previous":"out of the","count":28},{"next":"of the rug","previous":"and catching the","count":1},{"next":"east of the","previous":"of those fine","count":1},{"next":"of the earth","previous":"for the four","count":1},{"next":"of which were","previous":"with writing the","count":1},{"next":"with my notions","previous":"life squares nay","count":1},{"next":"of the pack","previous":"under the four","count":1},{"next":"searching the faces","previous":"shadows in the","count":1},{"next":"of the market","previous":"either at the","count":1},{"next":"and pits of","previous":"flashing it into","count":1},{"next":"the rash couples","previous":"got tangled in","count":1},{"next":"of the mouth","previous":"extended below the","count":1},{"next":"of the earth","previous":"errant explore the","count":1}]},{"secret_word":"courtesan","clues":[{"next":"s life the","previous":"scenes from a","count":42},{"next":"s life a","previous":"scenes from a","count":11},{"next":"s life another","previous":"scenes from a","count":10},{"next":"s life honorine","previous":"scenes from a","count":9},{"next":"s life letters","previous":"scenes from a","count":8},{"next":"s life ursule","previous":"scenes from a","count":4},{"next":"she could be","previous":"the most fascinating","count":2},{"next":"opening one of","previous":"woman said the","count":2},{"next":"who discovered cataline's","previous":"it was a","count":2},{"next":"s life berthier","previous":"scenes from a","count":2},{"next":"and had succeeded","previous":"of a petty","count":1},{"next":"cursing mercenary love","previous":"as the unhappy","count":1},{"next":"invited by titian","previous":"as the handsomest","count":1},{"next":"than a queen","previous":"more like a","count":1},{"next":"ladies did not","previous":"against all the","count":1},{"next":"after paying the","previous":"would of some","count":1}]},{"secret_word":"courtesan's","clues":[{"next":"life a daughter","previous":"scenes from a","count":5},{"next":"life the firm","previous":"scenes from a","count":4},{"next":"life another study","previous":"scenes from a","count":4},{"next":"life honorine the","previous":"scenes from a","count":4},{"next":"life the country","previous":"scenes from a","count":3},{"next":"life beatrix the","previous":"scenes from a","count":3},{"next":"temperament that prevented","previous":"her inability her","count":2},{"next":"life the government","previous":"scenes from a","count":2},{"next":"life cousin pons","previous":"scenes from a","count":2},{"next":"life letters of","previous":"scenes from a","count":2},{"next":"life nathan madame","previous":"scenes from a","count":1},{"next":"life ursule mirouet","previous":"scenes from a","count":1},{"next":"life tillet ferdinand","previous":"scenes from a","count":1},{"next":"life modeste mignon","previous":"scenes from a","count":1}]},{"secret_word":"coverley","clues":[{"next":"he was in","previous":"sir humphrey de","count":7},{"next":"was the tamest","previous":"sir roger de","count":6},{"next":"and sir andrew","previous":"sir roger de","count":5},{"next":"to pass away","previous":"sir roger de","count":5},{"next":"applied to a","previous":"of roger of","count":2},{"next":"a whimsical country","previous":"sir roger de","count":2},{"next":"is said to","previous":"sir roger de","count":2},{"next":"papers was twice","previous":"sir roger de","count":2},{"next":"'against evil speaking","previous":"sir roger de","count":2},{"next":"and his christmas","previous":"sir roger de","count":1},{"next":"was known commenced","previous":"sir roger de","count":1},{"next":"because it happened","previous":"sir roger de","count":1},{"next":"papers becomes positively","previous":"sir roger de","count":1}]},{"secret_word":"cymier","clues":[{"next":"on a low","previous":"and gerard de","count":3},{"next":"secretary of embassy","previous":"the vicomte de","count":3},{"next":"seems to have","previous":"of monsieur de","count":3},{"next":"or like marien","previous":"all were like","count":3},{"next":"whom possibly you","previous":"a monsieur de","count":3},{"next":"or even talbrun","previous":"with wermant or","count":3},{"next":"was discouraged by","previous":"that gerard de","count":3},{"next":"whom she loves","previous":"not monsieur de","count":3},{"next":"behave in these","previous":"would gerard de","count":3},{"next":"has written a","previous":"angrily monsieur de","count":3}]},{"secret_word":"dammauville","clues":[{"next":"motionless and pink","previous":"his chair madame","count":3},{"next":"say to her","previous":"he heard madame","count":3},{"next":"might have told","previous":"he dreaded madame","count":3},{"next":"when the night","previous":"to see madame","count":3},{"next":"did after the","previous":"her what madame","count":3},{"next":"had said nothing","previous":"proved that madame","count":3},{"next":"he was so","previous":"death of madame","count":3},{"next":"pulled the bellcord","previous":"same time madame","count":3},{"next":"caffie and florentin","previous":"dwelt on madame","count":3},{"next":"nougarede had summoned","previous":"default of madame","count":3},{"next":"the only hope","previous":"intervention of madame","count":3},{"next":"in the night","previous":"resuscitated by madame","count":3}]},{"secret_word":"dechartre","clues":[{"next":"had modelled the","previous":"a medallion wherein","count":3},{"next":"came into the","previous":"at this instant","count":3},{"next":"and miss bell","previous":"her box only","count":3},{"next":"who designed this","previous":"it is monsieur","count":3},{"next":"and paul vence","previous":"out when jacques","count":3},{"next":"through the door","previous":"soul had followed","count":3},{"next":"who was looking","previous":"she said to","count":3},{"next":"i hope you","previous":"she turned toward","count":3},{"next":"is full of","previous":"mind of monsieur","count":3},{"next":"my friend do","previous":"pointed toward neuilly","count":3},{"next":"with his hand","previous":"cloak she saw","count":3},{"next":"of the girl","previous":"profile sketch by","count":3}]},{"secret_word":"delobelle","clues":[{"next":"in his stovepipe","previous":"and the illustrious","count":3},{"next":"at a cafe","previous":"of the illustrious","count":3},{"next":"appeared to his","previous":"picture the illustrious","count":3},{"next":"summoned all her","previous":"was flying desire","count":3},{"next":"obstinately declined to","previous":"but the woman","count":3},{"next":"and lectured her","previous":"at the woman","count":3},{"next":"had been making","previous":"time past mamma","count":3},{"next":"her old delobelle","previous":"she thought of","count":3},{"next":"who was asleep","previous":"because of madame","count":3},{"next":"his first moment","previous":"borrowers chebe and","count":3},{"next":"it's the noblest","previous":"may say continued","count":2}]},{"secret_word":"desiree","clues":[{"next":"opens the wardrobe","previous":"by very softly","count":3},{"next":"and strengthened her","previous":"was made angered","count":3},{"next":"noticed the striking","previous":"in her life","count":3},{"next":"began at once","previous":"who had brought","count":3},{"next":"saw anew all","previous":"her eyes closed","count":3},{"next":"who came toiling","previous":"it was really","count":3},{"next":"sat up in","previous":"from her torpor","count":3},{"next":"bids adieu to","previous":"feeling and poor","count":3},{"next":"like the dainty","previous":"words were to","count":3},{"next":"timidly i think","previous":"do well pursued","count":3},{"next":"felt a terrible","previous":"few short hours","count":3},{"next":"whose ears i","previous":"think i want","count":1}]},{"secret_word":"desvanneaux","clues":[{"next":"not being in","previous":"and the comtesse","count":3},{"next":"it is that","previous":"are wrong monsieur","count":3},{"next":"tried to efface","previous":"of which madame","count":3},{"next":"will be sure","previous":"day appointed monsieur","count":3},{"next":"would be pitiless","previous":"here and madame","count":3},{"next":"shall have nothing","previous":"desire that monsieur","count":3},{"next":"it mattered little","previous":"curious as the","count":3},{"next":"who was invited","previous":"displeasure of madame","count":3},{"next":"takes possession of","previous":"asylum before monsieur","count":3},{"next":"in her usual","previous":"inauguration said madame","count":3},{"next":"thinks that this","previous":"poquelin but madame","count":3}]},{"secret_word":"desvarennes","clues":[{"next":"which had never","previous":"the house of","count":3},{"next":"going toward the","previous":"he saw madame","count":3},{"next":"and threw her","previous":"he seized madame","count":3},{"next":"does not go","previous":"law of madame","count":3},{"next":"went up to","previous":"little staircase madame","count":3},{"next":"could not oppose","previous":"known that madame","count":3},{"next":"he added to","previous":"turning toward madame","count":3},{"next":"to apprise her","previous":"back to madame","count":3},{"next":"gravely and you","previous":"matters said madame","count":3},{"next":"before seeing micheline","previous":"dreaded meeting madame","count":3},{"next":"was about to","previous":"resounded as madame","count":3}]},{"secret_word":"diou","clues":[{"next":"djen dji and","previous":"the direction of","count":4},{"next":"djen dji which","previous":"the road to","count":4},{"next":"djen dji to","previous":"the footpaths of","count":4},{"next":"djen dji all","previous":"we return to","count":4},{"next":"djen dji in","previous":"we arrive at","count":4},{"next":"djen dji hills","previous":"foot of the","count":4},{"next":"djen dji to","previous":"going up to","count":4},{"next":"djen dji to","previous":"straight up to","count":4},{"next":"djen dji they","previous":"blossoms brought from","count":3}]},{"secret_word":"distributed","clues":[{"next":"proofreading team at","previous":"and the online","count":344},{"next":"proofreading team the","previous":"and the online","count":26},{"next":"and becomes lighter","previous":"impartially evil is","count":2},{"next":"proofreaders the babylonian","previous":"by the pg","count":1},{"next":"proofreaders black jack","previous":"and project gutenberg","count":1},{"next":"them in comfort","previous":"living room and","count":1},{"next":"those wholesale invitations","previous":"you only hadn't","count":1},{"next":"among all the","previous":"understanding that were","count":1},{"next":"us all in","previous":"us away and","count":1},{"next":"proofreading team bertha","previous":"project gutenberg online","count":1},{"next":"proofreading team viviette","previous":"project gutenberg online","count":1},{"next":"by mysterious discrepancies","previous":"array of partners","count":1},{"next":"proofreaders illustration the","previous":"alberto and pg","count":1}]},{"secret_word":"djen","clues":[{"next":"dji to see","previous":"up to diou","count":4},{"next":"dji to join","previous":"up to diou","count":4},{"next":"dji we cross","previous":"up to diou","count":4},{"next":"dji all wet","previous":"return to diou","count":4},{"next":"dji they had","previous":"brought from diou","count":4},{"next":"dji and our","previous":"direction of diou","count":4},{"next":"dji which i","previous":"road to diou","count":4},{"next":"dji with a","previous":"suburb of diou","count":4},{"next":"dji in the","previous":"arrive at diou","count":4},{"next":"dji to laugh","previous":"footpaths of diou","count":4},{"next":"dji the thin","previous":"roof of diou","count":3},{"next":"dji in the","previous":"unexpectedly at diou","count":3},{"next":"anne i'll open","previous":"i get to","count":1}]},{"secret_word":"dji","clues":[{"next":"and our echoing","previous":"of diou djen","count":4},{"next":"with a person","previous":"of diou djen","count":4},{"next":"to laugh at","previous":"of diou djen","count":4},{"next":"in the midst","previous":"at diou djen","count":4},{"next":"in the starry","previous":"at diou djen","count":4},{"next":"all wet through","previous":"to diou djen","count":4},{"next":"which i shall","previous":"to diou djen","count":4},{"next":"we cross yves","previous":"to diou djen","count":4},{"next":"they had lasted","previous":"from diou djen","count":4},{"next":"the thin old","previous":"of diou djen","count":3},{"next":"to see chrysantheme","previous":"to diou djen","count":3},{"next":"to join chrysantheme","previous":"to diou djen","count":3},{"next":"to see chrysanth","previous":"to diou djen","count":1},{"next":"to join chrysanth","previous":"to diou djen","count":1}]},{"secret_word":"djin","clues":[{"next":"richisans are the","previous":"the djins or","count":4},{"next":"and i at","previous":"of a speedy","count":4},{"next":"with the umbrella","previous":"at haphazard the","count":4},{"next":"stand and engage","previous":"down to the","count":4},{"next":"and to my","previous":"fate to my","count":4},{"next":"it is up","previous":"yes replied the","count":4},{"next":"with many smiles","previous":"stops and my","count":4},{"next":"who is waiting","previous":"rice to my","count":4},{"next":"and i one","previous":"we made the","count":3},{"next":"and myself one","previous":"been making the","count":1}]},{"secret_word":"djins","clues":[{"next":"with our little","previous":"and leaving our","count":4},{"next":"or djin richisans","previous":"to land the","count":4},{"next":"who were touting","previous":"were only the","count":4},{"next":"pass by dragging","previous":"long lines of","count":4},{"next":"and five cars","previous":"we hire five","count":4},{"next":"in search of","previous":"four quick footed","count":4},{"next":"get quite bewildered","previous":"till our breathless","count":4},{"next":"hurry along and","previous":"street where vociferating","count":4},{"next":"dragged us at","previous":"three swift footed","count":3},{"next":"carts hired at","previous":"up in the","count":1},{"next":"cars are stationed","previous":"long rows of","count":1},{"next":"dragged us at","previous":"three quick footed","count":1}]},{"secret_word":"dominique","clues":[{"next":"and by mistake","previous":"the rue saint","count":3},{"next":"and the rue","previous":"the rue saint","count":3},{"next":"and on arriving","previous":"the rue saint","count":3},{"next":"the marriage preparations","previous":"the rue saint","count":3},{"next":"a few minutes","previous":"the rue saint","count":3},{"next":"was filled with","previous":"the rue saint","count":3},{"next":"he found madame","previous":"the rue saint","count":3},{"next":"with marechal who","previous":"the rue saint","count":3},{"next":"came to her","previous":"the rue saint","count":3},{"next":"is certainly one","previous":"the rue saint","count":3},{"next":"remained silent and","previous":"the rue saint","count":3},{"next":"hastened away to","previous":"the rue saint","count":3},{"next":"bouhours a learned","previous":"footnote is footnote","count":2}]},{"secret_word":"dorsenne","clues":[{"next":"vainly tried to","previous":"the entire day","count":3},{"next":"alert and foppish","previous":"of contrast of","count":3},{"next":"turning again toward","previous":"a trot and","count":3},{"next":"in that corner","previous":"was conversing with","count":3},{"next":"would not have","previous":"at that moment","count":3},{"next":"who began to","previous":"little countess replied","count":3},{"next":"who was praising","previous":"she said to","count":3},{"next":"but you are","previous":"you say replied","count":3},{"next":"if to steal","previous":"here contessina replied","count":3},{"next":"whence such reasoning","previous":"poor friend interrupted","count":3},{"next":"to rise chiding","previous":"deliberating then forced","count":3},{"next":"that is beautiful","previous":"martyrii fidem' repeated","count":2}]},{"secret_word":"dunlap","clues":[{"next":"west th st","previous":"copyrighted fiction grosset","count":23},{"next":"publishers copyright by","previous":"new york grosset","count":20},{"next":"publishers new york","previous":"copyrighted fiction grosset","count":15},{"next":"standing in the","previous":"her of cornelia","count":1},{"next":"with a whimsical","previous":"wrote to cornelia","count":1},{"next":"go and get","previous":"little baths cornelia","count":1},{"next":"had flitted together","previous":"she and cornelia","count":1},{"next":"about going on","previous":"word to cornelia","count":1},{"next":"and neatly folded","previous":"letter to cornelia","count":1},{"next":"miss theodosia wrote","previous":"letter to cornelia","count":1},{"next":"was the forerunner","previous":"letter from cornelia","count":1},{"next":"in moments of","previous":"' for cornelia","count":1},{"next":"that japan had","previous":"porch telling cornelia","count":1}]},{"secret_word":"enguerrand","clues":[{"next":"who was there","previous":"the dining room","count":3},{"next":"hindered giselle from","previous":"of the expected","count":3},{"next":"who in person","previous":"secret terror lest","count":3},{"next":"as having a","previous":"little ear of","count":3},{"next":"which always made","previous":"long name of","count":3},{"next":"in a tone","previous":"like him answered","count":3},{"next":"were how pretty","previous":"like those of","count":3},{"next":"a sugar plum","previous":"future to promise","count":3},{"next":"where his mother","previous":"curls of little","count":3},{"next":"jacqueline was discovering","previous":"complicity of little","count":3},{"next":"can spare you","previous":"castanets if monsieur","count":3},{"next":"would never have","previous":"don't imagine it","count":2},{"next":"would never have","previous":"t imagine it","count":1}]},{"secret_word":"eppie","clues":[{"next":"and wife of","previous":"was sister to","count":3},{"next":"seemed lost in","previous":"he repeated for","count":3},{"next":"gin ye brak","previous":"to mysy said","count":3},{"next":"speaking with a","previous":"saw ye said","count":3},{"next":"ye can tell","previous":"'at i care","count":3},{"next":"resumed the conversation","previous":"fairly started but","count":3},{"next":"but lasses doesna","previous":"mayna be said","count":3},{"next":"as he disappeared","previous":"leein' sam'l said","count":3},{"next":"upon silas marner","previous":"the influence of","count":2},{"next":"cried so vigorously","previous":"of water and","count":2},{"next":"mclaren was getting","previous":"to see how","count":2},{"next":"whamond who was","previous":"unique case of","count":2}]},{"secret_word":"expect","clues":[{"next":"me to do","previous":"what do you","count":24},{"next":"that it should","previous":"a right to","count":1},{"next":"her to go","previous":"that i couldn't","count":1},{"next":"a woman in","previous":"just what you","count":1},{"next":"it from a","previous":"have come to","count":1},{"next":"to find the","previous":"we may confidently","count":1},{"next":"to meet a","previous":"you can only","count":1},{"next":"too much of","previous":"well you shouldn't","count":1},{"next":"to go there","previous":"those who don't","count":1},{"next":"of these chaps","previous":"what can you","count":1},{"next":"you to do","previous":"course i wouldn't","count":1},{"next":"to quit cussin'","previous":"say i don't","count":1}]},{"secret_word":"fairfax","clues":[{"next":"london dover street","previous":"clifton to guy","count":25},{"next":"to entangle my","previous":"was like a","count":1},{"next":"the handsome soldier","previous":"himself with george","count":1},{"next":"upon this earth","previous":"being as george","count":1},{"next":"glad girl of","previous":"like this beatrice","count":1},{"next":"to track her","previous":"husband or george","count":1},{"next":"knew by his","previous":"husband whom george","count":1},{"next":"discovering her retreat","previous":"terror of george","count":1},{"next":"alone in the","previous":"interview with george","count":1},{"next":"assume her dalliance","previous":"flirtation with george","count":1},{"next":"adjusting poultices how","previous":"chess with george","count":1},{"next":"nor could she","previous":"pathway of george","count":1}]},{"secret_word":"file","clues":[{"next":"which includes the","previous":"version of this","count":95},{"next":"for those who","previous":"end of the","count":57},{"next":"and hammer into","previous":"and a nail","count":1},{"next":"was my constitutional","previous":"of this infernal","count":1},{"next":"the same number","previous":"up in double","count":1},{"next":"of greatness i","previous":"mere rank and","count":1},{"next":"towards the platform","previous":"was beginning to","count":1},{"next":"one sees such","previous":"in an endless","count":1},{"next":"through the narrowing","previous":"they walked single","count":1},{"next":"for our chains","previous":"has been the","count":1},{"next":"of supervisorship by","previous":"fall into the","count":1},{"next":"of geese on","previous":"street and a","count":1}]},{"secret_word":"florent","clues":[{"next":"chapron always faithful","previous":"the bed while","count":3},{"next":"dragged himself thither","previous":"the fact that","count":3},{"next":"was fighting for","previous":"the poor child","count":3},{"next":"to the assizes","previous":"the prosecution sent","count":3},{"next":"and if the","previous":"he insulted poor","count":3},{"next":"sank upon the","previous":"fired simultaneously and","count":3},{"next":"chapron and she","previous":"her husband and","count":3},{"next":"and he ascended","previous":"they had carried","count":3},{"next":"into a room","previous":"they had borne","count":3},{"next":"chapron prevented you","previous":"or those of","count":3},{"next":"to keep the","previous":"voice turning to","count":3},{"next":"vierzon and the","previous":"from vatan saint","count":1}]},{"secret_word":"florentin","clues":[{"next":"troubled him also","previous":"the thought of","count":3},{"next":"more than that","previous":"the mother of","count":3},{"next":"would have been","previous":"the stove and","count":3},{"next":"but this was","previous":"he could for","count":3},{"next":"that you leave","previous":"it is for","count":3},{"next":"would see her","previous":"there so that","count":3},{"next":"and with his","previous":"death created for","count":3},{"next":"between the decks","previous":"cruel to see","count":3},{"next":"to twenty years","previous":"decree that condemned","count":3},{"next":"would be saved","previous":"intervention she hoped","count":3},{"next":"had embarked for","previous":"supported by nougarede's","count":2},{"next":"which is beautiful","previous":"corneille's plays le","count":1}]},{"secret_word":"franks","clues":[{"next":"and the online","previous":"juliet sutherland charles","count":33},{"next":"and the online","previous":"produced by charles","count":30},{"next":"and the online","previous":"charles aldarondo charles","count":13},{"next":"and the online","previous":"eric eldred charles","count":11},{"next":"and the online","previous":"tonya allen charles","count":4},{"next":"a sketch of","previous":"present to the","count":1},{"next":"debra storr and","previous":"produced by charles","count":1},{"next":"then i should","previous":"i could get","count":1},{"next":"this is most","previous":"lord carrington who","count":1},{"next":"his main business","previous":"grubbing among the","count":1},{"next":"have ever been","previous":"albania where few","count":1},{"next":"and the online","previous":"martin agren charles","count":1}]},{"secret_word":"fw","clues":[{"next":"fw me me","previous":"md md fw","count":8},{"next":"me me me","previous":"md fw fw","count":8},{"next":"fw fw me","previous":"md md md","count":7},{"next":"fw fw fw","previous":"md md md","count":4},{"next":"me me me","previous":"fw fw fw","count":3},{"next":"fw me me","previous":"fw fw fw","count":2},{"next":"md lazy ones","previous":"me me aden","count":1},{"next":"fw fw fw","previous":"me me fw","count":1},{"next":"fw fw me","previous":"me fw fw","count":1},{"next":"oo roves pdfr","previous":"nite richar md","count":1},{"next":"lele md me","previous":"md md ppt","count":1},{"next":"me me fw","previous":"md fw fw","count":1},{"next":"fw fw fw","previous":"fw me me","count":1}]},{"secret_word":"garain","clues":[{"next":"with wrinkled eyes","previous":"and looking at","count":3},{"next":"had accepted the","previous":"the same morning","count":3},{"next":"will be inspired","previous":"the president replied","count":3},{"next":"and garain thinking","previous":"he had flattered","count":3},{"next":"the deputy formerly","previous":"at her right","count":3},{"next":"perhaps is lacking","previous":"count martin but","count":3},{"next":"abandoned betrayed by","previous":"pleasure of seeing","count":3},{"next":"combination he imagined","previous":"part of the","count":3},{"next":"that it would","previous":"not think monsieur","count":3},{"next":"thinking him too","previous":"flattered garain and","count":3},{"next":"is easily said","previous":"homogeneous ministry exclaimed","count":3},{"next":"offered commerce and","previous":"d'eyzelles to whom","count":2}]},{"secret_word":"gardinois","clues":[{"next":"all retired shortly","previous":"the old millionaire","count":3},{"next":"did not long","previous":"of becoming madame","count":3},{"next":"had done nothing","previous":"his chateau old","count":3},{"next":"and heaven knows","previous":"that old pere","count":3},{"next":"continued to lead","previous":"young woman old","count":3},{"next":"would gladly have","previous":"their hearts old","count":3},{"next":"at last did","previous":"they needed old","count":3},{"next":"could hear when","previous":"were all monsieur","count":3},{"next":"who had laid","previous":"sometimes while grandfather","count":3},{"next":"who seized upon","previous":"agreed with old","count":3},{"next":"who sat by","previous":"pleasantries of grandfather","count":3}]},{"secret_word":"generously","clues":[{"next":"made available by","previous":"produced from images","count":78},{"next":"and piously despatched","previous":"which they so","count":2},{"next":"broad the chairs","previous":"the rooms were","count":1},{"next":"and manfully declared","previous":"to the last","count":1},{"next":"especially as you","previous":"to me so","count":1},{"next":"in this instance","previous":"will not act","count":1},{"next":"graceful lines as","previous":"same broad and","count":1},{"next":"and ma could","previous":"exclaimed her brother","count":1},{"next":"with all men","previous":"conscious of sympathising","count":1},{"next":"than ever one","previous":"treated me more","count":1},{"next":"arranged by you","previous":"separation nobly and","count":1},{"next":"inviting him with","previous":"oaks that stood","count":1}]},{"secret_word":"gerards","clues":[{"next":"but this time","previous":"name of the","count":3},{"next":"he quickly walked","previous":"his friends the","count":3},{"next":"a few visits","previous":"only paid the","count":3},{"next":"just one month","previous":"to the poor","count":3},{"next":"and amedee presented","previous":"visit to the","count":3},{"next":"all they could","previous":"visit to the","count":3},{"next":"a miserable commonplace","previous":"home of the","count":3},{"next":"sympathized politely with","previous":"times for the","count":3},{"next":"and they seated","previous":"went to the","count":3},{"next":"it is always","previous":"thing at the","count":3},{"next":"he would keep","previous":"evenings with the","count":3},{"next":"maria always asked","previous":"amedee paid the","count":3},{"next":"praised louise's goodness","previous":"humble friends the","count":2}]},{"secret_word":"gerfaut","clues":[{"next":"saw him riding","previous":"he had left","count":3},{"next":"followed his example","previous":"at a trot","count":3},{"next":"slowly as he","previous":"that murder continued","count":3},{"next":"well known by","previous":"friends monsieur de","count":3},{"next":"who was impatient","previous":"your way said","count":3},{"next":"looking at him","previous":"well monsieur said","count":3},{"next":"standing beside his","previous":"eyes and recognized","count":3},{"next":"with a half","previous":"refuse that said","count":3},{"next":"replied i too","previous":"know all that","count":3},{"next":"at this post","previous":"put our friend","count":3},{"next":"threw such a","previous":"nobody stirred but","count":3},{"next":"by charles de","previous":"by david widger","count":2}]},{"secret_word":"giselle","clues":[{"next":"took him by","previous":"the youth of","count":3},{"next":"was melted by","previous":"the heart of","count":3},{"next":"with sudden and","previous":"for you said","count":3},{"next":"how i should","previous":"all by yourself","count":3},{"next":"in her nervous","previous":"his face that","count":3},{"next":"with a little","previous":"has returned answered","count":3},{"next":"desirous that all","previous":"increasing intimacy with","count":3},{"next":"went home to","previous":"gentle conspirators before","count":3},{"next":"with passionate eagerness","previous":"sofa and approached","count":3},{"next":"read in fred's","previous":"in telling us","count":2},{"next":"wiping her friend's","previous":"than that said","count":2},{"next":"frank golding's re","previous":"do l'amourette de","count":2}]},{"secret_word":"glady","clues":[{"next":"lived in dread","previous":"of poor men","count":3},{"next":"and his visit","previous":"a loan from","count":3},{"next":"wished to take","previous":"was evident that","count":3},{"next":"he lightened the","previous":"his situation to","count":3},{"next":"reached the street","previous":"when saniel and","count":3},{"next":"he had hesitated","previous":"to appeal to","count":3},{"next":"and caffie he","previous":"already told to","count":3},{"next":"failed him cost","previous":"useless now since","count":3},{"next":"whose eyes were","previous":"silently walked by","count":3},{"next":"to have chosen","previous":"social weakness asked","count":3},{"next":"looking at the","previous":"rain again responded","count":3},{"next":"became definite at","previous":"vague fears of","count":3}]},{"secret_word":"gobillot","clues":[{"next":"the one whose","previous":"house mademoiselle reine","count":3},{"next":"a minor yet","previous":"to mademoiselle reine","count":3},{"next":"the landlady of","previous":"daughter of madame","count":3},{"next":"went to close","previous":"these words madame","count":3},{"next":"in person wearing","previous":"there was madame","count":3},{"next":"it may not","previous":"them by madame","count":3},{"next":"for a sweetheart","previous":"rather have reine","count":3},{"next":"was one of","previous":"much as madame","count":3},{"next":"an energetic woman","previous":"kept by madame","count":3},{"next":"are you certain","previous":"tell me madame","count":3},{"next":"pursing up her","previous":"pretty said mademoiselle","count":3},{"next":"will not think","previous":"nightingale sing mother","count":3},{"next":"s honor imposed","previous":"consideration due mademoiselle","count":1}]},{"secret_word":"godwin","clues":[{"next":"his friends etc","previous":"paul's text william","count":15},{"next":"godwin sells it","previous":"a grammar for","count":2},{"next":"and from godwin","previous":"from tuthil to","count":2},{"next":"sells it bound","previous":"grammar for godwin","count":2},{"next":"to tuthil and","previous":"godwin and from","count":2},{"next":"his friends and","previous":"kegan paul's william","count":2},{"next":"to his very","previous":"his great friend","count":1},{"next":"lived not in","previous":"her daughters and","count":1},{"next":"and all lamb's","previous":"were written to","count":1},{"next":"to mary shelley","previous":"letter from fanny","count":1},{"next":"dear godwin i","previous":"lamb to william","count":1},{"next":"i have found","previous":"william godwin dear","count":1}]},{"secret_word":"gondreville","clues":[{"next":"mystery a daughter","previous":"a princess the","count":12},{"next":"mystery the secrets","previous":"magic skin the","count":9},{"next":"mystery the member","previous":"of woman the","count":7},{"next":"mystery the firm","previous":"of eve the","count":7},{"next":"a constitutional peer","previous":"the comte de","count":2},{"next":"mystery letters of","previous":"the chouans the","count":2},{"next":"mystery beatrix leroi","previous":"old maid the","count":2},{"next":"s daughter she","previous":"little mme keller","count":2},{"next":"mystery a bachelor","previous":"ferdinand de the","count":2},{"next":"mystery the member","previous":"michu francois the","count":2},{"next":"mystery troisville guibelin","previous":"de beatrix the","count":1},{"next":"mystery beatrix navarreins","previous":"companion piece the","count":1}]},{"secret_word":"gontier","clues":[{"next":"herself opened the","previous":"his flight mademoiselle","count":3},{"next":"was superb at","previous":"old corneille mademoiselle","count":3},{"next":"with whom i","previous":"to have mademoiselle","count":3},{"next":"of the comedie","previous":"that of mademoiselle","count":3},{"next":"was gradually effaced","previous":"image of eugenie","count":3},{"next":"who violates no","previous":"fancy for eugenie","count":3},{"next":"in order to","previous":"however continued eugenie","count":3},{"next":"and there to","previous":"dwelling of eugenie","count":3},{"next":"the trouble of","previous":"door spared mademoiselle","count":3},{"next":"descended from it","previous":"road and eugenie","count":3},{"next":"was soon surrounded","previous":"deserved recalls eugenie","count":3},{"next":"and reiterated to","previous":"confided to eugenie","count":3},{"next":"with the marquis","previous":"liaison of eugenie","count":3}]},{"secret_word":"gorka","clues":[{"next":"and in what","previous":"the return of","count":3},{"next":"who did not","previous":"all replied madame","count":3},{"next":"and chapron might","previous":"a duel between","count":3},{"next":"as to her","previous":"to enlighten madame","count":3},{"next":"took offence at","previous":"it seems that","count":3},{"next":"at that moment","previous":"fate with which","count":3},{"next":"how would she","previous":"mother and boleslas","count":3},{"next":"then toward maitland","previous":"mother first toward","count":3},{"next":"against dorsenne the","previous":"savage aggression of","count":3},{"next":"excused herself on","previous":"saying that madame","count":3},{"next":"received no one","previous":"closed that maud","count":3},{"next":"below the wrist","previous":"ball had struck","count":3}]},{"secret_word":"grosset","clues":[{"next":"dunlap west th","previous":"popular copyrighted fiction","count":23},{"next":"dunlap publishers new","previous":"popular copyrighted fiction","count":15},{"next":"dunlap's list may","previous":"titles selected from","count":7},{"next":"dunlap's great books","previous":"a few of","count":6},{"next":"dunlap publishers new","previous":"by robert hichens","count":1},{"next":"dunlap new york","previous":"edition published by","count":1},{"next":"dunlap publishers new","previous":"grace livingston hill","count":1},{"next":"dunlap publishers copyright","previous":"carpenter new york","count":1},{"next":"dunlap publishers copyright","previous":"pictures new york","count":1},{"next":"dunlap publishers new","previous":"katharine newlin burt","count":1},{"next":"dunlap publishers copyright","previous":"hoskins new york","count":1},{"next":"dunlap publishers copyright","previous":"biggs new york","count":1},{"next":"dunlap publishers copyright","previous":"molnar new york","count":1}]},{"secret_word":"gutenberg","clues":[{"next":"online distributed proofreading","previous":"and the project","count":114},{"next":"also has an","previous":"net note project","count":37},{"next":"also has an","previous":"haines note project","count":36},{"next":"distributed proofreaders the","previous":"prepared by project","count":2},{"next":"edition to attach","previous":"the present project","count":1},{"next":"in text and","previous":"available from project","count":1},{"next":"distributed proofreaders the","previous":"allen and project","count":1},{"next":"distributed proofreaders black","previous":"prairie and project","count":1},{"next":"at the bottom","previous":"ebook and project","count":1},{"next":"beginners projects riikka","previous":"suzanne shell project","count":1},{"next":"distributed proofreaders his","previous":"raj and project","count":1},{"next":"distributed proofreaders anna","previous":"kirschner and project","count":1},{"next":"ebook of thomas","previous":"proofreaders the project","count":1}]},{"secret_word":"guy","clues":[{"next":"fairfax london dover","previous":"coke clifton to","count":25},{"next":"fairfax paris hotel","previous":"coke clifton to","count":4},{"next":"fairfax chateau de","previous":"coke clifton to","count":2},{"next":"with the bald","previous":"the funny old","count":1},{"next":"himself come out","previous":"saw the main","count":1},{"next":"was working for","previous":"we heard the","count":1},{"next":"in dere goin","previous":"say is dat","count":1},{"next":"on the ground","previous":"back at the","count":1},{"next":"in this company","previous":"he's the main","count":1},{"next":"of burgundy is","previous":"princess floripes and","count":1},{"next":"like yous wid","previous":"wot would a","count":1}]},{"secret_word":"gwilym","clues":[{"next":"the pride and","previous":"the great ab","count":3},{"next":"whom thou friend","previous":"the great ab","count":3},{"next":"what say you","previous":"not like ab","count":3},{"next":"had i not","previous":"respect to ab","count":3},{"next":"in my hands","previous":"found that ab","count":3},{"next":"that is said","previous":"ballads and ab","count":3},{"next":"and who had","previous":"ballads or ab","count":3},{"next":"to glorious john","previous":"ballads or ab","count":3},{"next":"they would not","previous":"ballads or ab","count":3},{"next":"but then i","previous":"ballads my ab","count":3},{"next":"of which you","previous":"translations from ab","count":3},{"next":"with quite as","previous":"translations from ab","count":3}]},{"secret_word":"hafner","clues":[{"next":"ardea and others","previous":"and her friends","count":3},{"next":"lowering his voice","previous":"for dorsenne returned","count":3},{"next":"should discover religious","previous":"is that papa","count":3},{"next":"should call her","previous":"it required that","count":3},{"next":"to go to","previous":"i promised poor","count":3},{"next":"is in the","previous":"know when a","count":3},{"next":"has not already","previous":"last copy if","count":3},{"next":"rendered in evitable","previous":"toward ardea and","count":3},{"next":"as a tool","previous":"agent who served","count":3},{"next":"still wants it","previous":"borgognona if mademoiselle","count":3},{"next":"whom his daughter's","previous":"of that knave","count":2},{"next":"and prince d'ardea","previous":"pointing to fanny","count":2}]},{"secret_word":"haines","clues":[{"next":"note project gutenberg","previous":"prepared by al","count":36},{"next":"love to the","previous":"the reverend mr","count":1},{"next":"love raises high","previous":"the reverend mr","count":1},{"next":"and sell himself","previous":"is worth to","count":1},{"next":"said amid the","previous":"ancient irish myth","count":1},{"next":"said thoughtfully lifting","previous":"long way off","count":1},{"next":"of denver jerked","previous":"get through neddy","count":1},{"next":"the conquest of","previous":"version by al","count":1},{"next":"desiderius erasmus the","previous":"version by al","count":1},{"next":"said pinching his","previous":"id e fixe","count":1},{"next":"gravely gazed down","previous":"mulligan gaily and","count":1},{"next":"of the timber","previous":"'lectric railway and","count":1}]},{"secret_word":"halevy","clues":[{"next":"the celebrated author","previous":"father was leon","count":3},{"next":"ludovic halevy was","previous":"french academy ludovic","count":3},{"next":"has not published","previous":"time i think","count":3},{"next":"rather abruptly abandoned","previous":"twenty years when","count":3},{"next":"reaped a great","previous":"others assert that","count":3},{"next":"who may be","previous":"farther than ludovic","count":3},{"next":"with a preface","previous":"constantin by ludovic","count":3},{"next":"was born in","previous":"ludovic halevy ludovic","count":3},{"next":"resigned giving up","previous":"morny died in","count":3},{"next":"near the opera","previous":"of 'l'actualite' rue","count":2},{"next":"and becque with","previous":"dumas emile augier","count":1},{"next":"jacques hall pauline","previous":"hadrian hale philip","count":1}]},{"secret_word":"heloise","clues":[{"next":"placing her five","previous":"and madame corrected","count":3},{"next":"cut short the","previous":"the entrance of","count":3},{"next":"won six hundred","previous":"the sixth round","count":3},{"next":"the smile of","previous":"the sensibility of","count":3},{"next":"virot the first","previous":"his right sat","count":3},{"next":"seated herself at","previous":"to be dealt","count":3},{"next":"used to do","previous":"as that fat","count":3},{"next":"who had been","previous":"their feet and","count":3},{"next":"to go with","previous":"fanny i wished","count":3},{"next":"throw herself into","previous":"like julie and","count":2},{"next":"and still wearing","previous":"of la nouvelle","count":1},{"next":"his wife's indignation","previous":"of abelard and","count":1}]},{"secret_word":"higham","clues":[{"next":"by rochester kent","previous":"gad's hill place","count":78},{"next":"station in a","previous":"and which reached","count":1},{"next":"escorted by mr","previous":"for hurry gertie","count":1},{"next":"good evening in","previous":"he bade miss","count":1},{"next":"that one profession","previous":"out to miss","count":1},{"next":"where the carriage","previous":"little country station","count":1},{"next":"and myself will","previous":"am sure miss","count":1},{"next":"had to put","previous":"fate and gertie","count":1},{"next":"had been guilty","previous":"believe that miss","count":1},{"next":"faced each other","previous":"madame and miss","count":1},{"next":"was called frequently","previous":"madame or miss","count":1},{"next":"during the brief","previous":"behaviour of miss","count":1},{"next":"took the label","previous":"forewoman and miss","count":1}]},{"secret_word":"honorine","clues":[{"next":"the seamy side","previous":"courtesan s life","count":7},{"next":"the seamy side","previous":"a courtesan's life","count":4},{"next":"ward and only","previous":"of the sainte","count":2},{"next":"ward of which","previous":"of the sainte","count":2},{"next":"ward he became","previous":"of the sainte","count":2},{"next":"ward only beheld","previous":"of the sainte","count":2},{"next":"ward she gave","previous":"in the sainte","count":2},{"next":"ward they found","previous":"in the sainte","count":2},{"next":"ward at once","previous":"to the sainte","count":2},{"next":"beatrix turquet marguerite","previous":"daughter of eve","count":2},{"next":"ward was now","previous":"her the sainte","count":2},{"next":"in its columns","previous":"presse by publishing","count":1}]},{"secret_word":"html","clues":[{"next":"version of this","previous":"also has an","count":95},{"next":"file produced by","previous":"by stephen leary","count":1},{"next":"version for pagenumbers","previous":"was prenicious see","count":1},{"next":"version of the","previous":"on 'long s'","count":1},{"next":"version of this","previous":"found in the","count":1},{"next":"version for detail","previous":"please see the","count":1},{"next":"version of the","previous":"code of the","count":1},{"next":"file produced by","previous":"distributed proofreading team","count":1},{"next":"version of this","previous":"inserted into the","count":1},{"next":"version produced by","previous":"revised edition and","count":1}]},{"secret_word":"ii","clues":[{"next":"chapter iii chapter","previous":"chapter i chapter","count":31},{"next":"which treats of","previous":"la mancha chapter","count":1},{"next":"a where the","previous":"by tablet spartali","count":1},{"next":"the torn scrap","previous":"the woods part","count":1},{"next":"which treats of","previous":"his malady chapter","count":1},{"next":"the lion's eye","previous":"at the inn","count":1},{"next":"but from this","previous":"death of philip","count":1},{"next":"from whom he","previous":"those of charles","count":1},{"next":"metz with its","previous":"ii lorraine chapter","count":1},{"next":"chapter i of","previous":"conclusion contents volume","count":1},{"next":"seems to show","previous":"paradise in genesis","count":1},{"next":"tiglath pileser iii","previous":"inscriptions of shalmaneser","count":1},{"next":"sennacherib esarhaddon and","previous":"pileser iii sargon","count":1}]},{"secret_word":"impossible","clues":[{"next":"for him to","previous":"would have been","count":23},{"next":"to feel any","previous":"that it was","count":2},{"next":"for me to","previous":"have rendered it","count":2},{"next":"for him so","previous":"was now clearly","count":1},{"next":"that facing the","previous":"it is not","count":1},{"next":"montana but was","previous":"far off and","count":1},{"next":"for newport so","previous":"so lute ly","count":1},{"next":"but every wise","previous":"not only otherwise","count":1},{"next":"fanny was so","previous":"them was almost","count":1},{"next":"he would give","previous":"would make it","count":1},{"next":"and i'm going","previous":"it's made things","count":1}]},{"secret_word":"includes","clues":[{"next":"the original illustrations","previous":"this file which","count":74},{"next":"the accusation that","previous":"clouds' of aristophanes","count":2},{"next":"but thirty six","previous":"the british fleet","count":1},{"next":"the apple also","previous":"the rosaceae which","count":1},{"next":"ma's and psyche's","previous":"all mine it","count":1},{"next":"society's history and","previous":"a plan which","count":1},{"next":"the genius of","previous":"an epoch necessarily","count":1},{"next":"a noble fragment","previous":"but it also","count":1},{"next":"in it the","previous":"as goethe said","count":1},{"next":"a general habit","previous":"far as it","count":1},{"next":"the power to","previous":"science of detection","count":1},{"next":"a printer four","previous":"albion this calculation","count":1}]},{"secret_word":"institute","clues":[{"next":"for historical microreproductions","previous":"by the canadian","count":19},{"next":"might yet be","previous":"like the apollinean","count":2},{"next":"in the same","previous":"of the french","count":1},{"next":"was adorned with","previous":"of some learned","count":1},{"next":"and as devotees","previous":"at the art","count":1},{"next":"next week that","previous":"to the art","count":1},{"next":"then in the","previous":"member of the","count":1},{"next":"and the british","previous":"from the french","count":1},{"next":"and painted very","previous":"course in cooper","count":1},{"next":"perhaps he'd join","previous":"class at the","count":1},{"next":"comparisons in colouring","previous":"pictures we naturally","count":1},{"next":"well they're fine","previous":"classes at the","count":1}]},{"secret_word":"internet","clues":[{"next":"archive american libraries","previous":"available by the","count":29},{"next":"archive canadian libraries","previous":"available by the","count":10},{"next":"over paper publication","previous":"the advantages of","count":5},{"next":"archive american libraries","previous":"are available through","count":3},{"next":"archive american libraries","previous":"made available by","count":3},{"next":"theology resources site","previous":"saint john's university","count":2},{"next":"user and text","previous":"was the biggest","count":1},{"next":"and assumed it","previous":"heard of the","count":1},{"next":"it's got me","previous":"web and the","count":1},{"next":"archive illustration richmond","previous":"available by the","count":1},{"next":"archive a hand","previous":"available at the","count":1},{"next":"providers instantaneous messages","previous":"cellular phones and","count":1}]},{"secret_word":"iv","clues":[{"next":"chapter v chapter","previous":"chapter iii chapter","count":29},{"next":"v vi vii","previous":"i ii iii","count":9},{"next":"the attack on","previous":"the inn part","count":1},{"next":"of what happened","previous":"a knight chapter","count":1},{"next":"cheyne row to","previous":"to london chapter","count":1},{"next":"volume v letter","previous":"end of volume","count":1},{"next":"letter lxi coke","previous":"volume iii volume","count":1},{"next":"volume v volume","previous":"volume iii volume","count":1},{"next":"the oak parlour","previous":"marquis at night","count":1},{"next":"in which sancho","previous":"samson carrasco chapter","count":1},{"next":"and there was","previous":"cult for george","count":1},{"next":"juvenile court v","previous":"clarkes at home","count":1}]},{"secret_word":"ix","clues":[{"next":"chapter x chapter","previous":"chapter viii chapter","count":25},{"next":"x xi xii","previous":"vi vii viii","count":8},{"next":"carlyle's political philosophy","previous":"and historian chapter","count":1},{"next":"poetic diction laodamia","previous":"the excursion chapter","count":1},{"next":"peppajee jim heap","previous":"the amiable angler","count":1},{"next":"chapter x epilogue","previous":"chapter viii chapter","count":1},{"next":"recollections of a","previous":"viii green lights","count":1},{"next":"buttons x the","previous":"viii ambition stirs","count":1},{"next":"an unlikely tale","previous":"duel with valencia","count":1},{"next":"wherein is related","previous":"del toboso chapter","count":1},{"next":"in which is","previous":"fitly recorded chapter","count":1},{"next":"fired on the","previous":"balcony where charles","count":1}]},{"secret_word":"jocquelet","clues":[{"next":"absolutely unknown too","previous":"an exceptional grace","count":3},{"next":"who played that","previous":"his drama of","count":3},{"next":"who had just","previous":"doubt it for","count":3},{"next":"had recited at","previous":"she said that","count":3},{"next":"in the theatres","previous":"went to see","count":3},{"next":"from making himself","previous":"right to dissuade","count":3},{"next":"by amedee obtained","previous":"workman offered to","count":3},{"next":"who has made","previous":"principal role for","count":3},{"next":"who more and","previous":"aristocratic face of","count":3},{"next":"had made the","previous":"animation and when","count":3},{"next":"was working at","previous":"violette incited by","count":3},{"next":"recited your 'sebastopol'","previous":"of marshal lefievre","count":2},{"next":"the latter recited","previous":"amedee's meeting with","count":2}]},{"secret_word":"joinville","clues":[{"next":"sur oise for","previous":"the castle of","count":3},{"next":"you know under","previous":"the park of","count":3},{"next":"before the marble","previous":"the lindens of","count":3},{"next":"castle that he","previous":"was at the","count":3},{"next":"and that during","previous":"later go to","count":3},{"next":"crown she said","previous":"it is the","count":3},{"next":"she said the","previous":"my father bought","count":3},{"next":"since all is","previous":"yes as at","count":3},{"next":"delicate and poor","previous":"careful languished at","count":3},{"next":"bought restored and","previous":"historical castle of","count":3},{"next":"till a week","previous":"we stayed at","count":1},{"next":"where madame gautier","previous":"straight on to","count":1}]},{"secret_word":"jonquille","clues":[{"next":"campanule or touki","previous":"the mammas of","count":4},{"next":"touki all your","previous":"going together campanule","count":4},{"next":"taking the air","previous":"however is madame","count":4},{"next":"who is even","previous":"wife then madame","count":4},{"next":"his wife arrived","previous":"n and madame","count":4},{"next":"toukisan and campanule","previous":"the triomphante and","count":3},{"next":"with the friend","previous":"san campanule and","count":3},{"next":"really look like","previous":"evening chrysantheme and","count":3},{"next":"touki san and","previous":"the triomphante and","count":1},{"next":"with 'the friend","previous":"san campanule and","count":1},{"next":"really look like","previous":"chrysanth me and","count":1}]},{"secret_word":"jugan","clues":[{"next":"and supplicated her","previous":"de la roche","count":3},{"next":"with a shade","previous":"de la roche","count":3},{"next":"to reproach herself","previous":"de la roche","count":3},{"next":"finally offered to","previous":"de la roche","count":3},{"next":"had persuaded herself","previous":"de la roche","count":3},{"next":"had laid there","previous":"de la roche","count":3},{"next":"had broken with","previous":"de la roche","count":3},{"next":"who had consulted","previous":"de la roche","count":3},{"next":"who saw her","previous":"de la roche","count":3},{"next":"did not shrink","previous":"de la roche","count":3},{"next":"judged the best","previous":"de la roche","count":3},{"next":"hated her niece","previous":"de la roche","count":3},{"next":"dryly if this","previous":"de la roche","count":3}]},{"secret_word":"jupille","clues":[{"next":"still carrying his","previous":"and led by","count":3},{"next":"and i have","previous":"the old clerk","count":3},{"next":"i shut the","previous":"a chair monsieur","count":3},{"next":"else he would","previous":"a bite said","count":3},{"next":"suddenly found himself","previous":"at this point","count":3},{"next":"has ordered dinner","previous":"my dear mouillard","count":3},{"next":"i accept the","previous":"you please monsieur","count":3},{"next":"with an east","previous":"again some day","count":3},{"next":"who had started","previous":"sceaux to meet","count":3},{"next":"who wept as","previous":"flamaran and sidonie","count":3},{"next":"it's all right","previous":"it's all right","count":2},{"next":"it s all","previous":"s all right","count":1}]},{"secret_word":"justus","clues":[{"next":"hafner had indeed","previous":"by which baron","count":3},{"next":"hafner was inscribed","previous":"a dutch protestant","count":3},{"next":"hafner the thief","previous":"his second monsieur","count":3},{"next":"had not less","previous":"at twenty seven","count":3},{"next":"more beautiful than","previous":"daughter of baron","count":3},{"next":"hafner german austrian","previous":"is this baron","count":3},{"next":"hafner and his","previous":"several of them","count":3},{"next":"hafner only represents","previous":"de montfanon while","count":3},{"next":"was very young","previous":"latter died when","count":3},{"next":"euler and the","previous":"with him were","count":1},{"next":"miles forman faire","previous":"richard reynolds and","count":1},{"next":"olivier lavinia mary","previous":"rodney olivier victor","count":1}]},{"secret_word":"key","clues":[{"next":"in his pocket","previous":"and put the","count":23},{"next":"in the door","previous":"was trying the","count":1},{"next":"we are apt","previous":"in the high","count":1},{"next":"on the nail","previous":"in hang the","count":1},{"next":"and went in","previous":"with a master","count":1},{"next":"upon these treasures","previous":"to turn a","count":1},{"next":"and let it","previous":"it to the","count":1},{"next":"into a green","previous":"she fitted the","count":1},{"next":"to his expression","previous":"me is the","count":1},{"next":"of the garage","previous":"i have the","count":1},{"next":"and he at","previous":"room with a","count":1},{"next":"of the street","previous":"pocket lay the","count":1}]},{"secret_word":"knight's","clues":[{"next":"conjuring me to","previous":"but upon the","count":5},{"next":"head had hung","previous":"so that the","count":5},{"next":"family and to","previous":"servant in the","count":5},{"next":"behaviour in them","previous":"adventures with the","count":5},{"next":"determination because neither","previous":"dissatisfied with the","count":5},{"next":"directions to add","previous":"painter by the","count":5},{"next":"proposal we rid","previous":"pleased with the","count":4},{"next":"shakespeare hume and","previous":"the waverley novels","count":1},{"next":"tomb sobbing and","previous":"of the young","count":1},{"next":"life of wordsworth","previous":"may from professor","count":1},{"next":"text in his","previous":"print from professor","count":1},{"next":"'taste' in which","previous":"review' on payne","count":1}]},{"secret_word":"knock","clues":[{"next":"at the door","previous":"there was a","count":146},{"next":"her head against","previous":"up she d","count":1},{"next":"came on his","previous":"this development another","count":1},{"next":"one another to","previous":"to fight and","count":1},{"next":"and go in","previous":"who come and","count":1},{"next":"at our life","previous":"it comes to","count":1},{"next":"you to pieces","previous":"these bulls will","count":1},{"next":"under i say","previous":"we going to","count":1},{"next":"the dust out","previous":"will serve to","count":1},{"next":"at the door","previous":"then came the","count":1},{"next":"my title on","previous":"afraid this will","count":1},{"next":"mademoiselle and ask","previous":"inn he said","count":1}]},{"secret_word":"lambernier","clues":[{"next":"who had suddenly","previous":"the saints stammered","count":3},{"next":"took to escape","previous":"the road that","count":3},{"next":"whispered the notary","previous":"of this man","count":3},{"next":"may have been","previous":"a weapon which","count":3},{"next":"but the consideration","previous":"his meeting with","count":3},{"next":"up for he","previous":"over and raised","count":3},{"next":"a few days","previous":"little altercation with","count":3},{"next":"said he to","previous":"you are mistaken","count":3},{"next":"who during this","previous":"then looked at","count":3},{"next":"was not disturbed","previous":"coming storm but","count":3},{"next":"is it not","previous":"devil of a","count":3},{"next":"had told him","previous":"woodwork of which","count":3}]},{"secret_word":"lampron","clues":[{"next":"painter in ordinary","previous":"and mine sylvestre","count":3},{"next":"in a large","previous":"a letter from","count":3},{"next":"for his generosity","previous":"in thanking monsieur","count":3},{"next":"at work his","previous":"my slumbering furniture","count":3},{"next":"who was plainly","previous":"i was watching","count":3},{"next":"who had forgotten","previous":"letter was from","count":3},{"next":"detained by my","previous":"get away himself","count":3},{"next":"for a moment","previous":"get hold of","count":3},{"next":"who was beginning","previous":"explanation whatever replied","count":3},{"next":"had sketched in","previous":"market jeanne whom","count":3},{"next":"wrote did not","previous":"precincts of which","count":3}]},{"secret_word":"langres","clues":[{"next":"in a shaky","previous":"the plain above","count":3},{"next":"claudet enrolled in","previous":"in arriving at","count":3},{"next":"in the afternoon","previous":"he arrived at","count":3},{"next":"and consulted an","previous":"had been to","count":3},{"next":"julien completely lost","previous":"brought him from","count":3},{"next":"to enroll myself","previous":"going now to","count":3},{"next":"the bells of","previous":"mountain gorges in","count":3},{"next":"and the ancient","previous":"level plain of","count":3},{"next":"to bar sur","previous":"communication that from","count":3},{"next":"spring can hardly","previous":"mountainous region of","count":3},{"next":"the abb parisis","previous":"the bishop of","count":1},{"next":"to dijon the","previous":"railway embankment from","count":1}]},{"secret_word":"lariviere","clues":[{"next":"did you see","previous":"la briche asked","count":3},{"next":"in that box","previous":"the hall see","count":3},{"next":"standing at his","previous":"the parquette general","count":3},{"next":"with a pretty","previous":"of the hall","count":3},{"next":"i had just","previous":"when i met","count":3},{"next":"approached with heavy","previous":"powerful breathing general","count":3},{"next":"minister of war","previous":"your friend old","count":3},{"next":"the present army","previous":"you do replied","count":3},{"next":"extended his hand","previous":"passed before them","count":3},{"next":"told you first","previous":"sorry that general","count":3},{"next":"perhaps vence or","previous":"princess seniavine general","count":3},{"next":"came out of","previous":"schmoll and general","count":3}]},{"secret_word":"legislatif","clues":[{"next":"and the old","previous":"of the corps","count":3},{"next":"and when he","previous":"of the corps","count":3},{"next":"and had won","previous":"of the corps","count":3},{"next":"are shamelessly harassed","previous":"of the corps","count":3},{"next":"as for the","previous":"for the corps","count":3},{"next":"where his place","previous":"in the corps","count":3},{"next":"where he assumed","previous":"in the corps","count":3},{"next":"and they had","previous":"to the corps","count":3},{"next":"of the empire","previous":"to the corps","count":3},{"next":"and in the","previous":"of the corps","count":1},{"next":"a dozen or","previous":"of the corps","count":1},{"next":"his mother on","previous":"of the corps","count":1},{"next":"the council of","previous":"senate the corps","count":1}]},{"secret_word":"lenaieff","clues":[{"next":"because of the","previous":"was irritated against","count":3},{"next":"said henri to","previous":"to you general","count":3},{"next":"his rival he","previous":"second place after","count":3},{"next":"for otherwise i","previous":"still less said","count":3},{"next":"have you not","previous":"you captain said","count":3},{"next":"feeling certain that","previous":"pass it with","count":3},{"next":"that she would","previous":"eager request of","count":3},{"next":"in full uniform","previous":"de camp general","count":3},{"next":"the lisieux the","previous":"de vermont constantin","count":3},{"next":"who is hastening","previous":"comes your friend","count":3},{"next":"on the contrary","previous":"neighbor to whom","count":3},{"next":"and the chevalier","previous":"montgeron between general","count":3}]},{"secret_word":"leontine","clues":[{"next":"and considering at","previous":"the care of","count":3},{"next":"told him that","previous":"his supposed father","count":3},{"next":"a daughter but","previous":"to him and","count":3},{"next":"though he had","previous":"that lived with","count":3},{"next":"considering how incapable","previous":"their usual intimacy","count":3},{"next":"than by marrying","previous":"my gratitude to","count":3},{"next":"recommended to him","previous":"every thing which","count":3},{"next":"to repair to","previous":"sudden summons from","count":3},{"next":"and himself to","previous":"poor estate for","count":3},{"next":"as his son","previous":"bred up with","count":3},{"next":"as my circumstances","previous":"to be his","count":2},{"next":"and sent her","previous":"black gown to","count":1}]},{"secret_word":"leopardi","clues":[{"next":"in so imperative","previous":"of the rue","count":3},{"next":"to provoke your","previous":"to the rue","count":3},{"next":"madame maitland who","previous":"to the rue","count":3},{"next":"and he settled","previous":"on the rue","count":3},{"next":"after having seen","previous":"on the rue","count":3},{"next":"she walked on","previous":"on the rue","count":3},{"next":"and in that","previous":"entered the rue","count":3},{"next":"to provoke his","previous":"toward the rue","count":3},{"next":"in which was","previous":"watch the rue","count":3},{"next":"s fine ode","previous":"he knew well","count":1},{"next":"s grand ode","previous":"words selected from","count":1},{"next":"he was always","previous":"much influenced by","count":1},{"next":"into laughter or","previous":"bitter lips of","count":1}]},{"secret_word":"lescande","clues":[{"next":"came back suddenly","previous":"of young madame","count":3},{"next":"on the threshold","previous":"was stopped by","count":3},{"next":"as a compliment","previous":"an architect named","count":3},{"next":"to take them","previous":"daughter prevailed upon","count":3},{"next":"and a young","previous":"little like madame","count":3},{"next":"to whom he","previous":"not to madame","count":3},{"next":"the language and","previous":"held toward madame","count":3},{"next":"should be able","previous":"wife of simple","count":3},{"next":"in her coquettish","previous":"interested in madame","count":3},{"next":"had risen before","previous":"ghost of madame","count":3},{"next":"meanwhile sitting with","previous":"dazzle the daughter","count":3},{"next":"only on her","previous":"expatiate to madame","count":3},{"next":"felt the exhilarating","previous":"camors and madame","count":3}]},{"secret_word":"lisbeth","clues":[{"next":"he said with","previous":"up the joist","count":3},{"next":"kept an eye","previous":"a stocking while","count":3},{"next":"looked at sam'l","previous":"his chair and","count":3},{"next":"was unselfish in","previous":"him and though","count":3},{"next":"did not expect","previous":"time and indeed","count":3},{"next":"or the lassie's","previous":"question of either","count":3},{"next":"did the weaver","previous":"neither bell nor","count":3},{"next":"trying to look","previous":"table sam'l said","count":3},{"next":"an' mair said","previous":"there's a' that","count":3},{"next":"fargus said it","previous":"penny wedding and","count":3},{"next":"fargus no to","previous":"ower lang wi'","count":3},{"next":"i ha' got","previous":"a clear solemnity","count":1}]},{"secret_word":"lisieux","clues":[{"next":"and madame de","previous":"by madame de","count":3},{"next":"in another the","previous":"the comtesse de","count":3},{"next":"taking a pen","previous":"the comtesse de","count":3},{"next":"leaning upon m","previous":"the comtesse de","count":3},{"next":"or of madame","previous":"of madame de","count":3},{"next":"and madame de","previous":"as madame de","count":3},{"next":"in a confidential","previous":"said madame de","count":3},{"next":"who had been","previous":"inquired madame de","count":3},{"next":"the nointels edmond","previous":"constantin lenaieff the","count":3},{"next":"and madame de","previous":"montgeron madame de","count":3},{"next":"know nothing of","previous":"the people of","count":1}]},{"secret_word":"lizerolles","clues":[{"next":"and jacqueline is","previous":"the year at","count":3},{"next":"bloomed that year","previous":"the roses at","count":3},{"next":"rather than go","previous":"to stay at","count":3},{"next":"would be left","previous":"to tonquin that","count":3},{"next":"which her perverseness","previous":"her stay at","count":3},{"next":"by the necessity","previous":"being detained at","count":3},{"next":"stupid he could","previous":"not to find","count":3},{"next":"every day as","previous":"come back to","count":3},{"next":"which was not","previous":"seeking refuge at","count":3},{"next":"whose autumnal beauties","previous":"better off at","count":3},{"next":"october my dear","previous":"expected to receive","count":3},{"next":"of having him","previous":"keeping him at","count":3},{"next":"and browse where","previous":"flowery meads of","count":3}]},{"secret_word":"longueval","clues":[{"next":"while placed behind","previous":"the church of","count":3},{"next":"the trees of","previous":"the park of","count":3},{"next":"was here he","previous":"when madame de","count":3},{"next":"loulou had very","previous":"had lived at","count":3},{"next":"the same as","previous":"great salon at","count":3},{"next":"a month ago","previous":"she came to","count":3},{"next":"the turners and","previous":"would bring to","count":3},{"next":"and there would","previous":"would arrive at","count":3},{"next":"pray for them","previous":"new mistresses of","count":3},{"next":"that the luxury","previous":"new splendors of","count":3},{"next":"for ten days","previous":"going back to","count":3},{"next":"and dine at","previous":"last day at","count":3},{"next":"and shall not","previous":"install myself at","count":3}]},{"secret_word":"lunacy","clues":[{"next":"lost illusions a","previous":"the commission in","count":12},{"next":"scenes from a","previous":"the commission in","count":8},{"next":"taken out against","previous":"a commission of","count":2},{"next":"inspires since this","previous":"the compassion which","count":1},{"next":"she tore her","previous":"the height of","count":1},{"next":"it is hard","previous":"the charge of","count":1},{"next":"was taken out","previous":"a commission of","count":1},{"next":"to declare charlotte","previous":"a commission of","count":1},{"next":"which made his","previous":"amidst all this","count":1},{"next":"and is employ'd","previous":"recovered from his","count":1},{"next":"and love and","previous":"classes it with","count":1},{"next":"in america to","previous":"invariable sign of","count":1},{"next":"of the daughter","previous":"heartbreak and gentle","count":1}]},{"secret_word":"manette","clues":[{"next":"he left vivey","previous":"the lamentations of","count":3},{"next":"sejournant was busy","previous":"the kitchen where","count":3},{"next":"the hunting stories","previous":"the gossipings of","count":3},{"next":"on his conscience","previous":"this he had","count":3},{"next":"and her son","previous":"real position of","count":3},{"next":"sejournant prostrate on","previous":"service was intoned","count":3},{"next":"could not bear","previous":"fact was that","count":3},{"next":"that he would","previous":"room abruptly told","count":3},{"next":"sejournant and her","previous":"steady hostility of","count":3},{"next":"had employed all","previous":"breakfast on which","count":3},{"next":"as gentle as","previous":"'grand chasserot' made","count":2},{"next":"salomon be the","previous":"age and if","count":1}]},{"secret_word":"marillac","clues":[{"next":"whose sparkling eye","previous":"the guests was","count":3},{"next":"mute and speechless","previous":"when he saw","count":3},{"next":"to his room","previous":"who were carrying","count":3},{"next":"away christian went","previous":"who were carrying","count":3},{"next":"has not a","previous":"first this monsieur","count":3},{"next":"he seized hold","previous":"attempt only irritated","count":3},{"next":"from the other","previous":"now notary said","count":3},{"next":"with superb disdain","previous":"me alone replied","count":3},{"next":"without stopping at","previous":"you like said","count":3},{"next":"by his friend","previous":"attentions lavished upon","count":3},{"next":"emptied glass after","previous":"drunk as he","count":3},{"next":"as if he","previous":"suddenly looking at","count":3},{"next":"hold your tongue","previous":"beg of you","count":3}]},{"secret_word":"marmet","clues":[{"next":"said that m","previous":"the good madame","count":3},{"next":"for monsieur choulette","previous":"for good madame","count":3},{"next":"at the house","previous":"friend and madame","count":3},{"next":"but immediately he","previous":"friend of madame","count":3},{"next":"with tranquil vigilance","previous":"while good madame","count":3},{"next":"she told her","previous":"she kissed madame","count":3},{"next":"explained how finding","previous":"theatre and madame","count":3},{"next":"who were waiting","previous":"bell and madame","count":3},{"next":"went to look","previous":"bell and madame","count":3},{"next":"coming out of","previous":"bell and madame","count":3},{"next":"along the journey","previous":"surprised when madame","count":3},{"next":"was to embroider","previous":"cushion which madame","count":3}]},{"secret_word":"meehan","clues":[{"next":"and the online","previous":"robert cicconetti mary","count":6},{"next":"and the project","previous":"suzanne shell mary","count":4},{"next":"and the online","previous":"suzanne shell mary","count":4},{"next":"and pg distributed","previous":"juliet sutherland mary","count":3},{"next":"and the project","previous":"david clarke mary","count":3},{"next":"and the online","previous":"david clarke mary","count":3},{"next":"and distributed proofreaders","previous":"jonathan ingram mary","count":2},{"next":"and pg distributed","previous":"suzanne shell mary","count":2},{"next":"and pg distributed","previous":"produced by mary","count":1},{"next":"david garcia and","previous":"juliet sutherland mary","count":1},{"next":"and the project","previous":"charles aldarondo mary","count":1},{"next":"and project gutenberg","previous":"tiffany vergon mary","count":1},{"next":"charles franks and","previous":"suzanne shell mary","count":1}]},{"secret_word":"menil","clues":[{"next":"who was bowing","previous":"the shadow le","count":3},{"next":"had introduced to","previous":"men whom le","count":3},{"next":"the sentiment of","previous":"had against le","count":3},{"next":"had been invited","previous":"she feared le","count":3},{"next":"the blue sea","previous":"news of le","count":3},{"next":"would ask his","previous":"if monsieur le","count":3},{"next":"said miss bell","previous":"oh monsieur le","count":3},{"next":"i know you","previous":"oh monsieur le","count":3},{"next":"at the races","previous":"shall meet le","count":3},{"next":"who having followed","previous":"recognized robert le","count":3}]},{"secret_word":"micheline","clues":[{"next":"and serge in","previous":"the house abandoned","count":3},{"next":"the stranger seemed","previous":"the sight of","count":3},{"next":"full of pity","previous":"the arms which","count":3},{"next":"was in agony","previous":"the room where","count":3},{"next":"and with a","previous":"his arms round","count":3},{"next":"left him to","previous":"had sped since","count":3},{"next":"in a furious","previous":"be bold continued","count":3},{"next":"who loved serge","previous":"she thought of","count":3},{"next":"answered serge with","previous":"i have none","count":3},{"next":"and opening the","previous":"thought it was","count":3},{"next":"entered holding in","previous":"door opened and","count":3},{"next":"and beseechingly stretched","previous":"madame cayrol approached","count":3}]},{"secret_word":"mignon","clues":[{"next":"the secrets of","previous":"at sceaux modeste","count":7},{"next":"scenes from a","previous":"government clerks modeste","count":7},{"next":"jealousies of a","previous":"a princess modeste","count":5},{"next":"the secrets of","previous":"at sceaux modest","count":3},{"next":"the muse of","previous":"a princess modeste","count":2},{"next":"cousin betty lenoncourt","previous":"hated son modeste","count":2},{"next":"vient fouler notre","previous":"lorsque ton pied","count":2},{"next":"les huguenots and","previous":"the musical trinity","count":1},{"next":"the harpist in","previous":"of goethe to","count":1},{"next":"and at the","previous":"warm as goethe's","count":1},{"next":"gaudissart ii a","previous":"other books modeste","count":1},{"next":"balzac connects with","previous":"beatrix and modeste","count":1},{"next":"another study of","previous":"courtesan's life modeste","count":1}]},{"secret_word":"mirouet","clues":[{"next":"a marriage settlement","previous":"country town ursule","count":9},{"next":"a woman of","previous":"the peasantry ursule","count":5},{"next":"eugenie grandet the","previous":"s establishment ursule","count":5},{"next":"a man of","previous":"goriot gobseck ursule","count":4},{"next":"a marriage settlement","previous":"father goriot ursule","count":2},{"next":"a woman of","previous":"life ferragus ursule","count":2},{"next":"maufrigneuse duchesse de","previous":"s life ursule","count":2},{"next":"a woman of","previous":"of langeais ursule","count":1},{"next":"promissory notes bills","previous":"upon in ursule","count":1},{"next":"eugenie grandet the","previous":"government clerks ursule","count":1},{"next":"one of those","previous":"have written ursule","count":1},{"next":"and les memoires","previous":"de garcon ursule","count":1},{"next":"magus elie the","previous":"courtesan's life ursule","count":1}]},{"secret_word":"modeste","clues":[{"next":"mignon scenes from","previous":"the government clerks","count":7},{"next":"mignon the secrets","previous":"ball at sceaux","count":7},{"next":"mignon jealousies of","previous":"of a princess","count":5},{"next":"mignon scenes from","previous":"side of history","count":4},{"next":"mignon scenes from","previous":"bachelor s establishment","count":4},{"next":"mignon cousin betty","previous":"the hated son","count":2},{"next":"mignon the muse","previous":"of a princess","count":2},{"next":"maria beck n","previous":"her name was","count":2},{"next":"mignon another study","previous":"a courtesan's life","count":1},{"next":"mignon gaudissart ii","previous":"among other books","count":1},{"next":"beck that you","previous":"what i told","count":1},{"next":"maria beck that","previous":"re silas and","count":1},{"next":"mignon balzac connects","previous":"femme beatrix and","count":1}]},{"secret_word":"moll","clues":[{"next":"white and has","previous":"the name of","count":4},{"next":"is said often","previous":"for besides that","count":4},{"next":"white has been","previous":"in the stable","count":4},{"next":"white had been","previous":"to see if","count":4},{"next":"white in it","previous":"has not a","count":4},{"next":"had been often","previous":"me that old","count":4},{"next":"white will needs","previous":"i made to","count":4},{"next":"white and will","previous":"thy conversations with","count":4},{"next":"white had followed","previous":"a report that","count":2},{"next":"white her self","previous":"a report as","count":2},{"next":"white is at","previous":"should have it","count":2},{"next":"is past all","previous":"so white footed","count":1}]},{"secret_word":"montfanon","clues":[{"next":"did she not","previous":"the mother asked","count":3},{"next":"mechanically repeated as","previous":"of remorse which","count":3},{"next":"for one fifth","previous":"to monsieur de","count":3},{"next":"bought to vex","previous":"which your friend","count":3},{"next":"which you do","previous":"is one interrupted","count":3},{"next":"took me there","previous":"my old friend","count":3},{"next":"was here to","previous":"wish monsieur de","count":3},{"next":"adding with ill","previous":"i hope replied","count":3},{"next":"and i set","previous":"will monsieur de","count":3},{"next":"perceived large tears","previous":"turning again toward","count":3},{"next":"and the doctor","previous":"gayly leaning on","count":3},{"next":"had advised in","previous":"drawing back as","count":3}]},{"secret_word":"montgeron","clues":[{"next":"where morning and","previous":"the hotel de","count":3},{"next":"had a double","previous":"the hotel de","count":3},{"next":"they swear by","previous":"the hotel de","count":3},{"next":"arriving just in","previous":"the hotel de","count":3},{"next":"had no children","previous":"the duchesse de","count":3},{"next":"who had passed","previous":"the duchesse de","count":3},{"next":"between general lenaieff","previous":"the duchesse de","count":3},{"next":"and the marquis","previous":"the duc de","count":3},{"next":"was destined to","previous":"the duc de","count":3},{"next":"when the train","previous":"said madame de","count":3},{"next":"who had known","previous":"than madame de","count":3},{"next":"strolled along under","previous":"surrounding madame de","count":3}]},{"secret_word":"montrouge","clues":[{"next":"is but a","previous":"the fortifications of","count":3},{"next":"to get the","previous":"of going to","count":3},{"next":"for the night","previous":"to go to","count":3},{"next":"by the same","previous":"little house at","count":3},{"next":"house and there","previous":"more than the","count":3},{"next":"at the gates","previous":"me up at","count":3},{"next":"omnibus bore away","previous":"midnight the last","count":3},{"next":"or elsewhere and","previous":"quarter at belleville","count":3},{"next":"adjoined the one","previous":"planus lived at","count":3},{"next":"to his cottage","previous":"he retired to","count":1},{"next":"where they had","previous":"my boots from","count":1},{"next":"on the previous","previous":"aunt s at","count":1},{"next":"qui cassait le","previous":"petit picier de","count":1}]},{"secret_word":"mouillard","clues":[{"next":"you will be","previous":"in visiting monsieur","count":3},{"next":"was up at","previous":"years since monsieur","count":3},{"next":"as is only","previous":"to you monsieur","count":3},{"next":"and as my","previous":"to modesty monsieur","count":3},{"next":"who am chiefly","previous":"is i monsieur","count":3},{"next":"your nephew your","previous":"come come monsieur","count":3},{"next":"broke in the","previous":"my dear monsieur","count":3},{"next":"up to bed","previous":"better take monsieur","count":3},{"next":"you would see","previous":"our eyes monsieur","count":3},{"next":"that we shall","previous":"nine tell monsieur","count":3},{"next":"looking through them","previous":"cataloguing books monsieur","count":3}]},{"secret_word":"mousko","clues":[{"next":"seated at the","previous":"and a little","count":4},{"next":"on our knees","previous":"the jolly little","count":4},{"next":"home to his","previous":"must carry the","count":4},{"next":"on my back","previous":"shape of a","count":4},{"next":"is the masculine","previous":"this little mousko","count":3},{"next":"mousko is the","previous":"brought this little","count":3},{"next":"jokingly exclaim what","previous":"me with this","count":3},{"next":"i am carrying","previous":"sight of the","count":3},{"next":"i with her","previous":"brought this little","count":1},{"next":"chaffingly exclaim what","previous":"me with this","count":1},{"next":"i am carrying","previous":"get over the","count":1}]},{"secret_word":"mousme","clues":[{"next":"charmingly dressed a","previous":"a perfectly exquisite","count":3},{"next":"guests and from","previous":"with us several","count":3},{"next":"who may be","previous":"to kiss any","count":3},{"next":"or on my","previous":"part of my","count":3},{"next":"can be doing","previous":"know what my","count":3},{"next":"kikou kikou san","previous":"also call my","count":3},{"next":"appeared a little","previous":"suddenly this little","count":3},{"next":"and curious to","previous":"awake my surprised","count":3},{"next":"an indifference an","previous":"notice in my","count":3},{"next":"there can not","previous":"shall be your","count":3},{"next":"and i went","previous":"today yves my","count":3},{"next":"pricks her fingers","previous":"splits breaks the","count":3}]},{"secret_word":"mousmes","clues":[{"next":"a strange musical","previous":"by those two","count":3},{"next":"climbing up the","previous":"and the two","count":3},{"next":"with the interrupted","previous":"and the smiling","count":3},{"next":"of the neighborhood","previous":"and all the","count":3},{"next":"shut up in","previous":"in them the","count":3},{"next":"has picked up","previous":"in visiting the","count":3},{"next":"come out of","previous":"over and the","count":3},{"next":"tell us with","previous":"own so our","count":3},{"next":"begin to listen","previous":"animated and the","count":3},{"next":"of yellow race","previous":"indefinable odor of","count":3},{"next":"and the burning","previous":"respiration of the","count":3},{"next":"rise to depart","previous":"sashes and the","count":3},{"next":"to watch your","previous":"touki all your","count":3}]},{"secret_word":"nagasaki","clues":[{"next":"above all very","previous":"a thing in","count":4},{"next":"i had engaged","previous":"in renown in","count":4},{"next":"appeared to me","previous":"old town of","count":4},{"next":"to be taken","previous":"best photographer in","count":4},{"next":"is spread out","previous":"beyond behind them","count":4},{"next":"is at this","previous":"yesterday and all","count":4},{"next":"illumined by moonlight","previous":"immense blue background","count":4},{"next":"in the most","previous":"farthest end of","count":4},{"next":"mesdemoiselles purete orange","previous":"in vogue in","count":3},{"next":"tonight but like","previous":"go down into","count":3},{"next":"arises a sudden","previous":"depths below in","count":3},{"next":"about five or","previous":"fine town of","count":3},{"next":"in the hope","previous":"a steamer at","count":1}]},{"secret_word":"nailles","clues":[{"next":"has the honor","previous":"the baroness de","count":3},{"next":"have long ceased","previous":"of mademoiselle de","count":3},{"next":"having come back","previous":"this madame de","count":3},{"next":"was far from","previous":"to mademoiselle de","count":3},{"next":"had been once","previous":"another jacqueline de","count":3},{"next":"was fanciful and","previous":"that mademoiselle de","count":3},{"next":"has not just","previous":"that mademoiselle de","count":3},{"next":"and authorizing me","previous":"on mademoiselle de","count":3},{"next":"was sent for","previous":"said mademoiselle de","count":3},{"next":"a few days","previous":"keep mademoiselle de","count":3},{"next":"all the summer","previous":"keeping mademoiselle de","count":3},{"next":"her stepdaughter to","previous":"mademoiselle jacqueline de","count":3}]},{"secret_word":"nointel","clues":[{"next":"whose influence was","previous":"and madame de","count":3},{"next":"did not escape","previous":"and madame de","count":3},{"next":"and madame thomery","previous":"the vicomtesse de","count":3},{"next":"is a tax","previous":"the vicomtesse de","count":3},{"next":"let him sit","previous":"of madame de","count":3},{"next":"said with some","previous":"him madame de","count":3},{"next":"of the circle","previous":"asked madame de","count":3},{"next":"with a burst","previous":"added madame de","count":3},{"next":"to her neighbor","previous":"whispered madame de","count":3},{"next":"behind the shelter","previous":"whispered madame de","count":3},{"next":"has wittily named","previous":"circumstance madame de","count":3},{"next":"with the general","previous":"nointel madame de","count":3}]},{"secret_word":"notre","clues":[{"next":"dame des champs","previous":"in the rue","count":15},{"next":"dame des champs","previous":"to the rue","count":4},{"next":"vie est peu","previous":"cher maupertuis que","count":2},{"next":"dame madame in","previous":"the neighbourhood of","count":1},{"next":"brillante capitale o","previous":"on may 'dans","count":1},{"next":"dame was booming","previous":"great bell of","count":1},{"next":"dame des champs","previous":"along the rue","count":1},{"next":"dame des champs","previous":"six bis rue","count":1},{"next":"dame de champs","previous":"s flat in","count":1},{"next":"ame c'est cet","previous":"se plait d'entretenir","count":1},{"next":"dame de carmel","previous":"esprit saint michel","count":1},{"next":"amiti nous ne","previous":"seul qui produit","count":1},{"next":"sang nous m","previous":"indiff rence serait","count":1}]},{"secret_word":"nougarede","clues":[{"next":"expects as madame","previous":"the result monsieur","count":3},{"next":"had given him","previous":"the reasons that","count":3},{"next":"had summoned the","previous":"of madame dammauville","count":3},{"next":"asked him to","previous":"when phillis and","count":3},{"next":"of an affection","previous":"to phillis and","count":3},{"next":"was nothing to","previous":"or disappointment of","count":3},{"next":"should find a","previous":"room and that","count":3},{"next":"and of all","previous":"madame cormier and","count":3},{"next":"he repeated to","previous":"phillis and to","count":3},{"next":"florentin himself whom","previous":"phillis madame cormier","count":3},{"next":"but for himself","previous":"theatre' prepared by","count":2}]},{"secret_word":"nucingen","clues":[{"next":"the middle classes","previous":"the firm of","count":9},{"next":"father goriot pierrette","previous":"the firm of","count":8},{"next":"cousin betty the","previous":"the firm of","count":7},{"next":"a man of","previous":"the firm of","count":6},{"next":"the peasantry blondet","previous":"the firm of","count":4},{"next":"and the marquis","previous":"the baron de","count":2},{"next":"with a wave","previous":"to monsieur de","count":2},{"next":"the dish covers","previous":"showing monsieur de","count":2},{"next":"baron frederic de","previous":"princess cousin betty","count":2},{"next":"and gamble on","previous":"tillet or a","count":2},{"next":"and several less","previous":"la maison de","count":1},{"next":"for la presse","previous":"la maison de","count":1},{"next":"gaudissart felix scenes","previous":"the firm of","count":1}]},{"secret_word":"occur","clues":[{"next":"to him that","previous":"it did not","count":68},{"next":"to me to","previous":"it did not","count":12},{"next":"to him that","previous":"it would never","count":3},{"next":"to him that","previous":"never seems to","count":2},{"next":"the knights of","previous":"this should not","count":1},{"next":"that might win","previous":"an adventure might","count":1},{"next":"to her at","previous":"time did not","count":1},{"next":"to lothario that","previous":"it did not","count":1},{"next":"to me you","previous":"if any accident","count":1},{"next":"so going up","previous":"further misadventure could","count":1},{"next":"to us youth","previous":"circumstances which occasionally","count":1},{"next":"in it and","previous":"translations or mistranslations","count":1}]},{"secret_word":"online","clues":[{"next":"distributed proofreading team","previous":"franks and the","count":134},{"next":"distributed proofreading team","previous":"the project gutenberg","count":114},{"next":"distributed proofreading team","previous":"frank and the","count":41},{"next":"distributed proofreading team","previous":"meehan and the","count":31},{"next":"distributed proofreading team","previous":"and the pg","count":18},{"next":"distributed proofreading team","previous":"produced by the","count":6},{"next":"distributed proofreading team","previous":"garcia and the","count":6},{"next":"distributed proofreading team","previous":"aldarondo and the","count":6},{"next":"distributed proofreading team","previous":"weyant and the","count":5},{"next":"distributed proofreading team","previous":"connal and the","count":4},{"next":"distributed proofreading team","previous":"berger and the","count":3},{"next":"distributed proofreading team","previous":"widger and the","count":3},{"next":"distributed proofreading team","previous":"the project gutenbert","count":2},{"next":"distributed proofreading team","previous":"vergon and the","count":2},{"next":"distributed proofreaders boswell's","previous":"king and the","count":1},{"next":"distributed proofreading team","previous":"moynihan and the","count":1},{"next":"distributed proofreading team","previous":"agren and the","count":1},{"next":"distributed proofreading team","previous":"d'hooghe and the","count":1},{"next":"distributed proofreading team","previous":"ehler and the","count":1}]},{"secret_word":"oyouki","clues":[{"next":"san madame touki","previous":"while her friends","count":4},{"next":"and mademoiselle dede","previous":"are grouped chrysantheme","count":3},{"next":"very taking in","previous":"first comes mademoiselle","count":3},{"next":"some romance slow","previous":"she often teaches","count":3},{"next":"and myself have","previous":"we yves chrysantheme","count":3},{"next":"bursts into our","previous":"moment after mademoiselle","count":3},{"next":"pretty little physiognomies","previous":"silver topknots like","count":3},{"next":"and i in","previous":"town yves chrysantheme","count":3},{"next":"san and mademoiselle","previous":"mademoiselle la neige","count":3},{"next":"or their young","previous":"prune or mademoiselle","count":3},{"next":"with me i","previous":"yves with chrysantheme","count":3},{"next":"with me fraise","previous":"chrysantheme with yves","count":3}]},{"secret_word":"pagodas","clues":[{"next":"which at certain","previous":"and its great","count":4},{"next":"of which the","previous":"of the thousand","count":4},{"next":"its mountains its","previous":"all nagasaki its","count":4},{"next":"where the other","previous":"trees and gloomy","count":4},{"next":"situated in the","previous":"seals for inferior","count":4},{"next":"and mountains i","previous":"marvellous panorama of","count":3},{"next":"down with the","previous":"down with the","count":2},{"next":"of ganjam jeremy","previous":"the three juggernaut","count":1},{"next":"and green dragons","previous":"of mandarins and","count":1},{"next":"or swiss cottages","previous":"water no chinese","count":1},{"next":"were bright and","previous":"chinese dragons and","count":1},{"next":"and the brahmins","previous":"priests in the","count":1}]},{"secret_word":"panine","clues":[{"next":"and not that","previous":"the name of","count":3},{"next":"were just coming","previous":"prince and princess","count":3},{"next":"eager to find","previous":"in short said","count":3},{"next":"what do you","previous":"well then cried","count":3},{"next":"making the young","previous":"am ungrateful interrupted","count":3},{"next":"who was no","previous":"mistress to enlighten","count":3},{"next":"who was at","previous":"sought to save","count":3},{"next":"sadly and believe","previous":"yes madame answered","count":3},{"next":"simply saying read","previous":"handed it to","count":3},{"next":"if the shareholders","previous":"fraud without implicating","count":3},{"next":"a man weeps","previous":"the entire serge","count":1},{"next":"if he looked","previous":"again to serge","count":1}]},{"secret_word":"papillon","clues":[{"next":"is the inevitable","previous":"by turns arthur","count":3},{"next":"pointed out to","previous":"by pere issacar","count":3},{"next":"seated at one","previous":"the lycee arthur","count":3},{"next":"like a frail","previous":"he followed arthur","count":3},{"next":"who paves the","previous":"that day arthur","count":3},{"next":"the distinguished latin","previous":"it is arthur","count":3},{"next":"pointed out to","previous":"these notabilities whom","count":3},{"next":"on the subject","previous":"not attacked arthur","count":3},{"next":"stopped before the","previous":"seated beside arthur","count":3},{"next":"a pedant and","previous":"genuine idiot arthur","count":3},{"next":"who gave him","previous":"carriage with arthur","count":3},{"next":"and so on","previous":"over swimming en","count":2},{"next":"and been very","previous":"dusantoy and miss","count":1}]},{"secret_word":"parva","clues":[{"next":"of the adi","previous":"in the astika","count":24},{"next":"seges satis est","previous":"of this kind","count":2},{"next":"of the sabha","previous":"in the rajasuyika","count":1},{"next":"sed apta mihi","previous":"over ariosto's door","count":1},{"next":"naturalia by w","previous":"de anima with","count":1},{"next":"in the wye","previous":"building at tintern","count":1},{"next":"vaisampayana said beholding","previous":"xxxix sisupala badha","count":1},{"next":"naturaha greek and","previous":"fallacies e poste","count":1},{"next":"vaisampayana said in","previous":"section xxxii rajasuyika","count":1},{"next":"vaisampayana said on","previous":"section xxxv arghyaharana","count":1},{"next":"vaisampayana said when","previous":"section xlv dyuta","count":1},{"next":"in the delta","previous":"behutet or diospolis","count":1}]},{"secret_word":"peppino","clues":[{"next":"ardea words almost","previous":"by saying to","count":3},{"next":"ardea and fanny","previous":"in honor of","count":3},{"next":"ardea i know","previous":"in saying to","count":3},{"next":"that poor alba","previous":"her conversation with","count":3},{"next":"ardea well i","previous":"she said to","count":3},{"next":"countess added he","previous":"leave you to","count":3},{"next":"ardea who will","previous":"i was with","count":3},{"next":"ardea laughing i","previous":"believe me replied","count":3},{"next":"shaking his head","previous":"ah contessina replied","count":3},{"next":"is not worthy","previous":"embraced her saying","count":3},{"next":"said to himself","previous":"cross street while","count":3},{"next":"was were on","previous":"salon in which","count":3}]},{"secret_word":"pernot","clues":[{"next":"weighed heavily upon","previous":"by the abbe","count":3},{"next":"the curate of","previous":"of the abbe","count":3},{"next":"had made up","previous":"of the abbe","count":3},{"next":"himself were made","previous":"to the abbe","count":3},{"next":"and leaning toward","previous":"from the abbe","count":3},{"next":"was walking as","previous":"true the abbe","count":3},{"next":"seated on a","previous":"found the abbe","count":3},{"next":"making a slight","previous":"replied the abbe","count":3},{"next":"who was striding","previous":"across the abbe","count":3},{"next":"inquiringly rolling his","previous":"repeated the abby","count":3},{"next":"flinging to one","previous":"claudet the abbe","count":3}]},{"secret_word":"pierrepont","clues":[{"next":"at the union","previous":"to his son","count":14},{"next":"at harvard university","previous":"to his son","count":6},{"next":"at the scrub","previous":"to his son","count":2},{"next":"afterwards lady mary","previous":"of lady mary","count":1},{"next":"eldest daughter of","previous":"famous lady mary","count":1},{"next":"well i'm headed","previous":"london october dear","count":1},{"next":"yours of the","previous":"london october dear","count":1},{"next":"who is this","previous":"york november dear","count":1},{"next":"if that's what","previous":"boston november dear","count":1},{"next":"i met young","previous":"chicago july dear","count":1},{"next":"i judge from","previous":"chicago september dear","count":1},{"next":"if you happen","previous":"karlsbad october dear","count":1}]},{"secret_word":"pierrette","clues":[{"next":"a study of","previous":"the government clerks","count":11},{"next":"cesar birotteau lost","previous":"nucingen father goriot","count":8},{"next":"melmoth reconciled a","previous":"the middle classes","count":1},{"next":"the seamy side","previous":"the government clerks","count":1},{"next":"lay and went","previous":"the grave where","count":1},{"next":"daily doctor martener","previous":"men think of","count":1},{"next":"quite pretty but","previous":"a girl named","count":1},{"next":"for her journey","previous":"he had given","count":1},{"next":"in her grave","previous":"which laid our","count":1},{"next":"concealed the effects","previous":"is proved that","count":1},{"next":"made him a","previous":"last offices for","count":1},{"next":"the vendetta rouget","previous":"birotteau eugenie grandet","count":1},{"next":"and le cure","previous":"vallee l'illustre gaudissart","count":1}]},{"secret_word":"pietrapertosa","clues":[{"next":"and after her","previous":"of old duchess","count":3},{"next":"when that snob","previous":"of casal interrupted","count":3},{"next":"sententiously one should","previous":"a duel continued","count":3},{"next":"making with his","previous":"was there replied","count":3},{"next":"and cibo who","previous":"he came upon","count":3},{"next":"and the doctor","previous":"had brought cibo","count":3},{"next":"hafner ardea try","previous":"vain did cibo","count":3},{"next":"who did not","previous":"addressing cibo and","count":3},{"next":"and that the","previous":"cibo and of","count":3},{"next":"would have consented","previous":"cibo and that","count":3},{"next":"such preliminaries are","previous":"montfanon cibo and","count":3},{"next":"heedless of cibo's","previous":"her husband said","count":2},{"next":"heedless of cibo","previous":"her husband said","count":1}]},{"secret_word":"planus","clues":[{"next":"had the greatest","previous":"and yet sigismond","count":3},{"next":"came to say","previous":"that moment mademoiselle","count":3},{"next":"entered the room","previous":"that moment mademoiselle","count":3},{"next":"ventured to say","previous":"after all mademoiselle","count":3},{"next":"a melancholy outlook","previous":"so vaunted by","count":3},{"next":"recognize risler aine","previous":"then did mademoiselle","count":3},{"next":"my brother risler","previous":"know beside monsieur","count":3},{"next":"as he dressed","previous":"sister said poor","count":3},{"next":"had no great","previous":"reached that point","count":3},{"next":"was sitting in","previous":"removed untouched mademoiselle","count":3},{"next":"and began to","previous":"everybody looked at","count":3},{"next":"went up to","previous":"garden door mademoiselle","count":3}]},{"secret_word":"plastramengro","clues":[{"next":"went to the","previous":"full moon the","count":3},{"next":"from behind the","previous":"out bolted the","count":3},{"next":"held on like","previous":"not do the","count":3},{"next":"thought of himself","previous":"know what the","count":3},{"next":"which if it","previous":"blow at the","count":3},{"next":"placed himself behind","previous":"brother where the","count":3},{"next":"pulled out his","previous":"lane and the","count":3},{"next":"would never have","previous":"rommany chal the","count":3},{"next":"from bow street","previous":"sent for a","count":2},{"next":"placed himself in","previous":"trees so the","count":2},{"next":"waited behind the","previous":"risen and the","count":2},{"next":"notwithstanding he went","previous":"brother that the","count":2},{"next":"waited behind a","previous":"risen and the","count":1}]},{"secret_word":"plumet","clues":[{"next":"told her you","previous":"her portrait madame","count":3},{"next":"about packing it","previous":"just arranged with","count":3},{"next":"who is sure","previous":"go to madame","count":3},{"next":"who leaned motionless","previous":"turning to madame","count":3},{"next":"to tell me","previous":"shall ask monsieur","count":3},{"next":"in person who","previous":"details from madame","count":3},{"next":"to tell me","previous":"note from madame","count":3},{"next":"unknown to all","previous":"arranged by madame","count":3},{"next":"have locked up","previous":"monsieur and madame","count":3},{"next":"broke in 'excuse","previous":"grasp it madame","count":2},{"next":"he saw a","previous":"the rue de","count":1}]},{"secret_word":"pointers","clues":[{"next":"at the end","previous":"of bookmarks or","count":57},{"next":"during that week","previous":"the older west","count":1},{"next":"had once yapped","previous":"which the colonel's","count":1},{"next":"over the head","previous":"one of my","count":1},{"next":"are useless for","previous":"my north carolina","count":1},{"next":"are not yet","previous":"my poney and","count":1},{"next":"were visible in","previous":"nor the two","count":1},{"next":"as to put","previous":"given me such","count":1},{"next":"might have afforded","previous":"horses greyhounds and","count":1},{"next":"responded the sitter","previous":"chance to get","count":1},{"next":"lying under a","previous":"fiercest of the","count":1},{"next":"and so forth","previous":"artists' colourmen models","count":1}]},{"secret_word":"prerolles","clues":[{"next":"went to visit","previous":"and henri de","count":3},{"next":"it had become","previous":"the lords of","count":3},{"next":"hardly more than","previous":"the tower of","count":3},{"next":"was inscribed in","previous":"the marquis de","count":3},{"next":"in full uniform","previous":"the marquis de","count":3},{"next":"your glorious career","previous":"the marquis de","count":3},{"next":"the next day","previous":"the marquise de","count":3},{"next":"assume this responsibility","previous":"the marquise de","count":3},{"next":"who at that","previous":"asked general de","count":3},{"next":"realized her ideal","previous":"like general de","count":3},{"next":"said the military","previous":"yourself general de","count":3},{"next":"sustained by a","previous":"solicitude henri de","count":3}]},{"secret_word":"prevention","clues":[{"next":"of cruelty to","previous":"society for the","count":20},{"next":"of cruelty to","previous":"bill for the","count":2},{"next":"bill by the","previous":"opposing the cruelty","count":2},{"next":"into holy orders","previous":"all possibility of","count":1},{"next":"though base yet","previous":"him upon a","count":1},{"next":"i shall have","previous":"which without some","count":1},{"next":"of spinsterhood to","previous":"society for the","count":1},{"next":"rather than cure","previous":"be that of","count":1},{"next":"of the same","previous":"before yudhishthira the","count":1},{"next":"of much misery","previous":"providence for the","count":1},{"next":"of your ruin","previous":"authority for the","count":1},{"next":"of capital punishment","previous":"abstinence and the","count":1}]},{"secret_word":"priced","clues":[{"next":"editions re issues","previous":"books in popular","count":21},{"next":"at one shilling","previous":"and might be","count":2},{"next":"at fifty francs","previous":"for gavarnie was","count":2},{"next":"which is of","previous":"the original option","count":1},{"next":"sketches in vaudeville","previous":"of the highest","count":1},{"next":"tenants they enjoyed","previous":"from its highest","count":1},{"next":"rooms with or","previous":"were offered low","count":1},{"next":"articles of everyday","previous":"were instituted low","count":1},{"next":"them a hundred","previous":"them over and","count":1},{"next":"place to live","previous":"want a medium","count":1},{"next":"duties per quarter","previous":"grain at various","count":1},{"next":"and placed house","previous":"send word what","count":1},{"next":"medicines of which","previous":"buy some high","count":1}]},{"secret_word":"project","clues":[{"next":"gutenberg online distributed","previous":"meehan and the","count":18},{"next":"gutenberg edition to","previous":"in the present","count":1},{"next":"applauded his crazy","previous":"with his new","count":1},{"next":"but mine cruel","previous":"out his vile","count":1},{"next":"that of a","previous":"been a favourite","count":1},{"next":"gutenberg in text","previous":"also available from","count":1},{"next":"may appear it","previous":"wild as the","count":1},{"next":"to limit six","previous":"thy horns to","count":1},{"next":"of the duke","previous":"greatly aided the","count":1},{"next":"of removing the","previous":"connected with his","count":1},{"next":"gutenberg distributed proofreaders","previous":"richard prairie and","count":1},{"next":"ready prepared and","previous":"gemma with a","count":1},{"next":"gutenberg online distributed","previous":"maddock and the","count":1}]},{"secret_word":"proofreading","clues":[{"next":"team at http","previous":"the online distributed","count":209},{"next":"team at https","previous":"the online distributed","count":134},{"next":"team https www","previous":"gutenberg online distributed","count":58},{"next":"team http www","previous":"gutenberg online distributed","count":32},{"next":"team html file","previous":"and the distributed","count":1},{"next":"team the story","previous":"the online distributed","count":1},{"next":"team the works","previous":"the online distributed","count":1},{"next":"team the living","previous":"the online distributed","count":1},{"next":"team the abbot's","previous":"the online distributed","count":1},{"next":"team behind a","previous":"the online distributed","count":1},{"next":"team love at","previous":"gutenberg online distributed","count":1},{"next":"team love's shadow","previous":"gutenberg online distributed","count":1},{"next":"team bertha garlan","previous":"gutenberg online distributed","count":1},{"next":"team viviette by","previous":"gutenberg online distributed","count":1},{"next":"team the life","previous":"gutenbert online distributed","count":1}]},{"secret_word":"rameures","clues":[{"next":"or his niece","previous":"the terrible des","count":3},{"next":"but the old","previous":"of the des","count":3},{"next":"may i have","previous":"of monsieur des","count":3},{"next":"frequently occurred in","previous":"name of des","count":3},{"next":"lives much farther","previous":"woman monsieur des","count":3},{"next":"which gives an","previous":"her uncle des","count":3},{"next":"notwithstanding the tender","previous":"their uncle des","count":3},{"next":"is the master","previous":"them for des","count":3},{"next":"but paris is","previous":"my uncle des","count":3},{"next":"and his niece","previous":"those of des","count":3},{"next":"will not hear","previous":"those of des","count":3}]},{"secret_word":"reason","clues":[{"next":"why he should","previous":"there was no","count":53},{"next":"for prompt action","previous":"all the more","count":1},{"next":"about so lucidly","previous":"all he could","count":1},{"next":"and the flow","previous":"this feast of","count":1},{"next":"less a favourite","previous":"was for some","count":1},{"next":"as i can","previous":"there ain't any","count":1},{"next":"a new reason","previous":"you yet the","count":1},{"next":"finished shepler who","previous":"something superior to","count":1},{"next":"why you must","previous":"reason a new","count":1},{"next":"why new york","previous":"us that's no","count":1},{"next":"for descending upon","previous":"uncle peter's true","count":1},{"next":"why you can't","previous":"ain't really any","count":1},{"next":"that the father","previous":"alternative for the","count":1}]},{"secret_word":"redingote","clues":[{"next":"was seated on","previous":"of his black","count":3},{"next":"trimmed with braid","previous":"a long travelling","count":3},{"next":"exhibited a face","previous":"a somewhat shabby","count":3},{"next":"departed regularly every","previous":"in a black","count":3},{"next":"with military buttons","previous":"in his long","count":3},{"next":"and balancing with","previous":"in his travelling","count":3},{"next":"on the buttons","previous":"with his long","count":3},{"next":"the waiting cavalier","previous":"pockets in his","count":3},{"next":"and put on","previous":"buttoned up his","count":3},{"next":"type trimmed with","previous":"of the antiquated","count":1},{"next":"my black trousers","previous":"with my maroon","count":1},{"next":"and loose byron","previous":"light kerseymere breeches","count":1},{"next":"and holding his","previous":"clad in his","count":1}]},{"secret_word":"reign","clues":[{"next":"of george iii","previous":"journal of the","count":36},{"next":"of george iii","previous":"memoirs of the","count":26},{"next":"in the spring","previous":"that during my","count":2},{"next":"in one of","previous":"certainly ceased to","count":2},{"next":"and recover his","previous":"to return to","count":1},{"next":"with science dignifies","previous":"were renown'd whose","count":1},{"next":"to quit she","previous":"length her ancient","count":1},{"next":"translated royal anne","previous":"mortal to immortal","count":1},{"next":"but distant be","previous":"blissful isles to","count":1},{"next":"to all eternity","previous":"ceasing may they","count":1},{"next":"of alfonso vii","previous":"moors in the","count":1},{"next":"of nebuchadnezzar i","previous":"zodiac in the","count":1},{"next":"of that fortuitous","previous":"fabricated in the","count":1}]},{"secret_word":"resurrection","clues":[{"next":"and the life","previous":"i am the","count":26},{"next":"through thoth and","previous":"and of his","count":1},{"next":"of osiris were","previous":"the sufferings and","count":1},{"next":"ascension or atonement","previous":"in no historical","count":1},{"next":"in a corner","previous":"who await the","count":1},{"next":"of altisidora though","previous":"proved by the","count":1},{"next":"of the just","previous":"man and the","count":1},{"next":"of this damsel","previous":"do with the","count":1},{"next":"man of science","previous":"fame trumpets this","count":1},{"next":"of the just","previous":"partake of the","count":1},{"next":"and numerous texts","previous":"persecution murder and","count":1},{"next":"and real fireworks","previous":"crucifixion with the","count":1}]},{"secret_word":"reuilly","clues":[{"next":"was several miles","previous":"the station at","count":3},{"next":"at the close","previous":"the woods of","count":3},{"next":"accompanied by the","previous":"the marquise visited","count":3},{"next":"the chateau on","previous":"his estate at","count":3},{"next":"when his first","previous":"his arrival at","count":3},{"next":"as was his","previous":"he remained at","count":3},{"next":"only once during","previous":"he went to","count":3},{"next":"since her husband","previous":"to live at","count":3},{"next":"the preceding week","previous":"had gone to","count":3},{"next":"and make of","previous":"your wand over","count":3},{"next":"during the summer","previous":"kept him at","count":3},{"next":"if he wished","previous":"immediately required at","count":3},{"next":"remarking in the","previous":"eight days at","count":3}]},{"secret_word":"ribalta","clues":[{"next":"wrapping up his","previous":"the better said","count":3},{"next":"growing more and","previous":"for four insisted","count":3},{"next":"the latter told","previous":"returned it to","count":3},{"next":"had bought the","previous":"to know that","count":3},{"next":"made up his","previous":"greatest care while","count":3},{"next":"who leaping over","previous":"it is said","count":3},{"next":"replied with a","previous":"your inspiration comfortably","count":3},{"next":"arrested tried and","previous":"would undoubtedly have","count":3},{"next":"to morrow and","previous":"anarchist of a","count":3},{"next":"who is ending","previous":"revolutionists like boorish","count":3},{"next":"s in time","previous":"haste to reach","count":1}]},{"secret_word":"roger's","clues":[{"next":"friends are afraid","previous":"some of sir","count":4},{"next":"party has it","previous":"not of sir","count":4},{"next":"servants would ride","previous":"one of sir","count":3},{"next":"dinner almost cold","previous":"my friend sir","count":3},{"next":"upon the coming","previous":"custom at sir","count":3},{"next":"may have created","previous":"enjoy at sir","count":3},{"next":"in the country","previous":"stay at sir","count":3},{"next":"alighting told him","previous":"keeper upon sir","count":3},{"next":"who pretended to","previous":"said of sir","count":2},{"next":"charge are the","previous":"merry on sir","count":2},{"next":"chaplain but actually","previous":"counsellor than sir","count":2},{"next":"false nattering tongue","previous":"deluded away by","count":1}]},{"secret_word":"rommany","clues":[{"next":"chal shall jaw","previous":"chi and the","count":6},{"next":"churl and the","previous":"and sang the","count":4},{"next":"girl to morrow","previous":"churl and the","count":4},{"next":"chal i should","previous":"and become a","count":3},{"next":"chi ' none","previous":"the drom miro","count":3},{"next":"chal after he","previous":"why brother the","count":3},{"next":"chies young fellow","previous":"none of your","count":3},{"next":"chal the plastramengro","previous":"favour of the","count":3},{"next":"chal to escape","previous":"so that the","count":2},{"next":"churl and the","previous":"the gillie the","count":1},{"next":"instead of roman","previous":"is somewhat different","count":1},{"next":"girl love thieving","previous":"churl and the","count":1}]},{"secret_word":"rousselet","clues":[{"next":"he understands all","previous":"and send for","count":3},{"next":"backed out of","previous":"to be repeated","count":3},{"next":"turning to lambernier","previous":"as that observed","count":3},{"next":"that it was","previous":"as well as","count":3},{"next":"more politic than","previous":"themselves as to","count":3},{"next":"is well known","previous":"you madame leonard","count":3},{"next":"said mademoiselle de","previous":"needed no longer","count":3},{"next":"has nothing to","previous":"coachman first that","count":3},{"next":"and that old","previous":"idiot of a","count":3},{"next":"advanced stretching his","previous":"hostilities had begun","count":3}]},{"secret_word":"sam'l","clues":[{"next":"had treated bell","previous":"in thrums that","count":3},{"next":"superintend the fitting","previous":"delicacy that made","count":3},{"next":"dickie trying to","previous":"i remember seeing","count":3},{"next":"would reply but","previous":"i d'na kin","count":3},{"next":"and sanders at","previous":"then praying for","count":3},{"next":"he's a mairit","previous":"gran' prayers but","count":3},{"next":"said sanders soothingly","previous":"a' oor troubles","count":3},{"next":"no to be","previous":"warnin' to ye","count":3},{"next":"in a voice","previous":"sanders sanders said","count":3},{"next":"bending forward and","previous":"sanders laddie said","count":3},{"next":"wilkie respectively a","previous":"silva mcqueen and","count":2},{"next":"todd by himself","previous":"afterward told of","count":1}]},{"secret_word":"sample","clues":[{"next":"the author's ideas","previous":"may wish to","count":57},{"next":"of personal attributes","previous":"by a faultless","count":1},{"next":"room that nothing","previous":"the bigelow house","count":1},{"next":"of beauty and","previous":"was a striking","count":1},{"next":"as soon as","previous":"he gave a","count":1},{"next":"case beside the","previous":"he dropped his","count":1},{"next":"rooms in the","previous":"as against two","count":1},{"next":"of to begin","previous":"have given a","count":1},{"next":"of the two","previous":"we offer a","count":1},{"next":"of my hand","previous":"merely as a","count":1},{"next":"packages of fine","previous":"discreetly at the","count":1},{"next":"of folks said","previous":"masons a curious","count":1}]},{"secret_word":"saniel","clues":[{"next":"accepted all his","previous":"and fetes and","count":3},{"next":"for it manifested","previous":"the change from","count":3},{"next":"had made did","previous":"the connections that","count":3},{"next":"with outstretched hands","previous":"he came to","count":3},{"next":"has originality and","previous":"no chance friend","count":3},{"next":"did not return","previous":"after long years","count":3},{"next":"entered her room","previous":"she was dressing","count":3},{"next":"tried to transform","previous":"she slept that","count":3},{"next":"they were too","previous":"did not please","count":3},{"next":"had felt since","previous":"relative calm that","count":3},{"next":"taking off his","previous":"outstretched hands and","count":3},{"next":"for whom he","previous":"facial neuralgia by","count":3}]},{"secret_word":"savigny","clues":[{"next":"in the vast","previous":"the road to","count":3},{"next":"by the lyon","previous":"to connect with","count":3},{"next":"watched her approach","previous":"to het that","count":3},{"next":"is open to","previous":"one is that","count":3},{"next":"and that i","previous":"things down at","count":3},{"next":"tomorrow and ask","previous":"will go to","count":3},{"next":"in the evening","previous":"sometimes too at","count":3},{"next":"seemed to say","previous":"tightly closed exterior","count":3},{"next":"no matter where","previous":"orleans perhaps to","count":3},{"next":"did for the","previous":"the mollusca what","count":1},{"next":"had to arrive","previous":"i berthe de","count":1},{"next":"delaunay who was","previous":"blanche croizette kissing","count":1}]},{"secret_word":"savinien","clues":[{"next":"rushed forward and","previous":"his aunt enter","count":3},{"next":"and with an","previous":"is here replied","count":3},{"next":"who abashed went","previous":"hand she dismissed","count":3},{"next":"quickly i wish","previous":"my income interrupted","count":3},{"next":"with an indignant","previous":"i want said","count":3},{"next":"followed by marechal","previous":"heard approaching and","count":3},{"next":"and said by","previous":"mistress turned to","count":3},{"next":"like two aides","previous":"stood marechal and","count":3},{"next":"herzog and his","previous":"carriages bearing away","count":3},{"next":"that i a","previous":"idiots marechal sighed","count":3},{"next":"were opened and","previous":"herzog marechal and","count":3},{"next":"de portenduere who","previous":"like his companion","count":1}]},{"secret_word":"schult","clues":[{"next":"having told her","previous":"for goethe fraulein","count":3},{"next":"was false to","previous":"cause that fraulein","count":3},{"next":"and jacqueline to","previous":"habit with fraulein","count":3},{"next":"who was still","previous":"back to fraulein","count":3},{"next":"who was not","previous":"amusement of fraulein","count":3},{"next":"who had known","previous":"intercourse with fraulein","count":3},{"next":"moved much as","previous":"confided to fraulein","count":3},{"next":"who was at","previous":"glanced at fraulein","count":3},{"next":"after listening day","previous":"surprising that fraulein","count":3},{"next":"were well calculated","previous":"propriety of fraulein","count":3},{"next":"who perfidiously day","previous":"wretchedness to fraulein","count":3},{"next":"to imagine something","previous":"jacqueline begged fraulein","count":3}]},{"secret_word":"sciences","clues":[{"next":"morales et politiques","previous":"de l'academie des","count":25},{"next":"have you studied","previous":"the schools what","count":1},{"next":"you must descend","previous":"of the high","count":1},{"next":"especially that one","previous":"of all the","count":1},{"next":"and other knowledge","previous":"was like other","count":1},{"next":"i found him","previous":"study of other","count":1},{"next":"in the world","previous":"most of the","count":1},{"next":"to adorn and","previous":"other languages or","count":1},{"next":"laboriously piecing together","previous":"aid of several","count":1},{"next":"and she must","previous":"rest of the","count":1},{"next":"which is that","previous":"step of the","count":1},{"next":"and took long","previous":"teacher of natural","count":1},{"next":"and cut down","previous":"vessel of the","count":1}]},{"secret_word":"scribner's","clues":[{"next":"sons copyright by","previous":"new york charles","count":11},{"next":"sons published march","previous":"copyright by charles","count":5},{"next":"magazine appeared and","previous":"when the new","count":2},{"next":"sons if he","previous":"house of charles","count":2},{"next":"magazine and mr","previous":"decided to start","count":2},{"next":"sons as stenographer","previous":"employ of charles","count":2},{"next":"sons which mr","previous":"advertisements of charles","count":2},{"next":"magazine saw my","previous":"the editors of","count":1},{"next":"and the broken","previous":"of harper's and","count":1},{"next":"monthly which contains","previous":"was published in","count":1},{"next":"under the title","previous":"in the christmas","count":1},{"next":"magazine to write","previous":"present editor of","count":1},{"next":"harper's and the","previous":"sized magazines namely","count":1}]},{"secret_word":"seamy","clues":[{"next":"side of history","previous":"life honorine the","count":11},{"next":"side of history","previous":"the chouans the","count":10},{"next":"side of history","previous":"s establishment the","count":5},{"next":"side of history","previous":"or choisnel the","count":3},{"next":"side of history","previous":"vicomte de the","count":3},{"next":"side of it","previous":"it was the","count":2},{"next":"side without and","previous":"old wits the","count":1},{"next":"side of me","previous":"to see the","count":1},{"next":"side and the","previous":"material has a","count":1},{"next":"side fate attacking","previous":"lady holme its","count":1},{"next":"side of it","previous":"upon her the","count":1},{"next":"sides where none","previous":"i don't invent","count":1},{"next":"kind of thing","previous":"question about that","count":1}]},{"secret_word":"sejournant","clues":[{"next":"volunteer in the","previous":"of germain claudet","count":3},{"next":"prostrate on her","previous":"was intoned manette","count":3},{"next":"replied julien very","previous":"it is claudet","count":3},{"next":"was outlined against","previous":"form of claudet","count":3},{"next":"said he to","previous":"will inform madame","count":3},{"next":"this picturesque expression","previous":"mouth of madame","count":3},{"next":"so powerful that","previous":"affection for young","count":3},{"next":"who is very","previous":"apply to claudet","count":3},{"next":"with her treacherous","previous":"people this manette","count":3},{"next":"the marriage that","previous":"yesterday to claudet","count":3},{"next":"was busy preparing","previous":"kitchen where manette","count":3},{"next":"and her son","previous":"hostility of manette","count":3}]},{"secret_word":"seniavine","clues":[{"next":"general lariviere perhaps","previous":"with us princess","count":3},{"next":"has a fine","previous":"at night princess","count":3},{"next":"at his left","previous":"to the princess","count":3},{"next":"do you ever","previous":"asked the princess","count":3},{"next":"to the buffet","previous":"you escorted princess","count":3},{"next":"this winter asked","previous":"why the princess","count":3},{"next":"who looking superb","previous":"pure cheeks princess","count":3},{"next":"and madame martin","previous":"seat between princess","count":3},{"next":"he added negligently","previous":"berthier or princess","count":3},{"next":"as a page","previous":"schmoll the princess","count":3},{"next":"madame berthier d'eyzelles","previous":"husband the princess","count":2}]},{"secret_word":"side","clues":[{"next":"of the table","previous":"at the other","count":28},{"next":"of the old","previous":"at the other","count":2},{"next":"announcing him on","previous":"name on one","count":1},{"next":"and climbed a","previous":"on the farther","count":1},{"next":"issues he's too","previous":"on those little","count":1},{"next":"as they denominated","previous":"things on this","count":1},{"next":"line of corn","previous":"well take the","count":1},{"next":"of council bluffs","previous":"right the other","count":1},{"next":"allured him with","previous":"woods at either","count":1},{"next":"street where slovenly","previous":"slowly up a","count":1},{"next":"while the driver","previous":"rails on either","count":1},{"next":"' worth speakin'","previous":"wa'n't any 'this","count":1},{"next":"of their stock","previous":"independents know which","count":1}]},{"secret_word":"sigismond","clues":[{"next":"old friend will","previous":"in an undertone","count":3},{"next":"as became an","previous":"his dealings with","count":3},{"next":"she came to","previous":"when she saw","count":3},{"next":"made himself as","previous":"her room and","count":3},{"next":"planus had the","previous":"away and yet","count":3},{"next":"the effect of","previous":"crowd produced upon","count":3},{"next":"who was still","previous":"passed it to","count":3},{"next":"in an undertone","previous":"again and asked","count":3},{"next":"with beaming face","previous":"yourself said honest","count":3},{"next":"planus returned home","previous":"vengeance never had","count":3},{"next":"were drinking their","previous":"stamp risler and","count":3},{"next":"thought he hasn't","previous":"at the bed","count":2}]},{"secret_word":"sillery","clues":[{"next":"with a jeering","previous":"the amiable paul","count":3},{"next":"who breakfasted with","previous":"old friend paul","count":3},{"next":"by the hand","previous":"to take paul","count":3},{"next":"to him as","previous":"it said paul","count":3},{"next":"each would rise","previous":"called upon by","count":3},{"next":"like an apostate","previous":"its decrees paul","count":3},{"next":"who now held","previous":"among others paul","count":3},{"next":"called his name","previous":"fear and when","count":3},{"next":"had talked of","previous":"violette and paul","count":3},{"next":"the call has","previous":"to all from","count":1},{"next":"niece of la","previous":"oise brulart de","count":1},{"next":"soft and creamy","previous":"verzenay and the","count":1}]},{"secret_word":"souvigny","clues":[{"next":"but how sadly","previous":"the pavement of","count":3},{"next":"told us the","previous":"the lawyer from","count":3},{"next":"but cannon ammunition","previous":"the butts at","count":3},{"next":"and when they","previous":"the grisettes of","count":3},{"next":"on the northern","previous":"of longueval near","count":3},{"next":"who was your","previous":"old lawyer in","count":3},{"next":"is necessary it","previous":"but to leave","count":3},{"next":"was three miles","previous":"at souvigny and","count":3},{"next":"while she is","previous":"no more to","count":3},{"next":"for a short","previous":"i must leave","count":3},{"next":"on the th","previous":"will return to","count":3},{"next":"mobiles killed january","previous":"major of the","count":3},{"next":"or the castles","previous":"episcopal palace of","count":3}]},{"secret_word":"steno","clues":[{"next":"was possessed to","previous":"by which madame","count":3},{"next":"aside and saying","previous":"by taking madame","count":3},{"next":"to give an","previous":"of the villa","count":3},{"next":"from connection with","previous":"of exempting madame","count":3},{"next":"as to her","previous":"in consequence mademoiselle","count":3},{"next":"had seated herself","previous":"he when mademoiselle","count":3},{"next":"aided her by","previous":"more easy madame","count":3},{"next":"to rise from","previous":"she forced alba","count":3},{"next":"while lincoln gave","previous":"seated beside madame","count":3},{"next":"that he was","previous":"arriving at villa","count":3},{"next":"in a mournful","previous":"deserves interrupted alba","count":3},{"next":"at six o'clock","previous":"to the villa","count":2},{"next":"in the green","previous":"here the little","count":1}]},{"secret_word":"storks","clues":[{"next":"are playfully disporting","previous":"a few white","count":4},{"next":"is the most","previous":"with flights of","count":4},{"next":"and they all","previous":"with paintings of","count":4},{"next":"but i am","previous":"groups his charming","count":4},{"next":"painted in gray","previous":"group of two","count":4},{"next":"forming a wreath","previous":"inevitable flight of","count":4},{"next":"in a variety","previous":"paint him some","count":4},{"next":"and humorous subjects","previous":"towels decorated with","count":4},{"next":"are similar to","previous":"automatic painters whose","count":4},{"next":"on a pretty","previous":"pair of charming","count":3},{"next":"walk gravely among","previous":"meadows where the","count":1},{"next":"and water lilies","previous":"screens painted with","count":1}]},{"secret_word":"strahlberg","clues":[{"next":"swept away as","previous":"the stage madame","count":3},{"next":"without any reserve","previous":"was praising madame","count":3},{"next":"but that lady","previous":"to rejoin madame","count":3},{"next":"had frightened her","previous":"her by madame","count":3},{"next":"saying that she","previous":"her against madame","count":3},{"next":"kissed her with","previous":"first story madame","count":3},{"next":"of her expulsion","previous":"intimacy with madame","count":3},{"next":"had leaped over","previous":"or rather madame","count":3},{"next":"now absorbed in","previous":"why was madame","count":3},{"next":"was eager for","previous":"excluded for madame","count":3}]},{"secret_word":"sutherland","clues":[{"next":"charles franks and","previous":"produced by juliet","count":13},{"next":"mary meehan and","previous":"produced by juliet","count":6},{"next":"david widger and","previous":"produced by juliet","count":5},{"next":"charles franks and","previous":"andrea ball juliet","count":4},{"next":"thomas berger and","previous":"andrew templeton juliet","count":2},{"next":"charles franks and","previous":"david king juliet","count":2},{"next":"and baring brothers","previous":"the duke of","count":1},{"next":"is described by","previous":"present duchess of","count":1},{"next":"mary meehan david","previous":"produced by juliet","count":1},{"next":"beth trapaga and","previous":"produced by juliet","count":1},{"next":"tonya allen and","previous":"produced by juliet","count":1},{"next":"josephine paolucci tonya","previous":"andrew templeton juliet","count":1},{"next":"and was created","previous":"elizabeth countess of","count":1}]},{"secret_word":"sylvestre","clues":[{"next":"returned and held","previous":"a moment later","count":3},{"next":"did not seem","previous":"following words which","count":3},{"next":"and i owe","previous":"am quite happy","count":3},{"next":"to tell him","previous":"went to see","count":3},{"next":"is defeated for","previous":"broken for good","count":3},{"next":"stuff them away","previous":"hide your sketches","count":3},{"next":"lampron painter in","previous":"sake and mine","count":3},{"next":"no decidedly it","previous":"nice of you","count":3},{"next":"milan june th","previous":"startling news from","count":3},{"next":"lampron's mother the","previous":"dying wish of","count":2},{"next":"it's a customer","previous":"you are said","count":2}]},{"secret_word":"t'nowhead","clues":[{"next":"knew that the","previous":"the servant and","count":3},{"next":"was master in","previous":"a certain point","count":3},{"next":"to mcquhatty and","previous":"his sweetheart ay","count":3},{"next":"on the sabbath","previous":"set off to","count":3},{"next":"had an invitation","previous":"were burning and","count":3},{"next":"pew so well","previous":"them into the","count":3},{"next":"in an hour","previous":"would be at","count":3},{"next":"has wi' her","previous":"what a life","count":3},{"next":"with his feet","previous":"round the fire","count":3},{"next":"he was never","previous":"steep ascent to","count":3},{"next":"was a little","previous":"pig about which","count":3},{"next":"farmer was the","previous":"brother of the","count":2},{"next":"next morning sanders","previous":"the brae to","count":1}]},{"secret_word":"t'nowhead's","clues":[{"next":"bell reached its","previous":"the courting of","count":3},{"next":"wife who liked","previous":"good will of","count":3},{"next":"bell whom he","previous":"thoughts were of","count":3},{"next":"bell and i","previous":"took to wife","count":3},{"next":"litlins an' no","previous":"fell spoilt crew","count":3},{"next":"bell and that","previous":"thinking of courting","count":3},{"next":"bell and her","previous":"fateful sabbath for","count":3},{"next":"bell but it","previous":"the courting of","count":2},{"next":"bell who had","previous":"it happened that","count":2},{"next":"fields the snow","previous":"clear and from","count":2},{"next":"lassie and i","previous":"finger direct at","count":2},{"next":"pew and gavin's","previous":"as gavin passed","count":1}]},{"secret_word":"talbrun","clues":[{"next":"she said the","previous":"for madame de","count":3},{"next":"were aroused the","previous":"an oscar de","count":3},{"next":"seemed to him","previous":"but the name","count":3},{"next":"was in the","previous":"that madame de","count":3},{"next":"was waiting for","previous":"where madame de","count":3},{"next":"turning her head","previous":"said madame de","count":3},{"next":"said the young","previous":"not monsieur de","count":3},{"next":"might also have","previous":"if madame de","count":3},{"next":"to come in","previous":"beg madame de","count":3},{"next":"and tell her","previous":"see madame de","count":3},{"next":"her pale face","previous":"cried madame de","count":3},{"next":"who had secretly","previous":"bigot of a","count":3}]},{"secret_word":"team","clues":[{"next":"at http www","previous":"online distributed proofreading","count":212},{"next":"two hundred miles","previous":"by a mule","count":1},{"next":"all by herself","previous":"a four horse","count":1},{"next":"without any further","previous":"with all his","count":1},{"next":"and it was","previous":"to water his","count":1},{"next":"wound by with","previous":"as a long","count":1},{"next":"and given them","previous":"visit to his","count":1},{"next":"and pursued their","previous":"could loaded their","count":1},{"next":"of cart horses","previous":"crossing where a","count":1},{"next":"of bays that","previous":"slipped under a","count":1},{"next":"for carriage use","previous":"horses and a","count":1},{"next":"bertha garlan by","previous":"online distributed proofreading","count":1}]},{"secret_word":"thuiliere","clues":[{"next":"and spreading an","previous":"sent from la","count":3},{"next":"the grand chasserot","previous":"day at la","count":3},{"next":"in order to","previous":"be at la","count":3},{"next":"and the same","previous":"visit to la","count":3},{"next":"thought she and","previous":"going to la","count":3},{"next":"and soon reached","previous":"direction of la","count":3},{"next":"rose before him","previous":"roofs of la","count":3},{"next":"while the carriage","previous":"road to la","count":3},{"next":"are pouring forth","previous":"garden of la","count":3},{"next":"one june afternoon","previous":"garden of la","count":3},{"next":"the sending of","previous":"belonging to la","count":3},{"next":"the very certainty","previous":"quarters at la","count":3},{"next":"and i don't","previous":"visits to la","count":2}]},{"secret_word":"tour","clues":[{"next":"to the hebrides","previous":"journal of a","count":55},{"next":"was at some","previous":"an extended european","count":1},{"next":"of his clubs","previous":"made a conscientious","count":1},{"next":"de force that","previous":"is a little","count":1},{"next":"of inspection for","previous":"is on a","count":1},{"next":"through france and","previous":"after his professional","count":1},{"next":"four volumes of","previous":"out of this","count":1},{"next":"of inspection over","previous":"been making a","count":1},{"next":"which is so","previous":"you take a","count":1},{"next":"immediately after the","previous":"off on a","count":1},{"next":"of the walls","previous":"making a little","count":1},{"next":"of were paid","previous":"expenses on the","count":1},{"next":"in the private","previous":"latter the leisurely","count":1}]},{"secret_word":"treport","clues":[{"next":"in charge of","previous":"this time at","count":3},{"next":"in a charming","previous":"two miles from","count":3},{"next":"relating a thousand","previous":"first met at","count":3},{"next":"which make stops","previous":"from paris to","count":3},{"next":"very much because","previous":"i should like","count":3},{"next":"on that train","previous":"every saturday to","count":3},{"next":"he led the","previous":"last summer at","count":3},{"next":"except to invoke","previous":"frequently to visit","count":3},{"next":"is he not","previous":"wermant is at","count":3},{"next":"raoul with his","previous":"wermants came to","count":3},{"next":"but distinct from","previous":"adjoining the fashionable","count":1}]},{"secret_word":"trespasses","clues":[{"next":"as we forgive","previous":"forgive us our","count":12},{"next":"as we forgive","previous":"'forgive us our","count":4},{"next":"neither will your","previous":"not men their","count":3},{"next":"on my lands","previous":"every day committed","count":3},{"next":"your heavenly father","previous":"forgive men their","count":3},{"next":"on your time","previous":"for all my","count":2},{"next":"but as yet","previous":"retrospect my boyish","count":2},{"next":"and i felt","previous":"of other grave","count":1},{"next":"my boy if","previous":"other people s","count":1},{"next":"betray a revolutionary","previous":"established order such","count":1},{"next":"hoping to have","previous":"somebody forgave her","count":1},{"next":"in his neighborhood","previous":"boundaries and cattle","count":1},{"next":"and hawthorne was","previous":"correcting our daily","count":1}]},{"secret_word":"ursule","clues":[{"next":"mirouet a marriage","previous":"a country town","count":9},{"next":"mirouet eugenie grandet","previous":"bachelor s establishment","count":5},{"next":"mirouet a woman","previous":"mistress the peasantry","count":4},{"next":"mirouet a woman","previous":"in life ferragus","count":2},{"next":"mirouet a marriage","previous":"valley father goriot","count":2},{"next":"mirouet maufrigneuse duchesse","previous":"courtesan s life","count":2},{"next":"mirouet eugenie grandet","previous":"the government clerks","count":1},{"next":"we see that","previous":"the case of","count":1},{"next":"mirouet magus elie","previous":"a courtesan's life","count":1},{"next":"mirouet a woman","previous":"eyes the peasantry","count":1},{"next":"mirouet promissory notes","previous":"discoursed upon in","count":1},{"next":"mirouet a woman","previous":"duchesse of langeais","count":1},{"next":"mirouet and les","previous":"menage de garcon","count":1}]},{"secret_word":"v","clues":[{"next":"gm gm v","previous":"by george meredith","count":41},{"next":"chapter vi chapter","previous":"chapter iv chapter","count":28},{"next":"of a back","previous":"and into a","count":1},{"next":"of the shrewd","previous":"and telling chapter","count":1},{"next":"the walk through","previous":"the oak parlour","count":1},{"next":"in which the","previous":"the inn chapter","count":1},{"next":"of his waistcoat","previous":"hand down the","count":1},{"next":"ritables affections taient","previous":"et que ses","count":1},{"next":"cu m'ont r","previous":"parmi lesquels j'ai","count":1},{"next":"nements sont enchain","previous":"candide tous les","count":1},{"next":"ritable succ s","previous":"recueil eut un","count":1},{"next":"lent des analogies","previous":"eprouvons nous r","count":1}]},{"secret_word":"vautrot","clues":[{"next":"had at this","previous":"of the tragedy","count":3},{"next":"as if unconscious","previous":"returned it to","count":3},{"next":"who had so","previous":"to obtain from","count":3},{"next":"heard the sound","previous":"her boudoir and","count":3},{"next":"whose scruples he","previous":"once reverted to","count":3},{"next":"in the meritorious","previous":"therefore in engaging","count":3},{"next":"being careful not","previous":"told her by","count":3},{"next":"baffled like her","previous":"odious suspicions and","count":3},{"next":"humbly who knew","previous":"de camors said","count":3},{"next":"was too prudent","previous":"mystery but as","count":3},{"next":"to her that","previous":"offered to send","count":3},{"next":"had never suspected","previous":"haughtily and though","count":3}]},{"secret_word":"vence","clues":[{"next":"and throw handfuls","previous":"by monsieur paul","count":3},{"next":"has told you","previous":"that monsieur paul","count":3},{"next":"that signs also","previous":"you think monsieur","count":3},{"next":"and bring him","previous":"find him monsieur","count":3},{"next":"wished to introduce","previous":"place when paul","count":3},{"next":"who wishes to","previous":"room for paul","count":3},{"next":"you will go","previous":"madame said paul","count":3},{"next":"i shall not","previous":"madame continued paul","count":3},{"next":"who was near","previous":"sign to paul","count":3},{"next":"with very frivolous","previous":"inspire you monsieur","count":3},{"next":"came into the","previous":"dechartre and paul","count":3},{"next":"said madame martin","previous":"' but monsieur","count":2}]},{"secret_word":"vi","clues":[{"next":"chapter vii chapter","previous":"chapter v chapter","count":28},{"next":"the half of","previous":"of paper chapter","count":1},{"next":"and was rewarded","previous":"that of alfonso","count":1},{"next":"of the diverting","previous":"is continued chapter","count":1},{"next":"had been sent","previous":"fire where charles","count":1},{"next":"volume vii letter","previous":"end of volume","count":1},{"next":"shortly after his","previous":"restored by alfonso","count":1},{"next":"chapter i the","previous":"dark thought book","count":1},{"next":"butternut lane vii","previous":"v on probation","count":1},{"next":"letter xcix abimelech","previous":"volume v volume","count":1},{"next":"of what took","previous":"duly recorded chapter","count":1},{"next":"the half of","previous":"scrap of paper","count":1},{"next":"the minotaur to","previous":"carlyle's mother chapter","count":1}]},{"secret_word":"vicomte","clues":[{"next":"de spoelberch de","previous":"balzac by the","count":21},{"next":"de spoelberch de","previous":"possession of the","count":9},{"next":"de spoelberch de","previous":"d'amour by the","count":3},{"next":"de spoelberch de","previous":"sent by the","count":2},{"next":"de spoelberch de","previous":"collection of the","count":2},{"next":"de spoelberch de","previous":"the scenes the","count":1},{"next":"de spoelberch de","previous":"man as the","count":1},{"next":"de spoelberch de","previous":"hands of the","count":1},{"next":"de spoelberch de","previous":"about and the","count":1},{"next":"de spoelberch de","previous":"add that the","count":1},{"next":"de spoelberch de","previous":"property of the","count":1},{"next":"discovered many other","previous":"quest by the","count":1},{"next":"de spoelberch de","previous":"significant as the","count":1},{"next":"de spoelberche de","previous":"balzac by the","count":1},{"next":"de spoelberch de","previous":"carraud in the","count":1}]},{"secret_word":"vii","clues":[{"next":"chapter viii chapter","previous":"chapter vi chapter","count":28},{"next":"kings xxv etc","previous":"in i kings","count":1},{"next":"centre and watch","previous":"with its henry","count":1},{"next":"of what passed","previous":"whole history chapter","count":1},{"next":"inner hall and","previous":"through the henry","count":1},{"next":"of the second","previous":"ingenious gentleman chapter","count":1},{"next":"an eviction viii","previous":"vi butternut lane","count":1},{"next":"if the reader","previous":"scrutiny of chapter","count":1},{"next":"who certainly is","previous":"emancipation of ferdinand","count":1},{"next":"a disappearance viii","previous":"scrap of paper","count":1},{"next":"as the cid","previous":"reign of alfonso","count":1},{"next":"the first of","previous":"austin gray chapter","count":1}]},{"secret_word":"viii","clues":[{"next":"chapter ix chapter","previous":"chapter vii chapter","count":28},{"next":"ix x xi","previous":"v vi vii","count":8},{"next":"drained the site","previous":"footnote when henry","count":2},{"next":"of the good","previous":"la mancha chapter","count":1},{"next":"and he might","previous":"been a henry","count":1},{"next":"wherein is related","previous":"notable incidents chapter","count":1},{"next":"free grammar school","previous":"master of henry","count":1},{"next":"green lights ix","previous":"vii a disappearance","count":1},{"next":"ambition stirs ix","previous":"vii an eviction","count":1},{"next":"carlyle as man","previous":"vii decadence chapter","count":1},{"next":"children life at","previous":"patriotic poems chapter","count":1},{"next":"anna wenbourne st","previous":"abimelech henley letter","count":1},{"next":"the amiable angler","previous":"georgie howard operator","count":1}]},{"secret_word":"villegry","clues":[{"next":"jacqueline thought nothing","previous":"with madame de","count":3},{"next":"had first introduced","previous":"when madame de","count":3},{"next":"was at pains","previous":"that madame de","count":3},{"next":"leaning back in","previous":"where madame de","count":3},{"next":"with a deep","previous":"said madame de","count":3},{"next":"brought the young","previous":"not madame de","count":3},{"next":"did not talk","previous":"words madame de","count":3},{"next":"was her own","previous":"place madame de","count":3},{"next":"in stead of","previous":"stood madame de","count":3},{"next":"was pouring out","previous":"wearer madame de","count":3},{"next":"had sent to","previous":"gentleman madame de","count":3},{"next":"has sent me","previous":"newcomer madame de","count":3}]},{"secret_word":"vincart","clues":[{"next":"who was lying","previous":"the old man","count":3},{"next":"dozing in his","previous":"the old man","count":3},{"next":"the return to","previous":"to by reine","count":3},{"next":"and the unhappy","previous":"court to reine","count":3},{"next":"farm as unmindful","previous":"could to the","count":3},{"next":"of such treachery","previous":"you accuse mademoiselle","count":3},{"next":"for the last","previous":"without seeing reine","count":3},{"next":"of your return","previous":"company of reine","count":3},{"next":"repeated claudet somewhat","previous":"yes indeed reine","count":3},{"next":"you have relieved","previous":"greatly embarrassed mademoiselle","count":3},{"next":"had sent to","previous":"lilies which mademoiselle","count":3},{"next":"give in explanation","previous":"reasons does mademoiselle","count":3},{"next":"was probably interested","previous":"information that mademoiselle","count":3}]},{"secret_word":"violette","clues":[{"next":"was one went","previous":"of which amedee","count":3},{"next":"was dreamily walking","previous":"this time amedee","count":3},{"next":"enter his studio","previous":"he saw amedee","count":3},{"next":"acting thus by","previous":"only friend amedee","count":3},{"next":"was belated upon","previous":"one evening amedee","count":3},{"next":"incited by jocquelet","previous":"not say that","count":3},{"next":"to this spot","previous":"man urged amedee","count":3},{"next":"above all that","previous":"do not tell","count":3},{"next":"has a never","previous":"see that madame","count":3},{"next":"is almost tempted","previous":"fresh that amedee","count":3},{"next":"and paul sillery","previous":"silvery web amedee","count":3},{"next":"for the first","previous":"surgeon noticed amedee","count":3}]},{"secret_word":"vivey","clues":[{"next":"he made a","previous":"the path to","count":3},{"next":"who comes here","previous":"the shepherd of","count":3},{"next":"tolled for the","previous":"the bells of","count":3},{"next":"and in the","previous":"the park at","count":3},{"next":"seemed more unbearable","previous":"his position at","count":3},{"next":"and tried to","previous":"to returning to","count":3},{"next":"feeling his way","previous":"way back to","count":3},{"next":"after burying at","previous":"himself up at","count":3},{"next":"and i shall","previous":"will return to","count":3},{"next":"and the faint","previous":"defile leading to","count":3},{"next":"going by way","previous":"manette he left","count":3},{"next":"i can't help","previous":"returning despondently to","count":2},{"next":"house which belonged","previous":"and then at","count":1}]},{"secret_word":"wermant","clues":[{"next":"were not wanting","previous":"the three sisters","count":3},{"next":"and the two","previous":"the three demoiselles","count":3},{"next":"or cymier or","previous":"was dancing with","count":3},{"next":"the one who","previous":"on tuesdays raoul","count":3},{"next":"daughter of the","previous":"know that little","count":3},{"next":"crash but those","previous":"suffered by the","count":3},{"next":"to faust and","previous":"fellow compared raoul","count":3},{"next":"elegantly said of","previous":"shelf as raoul","count":3},{"next":"were excellent leaders","previous":"helene and claire","count":3},{"next":"the 'agent de","previous":"the inability of","count":2},{"next":"the 'agent de","previous":"to talk with","count":2},{"next":"gave the best","previous":"don't doubt that","count":2}]},{"secret_word":"why","clues":[{"next":"he should not","previous":"was no reason","count":23},{"next":"you shouldn't have","previous":"i don't see","count":3},{"next":"don't you go","previous":"to take boarders","count":1},{"next":"should i skin","previous":"later to psyche","count":1},{"next":"you can't be","previous":"really any reason","count":1},{"next":"naturally he'd jump","previous":"than she's got","count":1},{"next":"burman isn't as","previous":"i don't see","count":1},{"next":"she was and","previous":"clearly than ever","count":1},{"next":"it's got to","previous":"sound in poker","count":1},{"next":"what's the matter","previous":"hair of the","count":1},{"next":"when she stopped","previous":"glad without knowing","count":1}]},{"secret_word":"wolf","clues":[{"next":"from the door","previous":"to keep the","count":20},{"next":"chased her and","previous":"and a biting","count":1},{"next":"loose among the","previous":"to let the","count":1},{"next":"galley was bearing","previous":"that the she","count":1},{"next":"weary of watching","previous":"as if the","count":1},{"next":"like action and","previous":"on with its","count":1},{"next":"commanded by that","previous":"called the she","count":1},{"next":"and lamb i","previous":"went on for","count":1},{"next":"s eyes from","previous":"sea like a","count":1},{"next":"s mouth as","previous":"dark as a","count":1},{"next":"at all and","previous":"wasn't a biting","count":1},{"next":"s savage howl","previous":"roar the fierce","count":1},{"next":"s skin for","previous":"baldric of sea","count":1}]},{"secret_word":"x","clues":[{"next":"chapter xi chapter","previous":"chapter ix chapter","count":23},{"next":"plus y at","previous":"i should think","count":2},{"next":"y and z","previous":"and of privates","count":1},{"next":"on which the","previous":"the kur'an surah","count":1},{"next":"midnight vigils part","previous":"a french exile","count":1},{"next":"does not suit","previous":"then tender veracious","count":1},{"next":"wherein is related","previous":"seen there chapter","count":1},{"next":"across her breast","previous":"hands in an","count":1},{"next":"of the pleasant","previous":"valiant manchegan chapter","count":1},{"next":"to a five","previous":"signed his famous","count":1},{"next":"condition repaired to","previous":"landlord in the","count":1},{"next":"the princess comes","previous":"stirs ix buttons","count":1}]},{"secret_word":"xi","clues":[{"next":"chapter xii chapter","previous":"chapter x chapter","count":22},{"next":"xii xiii xiv","previous":"viii ix x","count":7},{"next":"of the strange","previous":"are true chapter","count":1},{"next":"the southern cross","previous":"the cove chapter","count":1},{"next":"the state takes","previous":"born king chapter","count":1},{"next":"the southern cross","previous":"in the cove","count":1},{"next":"'for my part","previous":"to conclude speech","count":1},{"next":"xiii five illustrations","previous":"three consecutive letters","count":1},{"next":"the state takes","previous":"comes to grief","count":1},{"next":"you can't play","previous":"x midnight prowlers","count":1},{"next":"it was monday","previous":"jerky eccentric incoherent","count":1},{"next":"of what befell","previous":"sancho panza chapter","count":1}]},{"secret_word":"xii","clues":[{"next":"chapter xiii chapter","previous":"chapter xi chapter","count":21},{"next":"xiii xiv xv","previous":"ix x xi","count":7},{"next":"of sweden to","previous":"march of charles","count":2},{"next":"emperor of the","previous":"tragedy of 'ibrahim","count":2},{"next":"tom turns the","previous":"the southern cross","count":1},{"next":"of the strange","previous":"of death chapter","count":1},{"next":"precy sur oise","previous":"of chantilly chapter","count":1},{"next":"of what a","previous":"certain goatherds chapter","count":1},{"next":"clarke's xiii eight","previous":"takes a hand","count":1},{"next":"vivian read the","previous":"you sybilla chapter","count":1},{"next":"them damn' snake","previous":"play with me","count":1},{"next":"letters on the","previous":"views laureateship chapter","count":1}]},{"secret_word":"xiii","clues":[{"next":"chapter xiv chapter","previous":"chapter xii chapter","count":20},{"next":"xiv xv xvi","previous":"x xi xii","count":5},{"next":"lviii lx lxii","previous":"love x xi","count":1},{"next":"in which is","previous":"the mirrors chapter","count":1},{"next":"eight to six","previous":"hand xii clarke's","count":1},{"next":"cloud sign versus","previous":"them damn' snake","count":1},{"next":"lady de courcy","previous":"reginald de courcy","count":1},{"next":"in which is","previous":"don quixote chapter","count":1},{"next":"madame de la","previous":"turns the tables","count":1},{"next":"five illustrations drawn","previous":"consecutive letters xi","count":1},{"next":"and transcripts of","previous":"cuneiform texts part","count":1},{"next":"plate and ebellog","previous":"cuneiform texts part","count":1}]},{"secret_word":"xiv","clues":[{"next":"chapter xv chapter","previous":"chapter xiii chapter","count":20},{"next":"xv xvi xvii","previous":"xi xii xiii","count":5},{"next":"they would not","previous":"actions of lewis","count":2},{"next":"he lost the","previous":"iii against louis","count":2},{"next":"wherein is continued","previous":"two squires chapter","count":1},{"next":"who said it","previous":"it was lewis","count":1},{"next":"wherein are inserted","previous":"other incidents chapter","count":1},{"next":"in the fog","previous":"de la fontaine","count":1},{"next":"'i make an","previous":"' said lewis","count":1},{"next":"the claim jumpers","previous":"sign versus cupid","count":1},{"next":"idleness xv marking","previous":"eight to six","count":1},{"next":"continues 'mais un","previous":"reign of lewis","count":1}]},{"secret_word":"xix","clues":[{"next":"chapter xx chapter","previous":"chapter xviii chapter","count":17},{"next":"xx xxi xxii","previous":"xvi xvii xviii","count":3},{"next":"mistaking it for","previous":"figure of number","count":2},{"next":"preparations for flight","previous":"the first night","count":1},{"next":"in which is","previous":"the common chapter","count":1},{"next":"evadna goes calling","previous":"the rim rock","count":1},{"next":"in which he","previous":"from the sonnet","count":1},{"next":"century the villa","previous":"beginning of the","count":1},{"next":"of the shrewd","previous":"worth relating chapter","count":1},{"next":"the fight for","previous":"declaration of war","count":1},{"next":"coke clifton to","previous":"volume ii letter","count":1},{"next":"the attack xx","previous":"avenue of maples","count":1},{"next":"c sar s","previous":"sar aut nihil","count":1}]},{"secret_word":"xv","clues":[{"next":"chapter xvi chapter","previous":"chapter xiv chapter","count":20},{"next":"xvi xvii xviii","previous":"xii xiii xiv","count":5},{"next":"squaw talk far","previous":"the claim jumpers","count":1},{"next":"wherein it is","previous":"the grove chapter","count":1},{"next":"nancy xvi madame","previous":"in the fog","count":1},{"next":"gilt boiseries the","previous":"their perfect louis","count":1},{"next":"being delighted with","previous":"place de louis","count":1},{"next":"in which is","previous":"looked for chapter","count":1},{"next":"marking time xvi","previous":"six xiv idleness","count":1},{"next":"driveller juan and","previous":"xiv intransigence lost","count":1},{"next":"and xvi centuries","previous":"sculptures of the","count":1}]},{"secret_word":"xvi","clues":[{"next":"chapter xvii chapter","previous":"chapter xv chapter","count":17},{"next":"xvii xviii xix","previous":"xiii xiv xv","count":5},{"next":"centuries badges of","previous":"the xv and","count":1},{"next":"pity a mask","previous":"the cub slut","count":1},{"next":"he meant his","previous":"the transgressor chapter","count":1},{"next":"don't get excited","previous":"off heap smart","count":1},{"next":"lewis xviii and","previous":"children afterwards lewis","count":1},{"next":"of what befell","previous":"squire were chapter","count":1},{"next":"miss bobinet's xvii","previous":"xv marking time","count":1},{"next":"of what happened","previous":"heartless yanguesans chapter","count":1},{"next":"vous qui n'avez","previous":"en occuper louis","count":1},{"next":"madame at the","previous":"fog xv nancy","count":1}]},{"secret_word":"xvii","clues":[{"next":"chapter xviii chapter","previous":"chapter xvi chapter","count":17},{"next":"xviii xix xx","previous":"xiv xv xvi","count":3},{"next":"wherein is shown","previous":"la mancha chapter","count":1},{"next":"evil days xviii","previous":"of a pope","count":1},{"next":"in which are","previous":"a castle chapter","count":1},{"next":"the stuffed owl","previous":"in charleville chapter","count":1},{"next":"the marquis leaves","previous":"at the inn","count":1},{"next":"voyage to lisbon","previous":"law reform chapter","count":1},{"next":"xxviii xxxiii lxvi","previous":"self love i","count":1},{"next":"behind the twinkling","previous":"xvi miss bobinet's","count":1},{"next":"first victory xviii","previous":"mask of cowardice","count":1},{"next":"the red angel","previous":"dragon s grandmother","count":1},{"next":"the honourable mrs","previous":"abimelech henley letter","count":1}]},{"secret_word":"xviii","clues":[{"next":"chapter xix chapter","previous":"chapter xvii chapter","count":17},{"next":"and she was","previous":"days of louis","count":3},{"next":"xix xx xxi","previous":"xv xvi xvii","count":3},{"next":"of what happened","previous":"the lions chapter","count":1},{"next":"the first night","previous":"the twinkling lights","count":1},{"next":"the avenue of","previous":"the inn chapter","count":1},{"next":"in which is","previous":"a castle chapter","count":1},{"next":"the avenue of","previous":"on the inn","count":1},{"next":"a shot from","previous":"little target practice","count":1},{"next":"civ i ff","previous":"footnote compare psalms","count":1},{"next":"and charles x","previous":"lewis xvi lewis","count":1}]},{"secret_word":"yves","clues":[{"next":"than for me","previous":"not more for","count":4},{"next":"and i in","previous":"we shall go","count":4},{"next":"and the two","previous":"once more with","count":4},{"next":"has any feeling","previous":"me than for","count":4},{"next":"who will not","previous":"therefore come for","count":4},{"next":"am quite disposed","previous":"about my poor","count":4},{"next":"and chrysantheme i","previous":"the parting between","count":3},{"next":"chrysantheme madame prune","previous":"a helping hand","count":3},{"next":"chrysantheme oyouki and","previous":"to the town","count":3},{"next":"about chrysantheme it","previous":"to speak to","count":3},{"next":"of bygone days","previous":"finding my stanch","count":3},{"next":"who in visiting","previous":"thieves fashion remarks","count":3}]},{"secret_word":"zibeline","clues":[{"next":"who had come","previous":"and he beheld","count":3},{"next":"on the litter","previous":"the general placed","count":3},{"next":"on the subject","previous":"the mystery surrounding","count":3},{"next":"apparently intended to","previous":"the grand stand","count":3},{"next":"had gone over","previous":"of the shock","count":3},{"next":"awaited the three","previous":"a bridge where","count":3},{"next":"at the end","previous":"he should find","count":3},{"next":"riding with their","previous":"not to find","count":3},{"next":"and i have","previous":"last night said","count":3},{"next":"on the other","previous":"fence landed beside","count":3},{"next":"lay then he","previous":"mattress on which","count":3},{"next":"by phillipe de","previous":"by david widger","count":1}]}]
\ No newline at end of file
--- /dev/null
+create table if not exists app_users (
+ id serial primary key,
+ username text not null unique,
+ password_hash text not null,
+ created_at timestamptz not null default now()
+);
+
+create table if not exists project (
+ id serial primary key,
+ name text not null,
+ description text not null default '',
+ created_at timestamptz not null default now()
+);
+
+create table if not exists task (
+ id serial primary key,
+ project_id int not null references project(id) on delete cascade,
+ title text not null,
+ description text not null default '',
+ status text not null default 'todo' check (status in ('todo', 'doing', 'done')),
+ assignee text not null default '',
+ assignees text not null default '',
+ due_date date,
+ created_at timestamptz not null default now()
+);
+
+alter table task add column if not exists assignees text not null default '';
+
+create table if not exists session (
+ token text primary key,
+ user_id int not null references app_users(id) on delete cascade,
+ expires_at timestamptz not null
+);
--- /dev/null
+name = "server"
+version = "1.0.0"
+
+# Fill out these fields if you intend to generate HTML documentation or publish
+# your project to the Hex package manager.
+#
+# description = ""
+# licences = ["Apache-2.0"]
+# repository = { type = "github", user = "", repo = "" }
+# links = [{ title = "Website", href = "" }]
+#
+# For a full reference of all the available options, you can have a look at
+# https://gleam.run/writing-gleam/gleam-toml/.
+
+[dependencies]
+gleam_stdlib = ">= 1.0.0 and < 2.0.0"
+gleam_erlang = ">= 1.3.0 and < 2.0.0"
+gleam_otp = ">= 1.3.0 and < 2.0.0"
+gleam_http = ">= 4.4.0 and < 5.0.0"
+lustre = ">= 5.7.1 and < 6.0.0"
+mist = ">= 6.0.3 and < 7.0.0"
+simplifile = ">= 2.7.0 and < 3.0.0"
+shared = { path = "../shared" }
+gleam_json = ">= 3.1.0 and < 4.0.0"
+birl = ">= 2.0.0 and < 3.0.0"
+wisp = ">= 2.2.2 and < 3.0.0"
+pog = ">= 4.1.0 and < 5.0.0"
+envoy = ">= 1.0.0 and < 2.0.0"
+squirrel = ">= 4.7.0 and < 5.0.0"
+gleam_crypto = ">= 1.5.0 and < 2.0.0"
+
+[dev_dependencies]
+gleeunit = ">= 1.0.0 and < 2.0.0"
+gsh = ">= 1.1.9 and < 2.0.0"
--- /dev/null
+build:
+ cd ../client && gleam run -m lustre/dev build --outdir=../server/static --no-html=true
+ cd -
+
+run: build
+ gleam run
+
--- /dev/null
+# Do not manually edit this file, it is managed by Gleam.
+#
+# This file locks the dependency versions used, to make your build
+# deterministic and to prevent unexpected versions from being included
+# in your application.
+#
+# You should check this file into your source control repository.
+
+packages = [
+ { name = "argv", version = "1.1.0", build_tools = ["gleam"], requirements = [], otp_app = "argv", source = "hex", outer_checksum = "3277D100448BDB4A29B6D58C0F36F631CBC349E8BDD09766C6309DF202831140" },
+ { name = "backoff", version = "1.1.6", build_tools = ["rebar3"], requirements = [], otp_app = "backoff", source = "hex", outer_checksum = "CF0CFFF8995FB20562F822E5CC47D8CCF664C5ECDC26A684CBE85C225F9D7C39" },
+ { name = "birl", version = "2.0.0", build_tools = ["gleam"], requirements = ["gleam_regexp", "gleam_stdlib", "gleam_time", "ranger"], otp_app = "birl", source = "hex", outer_checksum = "51F9D18050231ED8A324A5A87C07F2582E22C1CA8BBDEC213623A7B39AF060F1" },
+ { name = "contour", version = "1.2.1", build_tools = ["gleam"], requirements = ["gleam_community_ansi", "gleam_stdlib", "glexer", "houdini"], otp_app = "contour", source = "hex", outer_checksum = "C7895472BBAAC5D15DBDBAF6DD1847F6981F2F6132F726BAD30434A6E3BAAB95" },
+ { name = "directories", version = "1.2.0", build_tools = ["gleam"], requirements = ["envoy", "gleam_stdlib", "platform", "simplifile"], otp_app = "directories", source = "hex", outer_checksum = "D13090CFCDF6759B87217E8DDD73A75903A700148A82C1D33799F333E249BF9E" },
+ { name = "envoy", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "envoy", source = "hex", outer_checksum = "9C6FBB6BFA02A52798BEEC5977A738CAD6E4A057F4B67FD0C8061AD2502C191A" },
+ { name = "etch", version = "1.4.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "etch", source = "hex", outer_checksum = "A4B4458EE1E7D22753538C03F0D64C930309863365D2D26570E2D2C6B7CFC5EA" },
+ { name = "etch_erlang", version = "1.1.0", build_tools = ["gleam"], requirements = ["etch", "gleam_erlang", "gleam_stdlib"], otp_app = "etch_erlang", source = "hex", outer_checksum = "CDD5BCBF680A97AF979EF1FD18F4E39E64DA2D7938422DEF938A69F26B38BF32" },
+ { name = "eval", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "eval", source = "hex", outer_checksum = "264DAF4B49DF807F303CA4A4E4EBC012070429E40BE384C58FE094C4958F9BDA" },
+ { name = "exception", version = "2.1.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "exception", source = "hex", outer_checksum = "6BDEA95248093599391C3B5DF1835C5C6A86C353C2F99CE539B450E3432FE117" },
+ { name = "filepath", version = "1.1.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "B06A9AF0BF10E51401D64B98E4B627F1D2E48C154967DA7AF4D0914780A6D40A" },
+ { name = "format", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "format", source = "hex", outer_checksum = "7654EE35E01394BF558F364542F163941A66CBA1512AA7D53F2A794BBD90BD9D" },
+ { name = "glam", version = "2.0.4", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "glam", source = "hex", outer_checksum = "48A043A12091F93D911C316DD8F7FFD03CD9FF6F50848FC56E359D3C168DF0FA" },
+ { name = "glance", version = "7.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "glexer"], otp_app = "glance", source = "hex", outer_checksum = "EA52986965408D43003A1760E41457493EB96098DE193E6AD8646930EC190CB9" },
+ { name = "gleam_community_ansi", version = "1.5.0", build_tools = ["gleam"], requirements = ["gleam_community_colour", "gleam_regexp", "gleam_stdlib"], otp_app = "gleam_community_ansi", source = "hex", outer_checksum = "B5AA433AF84313E23FDF90CCFF752B9380FE9FFCE02B2949D49B7AACCC77B16D" },
+ { name = "gleam_community_colour", version = "2.0.4", build_tools = ["gleam"], requirements = ["gleam_json", "gleam_stdlib"], otp_app = "gleam_community_colour", source = "hex", outer_checksum = "6DB4665555D7D2B27F0EA32EF47E8BEBC4303821765F9C73D483F38EE24894F0" },
+ { name = "gleam_crypto", version = "1.6.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_crypto", source = "hex", outer_checksum = "2DE9E4EF53CF6FEE049D4F765731F7178F7A11AEFAE00EEE63BF7536B354AD3F" },
+ { name = "gleam_erlang", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "1124AD3AA21143E5AF0FC5CF3D9529F6DB8CA03E43A55711B60B6B7B3874375C" },
+ { name = "gleam_http", version = "4.4.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_http", source = "hex", outer_checksum = "F065CE9941A7756ABBAEAE7F9F32A96CAD29DA3311A381DB2D926EA8E8C156DC" },
+ { name = "gleam_json", version = "3.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_json", source = "hex", outer_checksum = "44FDAA8847BE8FC48CA7A1C089706BD54BADCC4C45B237A992EDDF9F2CDB2836" },
+ { name = "gleam_otp", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "gleam_otp", source = "hex", outer_checksum = "DE4CA6850842F0266EE95317A25DD6A0A0F20CDFAB7C0ADC2E63251D7C3C72EC" },
+ { name = "gleam_regexp", version = "1.1.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_regexp", source = "hex", outer_checksum = "9C215C6CA84A5B35BB934A9B61A9A306EC743153BE2B0425A0D032E477B062A9" },
+ { name = "gleam_stdlib", version = "1.0.5", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "CEE5B6C076A85B45F60C585F4316C63EC8B7127C119D5738C3958A9C4D50404E" },
+ { name = "gleam_time", version = "1.10.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_time", source = "hex", outer_checksum = "56539216E4C4B1748714652AB38F0BD16B9101F61DB62769FDC7CD42A8E5E833" },
+ { name = "gleam_yielder", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_yielder", source = "hex", outer_checksum = "8E4E4ECFA7982859F430C57F549200C7749823C106759F4A19A78AEA6687717A" },
+ { name = "gleeunit", version = "1.11.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "EC31ABA74256AEA531EDF8169931D775BBB384FED0A8A1BDC4DD9354E3E21826" },
+ { name = "glexer", version = "2.5.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "splitter"], otp_app = "glexer", source = "hex", outer_checksum = "D423CF63B8D4F9654EF53D0AF4904B249EB0679BD41C63440170AC508C9CC65E" },
+ { name = "glisten", version = "9.0.1", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_otp", "gleam_stdlib", "logging"], otp_app = "glisten", source = "hex", outer_checksum = "7795AA50830656F3A0316A6B26595F893C83272DA901B3405E31339CAA31A10B" },
+ { name = "gramps", version = "6.0.1", build_tools = ["gleam"], requirements = ["gleam_crypto", "gleam_erlang", "gleam_http", "gleam_stdlib"], otp_app = "gramps", source = "hex", outer_checksum = "D55636072DEE173F6586A5679D3C02EC7A0DE3F8646B78C351B72908FF223DF7" },
+ { name = "gsh", version = "1.1.9", build_tools = ["gleam"], requirements = ["contour", "etch", "etch_erlang", "format", "glance", "gleam_erlang", "gleam_json", "gleam_stdlib", "glexer", "in", "shellout", "simplifile", "tom"], otp_app = "gsh", source = "hex", outer_checksum = "8342B1CBA3430EA727D7D82D8AF11DAB85E79B446D8BE0B5A5A45E240F9C5AB1" },
+ { name = "houdini", version = "1.2.1", build_tools = ["gleam"], requirements = [], otp_app = "houdini", source = "hex", outer_checksum = "6F8AC2F12974567FB744BEA66AC93CEB76AAEA19AD28564623F76CDA9BC26A85" },
+ { name = "hpack_erl", version = "0.3.0", build_tools = ["rebar3"], requirements = [], otp_app = "hpack", source = "hex", outer_checksum = "D6137D7079169D8C485C6962DFE261AF5B9EF60FBC557344511C1E65E3D95FB0" },
+ { name = "in", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "in", source = "hex", outer_checksum = "5339494529936AF83EAA0B8368195DCA9505382836CDED4CD6B0F5F9FA93C2B8" },
+ { name = "justin", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "justin", source = "hex", outer_checksum = "8B1C62269E8607D0A0ED698B7903984CE0BF7B6B3C0DEA3C6C8302B39402837B" },
+ { name = "logging", version = "1.5.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "logging", source = "hex", outer_checksum = "BC5F18CE5DD9686100229FE5409BDC3DD5C46D5A7DF2F804AD2D8F0DD6C5060E" },
+ { name = "lustre", version = "5.7.1", build_tools = ["gleam"], requirements = ["exception", "gleam_erlang", "gleam_json", "gleam_otp", "gleam_stdlib", "houdini"], otp_app = "lustre", source = "hex", outer_checksum = "663A2D1A3458914CA537A42AC07E601DD3FD85415EBDAF4717F2DFF6E86F90F9" },
+ { name = "marceau", version = "1.3.0", build_tools = ["gleam"], requirements = [], otp_app = "marceau", source = "hex", outer_checksum = "2D1C27504BEF45005F5DFB18591F8610FB4BFA91744878210BDC464412EC44E9" },
+ { name = "mist", version = "6.0.3", build_tools = ["gleam"], requirements = ["exception", "gleam_erlang", "gleam_http", "gleam_otp", "gleam_stdlib", "glisten", "gramps", "hpack_erl", "logging"], otp_app = "mist", source = "hex", outer_checksum = "1B07F321D5FA0CB162D81496F2DE96AEB6EF8980F4F38230A4CC3F849497E020" },
+ { name = "mug", version = "3.1.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "mug", source = "hex", outer_checksum = "C01279D98E40371DA23461774B63F0E3581B8F1396049D881B0C7EB32799D93F" },
+ { name = "non_empty_list", version = "2.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "non_empty_list", source = "hex", outer_checksum = "06F9D3AC751CF7853AD5D24B8139CEB30E42D8799DE8D49F966A6197DF0B01CC" },
+ { name = "opentelemetry_api", version = "1.5.0", build_tools = ["rebar3", "mix"], requirements = [], otp_app = "opentelemetry_api", source = "hex", outer_checksum = "F53EC8A1337AE4A487D43AC89DA4BD3A3C99DDF576655D071DEED8B56A2D5DDA" },
+ { name = "pg_types", version = "0.6.0", build_tools = ["rebar3"], requirements = [], otp_app = "pg_types", source = "hex", outer_checksum = "9949A4849DD13408FA249AB7B745E0D2DFDB9532AEE2B9722326E33CD082A778" },
+ { name = "pgo", version = "0.20.0", build_tools = ["rebar3"], requirements = ["backoff", "opentelemetry_api", "pg_types"], otp_app = "pgo", source = "hex", outer_checksum = "2F11E6649CEB38E569EF56B16BE1D04874AE5B11A02867080A2817CE423C683B" },
+ { name = "platform", version = "1.0.0", build_tools = ["gleam"], requirements = [], otp_app = "platform", source = "hex", outer_checksum = "8339420A95AD89AAC0F82F4C3DB8DD401041742D6C3F46132A8739F6AEB75391" },
+ { name = "pog", version = "4.1.0", build_tools = ["gleam"], requirements = ["exception", "gleam_erlang", "gleam_otp", "gleam_stdlib", "gleam_time", "pgo"], otp_app = "pog", source = "hex", outer_checksum = "E4AFBA39A5FAA2E77291836C9683ADE882E65A06AB28CA7D61AE7A3AD61EBBD5" },
+ { name = "ranger", version = "1.4.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "gleam_yielder"], otp_app = "ranger", source = "hex", outer_checksum = "C8988E8F8CDBD3E7F4D8F2E663EF76490390899C2B2885A6432E942495B3E854" },
+ { name = "shared", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_json", "gleam_stdlib", "simplifile"], source = "local", path = "../shared" },
+ { name = "shellout", version = "1.8.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "shellout", source = "hex", outer_checksum = "C416356D45151F298108C9DB9CD1EDE0313F620B5EDBB5766CD7237659D87841" },
+ { name = "simplifile", version = "2.7.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "A2727627B063E87351934C7F7F008F2D1FDB16F6DE0B8C79F9E46459CFC9C164" },
+ { name = "splitter", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "splitter", source = "hex", outer_checksum = "8F1485306E0D59168A39E12ED8844F9F616EC59C3C63AFCFDAE04DBD68690CBC" },
+ { name = "squirrel", version = "4.7.0", build_tools = ["gleam"], requirements = ["argv", "envoy", "eval", "filepath", "glam", "gleam_community_ansi", "gleam_crypto", "gleam_json", "gleam_regexp", "gleam_stdlib", "gleam_time", "glexer", "justin", "mug", "non_empty_list", "pog", "simplifile", "splitter", "term_size", "tom", "tote", "youid"], otp_app = "squirrel", source = "hex", outer_checksum = "DD7D42F5EFE5E0FF597CF6D8E770C6327A7B10589BFCD3144EDC852AE2F6F0DE" },
+ { name = "term_size", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "term_size", source = "hex", outer_checksum = "D00BD2BC8FB3EBB7E6AE076F3F1FF2AC9D5ED1805F004D0896C784D06C6645F1" },
+ { name = "tom", version = "2.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "gleam_time"], otp_app = "tom", source = "hex", outer_checksum = "DCF04CB7AB35D58CFC598C66EA2E1816D160759802C89B2BA6238780D59BC256" },
+ { name = "tote", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "tote", source = "hex", outer_checksum = "30CBB77B72867B1DE2D271A7FE61DBE8BB81CA7DC385A0E1FDF7D38E71F3791A" },
+ { name = "wisp", version = "2.2.2", build_tools = ["gleam"], requirements = ["directories", "exception", "filepath", "gleam_crypto", "gleam_erlang", "gleam_http", "gleam_json", "gleam_stdlib", "houdini", "logging", "marceau", "mist", "simplifile"], otp_app = "wisp", source = "hex", outer_checksum = "5FF5F1E288C3437252ABB93D8F9CF42FF652CE7AD54480CFE736038DC09C4F22" },
+ { name = "youid", version = "1.6.0", build_tools = ["gleam"], requirements = ["gleam_crypto", "gleam_stdlib", "gleam_time"], otp_app = "youid", source = "hex", outer_checksum = "7A3ABA44B1B38BC2BDCB5474C5317AA372BE58DFBC649815EE08B03526DDA18D" },
+]
+
+[requirements]
+birl = { version = ">= 2.0.0 and < 3.0.0" }
+envoy = { version = ">= 1.0.0 and < 2.0.0" }
+gleam_crypto = { version = ">= 1.5.0 and < 2.0.0" }
+gleam_erlang = { version = ">= 1.3.0 and < 2.0.0" }
+gleam_http = { version = ">= 4.4.0 and < 5.0.0" }
+gleam_json = { version = ">= 3.1.0 and < 4.0.0" }
+gleam_otp = { version = ">= 1.3.0 and < 2.0.0" }
+gleam_stdlib = { version = ">= 1.0.0 and < 2.0.0" }
+gleeunit = { version = ">= 1.0.0 and < 2.0.0" }
+gsh = { version = ">= 1.1.9 and < 2.0.0" }
+lustre = { version = ">= 5.7.1 and < 6.0.0" }
+mist = { version = ">= 6.0.3 and < 7.0.0" }
+pog = { version = ">= 4.1.0 and < 5.0.0" }
+shared = { path = "../shared" }
+simplifile = { version = ">= 2.7.0 and < 3.0.0" }
+squirrel = { version = ">= 4.7.0 and < 5.0.0" }
+wisp = { version = ">= 2.2.2 and < 3.0.0" }
--- /dev/null
+import envoy
+import gleam/erlang/process
+import gleam/otp/static_supervisor
+import gleam/result
+import pog
+
+pub type Database {
+ Database(connection: pog.Connection)
+}
+
+pub fn start() -> Result(Database, Nil) {
+ let name = process.new_name("iron_claw_db")
+ echo "getting url"
+ use url <- result.try(envoy.get("DATABASE_URL"))
+ echo url
+ use config <- result.try(pog.url_config(name, url))
+ echo "config"
+ let assert Ok(_) =
+ static_supervisor.new(static_supervisor.OneForOne)
+ |> static_supervisor.add(pog.supervised(config))
+ |> static_supervisor.start
+ Ok(Database(pog.named_connection(name)))
+}
--- /dev/null
+import database.{type Database}
+import envoy
+import gleam/bit_array
+import gleam/crypto
+import gleam/erlang/process
+import gleam/http
+import gleam/int
+import gleam/io
+import gleam/json
+import gleam/list
+import gleam/result
+import gleam/string
+import mist
+import pog
+import shared
+import simplifile
+import sql
+import wisp.{type Request, type Response}
+import wisp/wisp_mist
+
+pub fn main() -> Nil {
+ wisp.configure_logger()
+ let assert Ok(db) = database.start()
+ let assert Ok(schema) = simplifile.read("./db/init.sql")
+ let assert Ok(_) = initialize_schema(db, schema)
+ let secret =
+ envoy.get("SESSION_SECRET")
+ |> result.unwrap("iron-claw-development-secret-change-me")
+ let assert Ok(_) =
+ handle_request(db, _)
+ |> wisp_mist.handler(secret)
+ |> mist.new
+ |> mist.port(
+ envoy.get("PORT")
+ |> result.unwrap("3000")
+ |> int.parse
+ |> result.unwrap(3000),
+ )
+ |> mist.start
+ process.sleep_forever()
+}
+
+fn initialize_schema(
+ db: Database,
+ schema: String,
+) -> Result(Nil, pog.QueryError) {
+ schema
+ |> string.split(";")
+ |> list.map(string.trim)
+ |> list.filter(fn(statement) { statement != "" })
+ |> list.try_fold(Nil, fn(_, statement) {
+ pog.query(statement)
+ |> pog.execute(db.connection)
+ |> result.map(fn(_) { Nil })
+ })
+}
+
+fn handle_request(db: Database, request: Request) -> Response {
+ use req <- middleware(request)
+ case req.method, wisp.path_segments(req) {
+ http.Get, [] -> shell()
+ http.Get, ["login"] -> shell()
+ http.Get, ["register"] -> shell()
+ http.Get, ["api", "dashboard"] -> api_dashboard(db, req)
+ http.Get, ["api", "logout"] -> logout(req)
+ http.Post, ["api", "login"] ->
+ json_body(req, fn(body) { login(db, req, body) })
+ http.Post, ["api", "register"] ->
+ json_body(req, fn(body) { register(db, req, body) })
+ http.Post, ["api", "projects"] ->
+ json_body(req, fn(body) { add_project(db, req, body) })
+ http.Post, ["api", "projects", project_id, "tasks"] ->
+ json_body(req, fn(body) { add_task(db, req, project_id, body) })
+ http.Post, ["api", "tasks", task_id, "status"] ->
+ json_body(req, fn(body) { change_status(db, req, task_id, body) })
+ _, _ -> wisp.not_found()
+ }
+}
+
+fn middleware(req: Request, next: fn(Request) -> Response) -> Response {
+ use <- wisp.log_request(req)
+ use <- wisp.rescue_crashes
+ wisp.handle_head(req, fn(req) {
+ wisp.serve_static(req, under: "/static", from: "./static", next: fn() {
+ next(req)
+ })
+ })
+}
+
+fn shell() -> Response {
+ wisp.html_response(
+ "<!doctype html><html><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"><title>Iron Claw</title><script type=\"module\" src=\"/static/client.js\"></script></head><body><div id=\"app\"></div></body></html>",
+ 200,
+ )
+}
+
+fn api_dashboard(db: Database, req: Request) -> Response {
+ case current_user(db, req) {
+ Error(_) -> wisp.json_response("{\"error\":\"unauthorized\"}", 401)
+ Ok(username) -> {
+ let projects =
+ rows([], sql.list_projects(db.connection))
+ |> list.map(fn(project: sql.Project) {
+ shared.Project(
+ id: project.id,
+ name: project.name,
+ description: project.description,
+ tasks: rows([], sql.list_tasks(db.connection, project.id))
+ |> list.map(to_shared_task),
+ )
+ })
+ shared.Dashboard(username:, projects:)
+ |> shared.dashboard_json
+ |> json.to_string
+ |> wisp.json_response(200)
+ }
+ }
+}
+
+fn login(db: Database, req: Request, body: String) -> Response {
+ case json.parse(body, shared.credentials_decoder()) {
+ Ok(credentials) ->
+ case sql.find_user(db.connection, credentials.username) {
+ Ok(pog.Returned(_, [user])) ->
+ case secure_compare(user.password_hash, credentials.password) {
+ True -> start_session(db, req, user.id)
+ False ->
+ wisp.json_response("{\"error\":\"invalid credentials\"}", 401)
+ }
+ _ -> wisp.json_response("{\"error\":\"invalid credentials\"}", 401)
+ }
+ Error(_) -> wisp.json_response("{\"error\":\"invalid JSON\"}", 400)
+ }
+}
+
+fn register(db: Database, req: Request, body: String) -> Response {
+ case json.parse(body, shared.credentials_decoder()) {
+ Ok(credentials) ->
+ case
+ string.length(credentials.username) >= 3
+ && string.length(credentials.password) >= 8
+ {
+ True ->
+ case
+ sql.create_user(
+ db.connection,
+ credentials.username,
+ password_hash(credentials.password),
+ )
+ {
+ Ok(pog.Returned(_, [user_id])) -> start_session(db, req, user_id)
+ Error(error) -> registration_error(error)
+ Ok(_) ->
+ wisp.json_response("{\"error\":\"username unavailable\"}", 409)
+ }
+
+ False ->
+ wisp.json_response(
+ "{\"error\":\"username and password are required\"}",
+ 400,
+ )
+ }
+ _ ->
+ wisp.json_response(
+ "{\"error\":\"username and password are required\"}",
+ 400,
+ )
+ }
+}
+
+fn registration_error(error: pog.QueryError) -> Response {
+ case error {
+ pog.ConstraintViolated(_, _, _) ->
+ wisp.json_response("{\"error\":\"username unavailable\"}", 409)
+ _ -> {
+ io.println("registration database error: " <> query_error_name(error))
+ wisp.json_response("{\"error\":\"database unavailable\"}", 503)
+ }
+ }
+}
+
+fn query_error_name(error: pog.QueryError) -> String {
+ case error {
+ pog.ConstraintViolated(message, _, _) -> message
+ pog.PostgresqlError(_, name, message) -> name <> ": " <> message
+ pog.UnexpectedArgumentCount(_, _) -> "unexpected argument count"
+ pog.UnexpectedArgumentType(_, _) -> "unexpected argument type"
+ pog.UnexpectedResultType(_) -> "unexpected result type"
+ pog.QueryTimeout -> "query timeout"
+ pog.ConnectionUnavailable -> "connection unavailable"
+ }
+}
+
+fn start_session(db: Database, req: Request, user_id: Int) -> Response {
+ let token = wisp.random_string(48)
+ let assert Ok(_) = sql.create_session(db.connection, token, user_id)
+ wisp.json_response("{\"ok\":true}", 200)
+ |> wisp.set_cookie(req, "session", token, wisp.Signed, 2_592_000)
+}
+
+fn add_project(db: Database, req: Request, body: String) -> Response {
+ case current_user(db, req), json.parse(body, shared.new_project_decoder()) {
+ Ok(_), Ok(project) -> {
+ let assert Ok(_) =
+ sql.create_project(db.connection, project.name, project.description)
+ wisp.json_response("{\"ok\":true}", 201)
+ }
+ _, _ -> wisp.json_response("{\"error\":\"unauthorized\"}", 401)
+ }
+}
+
+fn add_task(
+ db: Database,
+ req: Request,
+ project_id: String,
+ body: String,
+) -> Response {
+ case
+ current_user(db, req),
+ int.parse(project_id),
+ json.parse(body, shared.new_task_decoder())
+ {
+ Ok(_), Ok(id), Ok(task) -> {
+ let assert Ok(_) =
+ sql.create_task(
+ db.connection,
+ id,
+ task.title,
+ task.description,
+ task.assignee,
+ task.assignees,
+ task.due_date,
+ )
+ wisp.json_response("{\"ok\":true}", 201)
+ }
+ _, _, _ -> wisp.json_response("{\"error\":\"invalid request\"}", 400)
+ }
+}
+
+fn change_status(
+ db: Database,
+ req: Request,
+ task_id: String,
+ body: String,
+) -> Response {
+ case
+ current_user(db, req),
+ int.parse(task_id),
+ json.parse(body, shared.status_change_decoder())
+ {
+ Ok(_), Ok(id), Ok(change) -> {
+ let assert Ok(_) =
+ sql.update_task_status(db.connection, change.status, id)
+ wisp.json_response("{\"ok\":true}", 200)
+ }
+ _, _, _ -> wisp.json_response("{\"error\":\"invalid request\"}", 400)
+ }
+}
+
+fn logout(req: Request) -> Response {
+ wisp.json_response("{\"ok\":true}", 200)
+ |> wisp.set_cookie(req, "session", "", wisp.Signed, 0)
+}
+
+fn json_body(req: Request, next: fn(String) -> Response) -> Response {
+ wisp.require_string_body(req, next)
+}
+
+fn current_user(db: Database, req: Request) -> Result(String, Nil) {
+ use token <- result.try(wisp.get_cookie(req, "session", wisp.Signed))
+ echo token
+ case sql.find_session(db.connection, token) {
+ Ok(pog.Returned(_, [user_id])) ->
+ case sql.find_username(db.connection, user_id) {
+ Ok(pog.Returned(_, [username])) -> Ok(username)
+ _ -> Error(Nil)
+ }
+ _ -> Error(Nil)
+ }
+}
+
+fn to_shared_task(task: sql.Task) -> shared.Task {
+ shared.Task(
+ id: task.id,
+ project_id: task.project_id,
+ title: task.title,
+ description: task.description,
+ status: task.status,
+ assignee: task.assignee,
+ assignees: task.assignees,
+ due_date: task.due_date,
+ )
+}
+
+fn rows(
+ default: List(a),
+ value: Result(pog.Returned(a), pog.QueryError),
+) -> List(a) {
+ case value {
+ Ok(pog.Returned(_, values)) -> values
+ Error(_) -> default
+ }
+}
+
+fn password_hash(password: String) -> String {
+ crypto.hash(crypto.Sha512, <<password:utf8>>)
+ |> bit_array.base64_encode(False)
+}
+
+fn secure_compare(stored: String, password: String) -> Bool {
+ stored == password_hash(password)
+}
--- /dev/null
+import gleam/dynamic/decode
+import pog
+
+pub type User {
+ User(id: Int, username: String, password_hash: String)
+}
+
+pub type Project {
+ Project(id: Int, name: String, description: String)
+}
+
+pub type Task {
+ Task(
+ id: Int,
+ project_id: Int,
+ title: String,
+ description: String,
+ status: String,
+ assignee: String,
+ assignees: String,
+ due_date: String,
+ )
+}
+
+pub fn create_user(
+ db: pog.Connection,
+ username: String,
+ password_hash: String,
+) {
+ "insert into app_users (username, password_hash) values ($1, $2) returning id"
+ |> pog.query
+ |> pog.parameter(pog.text(username))
+ |> pog.parameter(pog.text(password_hash))
+ |> pog.returning(decode.field(0, decode.int, decode.success))
+ |> pog.execute(db)
+}
+
+pub fn find_user(db: pog.Connection, username: String) {
+ "select id, username, password_hash from app_users where username = $1"
+ |> pog.query
+ |> pog.parameter(pog.text(username))
+ |> pog.returning({
+ use id <- decode.field(0, decode.int)
+ use username <- decode.field(1, decode.string)
+ use password_hash <- decode.field(2, decode.string)
+ decode.success(User(id:, username:, password_hash:))
+ })
+ |> pog.execute(db)
+}
+
+pub fn find_username(db: pog.Connection, user_id: Int) {
+ "select username from app_users where id = $1"
+ |> pog.query
+ |> pog.parameter(pog.int(user_id))
+ |> pog.returning(decode.field(0, decode.string, decode.success))
+ |> pog.execute(db)
+}
+
+pub fn list_projects(db: pog.Connection) {
+ "select id, name, description from project order by created_at desc, id desc"
+ |> pog.query
+ |> pog.returning({
+ use id <- decode.field(0, decode.int)
+ use name <- decode.field(1, decode.string)
+ use description <- decode.field(2, decode.string)
+ decode.success(Project(id:, name:, description:))
+ })
+ |> pog.execute(db)
+}
+
+pub fn create_project(db: pog.Connection, name: String, description: String) {
+ "insert into project (name, description) values ($1, $2) returning id, name, description"
+ |> pog.query
+ |> pog.parameter(pog.text(name))
+ |> pog.parameter(pog.text(description))
+ |> pog.returning({
+ use id <- decode.field(0, decode.int)
+ use name <- decode.field(1, decode.string)
+ use description <- decode.field(2, decode.string)
+ decode.success(Project(id:, name:, description:))
+ })
+ |> pog.execute(db)
+}
+
+pub fn list_tasks(db: pog.Connection, project_id: Int) {
+ "select id, project_id, title, description, status, assignee, assignees, coalesce(due_date::text, '') from task where project_id = $1 order by case status when 'doing' then 0 when 'todo' then 1 else 2 end, created_at desc"
+ |> pog.query
+ |> pog.parameter(pog.int(project_id))
+ |> pog.returning({
+ use id <- decode.field(0, decode.int)
+ use project_id <- decode.field(1, decode.int)
+ use title <- decode.field(2, decode.string)
+ use description <- decode.field(3, decode.string)
+ use status <- decode.field(4, decode.string)
+ use assignee <- decode.field(5, decode.string)
+ use assignees <- decode.field(6, decode.string)
+ use due_date <- decode.field(7, decode.string)
+ decode.success(Task(
+ id:,
+ project_id:,
+ title:,
+ description:,
+ status:,
+ assignee:,
+ assignees:,
+ due_date:,
+ ))
+ })
+ |> pog.execute(db)
+}
+
+pub fn create_task(
+ db: pog.Connection,
+ project_id: Int,
+ title: String,
+ description: String,
+ assignee: String,
+ assignees: String,
+ due_date: String,
+) {
+ "insert into task (project_id, title, description, assignee, assignees, due_date) values ($1, $2, $3, $4, $5, nullif($6, '')::date) returning id"
+ |> pog.query
+ |> pog.parameter(pog.int(project_id))
+ |> pog.parameter(pog.text(title))
+ |> pog.parameter(pog.text(description))
+ |> pog.parameter(pog.text(assignee))
+ |> pog.parameter(pog.text(assignees))
+ |> pog.parameter(pog.text(due_date))
+ |> pog.returning(decode.field(0, decode.int, decode.success))
+ |> pog.execute(db)
+}
+
+pub fn update_task_status(db: pog.Connection, status: String, task_id: Int) {
+ "update task set status = $1 where id = $2"
+ |> pog.query
+ |> pog.parameter(pog.text(status))
+ |> pog.parameter(pog.int(task_id))
+ |> pog.execute(db)
+}
+
+pub fn create_session(db: pog.Connection, token: String, user_id: Int) {
+ "insert into session (token, user_id, expires_at) values ($1, $2, now() + interval '30 days')"
+ |> pog.query
+ |> pog.parameter(pog.text(token))
+ |> pog.parameter(pog.int(user_id))
+ |> pog.execute(db)
+}
+
+pub fn find_session(db: pog.Connection, token: String) {
+ "select user_id from session where token = $1 and expires_at > now()"
+ |> pog.query
+ |> pog.parameter(pog.text(token))
+ |> pog.returning(decode.field(0, decode.int, decode.success))
+ |> pog.execute(db)
+}
--- /dev/null
+insert into project (name, description)
+values ($1, $2)
+returning id, name, description
--- /dev/null
+insert into session (token, user_id, expires_at)
+values ($1, $2, now() + interval '30 days')
--- /dev/null
+insert into task (project_id, title, description, assignee, assignees, due_date)
+values ($1, $2, $3, $4, $5, nullif($6, '')::date)
+returning id
--- /dev/null
+insert into app_user (username, password_hash)
+values ($1, $2)
+on conflict (username) do nothing
+returning id
--- /dev/null
+select user_id
+from session
+where token = $1 and expires_at > now()
--- /dev/null
+select id, username, password_hash
+from app_user
+where username = $1
--- /dev/null
+select id, name, description
+from project
+order by created_at desc, id desc
--- /dev/null
+select id, project_id, title, description, status, assignee, assignees, coalesce(due_date::text, '')
+from task
+where project_id = $1
+order by
+ case status when 'doing' then 0 when 'todo' then 1 else 2 end,
+ created_at desc
--- /dev/null
+update task
+set status = $1
+where id = $2
--- /dev/null
+// build/dev/javascript/prelude.mjs
+class CustomType {
+ withFields(fields) {
+ let properties = Object.keys(this).map((label) => (label in fields) ? fields[label] : this[label]);
+ return new this.constructor(...properties);
+ }
+}
+
+class List {
+ static fromArray(array, tail) {
+ return toList(array, tail);
+ }
+ [Symbol.iterator]() {
+ return new ListIterator(this);
+ }
+ toArray() {
+ return [...this];
+ }
+ atLeastLength(desired) {
+ let current = this;
+ while (desired-- > 0 && current)
+ current = current.tail;
+ return current !== undefined;
+ }
+ hasLength(desired) {
+ let current = this;
+ while (desired-- > 0 && current)
+ current = current.tail;
+ return desired === -1 && current instanceof Empty;
+ }
+ countLength() {
+ let current = this;
+ let length = 0;
+ while (current) {
+ current = current.tail;
+ length++;
+ }
+ return length - 1;
+ }
+}
+function prepend(element, tail) {
+ return new NonEmpty(element, tail);
+}
+function toList(elements, tail) {
+ let t = tail || List$Empty$const;
+ for (let i = elements.length - 1;i >= 0; --i) {
+ t = new NonEmpty(elements[i], t);
+ }
+ return t;
+}
+
+class ListIterator {
+ #current;
+ constructor(current) {
+ this.#current = current;
+ }
+ next() {
+ if (this.#current instanceof Empty) {
+ return { done: true };
+ } else {
+ let { head, tail } = this.#current;
+ this.#current = tail;
+ return { value: head, done: false };
+ }
+ }
+}
+
+class Empty extends List {
+}
+var List$Empty$const = new Empty;
+var List$Empty = () => List$Empty$const;
+var List$isEmpty = (value) => value instanceof Empty;
+
+class NonEmpty extends List {
+ constructor(head, tail) {
+ super();
+ this.head = head;
+ this.tail = tail;
+ }
+}
+var List$NonEmpty = (head, tail) => new NonEmpty(head, tail);
+var List$isNonEmpty = (value) => value instanceof NonEmpty;
+var List$NonEmpty$first = (value) => value.head;
+var List$NonEmpty$rest = (value) => value.tail;
+
+class BitArray {
+ bitSize;
+ byteSize;
+ bitOffset;
+ rawBuffer;
+ constructor(buffer, bitSize, bitOffset) {
+ if (!(buffer instanceof Uint8Array)) {
+ throw globalThis.Error("BitArray can only be constructed from a Uint8Array");
+ }
+ this.bitSize = bitSize ?? buffer.length * 8;
+ this.byteSize = Math.trunc((this.bitSize + 7) / 8);
+ this.bitOffset = bitOffset ?? 0;
+ if (this.bitSize < 0) {
+ throw globalThis.Error(`BitArray bit size is invalid: ${this.bitSize}`);
+ }
+ if (this.bitOffset < 0 || this.bitOffset > 7) {
+ throw globalThis.Error(`BitArray bit offset is invalid: ${this.bitOffset}`);
+ }
+ if (buffer.length !== Math.trunc((this.bitOffset + this.bitSize + 7) / 8)) {
+ throw globalThis.Error("BitArray buffer length is invalid");
+ }
+ this.rawBuffer = buffer;
+ }
+ byteAt(index) {
+ if (index < 0 || index >= this.byteSize) {
+ return;
+ }
+ return bitArrayByteAt(this.rawBuffer, this.bitOffset, index);
+ }
+ equals(other) {
+ if (this.bitSize !== other.bitSize) {
+ return false;
+ }
+ const wholeByteCount = Math.trunc(this.bitSize / 8);
+ if (this.bitOffset === 0 && other.bitOffset === 0) {
+ for (let i = 0;i < wholeByteCount; i++) {
+ if (this.rawBuffer[i] !== other.rawBuffer[i]) {
+ return false;
+ }
+ }
+ const trailingBitsCount = this.bitSize % 8;
+ if (trailingBitsCount) {
+ const unusedLowBitCount = 8 - trailingBitsCount;
+ if (this.rawBuffer[wholeByteCount] >> unusedLowBitCount !== other.rawBuffer[wholeByteCount] >> unusedLowBitCount) {
+ return false;
+ }
+ }
+ } else {
+ for (let i = 0;i < wholeByteCount; i++) {
+ const a = bitArrayByteAt(this.rawBuffer, this.bitOffset, i);
+ const b = bitArrayByteAt(other.rawBuffer, other.bitOffset, i);
+ if (a !== b) {
+ return false;
+ }
+ }
+ const trailingBitsCount = this.bitSize % 8;
+ if (trailingBitsCount) {
+ const a = bitArrayByteAt(this.rawBuffer, this.bitOffset, wholeByteCount);
+ const b = bitArrayByteAt(other.rawBuffer, other.bitOffset, wholeByteCount);
+ const unusedLowBitCount = 8 - trailingBitsCount;
+ if (a >> unusedLowBitCount !== b >> unusedLowBitCount) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+ get buffer() {
+ if (this.bitOffset !== 0 || this.bitSize % 8 !== 0) {
+ throw new globalThis.Error("BitArray.buffer does not support unaligned bit arrays");
+ }
+ return this.rawBuffer;
+ }
+ get length() {
+ if (this.bitOffset !== 0 || this.bitSize % 8 !== 0) {
+ throw new globalThis.Error("BitArray.length does not support unaligned bit arrays");
+ }
+ return this.rawBuffer.length;
+ }
+}
+function bitArrayByteAt(buffer, bitOffset, index) {
+ if (bitOffset === 0) {
+ return buffer[index] ?? 0;
+ } else {
+ const a = buffer[index] << bitOffset & 255;
+ const b = buffer[index + 1] >> 8 - bitOffset;
+ return a | b;
+ }
+}
+
+class UtfCodepoint {
+ constructor(value) {
+ this.value = value;
+ }
+}
+class Result extends CustomType {
+ static isResult(data) {
+ return data instanceof Result;
+ }
+}
+
+class Ok extends Result {
+ constructor(value) {
+ super();
+ this[0] = value;
+ }
+ isOk() {
+ return true;
+ }
+}
+var Result$Ok = (value) => new Ok(value);
+var Result$isOk = (value) => value instanceof Ok;
+var Result$Ok$0 = (value) => value[0];
+
+class Error2 extends Result {
+ constructor(detail) {
+ super();
+ this[0] = detail;
+ }
+ isOk() {
+ return false;
+ }
+}
+var Result$Error = (detail) => new Error2(detail);
+var Result$isError = (value) => value instanceof Error2;
+function isEqual(x, y) {
+ let values = [x, y];
+ while (values.length) {
+ let a = values.pop();
+ let b = values.pop();
+ if (a === b)
+ continue;
+ if (!isObject(a) || !isObject(b))
+ return false;
+ let unequal = !structurallyCompatibleObjects(a, b) || unequalDates(a, b) || unequalBuffers(a, b) || unequalArrays(a, b) || unequalMaps(a, b) || unequalSets(a, b) || unequalRegExps(a, b);
+ if (unequal)
+ return false;
+ const proto = Object.getPrototypeOf(a);
+ if (proto !== null && typeof proto.equals === "function") {
+ try {
+ if (a.equals(b))
+ continue;
+ else
+ return false;
+ } catch {}
+ }
+ let [keys, get] = getters(a);
+ const ka = keys(a);
+ const kb = keys(b);
+ if (ka.length !== kb.length)
+ return false;
+ for (let k of ka) {
+ values.push(get(a, k), get(b, k));
+ }
+ }
+ return true;
+}
+function getters(object) {
+ if (object instanceof Map) {
+ return [(x) => x.keys(), (x, y) => x.get(y)];
+ } else {
+ let extra = object instanceof globalThis.Error ? ["message"] : [];
+ return [(x) => [...extra, ...Object.keys(x)], (x, y) => x[y]];
+ }
+}
+function unequalDates(a, b) {
+ return a instanceof Date && (a > b || a < b);
+}
+function unequalBuffers(a, b) {
+ return !(a instanceof BitArray) && a.buffer instanceof ArrayBuffer && a.BYTES_PER_ELEMENT && !(a.byteLength === b.byteLength && a.every((n, i) => n === b[i]));
+}
+function unequalArrays(a, b) {
+ return Array.isArray(a) && a.length !== b.length;
+}
+function unequalMaps(a, b) {
+ return a instanceof Map && a.size !== b.size;
+}
+function unequalSets(a, b) {
+ return a instanceof Set && (a.size != b.size || [...a].some((e) => !b.has(e)));
+}
+function unequalRegExps(a, b) {
+ return a instanceof RegExp && (a.source !== b.source || a.flags !== b.flags);
+}
+function isObject(a) {
+ return typeof a === "object" && a !== null;
+}
+function structurallyCompatibleObjects(a, b) {
+ if (typeof a !== "object" && typeof b !== "object" && (!a || !b))
+ return false;
+ let nonstructural = [Promise, WeakSet, WeakMap, Function];
+ if (nonstructural.some((c) => a instanceof c))
+ return false;
+ return a.constructor === b.constructor;
+}
+function makeError(variant, file, module, line, fn, message, extra) {
+ let error = new globalThis.Error(message);
+ error.gleam_error = variant;
+ error.file = file;
+ error.module = module;
+ error.line = line;
+ error.function = fn;
+ error.fn = fn;
+ for (let k in extra)
+ error[k] = extra[k];
+ return error;
+}
+// build/dev/javascript/gleam_stdlib/dict.mjs
+var referenceMap = /* @__PURE__ */ new WeakMap;
+var tempDataView = /* @__PURE__ */ new DataView(/* @__PURE__ */ new ArrayBuffer(8));
+var referenceUID = 0;
+function hashByReference(o) {
+ const known = referenceMap.get(o);
+ if (known !== undefined) {
+ return known;
+ }
+ const hash = referenceUID++;
+ if (referenceUID === 2147483647) {
+ referenceUID = 0;
+ }
+ referenceMap.set(o, hash);
+ return hash;
+}
+function hashMerge(a, b) {
+ return a ^ b + 2654435769 + (a << 6) + (a >> 2) | 0;
+}
+function hashString(s) {
+ let hash = 0;
+ const len = s.length;
+ for (let i = 0;i < len; i++) {
+ hash = Math.imul(31, hash) + s.charCodeAt(i) | 0;
+ }
+ return hash;
+}
+function hashNumber(n) {
+ tempDataView.setFloat64(0, n);
+ const i = tempDataView.getInt32(0);
+ const j = tempDataView.getInt32(4);
+ return Math.imul(73244475, i >> 16 ^ i) ^ j;
+}
+function hashBigInt(n) {
+ return hashString(n.toString());
+}
+function hashObject(o) {
+ const proto = Object.getPrototypeOf(o);
+ if (proto !== null && typeof proto.hashCode === "function") {
+ try {
+ const code = o.hashCode(o);
+ if (typeof code === "number") {
+ return code;
+ }
+ } catch {}
+ }
+ if (o instanceof Promise || o instanceof WeakSet || o instanceof WeakMap) {
+ return hashByReference(o);
+ }
+ if (o instanceof Date) {
+ return hashNumber(o.getTime());
+ }
+ let h = 0;
+ if (o instanceof ArrayBuffer) {
+ o = new Uint8Array(o);
+ }
+ if (Array.isArray(o) || o instanceof Uint8Array) {
+ for (let i = 0;i < o.length; i++) {
+ h = Math.imul(31, h) + getHash(o[i]) | 0;
+ }
+ } else if (o instanceof Set) {
+ o.forEach((v) => {
+ h = h + getHash(v) | 0;
+ });
+ } else if (o instanceof Map) {
+ o.forEach((v, k) => {
+ h = h + hashMerge(getHash(v), getHash(k)) | 0;
+ });
+ } else {
+ const keys = Object.keys(o);
+ for (let i = 0;i < keys.length; i++) {
+ const k = keys[i];
+ const v = o[k];
+ h = h + hashMerge(getHash(v), hashString(k)) | 0;
+ }
+ }
+ return h;
+}
+function getHash(u) {
+ if (u === null)
+ return 1108378658;
+ if (u === undefined)
+ return 1108378659;
+ if (u === true)
+ return 1108378657;
+ if (u === false)
+ return 1108378656;
+ switch (typeof u) {
+ case "number":
+ return hashNumber(u);
+ case "string":
+ return hashString(u);
+ case "bigint":
+ return hashBigInt(u);
+ case "object":
+ return hashObject(u);
+ case "symbol":
+ return hashByReference(u);
+ case "function":
+ return hashByReference(u);
+ default:
+ return 0;
+ }
+}
+
+class Dict {
+ constructor(size, root) {
+ this.size = size;
+ this.root = root;
+ }
+}
+var bits = 5;
+var mask = (1 << bits) - 1;
+var noElementMarker = Symbol();
+
+class Node {
+ constructor(generation, datamap, nodemap, data) {
+ this.datamap = datamap;
+ this.nodemap = nodemap;
+ this.data = data;
+ this.generation = generation;
+ }
+ equals(other) {
+ if (this === other)
+ return true;
+ if (!(other instanceof Node))
+ return false;
+ if (this.datamap !== other.datamap || this.nodemap !== other.nodemap) {
+ return false;
+ }
+ const leftData = this.data;
+ const rightData = other.data;
+ if (leftData.length !== rightData.length)
+ return false;
+ if (this.datamap === 0 && this.nodemap === 0) {
+ return this.#equalsOverflowEntries(rightData);
+ }
+ const edgesStart = leftData.length - popcount(this.nodemap);
+ for (let i = 0;i < edgesStart; i += 2) {
+ if (!isEqual(leftData[i], rightData[i]) || !isEqual(leftData[i + 1], rightData[i + 1])) {
+ return false;
+ }
+ }
+ for (let i = edgesStart;i < leftData.length; ++i) {
+ if (!leftData[i].equals(rightData[i]))
+ return false;
+ }
+ return true;
+ }
+ #equalsOverflowEntries(otherData) {
+ const data = this.data;
+ entries:
+ for (let i = 0;i < data.length; i += 2) {
+ for (let j = 0;j < otherData.length; j += 2) {
+ if (isEqual(data[i], otherData[j])) {
+ if (!isEqual(data[i + 1], otherData[j + 1]))
+ return false;
+ continue entries;
+ }
+ }
+ return false;
+ }
+ return true;
+ }
+ hashCode() {
+ const data = this.data;
+ const edgesStart = data.length - popcount(this.nodemap);
+ let hash = 0;
+ for (let i = 0;i < edgesStart; i += 2) {
+ hash = hash + hashMerge(getHash(data[i + 1]), getHash(data[i])) | 0;
+ }
+ for (let i = edgesStart;i < data.length; ++i) {
+ hash = hash + data[i].hashCode() | 0;
+ }
+ return hash;
+ }
+}
+var emptyNode = /* @__PURE__ */ newNode(0);
+var emptyDict = /* @__PURE__ */ new Dict(0, emptyNode);
+var errorNil = /* @__PURE__ */ Result$Error(undefined);
+function newNode(generation) {
+ return new Node(generation, 0, 0, []);
+}
+function copyNode(node, generation) {
+ if (node.generation === generation) {
+ return node;
+ }
+ const newData = node.data.slice(0);
+ return new Node(generation, node.datamap, node.nodemap, newData);
+}
+function copyAndSet(node, generation, idx, val) {
+ if (node.data[idx] === val) {
+ return node;
+ }
+ node = copyNode(node, generation);
+ node.data[idx] = val;
+ return node;
+}
+function copyAndInsertPair(node, generation, bit, idx, key, val) {
+ const data = node.data;
+ const length = data.length;
+ const newData = new Array(length + 2);
+ let readIndex = 0;
+ let writeIndex = 0;
+ while (readIndex < idx)
+ newData[writeIndex++] = data[readIndex++];
+ newData[writeIndex++] = key;
+ newData[writeIndex++] = val;
+ while (readIndex < length)
+ newData[writeIndex++] = data[readIndex++];
+ return new Node(generation, node.datamap | bit, node.nodemap, newData);
+}
+function copyAndRemovePair(node, generation, bit, idx) {
+ node = copyNode(node, generation);
+ const data = node.data;
+ const length = data.length;
+ for (let w = idx, r = idx + 2;r < length; ++r, ++w) {
+ data[w] = data[r];
+ }
+ data.pop();
+ data.pop();
+ node.datamap ^= bit;
+ return node;
+}
+function make() {
+ return emptyDict;
+}
+function get(dict, key) {
+ const result = lookup(dict.root, key, getHash(key));
+ return result !== noElementMarker ? Result$Ok(result) : errorNil;
+}
+function lookup(node, key, hash) {
+ for (let shift = 0;shift < 32; shift += bits) {
+ const data = node.data;
+ const bit = hashbit(hash, shift);
+ if (node.nodemap & bit) {
+ node = data[data.length - 1 - index(node.nodemap, bit)];
+ } else if (node.datamap & bit) {
+ const dataidx = Math.imul(index(node.datamap, bit), 2);
+ return isEqual(key, data[dataidx]) ? data[dataidx + 1] : noElementMarker;
+ } else {
+ return noElementMarker;
+ }
+ }
+ const overflow = node.data;
+ for (let i = 0;i < overflow.length; i += 2) {
+ if (isEqual(key, overflow[i])) {
+ return overflow[i + 1];
+ }
+ }
+ return noElementMarker;
+}
+function toTransient(dict) {
+ return {
+ generation: nextGeneration(dict),
+ root: dict.root,
+ size: dict.size,
+ dict
+ };
+}
+function fromTransient(transient) {
+ if (transient.root === transient.dict.root) {
+ return transient.dict;
+ }
+ return new Dict(transient.size, transient.root);
+}
+function nextGeneration(dict) {
+ const root = dict.root;
+ if (root.generation < Number.MAX_SAFE_INTEGER) {
+ return root.generation + 1;
+ }
+ const queue = [root];
+ while (queue.length) {
+ const node = queue.pop();
+ node.generation = 0;
+ const nodeStart = node.data.length - popcount(node.nodemap);
+ for (let i = nodeStart;i < node.data.length; ++i) {
+ queue.push(node.data[i]);
+ }
+ }
+ return 1;
+}
+var globalTransient = /* @__PURE__ */ toTransient(emptyDict);
+function insert(dict, key, value) {
+ globalTransient.generation = nextGeneration(dict);
+ globalTransient.size = dict.size;
+ const hash = getHash(key);
+ const root = insertIntoNode(globalTransient, dict.root, key, value, hash, 0);
+ if (root === dict.root) {
+ return dict;
+ }
+ return new Dict(globalTransient.size, root);
+}
+function insertIntoNode(transient, node, key, value, hash, shift) {
+ const data = node.data;
+ const generation = transient.generation;
+ if (shift > 32) {
+ for (let i = 0;i < data.length; i += 2) {
+ if (isEqual(key, data[i])) {
+ return copyAndSet(node, generation, i + 1, value);
+ }
+ }
+ transient.size += 1;
+ return copyAndInsertPair(node, generation, 0, data.length, key, value);
+ }
+ const bit = hashbit(hash, shift);
+ if (node.nodemap & bit) {
+ const nodeidx2 = data.length - 1 - index(node.nodemap, bit);
+ let child2 = data[nodeidx2];
+ child2 = insertIntoNode(transient, child2, key, value, hash, shift + bits);
+ return copyAndSet(node, generation, nodeidx2, child2);
+ }
+ const dataidx = Math.imul(index(node.datamap, bit), 2);
+ if ((node.datamap & bit) === 0) {
+ transient.size += 1;
+ return copyAndInsertPair(node, generation, bit, dataidx, key, value);
+ }
+ if (isEqual(key, data[dataidx])) {
+ return copyAndSet(node, generation, dataidx + 1, value);
+ }
+ const childShift = shift + bits;
+ let child = emptyNode;
+ child = insertIntoNode(transient, child, key, value, hash, childShift);
+ const key2 = data[dataidx];
+ const value2 = data[dataidx + 1];
+ const hash2 = getHash(key2);
+ child = insertIntoNode(transient, child, key2, value2, hash2, childShift);
+ transient.size -= 1;
+ const length = data.length;
+ const nodeidx = length - 1 - index(node.nodemap, bit);
+ const newData = new Array(length - 1);
+ let readIndex = 0;
+ let writeIndex = 0;
+ while (readIndex < dataidx)
+ newData[writeIndex++] = data[readIndex++];
+ readIndex += 2;
+ while (readIndex <= nodeidx)
+ newData[writeIndex++] = data[readIndex++];
+ newData[writeIndex++] = child;
+ while (readIndex < length)
+ newData[writeIndex++] = data[readIndex++];
+ return new Node(generation, node.datamap ^ bit, node.nodemap | bit, newData);
+}
+function destructiveTransientDelete(key, transient) {
+ const hash = getHash(key);
+ transient.root = deleteFromNode(transient, transient.root, key, hash, 0);
+ return transient;
+}
+function deleteFromNode(transient, node, key, hash, shift) {
+ const data = node.data;
+ const generation = transient.generation;
+ if (shift > 32) {
+ for (let i = 0;i < data.length; i += 2) {
+ if (isEqual(key, data[i])) {
+ transient.size -= 1;
+ return copyAndRemovePair(node, generation, 0, i);
+ }
+ }
+ return node;
+ }
+ const bit = hashbit(hash, shift);
+ const dataidx = Math.imul(index(node.datamap, bit), 2);
+ if ((node.nodemap & bit) !== 0) {
+ const nodeidx = data.length - 1 - index(node.nodemap, bit);
+ let child = data[nodeidx];
+ child = deleteFromNode(transient, child, key, hash, shift + bits);
+ if (child.nodemap !== 0 || child.data.length > 2) {
+ return copyAndSet(node, generation, nodeidx, child);
+ }
+ const length = data.length;
+ const newData = new Array(length + 1);
+ let readIndex = 0;
+ let writeIndex = 0;
+ while (readIndex < dataidx)
+ newData[writeIndex++] = data[readIndex++];
+ newData[writeIndex++] = child.data[0];
+ newData[writeIndex++] = child.data[1];
+ while (readIndex < nodeidx)
+ newData[writeIndex++] = data[readIndex++];
+ readIndex++;
+ while (readIndex < length)
+ newData[writeIndex++] = data[readIndex++];
+ return new Node(generation, node.datamap | bit, node.nodemap ^ bit, newData);
+ }
+ if ((node.datamap & bit) === 0 || !isEqual(key, data[dataidx])) {
+ return node;
+ }
+ transient.size -= 1;
+ return copyAndRemovePair(node, generation, bit, dataidx);
+}
+function fold(dict, state, fun) {
+ const queue = [dict.root];
+ while (queue.length) {
+ const node = queue.pop();
+ const data = node.data;
+ const edgesStart = data.length - popcount(node.nodemap);
+ for (let i = 0;i < edgesStart; i += 2) {
+ state = fun(state, data[i], data[i + 1]);
+ }
+ for (let i = edgesStart;i < data.length; ++i) {
+ queue.push(data[i]);
+ }
+ }
+ return state;
+}
+function popcount(n) {
+ n -= n >>> 1 & 1431655765;
+ n = (n & 858993459) + (n >>> 2 & 858993459);
+ return Math.imul(n + (n >>> 4) & 252645135, 16843009) >>> 24;
+}
+function index(bitmap, bit) {
+ return popcount(bitmap & bit - 1);
+}
+function hashbit(hash, shift) {
+ return 1 << (hash >>> shift & mask);
+}
+
+// build/dev/javascript/gleam_stdlib/gleam/option.mjs
+class Some extends CustomType {
+ constructor($0) {
+ super();
+ this[0] = $0;
+ }
+}
+var Option$isSome = (value) => value instanceof Some;
+var Option$Some$0 = (value) => value[0];
+
+class None extends CustomType {
+}
+var Option$None$const = new None;
+function to_result(option, e) {
+ if (option instanceof Some) {
+ let a = option[0];
+ return new Ok(a);
+ } else {
+ return new Error2(e);
+ }
+}
+function unwrap(option, default$) {
+ if (option instanceof Some) {
+ let x = option[0];
+ return x;
+ } else {
+ return default$;
+ }
+}
+
+// build/dev/javascript/gleam_stdlib/gleam/dict.mjs
+function keys(dict) {
+ return fold(dict, List$Empty$const, (acc, key, _) => {
+ return prepend(key, acc);
+ });
+}
+function delete$(dict, key) {
+ let _pipe = toTransient(dict);
+ let _pipe$1 = ((_capture) => {
+ return destructiveTransientDelete(key, _capture);
+ })(_pipe);
+ return fromTransient(_pipe$1);
+}
+
+// build/dev/javascript/gleam_stdlib/gleam/order.mjs
+class Lt extends CustomType {
+}
+var Order$Lt$const = new Lt;
+var Order$Lt = () => Order$Lt$const;
+class Eq extends CustomType {
+}
+var Order$Eq$const = new Eq;
+var Order$Eq = () => Order$Eq$const;
+class Gt extends CustomType {
+}
+var Order$Gt$const = new Gt;
+var Order$Gt = () => Order$Gt$const;
+
+// build/dev/javascript/gleam_stdlib/gleam/list.mjs
+class Ascending extends CustomType {
+}
+var Sorting$Ascending$const = new Ascending;
+
+class Descending extends CustomType {
+}
+var Sorting$Descending$const = new Descending;
+function reverse_and_prepend(loop$prefix, loop$suffix) {
+ while (true) {
+ let prefix = loop$prefix;
+ let suffix = loop$suffix;
+ if (prefix instanceof Empty) {
+ return suffix;
+ } else {
+ let first$1 = prefix.head;
+ let rest$1 = prefix.tail;
+ loop$prefix = rest$1;
+ loop$suffix = prepend(first$1, suffix);
+ }
+ }
+}
+function reverse(list) {
+ return reverse_and_prepend(list, List$Empty$const);
+}
+function filter_map_loop(loop$list, loop$fun, loop$acc) {
+ while (true) {
+ let list = loop$list;
+ let fun = loop$fun;
+ let acc = loop$acc;
+ if (list instanceof Empty) {
+ return reverse(acc);
+ } else {
+ let first$1 = list.head;
+ let rest$1 = list.tail;
+ let _block;
+ let $ = fun(first$1);
+ if ($ instanceof Ok) {
+ let first$2 = $[0];
+ _block = prepend(first$2, acc);
+ } else {
+ _block = acc;
+ }
+ let new_acc = _block;
+ loop$list = rest$1;
+ loop$fun = fun;
+ loop$acc = new_acc;
+ }
+ }
+}
+function filter_map(list, fun) {
+ return filter_map_loop(list, fun, List$Empty$const);
+}
+function map_loop(loop$list, loop$fun, loop$acc) {
+ while (true) {
+ let list = loop$list;
+ let fun = loop$fun;
+ let acc = loop$acc;
+ if (list instanceof Empty) {
+ return reverse(acc);
+ } else {
+ let first$1 = list.head;
+ let rest$1 = list.tail;
+ loop$list = rest$1;
+ loop$fun = fun;
+ loop$acc = prepend(fun(first$1), acc);
+ }
+ }
+}
+function map2(list, fun) {
+ return map_loop(list, fun, List$Empty$const);
+}
+function append_loop(loop$first, loop$second) {
+ while (true) {
+ let first = loop$first;
+ let second = loop$second;
+ if (first instanceof Empty) {
+ return second;
+ } else {
+ let first$1 = first.head;
+ let rest$1 = first.tail;
+ loop$first = rest$1;
+ loop$second = prepend(first$1, second);
+ }
+ }
+}
+function append(first, second) {
+ return append_loop(reverse(first), second);
+}
+function prepend2(list, item) {
+ return prepend(item, list);
+}
+function fold2(loop$list, loop$initial, loop$fun) {
+ while (true) {
+ let list = loop$list;
+ let initial = loop$initial;
+ let fun = loop$fun;
+ if (list instanceof Empty) {
+ return initial;
+ } else {
+ let first$1 = list.head;
+ let rest$1 = list.tail;
+ loop$list = rest$1;
+ loop$initial = fun(initial, first$1);
+ loop$fun = fun;
+ }
+ }
+}
+function find_map(loop$list, loop$fun) {
+ while (true) {
+ let list = loop$list;
+ let fun = loop$fun;
+ if (list instanceof Empty) {
+ return new Error2(undefined);
+ } else {
+ let first$1 = list.head;
+ let rest$1 = list.tail;
+ let $ = fun(first$1);
+ if ($ instanceof Ok) {
+ return $;
+ } else {
+ loop$list = rest$1;
+ loop$fun = fun;
+ }
+ }
+ }
+}
+function merge_descendings(loop$list1, loop$list2, loop$compare, loop$acc) {
+ while (true) {
+ let list1 = loop$list1;
+ let list2 = loop$list2;
+ let compare2 = loop$compare;
+ let acc = loop$acc;
+ if (list1 instanceof Empty) {
+ let list = list2;
+ return reverse_and_prepend(list, acc);
+ } else if (list2 instanceof Empty) {
+ let list = list1;
+ return reverse_and_prepend(list, acc);
+ } else {
+ let first1 = list1.head;
+ let rest1 = list1.tail;
+ let first2 = list2.head;
+ let rest2 = list2.tail;
+ let $ = compare2(first1, first2);
+ if ($ instanceof Lt) {
+ loop$list1 = list1;
+ loop$list2 = rest2;
+ loop$compare = compare2;
+ loop$acc = prepend(first2, acc);
+ } else if ($ instanceof Eq) {
+ loop$list1 = rest1;
+ loop$list2 = list2;
+ loop$compare = compare2;
+ loop$acc = prepend(first1, acc);
+ } else {
+ loop$list1 = rest1;
+ loop$list2 = list2;
+ loop$compare = compare2;
+ loop$acc = prepend(first1, acc);
+ }
+ }
+ }
+}
+function merge_descending_pairs(loop$sequences, loop$compare, loop$acc) {
+ while (true) {
+ let sequences = loop$sequences;
+ let compare2 = loop$compare;
+ let acc = loop$acc;
+ if (sequences instanceof Empty) {
+ return reverse(acc);
+ } else {
+ let $ = sequences.tail;
+ if ($ instanceof Empty) {
+ let sequence = sequences.head;
+ return reverse(prepend(reverse(sequence), acc));
+ } else {
+ let descending1 = sequences.head;
+ let descending2 = $.head;
+ let rest$1 = $.tail;
+ let ascending = merge_descendings(descending1, descending2, compare2, List$Empty$const);
+ loop$sequences = rest$1;
+ loop$compare = compare2;
+ loop$acc = prepend(ascending, acc);
+ }
+ }
+ }
+}
+function merge_ascendings(loop$list1, loop$list2, loop$compare, loop$acc) {
+ while (true) {
+ let list1 = loop$list1;
+ let list2 = loop$list2;
+ let compare2 = loop$compare;
+ let acc = loop$acc;
+ if (list1 instanceof Empty) {
+ let list = list2;
+ return reverse_and_prepend(list, acc);
+ } else if (list2 instanceof Empty) {
+ let list = list1;
+ return reverse_and_prepend(list, acc);
+ } else {
+ let first1 = list1.head;
+ let rest1 = list1.tail;
+ let first2 = list2.head;
+ let rest2 = list2.tail;
+ let $ = compare2(first1, first2);
+ if ($ instanceof Lt) {
+ loop$list1 = rest1;
+ loop$list2 = list2;
+ loop$compare = compare2;
+ loop$acc = prepend(first1, acc);
+ } else if ($ instanceof Eq) {
+ loop$list1 = list1;
+ loop$list2 = rest2;
+ loop$compare = compare2;
+ loop$acc = prepend(first2, acc);
+ } else {
+ loop$list1 = list1;
+ loop$list2 = rest2;
+ loop$compare = compare2;
+ loop$acc = prepend(first2, acc);
+ }
+ }
+ }
+}
+function merge_ascending_pairs(loop$sequences, loop$compare, loop$acc) {
+ while (true) {
+ let sequences = loop$sequences;
+ let compare2 = loop$compare;
+ let acc = loop$acc;
+ if (sequences instanceof Empty) {
+ return reverse(acc);
+ } else {
+ let $ = sequences.tail;
+ if ($ instanceof Empty) {
+ let sequence = sequences.head;
+ return reverse(prepend(reverse(sequence), acc));
+ } else {
+ let ascending1 = sequences.head;
+ let ascending2 = $.head;
+ let rest$1 = $.tail;
+ let descending = merge_ascendings(ascending1, ascending2, compare2, List$Empty$const);
+ loop$sequences = rest$1;
+ loop$compare = compare2;
+ loop$acc = prepend(descending, acc);
+ }
+ }
+ }
+}
+function merge_all(loop$sequences, loop$direction, loop$compare) {
+ while (true) {
+ let sequences = loop$sequences;
+ let direction = loop$direction;
+ let compare2 = loop$compare;
+ if (sequences instanceof Empty) {
+ return sequences;
+ } else if (direction instanceof Ascending) {
+ let $ = sequences.tail;
+ if ($ instanceof Empty) {
+ let sequence = sequences.head;
+ return sequence;
+ } else {
+ let sequences$1 = merge_ascending_pairs(sequences, compare2, List$Empty$const);
+ loop$sequences = sequences$1;
+ loop$direction = Sorting$Descending$const;
+ loop$compare = compare2;
+ }
+ } else {
+ let $ = sequences.tail;
+ if ($ instanceof Empty) {
+ let sequence = sequences.head;
+ return reverse(sequence);
+ } else {
+ let sequences$1 = merge_descending_pairs(sequences, compare2, List$Empty$const);
+ loop$sequences = sequences$1;
+ loop$direction = Sorting$Ascending$const;
+ loop$compare = compare2;
+ }
+ }
+ }
+}
+function sequences(loop$list, loop$compare, loop$growing, loop$direction, loop$prev, loop$acc) {
+ while (true) {
+ let list = loop$list;
+ let compare2 = loop$compare;
+ let growing = loop$growing;
+ let direction = loop$direction;
+ let prev = loop$prev;
+ let acc = loop$acc;
+ let growing$1 = prepend(prev, growing);
+ if (list instanceof Empty) {
+ if (direction instanceof Ascending) {
+ return prepend(reverse(growing$1), acc);
+ } else {
+ return prepend(growing$1, acc);
+ }
+ } else {
+ let new$1 = list.head;
+ let rest$1 = list.tail;
+ let $ = compare2(prev, new$1);
+ if (direction instanceof Ascending) {
+ if ($ instanceof Lt) {
+ loop$list = rest$1;
+ loop$compare = compare2;
+ loop$growing = growing$1;
+ loop$direction = direction;
+ loop$prev = new$1;
+ loop$acc = acc;
+ } else if ($ instanceof Eq) {
+ loop$list = rest$1;
+ loop$compare = compare2;
+ loop$growing = growing$1;
+ loop$direction = direction;
+ loop$prev = new$1;
+ loop$acc = acc;
+ } else {
+ let _block;
+ if (direction instanceof Ascending) {
+ _block = prepend(reverse(growing$1), acc);
+ } else {
+ _block = prepend(growing$1, acc);
+ }
+ let acc$1 = _block;
+ if (rest$1 instanceof Empty) {
+ return prepend(toList([new$1]), acc$1);
+ } else {
+ let next = rest$1.head;
+ let rest$2 = rest$1.tail;
+ let _block$1;
+ let $1 = compare2(new$1, next);
+ if ($1 instanceof Lt) {
+ _block$1 = Sorting$Ascending$const;
+ } else if ($1 instanceof Eq) {
+ _block$1 = Sorting$Ascending$const;
+ } else {
+ _block$1 = Sorting$Descending$const;
+ }
+ let direction$1 = _block$1;
+ loop$list = rest$2;
+ loop$compare = compare2;
+ loop$growing = toList([new$1]);
+ loop$direction = direction$1;
+ loop$prev = next;
+ loop$acc = acc$1;
+ }
+ }
+ } else if ($ instanceof Lt) {
+ let _block;
+ if (direction instanceof Ascending) {
+ _block = prepend(reverse(growing$1), acc);
+ } else {
+ _block = prepend(growing$1, acc);
+ }
+ let acc$1 = _block;
+ if (rest$1 instanceof Empty) {
+ return prepend(toList([new$1]), acc$1);
+ } else {
+ let next = rest$1.head;
+ let rest$2 = rest$1.tail;
+ let _block$1;
+ let $1 = compare2(new$1, next);
+ if ($1 instanceof Lt) {
+ _block$1 = Sorting$Ascending$const;
+ } else if ($1 instanceof Eq) {
+ _block$1 = Sorting$Ascending$const;
+ } else {
+ _block$1 = Sorting$Descending$const;
+ }
+ let direction$1 = _block$1;
+ loop$list = rest$2;
+ loop$compare = compare2;
+ loop$growing = toList([new$1]);
+ loop$direction = direction$1;
+ loop$prev = next;
+ loop$acc = acc$1;
+ }
+ } else if ($ instanceof Eq) {
+ let _block;
+ if (direction instanceof Ascending) {
+ _block = prepend(reverse(growing$1), acc);
+ } else {
+ _block = prepend(growing$1, acc);
+ }
+ let acc$1 = _block;
+ if (rest$1 instanceof Empty) {
+ return prepend(toList([new$1]), acc$1);
+ } else {
+ let next = rest$1.head;
+ let rest$2 = rest$1.tail;
+ let _block$1;
+ let $1 = compare2(new$1, next);
+ if ($1 instanceof Lt) {
+ _block$1 = Sorting$Ascending$const;
+ } else if ($1 instanceof Eq) {
+ _block$1 = Sorting$Ascending$const;
+ } else {
+ _block$1 = Sorting$Descending$const;
+ }
+ let direction$1 = _block$1;
+ loop$list = rest$2;
+ loop$compare = compare2;
+ loop$growing = toList([new$1]);
+ loop$direction = direction$1;
+ loop$prev = next;
+ loop$acc = acc$1;
+ }
+ } else {
+ loop$list = rest$1;
+ loop$compare = compare2;
+ loop$growing = growing$1;
+ loop$direction = direction;
+ loop$prev = new$1;
+ loop$acc = acc;
+ }
+ }
+ }
+}
+function sort(list, compare2) {
+ if (list instanceof Empty) {
+ return list;
+ } else {
+ let $ = list.tail;
+ if ($ instanceof Empty) {
+ return list;
+ } else {
+ let x = list.head;
+ let y = $.head;
+ let rest$1 = $.tail;
+ let _block;
+ let $1 = compare2(x, y);
+ if ($1 instanceof Lt) {
+ _block = Sorting$Ascending$const;
+ } else if ($1 instanceof Eq) {
+ _block = Sorting$Ascending$const;
+ } else {
+ _block = Sorting$Descending$const;
+ }
+ let direction = _block;
+ let sequences$1 = sequences(rest$1, compare2, toList([x]), direction, y, List$Empty$const);
+ return merge_all(sequences$1, Sorting$Ascending$const, compare2);
+ }
+ }
+}
+function key_find(keyword_list, desired_key) {
+ return find_map(keyword_list, (keyword) => {
+ let key = keyword[0];
+ let value = keyword[1];
+ let $ = isEqual(key, desired_key);
+ if ($) {
+ return new Ok(value);
+ } else {
+ return new Error2(undefined);
+ }
+ });
+}
+function key_set_loop(loop$list, loop$key, loop$value, loop$inspected) {
+ while (true) {
+ let list = loop$list;
+ let key = loop$key;
+ let value = loop$value;
+ let inspected = loop$inspected;
+ if (list instanceof Empty) {
+ return reverse(prepend([key, value], inspected));
+ } else {
+ let k = list.head[0];
+ if (isEqual(k, key)) {
+ let rest$1 = list.tail;
+ return reverse_and_prepend(inspected, prepend([k, value], rest$1));
+ } else {
+ let first$1 = list.head;
+ let rest$1 = list.tail;
+ loop$list = rest$1;
+ loop$key = key;
+ loop$value = value;
+ loop$inspected = prepend(first$1, inspected);
+ }
+ }
+ }
+}
+function key_set(list, key, value) {
+ return key_set_loop(list, key, value, List$Empty$const);
+}
+function each(loop$list, loop$f) {
+ while (true) {
+ let list = loop$list;
+ let f = loop$f;
+ if (list instanceof Empty) {
+ return;
+ } else {
+ let first$1 = list.head;
+ let rest$1 = list.tail;
+ f(first$1);
+ loop$list = rest$1;
+ loop$f = f;
+ }
+ }
+}
+
+// build/dev/javascript/gleam_stdlib/gleam/string_tree.mjs
+class All extends CustomType {
+}
+var Direction$All$const = new All;
+
+// build/dev/javascript/gleam_stdlib/gleam/string.mjs
+class Leading extends CustomType {
+}
+var Direction$Leading$const = new Leading;
+
+class Trailing extends CustomType {
+}
+var Direction$Trailing$const = new Trailing;
+function split2(x, substring) {
+ if (substring === "") {
+ return graphemes(x);
+ } else {
+ let _pipe = x;
+ let _pipe$1 = identity(_pipe);
+ let _pipe$2 = split(_pipe$1, substring);
+ return map2(_pipe$2, identity);
+ }
+}
+function concat_loop(loop$strings, loop$accumulator) {
+ while (true) {
+ let strings = loop$strings;
+ let accumulator = loop$accumulator;
+ if (strings instanceof Empty) {
+ return accumulator;
+ } else {
+ let string2 = strings.head;
+ let strings$1 = strings.tail;
+ loop$strings = strings$1;
+ loop$accumulator = accumulator + string2;
+ }
+ }
+}
+function concat2(strings) {
+ return concat_loop(strings, "");
+}
+
+// build/dev/javascript/gleam_stdlib/gleam/dynamic/decode.mjs
+class DecodeError extends CustomType {
+ constructor(expected, found, path) {
+ super();
+ this.expected = expected;
+ this.found = found;
+ this.path = path;
+ }
+}
+var DecodeError$DecodeError = (expected, found, path) => new DecodeError(expected, found, path);
+class Decoder extends CustomType {
+ constructor(function$) {
+ super();
+ this.function = function$;
+ }
+}
+var float2 = /* @__PURE__ */ new Decoder(decode_float);
+var int2 = /* @__PURE__ */ new Decoder(decode_int);
+var string3 = /* @__PURE__ */ new Decoder(decode_string);
+function run(data, decoder) {
+ let $ = decoder.function(data);
+ let maybe_invalid_data = $[0];
+ let errors = $[1];
+ if (errors instanceof Empty) {
+ return new Ok(maybe_invalid_data);
+ } else {
+ return new Error2(errors);
+ }
+}
+function run_dynamic_function(data, name, f) {
+ let $ = f(data);
+ if ($ instanceof Ok) {
+ let data$1 = $[0];
+ return [data$1, List$Empty$const];
+ } else {
+ let placeholder = $[0];
+ return [
+ placeholder,
+ toList([new DecodeError(name, classify_dynamic(data), List$Empty$const)])
+ ];
+ }
+}
+function decode_float(data) {
+ return run_dynamic_function(data, "Float", float);
+}
+function map3(decoder, transformer) {
+ return new Decoder((d) => {
+ let $ = decoder.function(d);
+ let data = $[0];
+ let errors = $[1];
+ return [transformer(data), errors];
+ });
+}
+function decode_int(data) {
+ return run_dynamic_function(data, "Int", int);
+}
+function decode_string(data) {
+ return run_dynamic_function(data, "String", string2);
+}
+function run_decoders(loop$data, loop$failure, loop$decoders) {
+ while (true) {
+ let data = loop$data;
+ let failure = loop$failure;
+ let decoders = loop$decoders;
+ if (decoders instanceof Empty) {
+ return failure;
+ } else {
+ let decoder = decoders.head;
+ let decoders$1 = decoders.tail;
+ let $ = decoder.function(data);
+ let layer = $;
+ let errors = $[1];
+ if (errors instanceof Empty) {
+ return layer;
+ } else {
+ loop$data = data;
+ loop$failure = failure;
+ loop$decoders = decoders$1;
+ }
+ }
+ }
+}
+function one_of(first, alternatives) {
+ return new Decoder((dynamic_data) => {
+ let $ = first.function(dynamic_data);
+ let layer = $;
+ let errors = $[1];
+ if (errors instanceof Empty) {
+ return layer;
+ } else {
+ return run_decoders(dynamic_data, layer, alternatives);
+ }
+ });
+}
+function path_segment_to_string(key) {
+ let decoder = one_of(string3, toList([
+ (() => {
+ let _pipe = int2;
+ return map3(_pipe, to_string);
+ })(),
+ (() => {
+ let _pipe = float2;
+ return map3(_pipe, float_to_string);
+ })()
+ ]));
+ let $ = run(key, decoder);
+ if ($ instanceof Ok) {
+ let key$1 = $[0];
+ return key$1;
+ } else {
+ return "<" + classify_dynamic(key) + ">";
+ }
+}
+function push_path(layer, path) {
+ let path$1 = map2(path, (key) => {
+ let _pipe = key;
+ let _pipe$1 = identity(_pipe);
+ return path_segment_to_string(_pipe$1);
+ });
+ let errors = map2(layer[1], (error) => {
+ return new DecodeError(error.expected, error.found, append(path$1, error.path));
+ });
+ return [layer[0], errors];
+}
+function list2(inner) {
+ return new Decoder((data) => {
+ return list(data, inner.function, (p, k) => {
+ return push_path(p, toList([k]));
+ }, 0, List$Empty$const);
+ });
+}
+function index3(loop$path, loop$position, loop$inner, loop$data, loop$handle_miss) {
+ while (true) {
+ let path = loop$path;
+ let position = loop$position;
+ let inner = loop$inner;
+ let data = loop$data;
+ let handle_miss = loop$handle_miss;
+ if (path instanceof Empty) {
+ let _pipe = data;
+ let _pipe$1 = inner(_pipe);
+ return push_path(_pipe$1, reverse(position));
+ } else {
+ let key = path.head;
+ let path$1 = path.tail;
+ let $ = index2(data, key);
+ if ($ instanceof Ok) {
+ let $1 = $[0];
+ if ($1 instanceof Some) {
+ let data$1 = $1[0];
+ loop$path = path$1;
+ loop$position = prepend(key, position);
+ loop$inner = inner;
+ loop$data = data$1;
+ loop$handle_miss = handle_miss;
+ } else {
+ return handle_miss(data, prepend(key, position));
+ }
+ } else {
+ let kind = $[0];
+ let $1 = inner(data);
+ let default$ = $1[0];
+ let _pipe = [
+ default$,
+ toList([
+ new DecodeError(kind, classify_dynamic(data), List$Empty$const)
+ ])
+ ];
+ return push_path(_pipe, reverse(position));
+ }
+ }
+ }
+}
+function subfield(field_path, field_decoder, next) {
+ return new Decoder((data) => {
+ let $ = index3(field_path, List$Empty$const, field_decoder.function, data, (data2, position) => {
+ let $12 = field_decoder.function(data2);
+ let default$ = $12[0];
+ let _pipe = [
+ default$,
+ toList([new DecodeError("Field", "Nothing", List$Empty$const)])
+ ];
+ return push_path(_pipe, reverse(position));
+ });
+ let out = $[0];
+ let errors1 = $[1];
+ let $1 = next(out).function(data);
+ let out$1 = $1[0];
+ let errors2 = $1[1];
+ return [out$1, append(errors1, errors2)];
+ });
+}
+function success(data) {
+ return new Decoder((_) => {
+ return [data, List$Empty$const];
+ });
+}
+function field(field_name, field_decoder, next) {
+ return subfield(toList([field_name]), field_decoder, next);
+}
+
+// build/dev/javascript/gleam_stdlib/gleam_stdlib.mjs
+function identity(x) {
+ return x;
+}
+function to_string(term) {
+ return term.toString();
+}
+function graphemes(string4) {
+ const iterator = graphemes_iterator(string4);
+ if (iterator) {
+ return arrayToList(Array.from(iterator).map((item) => item.segment));
+ } else {
+ return arrayToList(string4.match(/./gsu));
+ }
+}
+var segmenter = undefined;
+function graphemes_iterator(string4) {
+ if (globalThis.Intl && Intl.Segmenter) {
+ segmenter ||= new Intl.Segmenter;
+ return segmenter.segment(string4)[Symbol.iterator]();
+ }
+}
+function pop_codeunit(str) {
+ return [str.charCodeAt(0) | 0, str.slice(1)];
+}
+function lowercase(string4) {
+ return string4.toLowerCase();
+}
+function split(xs, pattern) {
+ return arrayToList(xs.split(pattern));
+}
+function string_codeunit_slice(str, from2, length2) {
+ return str.slice(from2, from2 + length2);
+}
+function starts_with(haystack, needle) {
+ return haystack.startsWith(needle);
+}
+var unicode_whitespaces = [
+ " ",
+ "\t",
+ `
+`,
+ "\v",
+ "\f",
+ "\r",
+ "\85",
+ "\u2028",
+ "\u2029"
+].join("");
+var trim_start_regex = /* @__PURE__ */ new RegExp(`^[${unicode_whitespaces}]*`);
+var trim_end_regex = /* @__PURE__ */ new RegExp(`[${unicode_whitespaces}]*$`);
+function classify_dynamic(data) {
+ if (typeof data === "string") {
+ return "String";
+ } else if (typeof data === "boolean") {
+ return "Bool";
+ } else if (isResult(data)) {
+ return "Result";
+ } else if (isList(data)) {
+ return "List";
+ } else if (data instanceof BitArray) {
+ return "BitArray";
+ } else if (data instanceof Dict) {
+ return "Dict";
+ } else if (Number.isInteger(data)) {
+ return "Int";
+ } else if (Array.isArray(data)) {
+ return `Array`;
+ } else if (typeof data === "number") {
+ return "Float";
+ } else if (data === null) {
+ return "Nil";
+ } else if (data === undefined) {
+ return "Nil";
+ } else {
+ const type = typeof data;
+ return type.charAt(0).toUpperCase() + type.slice(1);
+ }
+}
+var MIN_I32 = -(2 ** 31);
+var MAX_I32 = 2 ** 31 - 1;
+var U32 = 2 ** 32;
+var MAX_SAFE = Number.MAX_SAFE_INTEGER;
+var MIN_SAFE = Number.MIN_SAFE_INTEGER;
+function float_to_string(float3) {
+ const string4 = float3.toString().replace("+", "");
+ if (string4.indexOf(".") >= 0) {
+ return string4;
+ } else {
+ const index4 = string4.indexOf("e");
+ if (index4 >= 0) {
+ return string4.slice(0, index4) + ".0" + string4.slice(index4);
+ } else {
+ return string4 + ".0";
+ }
+ }
+}
+
+class Inspector {
+ #references = new Set;
+ inspect(v) {
+ const t = typeof v;
+ if (v === true)
+ return "True";
+ if (v === false)
+ return "False";
+ if (v === null)
+ return "//js(null)";
+ if (v === undefined)
+ return "Nil";
+ if (t === "string")
+ return this.#string(v);
+ if (t === "bigint" || Number.isInteger(v))
+ return v.toString();
+ if (t === "number")
+ return float_to_string(v);
+ if (v instanceof UtfCodepoint)
+ return this.#utfCodepoint(v);
+ if (v instanceof BitArray)
+ return this.#bit_array(v);
+ if (v instanceof RegExp)
+ return `//js(${v})`;
+ if (v instanceof Date)
+ return `//js(Date("${v.toISOString()}"))`;
+ if (v instanceof globalThis.Error)
+ return `//js(${v.toString()})`;
+ if (v instanceof Function) {
+ const args = [];
+ for (const i of Array(v.length).keys())
+ args.push(String.fromCharCode(i + 97));
+ return `//fn(${args.join(", ")}) { ... }`;
+ }
+ if (this.#references.size === this.#references.add(v).size) {
+ return "//js(circular reference)";
+ }
+ let printed;
+ if (Array.isArray(v)) {
+ printed = `#(${v.map((v2) => this.inspect(v2)).join(", ")})`;
+ } else if (isList(v)) {
+ printed = this.#list(v);
+ } else if (v instanceof CustomType) {
+ printed = this.#customType(v);
+ } else if (v instanceof Dict) {
+ printed = this.#dict(v);
+ } else if (v instanceof Set) {
+ return `//js(Set(${[...v].map((v2) => this.inspect(v2)).join(", ")}))`;
+ } else {
+ printed = this.#object(v);
+ }
+ this.#references.delete(v);
+ return printed;
+ }
+ #object(v) {
+ const name = Object.getPrototypeOf(v)?.constructor?.name || "Object";
+ const props = [];
+ for (const k of Object.keys(v)) {
+ props.push(`${this.inspect(k)}: ${this.inspect(v[k])}`);
+ }
+ const body = props.length ? " " + props.join(", ") + " " : "";
+ const head = name === "Object" ? "" : name + " ";
+ return `//js(${head}{${body}})`;
+ }
+ #dict(map4) {
+ let body = "dict.from_list([";
+ let first = true;
+ body = fold(map4, body, (body2, key, value) => {
+ if (!first)
+ body2 = body2 + ", ";
+ first = false;
+ return body2 + "#(" + this.inspect(key) + ", " + this.inspect(value) + ")";
+ });
+ return body + "])";
+ }
+ #customType(record) {
+ const props = Object.keys(record).map((label) => {
+ const value = this.inspect(record[label]);
+ return isNaN(parseInt(label)) ? `${label}: ${value}` : value;
+ }).join(", ");
+ return props ? `${record.constructor.name}(${props})` : record.constructor.name;
+ }
+ #list(list3) {
+ if (List$isEmpty(list3)) {
+ return "[]";
+ }
+ let char_out = 'charlist.from_string("';
+ let list_out = "[";
+ let current = list3;
+ while (List$isNonEmpty(current)) {
+ let element = current.head;
+ current = current.tail;
+ if (list_out !== "[") {
+ list_out += ", ";
+ }
+ list_out += this.inspect(element);
+ if (char_out) {
+ if (Number.isInteger(element) && element >= 32 && element <= 126) {
+ char_out += String.fromCharCode(element);
+ } else {
+ char_out = null;
+ }
+ }
+ }
+ if (char_out) {
+ return char_out + '")';
+ } else {
+ return list_out + "]";
+ }
+ }
+ #string(str) {
+ let new_str = '"';
+ for (let i = 0;i < str.length; i++) {
+ const char = str[i];
+ switch (char) {
+ case `
+`:
+ new_str += "\\n";
+ break;
+ case "\r":
+ new_str += "\\r";
+ break;
+ case "\t":
+ new_str += "\\t";
+ break;
+ case "\f":
+ new_str += "\\f";
+ break;
+ case "\\":
+ new_str += "\\\\";
+ break;
+ case '"':
+ new_str += "\\\"";
+ break;
+ default:
+ if (char < " " || char > "~" && char < " ") {
+ new_str += "\\u{" + char.charCodeAt(0).toString(16).toUpperCase().padStart(4, "0") + "}";
+ } else {
+ new_str += char;
+ }
+ }
+ }
+ new_str += '"';
+ return new_str;
+ }
+ #utfCodepoint(codepoint2) {
+ return `//utfcodepoint(${String.fromCodePoint(codepoint2.value)})`;
+ }
+ #bit_array(bits2) {
+ if (bits2.bitSize === 0) {
+ return "<<>>";
+ }
+ let acc = "<<";
+ for (let i = 0;i < bits2.byteSize - 1; i++) {
+ acc += bits2.byteAt(i).toString();
+ acc += ", ";
+ }
+ if (bits2.byteSize * 8 === bits2.bitSize) {
+ acc += bits2.byteAt(bits2.byteSize - 1).toString();
+ } else {
+ const trailingBitsCount = bits2.bitSize % 8;
+ acc += bits2.byteAt(bits2.byteSize - 1) >> 8 - trailingBitsCount;
+ acc += `:size(${trailingBitsCount})`;
+ }
+ acc += ">>";
+ return acc;
+ }
+}
+function index2(data, key) {
+ if (data instanceof Dict) {
+ const result = get(data, key);
+ return Result$Ok(result.isOk() ? new Some(result[0]) : new None);
+ }
+ if (data instanceof WeakMap || data instanceof Map) {
+ const token = {};
+ const entry = data.get(key, token);
+ if (entry === token)
+ return Result$Ok(new None);
+ return Result$Ok(new Some(entry));
+ }
+ const key_is_int = Number.isInteger(key);
+ if (key_is_int && key >= 0 && key < 8 && isList(data)) {
+ let i = 0;
+ for (const value of data) {
+ if (i === key)
+ return Result$Ok(new Some(value));
+ i++;
+ }
+ return Result$Error("Indexable");
+ }
+ if (key_is_int && Array.isArray(data) || data && typeof data === "object" || data && Object.getPrototypeOf(data) === Object.prototype) {
+ if (key in data)
+ return Result$Ok(new Some(data[key]));
+ return Result$Ok(new None);
+ }
+ return Result$Error(key_is_int ? "Indexable" : "Dict");
+}
+function list(data, decode, pushPath, index4, emptyList) {
+ if (!(isList(data) || Array.isArray(data))) {
+ const error = DecodeError$DecodeError("List", classify_dynamic(data), emptyList);
+ return [emptyList, arrayToList([error])];
+ }
+ const decoded = [];
+ for (const element of data) {
+ const layer = decode(element);
+ const [out, errors] = layer;
+ if (List$isNonEmpty(errors)) {
+ const [_, errors2] = pushPath(layer, index4.toString());
+ return [emptyList, errors2];
+ }
+ decoded.push(out);
+ index4++;
+ }
+ return [arrayToList(decoded), emptyList];
+}
+function float(data) {
+ if (typeof data === "number")
+ return Result$Ok(data);
+ return Result$Error(0);
+}
+function int(data) {
+ if (Number.isInteger(data))
+ return Result$Ok(data);
+ return Result$Error(0);
+}
+function string2(data) {
+ if (typeof data === "string")
+ return Result$Ok(data);
+ return Result$Error("");
+}
+function arrayToList(array) {
+ let list3 = List$Empty();
+ let i = array.length;
+ while (i--) {
+ list3 = List$NonEmpty(array[i], list3);
+ }
+ return list3;
+}
+function isList(data) {
+ return List$isEmpty(data) || List$isNonEmpty(data);
+}
+function isResult(data) {
+ return Result$isOk(data) || Result$isError(data);
+}
+
+// build/dev/javascript/gleam_stdlib/gleam/result.mjs
+function map4(result, fun) {
+ if (result instanceof Ok) {
+ let x = result[0];
+ return new Ok(fun(x));
+ } else {
+ return result;
+ }
+}
+function map_error(result, fun) {
+ if (result instanceof Ok) {
+ return result;
+ } else {
+ let error = result[0];
+ return new Error2(fun(error));
+ }
+}
+function try$(result, fun) {
+ if (result instanceof Ok) {
+ let x = result[0];
+ return fun(x);
+ } else {
+ return result;
+ }
+}
+function unwrap2(result, default$) {
+ if (result instanceof Ok) {
+ let v = result[0];
+ return v;
+ } else {
+ return default$;
+ }
+}
+function replace_error(result, error) {
+ if (result instanceof Ok) {
+ return result;
+ } else {
+ return new Error2(error);
+ }
+}
+function values2(results) {
+ return filter_map(results, (result) => {
+ return result;
+ });
+}
+// build/dev/javascript/gleam_erlang/gleam/erlang/process.mjs
+class Normal extends CustomType {
+}
+var ExitReason$Normal$const = new Normal;
+class Killed extends CustomType {
+}
+var ExitReason$Killed$const = new Killed;
+class Anything extends CustomType {
+}
+var AnythingSelectorTag$Anything$const = new Anything;
+
+class Process extends CustomType {
+}
+var ProcessMonitorFlag$Process$const = new Process;
+class TimerNotFound extends CustomType {
+}
+var Cancelled$TimerNotFound$const = new TimerNotFound;
+class Kill extends CustomType {
+}
+var KillFlag$Kill$const = new Kill;
+// build/dev/javascript/gleam_otp/gleam/otp/system.mjs
+class Running extends CustomType {
+}
+var Mode$Running$const = new Running;
+class Suspended extends CustomType {
+}
+var Mode$Suspended$const = new Suspended;
+class NoDebug extends CustomType {
+}
+var DebugOption$NoDebug$const = new NoDebug;
+
+// build/dev/javascript/gleam_otp/gleam/otp/actor.mjs
+class InitTimeout extends CustomType {
+}
+var StartError$InitTimeout$const = new InitTimeout;
+
+// build/dev/javascript/gleam_otp/gleam/otp/supervision.mjs
+class Permanent extends CustomType {
+}
+var Restart$Permanent$const = new Permanent;
+class Transient extends CustomType {
+}
+var Restart$Transient$const = new Transient;
+class Temporary extends CustomType {
+}
+var Restart$Temporary$const = new Temporary;
+class Supervisor extends CustomType {
+}
+var ChildType$Supervisor$const = new Supervisor;
+
+// build/dev/javascript/gleam_otp/gleam/otp/factory_supervisor.mjs
+class SimpleOneForOne extends CustomType {
+}
+var Strategy$SimpleOneForOne$const = new SimpleOneForOne;
+
+// build/dev/javascript/gleam_stdlib/gleam/bool.mjs
+function guard(requirement, consequence, alternative) {
+ if (requirement) {
+ return consequence;
+ } else {
+ return alternative();
+ }
+}
+
+// build/dev/javascript/gleam_stdlib/gleam/function.mjs
+function identity2(x) {
+ return x;
+}
+// build/dev/javascript/gleam_json/gleam_json_ffi.mjs
+function json_to_string(json) {
+ return JSON.stringify(json);
+}
+function object(entries) {
+ return Object.fromEntries(entries);
+}
+function identity3(x) {
+ return x;
+}
+function decode(string4) {
+ try {
+ const result = JSON.parse(string4);
+ return Result$Ok(result);
+ } catch (err) {
+ return Result$Error(getJsonDecodeError(err, string4));
+ }
+}
+function getJsonDecodeError(stdErr, json) {
+ if (isUnexpectedEndOfInput(stdErr))
+ return DecodeError$UnexpectedEndOfInput();
+ return toUnexpectedByteError(stdErr, json);
+}
+function isUnexpectedEndOfInput(err) {
+ const unexpectedEndOfInputRegex = /((unexpected (end|eof))|(end of data)|(unterminated string)|(json( parse error|\.parse)\: expected '(\:|\}|\])'))/i;
+ return unexpectedEndOfInputRegex.test(err.message);
+}
+function toUnexpectedByteError(err, json) {
+ let converters = [
+ v8UnexpectedByteError,
+ oldV8UnexpectedByteError,
+ jsCoreUnexpectedByteError,
+ spidermonkeyUnexpectedByteError
+ ];
+ for (let converter of converters) {
+ let result = converter(err, json);
+ if (result)
+ return result;
+ }
+ return DecodeError$UnexpectedByte("");
+}
+function v8UnexpectedByteError(err) {
+ const regex = /unexpected token '(.)', ".+" is not valid JSON/i;
+ const match = regex.exec(err.message);
+ if (!match)
+ return null;
+ const byte = toHex(match[1]);
+ return DecodeError$UnexpectedByte(byte);
+}
+function oldV8UnexpectedByteError(err) {
+ const regex = /unexpected token (.) in JSON at position (\d+)/i;
+ const match = regex.exec(err.message);
+ if (!match)
+ return null;
+ const byte = toHex(match[1]);
+ return DecodeError$UnexpectedByte(byte);
+}
+function spidermonkeyUnexpectedByteError(err, json) {
+ const regex = /(unexpected character|expected .*) at line (\d+) column (\d+)/i;
+ const match = regex.exec(err.message);
+ if (!match)
+ return null;
+ const line = Number(match[2]);
+ const column = Number(match[3]);
+ const position = getPositionFromMultiline(line, column, json);
+ const byte = toHex(json[position]);
+ return DecodeError$UnexpectedByte(byte);
+}
+function jsCoreUnexpectedByteError(err) {
+ const regex = /unexpected (identifier|token) "(.)"/i;
+ const match = regex.exec(err.message);
+ if (!match)
+ return null;
+ const byte = toHex(match[2]);
+ return DecodeError$UnexpectedByte(byte);
+}
+function toHex(char) {
+ return "0x" + char.charCodeAt(0).toString(16).toUpperCase();
+}
+function getPositionFromMultiline(line, column, string4) {
+ if (line === 1)
+ return column - 1;
+ let currentLn = 1;
+ let position = 0;
+ string4.split("").find((char, idx) => {
+ if (char === `
+`)
+ currentLn += 1;
+ if (currentLn === line) {
+ position = idx + column;
+ return true;
+ }
+ return false;
+ });
+ return position;
+}
+
+// build/dev/javascript/gleam_json/gleam/json.mjs
+class UnexpectedEndOfInput extends CustomType {
+}
+var DecodeError$UnexpectedEndOfInput$const = new UnexpectedEndOfInput;
+var DecodeError$UnexpectedEndOfInput = () => DecodeError$UnexpectedEndOfInput$const;
+class UnexpectedByte extends CustomType {
+ constructor($0) {
+ super();
+ this[0] = $0;
+ }
+}
+var DecodeError$UnexpectedByte = ($0) => new UnexpectedByte($0);
+class UnableToDecode extends CustomType {
+ constructor($0) {
+ super();
+ this[0] = $0;
+ }
+}
+function do_parse(json, decoder) {
+ return try$(decode(json), (dynamic_value) => {
+ let _pipe = run(dynamic_value, decoder);
+ return map_error(_pipe, (var0) => {
+ return new UnableToDecode(var0);
+ });
+ });
+}
+function parse(json, decoder) {
+ return do_parse(json, decoder);
+}
+function to_string2(json) {
+ return json_to_string(json);
+}
+function string4(input) {
+ return identity3(input);
+}
+function object2(entries) {
+ return object(entries);
+}
+// build/dev/javascript/houdini/houdini.ffi.mjs
+function escape(string5) {
+ return string5.replaceAll(/[><&"']/g, (replaced) => {
+ switch (replaced) {
+ case ">":
+ return ">";
+ case "<":
+ return "<";
+ case "'":
+ return "'";
+ case "&":
+ return "&";
+ case '"':
+ return """;
+ default:
+ return replaced;
+ }
+ });
+}
+
+// build/dev/javascript/lustre/lustre/internals/constants.mjs
+var empty_list = List$Empty$const;
+var error_nil = /* @__PURE__ */ new Error2(undefined);
+function singleton_list(item) {
+ return prepend(item, empty_list);
+}
+
+// build/dev/javascript/lustre/lustre/vdom/vattr.ffi.mjs
+var GT = /* @__PURE__ */ Order$Gt();
+var LT = /* @__PURE__ */ Order$Lt();
+var EQ = /* @__PURE__ */ Order$Eq();
+function compare2(a, b) {
+ if (a.name === b.name) {
+ return EQ;
+ } else if (a.name < b.name) {
+ return LT;
+ } else {
+ return GT;
+ }
+}
+
+// build/dev/javascript/lustre/lustre/vdom/vattr.mjs
+class Attribute extends CustomType {
+ constructor(kind, name, value) {
+ super();
+ this.kind = kind;
+ this.name = name;
+ this.value = value;
+ }
+}
+class Property extends CustomType {
+ constructor(kind, name, value) {
+ super();
+ this.kind = kind;
+ this.name = name;
+ this.value = value;
+ }
+}
+class Event2 extends CustomType {
+ constructor(kind, name, handler, include, prevent_default, stop_propagation, debounce, throttle) {
+ super();
+ this.kind = kind;
+ this.name = name;
+ this.handler = handler;
+ this.include = include;
+ this.prevent_default = prevent_default;
+ this.stop_propagation = stop_propagation;
+ this.debounce = debounce;
+ this.throttle = throttle;
+ }
+}
+class Handler extends CustomType {
+ constructor(prevent_default, stop_propagation, message) {
+ super();
+ this.prevent_default = prevent_default;
+ this.stop_propagation = stop_propagation;
+ this.message = message;
+ }
+}
+class Never extends CustomType {
+ constructor(kind) {
+ super();
+ this.kind = kind;
+ }
+}
+class Always extends CustomType {
+ constructor(kind) {
+ super();
+ this.kind = kind;
+ }
+}
+var attribute_kind = 0;
+var property_kind = 1;
+var event_kind = 2;
+var never_kind = 0;
+var never = /* @__PURE__ */ new Never(never_kind);
+var always_kind = 2;
+var always = /* @__PURE__ */ new Always(always_kind);
+function attribute(name, value) {
+ return new Attribute(attribute_kind, name, value);
+}
+function event(name, handler, include, prevent_default, stop_propagation, debounce, throttle) {
+ return new Event2(event_kind, name, handler, include, prevent_default, stop_propagation, debounce, throttle);
+}
+function merge(loop$attributes, loop$merged) {
+ while (true) {
+ let attributes = loop$attributes;
+ let merged = loop$merged;
+ if (attributes instanceof Empty) {
+ return merged;
+ } else {
+ let $ = attributes.head;
+ if ($ instanceof Attribute) {
+ let $1 = $.name;
+ if ($1 === "") {
+ let rest = attributes.tail;
+ loop$attributes = rest;
+ loop$merged = merged;
+ } else if ($1 === "class") {
+ let $2 = $.value;
+ if ($2 === "") {
+ let rest = attributes.tail;
+ loop$attributes = rest;
+ loop$merged = merged;
+ } else {
+ let $3 = attributes.tail;
+ if ($3 instanceof Empty) {
+ let attribute$1 = $;
+ let rest = $3;
+ loop$attributes = rest;
+ loop$merged = prepend(attribute$1, merged);
+ } else {
+ let $4 = $3.head;
+ if ($4 instanceof Attribute) {
+ let $5 = $4.name;
+ if ($5 === "class") {
+ let kind = $.kind;
+ let class1 = $2;
+ let rest = $3.tail;
+ let class2 = $4.value;
+ let value = class1 + " " + class2;
+ let attribute$1 = new Attribute(kind, "class", value);
+ loop$attributes = prepend(attribute$1, rest);
+ loop$merged = merged;
+ } else {
+ let attribute$1 = $;
+ let rest = $3;
+ loop$attributes = rest;
+ loop$merged = prepend(attribute$1, merged);
+ }
+ } else {
+ let attribute$1 = $;
+ let rest = $3;
+ loop$attributes = rest;
+ loop$merged = prepend(attribute$1, merged);
+ }
+ }
+ }
+ } else if ($1 === "style") {
+ let $2 = $.value;
+ if ($2 === "") {
+ let rest = attributes.tail;
+ loop$attributes = rest;
+ loop$merged = merged;
+ } else {
+ let $3 = attributes.tail;
+ if ($3 instanceof Empty) {
+ let attribute$1 = $;
+ let rest = $3;
+ loop$attributes = rest;
+ loop$merged = prepend(attribute$1, merged);
+ } else {
+ let $4 = $3.head;
+ if ($4 instanceof Attribute) {
+ let $5 = $4.name;
+ if ($5 === "style") {
+ let kind = $.kind;
+ let style1 = $2;
+ let rest = $3.tail;
+ let style2 = $4.value;
+ let value = style1 + ";" + style2;
+ let attribute$1 = new Attribute(kind, "style", value);
+ loop$attributes = prepend(attribute$1, rest);
+ loop$merged = merged;
+ } else {
+ let attribute$1 = $;
+ let rest = $3;
+ loop$attributes = rest;
+ loop$merged = prepend(attribute$1, merged);
+ }
+ } else {
+ let attribute$1 = $;
+ let rest = $3;
+ loop$attributes = rest;
+ loop$merged = prepend(attribute$1, merged);
+ }
+ }
+ }
+ } else {
+ let attribute$1 = $;
+ let rest = attributes.tail;
+ loop$attributes = rest;
+ loop$merged = prepend(attribute$1, merged);
+ }
+ } else {
+ let attribute$1 = $;
+ let rest = attributes.tail;
+ loop$attributes = rest;
+ loop$merged = prepend(attribute$1, merged);
+ }
+ }
+ }
+}
+function prepare(attributes) {
+ if (attributes instanceof Empty) {
+ return attributes;
+ } else {
+ let $ = attributes.tail;
+ if ($ instanceof Empty) {
+ return attributes;
+ } else {
+ let _pipe = attributes;
+ let _pipe$1 = sort(_pipe, (a, b) => {
+ return compare2(b, a);
+ });
+ return merge(_pipe$1, empty_list);
+ }
+ }
+}
+
+// build/dev/javascript/lustre/lustre/attribute.mjs
+function attribute2(name, value) {
+ return attribute(name, value);
+}
+function class$(name) {
+ return attribute2("class", name);
+}
+function href(url) {
+ return attribute2("href", url);
+}
+function name(element_name) {
+ return attribute2("name", element_name);
+}
+function placeholder(text) {
+ return attribute2("placeholder", text);
+}
+function type_(control_type) {
+ return attribute2("type", control_type);
+}
+function value(control_value) {
+ return attribute2("value", control_value);
+}
+
+// build/dev/javascript/lustre/lustre/effect.mjs
+class Effect extends CustomType {
+ constructor(synchronous, before_paint, after_paint) {
+ super();
+ this.synchronous = synchronous;
+ this.before_paint = before_paint;
+ this.after_paint = after_paint;
+ }
+}
+
+class Actions extends CustomType {
+ constructor(dispatch, emit, select, root, provide, subscribe, unsubscribe) {
+ super();
+ this.dispatch = dispatch;
+ this.emit = emit;
+ this.select = select;
+ this.root = root;
+ this.provide = provide;
+ this.subscribe = subscribe;
+ this.unsubscribe = unsubscribe;
+ }
+}
+var empty = /* @__PURE__ */ new Effect(empty_list, empty_list, empty_list);
+function none() {
+ return empty;
+}
+function from2(effect) {
+ let task = (actions) => {
+ let dispatch = actions.dispatch;
+ return effect(dispatch);
+ };
+ return new Effect(singleton_list(task), empty.before_paint, empty.after_paint);
+}
+function batch(effects) {
+ return fold2(effects, empty, (acc, eff) => {
+ return new Effect(fold2(eff.synchronous, acc.synchronous, prepend2), fold2(eff.before_paint, acc.before_paint, prepend2), fold2(eff.after_paint, acc.after_paint, prepend2));
+ });
+}
+function perform(effect, dispatch, emit, select, root, provide, subscribe, unsubscribe) {
+ let actions = new Actions(dispatch, emit, select, root, provide, subscribe, unsubscribe);
+ return each(effect.synchronous, (run2) => {
+ return run2(actions);
+ });
+}
+
+// build/dev/javascript/lustre/lustre/internals/mutable_map.ffi.mjs
+function empty2() {
+ return null;
+}
+function get2(map5, key) {
+ return map5?.get(key);
+}
+function get_or_compute(map5, key, compute) {
+ return map5?.get(key) ?? compute();
+}
+function has_key(map5, key) {
+ return map5 && map5.has(key);
+}
+function insert2(map5, key, value2) {
+ map5 ??= new Map;
+ map5.set(key, value2);
+ return map5;
+}
+function remove(map5, key) {
+ map5?.delete(key);
+ return map5;
+}
+
+// build/dev/javascript/lustre/lustre/internals/ref.ffi.mjs
+function sameValueZero(x, y) {
+ if (typeof x === "number" && typeof y === "number") {
+ return x === y || x !== x && y !== y;
+ }
+ return x === y;
+}
+
+// build/dev/javascript/lustre/lustre/internals/ref.mjs
+function equal_lists(loop$xs, loop$ys) {
+ while (true) {
+ let xs = loop$xs;
+ let ys = loop$ys;
+ if (xs instanceof Empty) {
+ if (ys instanceof Empty) {
+ return true;
+ } else {
+ return false;
+ }
+ } else if (ys instanceof Empty) {
+ return false;
+ } else {
+ let x = xs.head;
+ let xs$1 = xs.tail;
+ let y = ys.head;
+ let ys$1 = ys.tail;
+ let $ = sameValueZero(x, y);
+ if ($) {
+ loop$xs = xs$1;
+ loop$ys = ys$1;
+ } else {
+ return $;
+ }
+ }
+ }
+}
+
+// build/dev/javascript/lustre/lustre/vdom/vnode.mjs
+class Fragment extends CustomType {
+ constructor(kind, key, children, keyed_children) {
+ super();
+ this.kind = kind;
+ this.key = key;
+ this.children = children;
+ this.keyed_children = keyed_children;
+ }
+}
+class Element2 extends CustomType {
+ constructor(kind, key, namespace, tag, attributes, children, keyed_children, self_closing, void$) {
+ super();
+ this.kind = kind;
+ this.key = key;
+ this.namespace = namespace;
+ this.tag = tag;
+ this.attributes = attributes;
+ this.children = children;
+ this.keyed_children = keyed_children;
+ this.self_closing = self_closing;
+ this.void = void$;
+ }
+}
+class Text extends CustomType {
+ constructor(kind, key, content) {
+ super();
+ this.kind = kind;
+ this.key = key;
+ this.content = content;
+ }
+}
+class UnsafeInnerHtml extends CustomType {
+ constructor(kind, key, namespace, tag, attributes, inner_html) {
+ super();
+ this.kind = kind;
+ this.key = key;
+ this.namespace = namespace;
+ this.tag = tag;
+ this.attributes = attributes;
+ this.inner_html = inner_html;
+ }
+}
+class Map2 extends CustomType {
+ constructor(kind, key, mapper, child) {
+ super();
+ this.kind = kind;
+ this.key = key;
+ this.mapper = mapper;
+ this.child = child;
+ }
+}
+class Memo extends CustomType {
+ constructor(kind, key, dependencies, view) {
+ super();
+ this.kind = kind;
+ this.key = key;
+ this.dependencies = dependencies;
+ this.view = view;
+ }
+}
+var fragment_kind = 0;
+var element_kind = 1;
+var text_kind = 2;
+var unsafe_inner_html_kind = 3;
+var map_kind = 4;
+var memo_kind = 5;
+function fragment(key, children, keyed_children) {
+ return new Fragment(fragment_kind, key, children, keyed_children);
+}
+function element(key, namespace, tag, attributes, children, keyed_children, self_closing, void$) {
+ return new Element2(element_kind, key, namespace, tag, prepare(attributes), children, keyed_children, self_closing, void$);
+}
+function is_void_html_element(tag, namespace) {
+ if (namespace === "") {
+ if (tag === "area") {
+ return true;
+ } else if (tag === "base") {
+ return true;
+ } else if (tag === "br") {
+ return true;
+ } else if (tag === "col") {
+ return true;
+ } else if (tag === "embed") {
+ return true;
+ } else if (tag === "hr") {
+ return true;
+ } else if (tag === "img") {
+ return true;
+ } else if (tag === "input") {
+ return true;
+ } else if (tag === "link") {
+ return true;
+ } else if (tag === "meta") {
+ return true;
+ } else if (tag === "param") {
+ return true;
+ } else if (tag === "source") {
+ return true;
+ } else if (tag === "track") {
+ return true;
+ } else if (tag === "wbr") {
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+}
+function text(key, content) {
+ return new Text(text_kind, key, content);
+}
+function unsafe_inner_html(key, namespace, tag, attributes, inner_html) {
+ return new UnsafeInnerHtml(unsafe_inner_html_kind, key, namespace, tag, prepare(attributes), inner_html);
+}
+function map5(element2, mapper) {
+ if (element2 instanceof Map2) {
+ let child_mapper = element2.mapper;
+ return new Map2(map_kind, element2.key, (handler) => {
+ return identity2(mapper)(child_mapper(handler));
+ }, identity2(element2.child));
+ } else {
+ return new Map2(map_kind, element2.key, identity2(mapper), identity2(element2));
+ }
+}
+function memo(key, dependencies, view) {
+ return new Memo(memo_kind, key, dependencies, view);
+}
+function to_keyed(key, node) {
+ if (node instanceof Fragment) {
+ return new Fragment(node.kind, key, node.children, node.keyed_children);
+ } else if (node instanceof Element2) {
+ return new Element2(node.kind, key, node.namespace, node.tag, node.attributes, node.children, node.keyed_children, node.self_closing, node.void);
+ } else if (node instanceof Text) {
+ return new Text(node.kind, key, node.content);
+ } else if (node instanceof UnsafeInnerHtml) {
+ return new UnsafeInnerHtml(node.kind, key, node.namespace, node.tag, node.attributes, node.inner_html);
+ } else if (node instanceof Map2) {
+ let child = node.child;
+ return new Map2(node.kind, key, node.mapper, to_keyed(key, child));
+ } else {
+ let view = node.view;
+ return new Memo(node.kind, key, node.dependencies, () => {
+ return to_keyed(key, view());
+ });
+ }
+}
+
+// build/dev/javascript/lustre/lustre/element.mjs
+class Html extends CustomType {
+}
+var DocumentType$Html$const = new Html;
+
+class HeadOnly extends CustomType {
+}
+var DocumentType$HeadOnly$const = new HeadOnly;
+
+class BodyOnly extends CustomType {
+}
+var DocumentType$BodyOnly$const = new BodyOnly;
+
+class HeadAndBody extends CustomType {
+}
+var DocumentType$HeadAndBody$const = new HeadAndBody;
+
+class Other extends CustomType {
+}
+var DocumentType$Other$const = new Other;
+function element2(tag, attributes, children) {
+ return element("", "", tag, attributes, children, empty2(), false, is_void_html_element(tag, ""));
+}
+function text2(content) {
+ return text("", content);
+}
+function none2() {
+ return text("", "");
+}
+function unsafe_raw_html(namespace, tag, attributes, inner_html) {
+ return unsafe_inner_html("", namespace, tag, attributes, inner_html);
+}
+function memo2(dependencies, view) {
+ return memo("", dependencies, view);
+}
+function ref(value2) {
+ return identity2(value2);
+}
+function map6(element3, f) {
+ return map5(element3, f);
+}
+
+// build/dev/javascript/lustre/lustre/element/html.mjs
+function text3(content) {
+ return text2(content);
+}
+function style(attrs, css) {
+ return unsafe_raw_html("", "style", attrs, css);
+}
+function article(attrs, children) {
+ return element2("article", attrs, children);
+}
+function header(attrs, children) {
+ return element2("header", attrs, children);
+}
+function h1(attrs, children) {
+ return element2("h1", attrs, children);
+}
+function h2(attrs, children) {
+ return element2("h2", attrs, children);
+}
+function main(attrs, children) {
+ return element2("main", attrs, children);
+}
+function section(attrs, children) {
+ return element2("section", attrs, children);
+}
+function div(attrs, children) {
+ return element2("div", attrs, children);
+}
+function p(attrs, children) {
+ return element2("p", attrs, children);
+}
+function a(attrs, children) {
+ return element2("a", attrs, children);
+}
+function span(attrs, children) {
+ return element2("span", attrs, children);
+}
+function strong(attrs, children) {
+ return element2("strong", attrs, children);
+}
+function button(attrs, children) {
+ return element2("button", attrs, children);
+}
+function form(attrs, children) {
+ return element2("form", attrs, children);
+}
+function input(attrs) {
+ return element2("input", attrs, empty_list);
+}
+
+// build/dev/javascript/lustre/lustre/vdom/patch.mjs
+class Patch extends CustomType {
+ constructor(index4, path, removed, changes, children) {
+ super();
+ this.index = index4;
+ this.path = path;
+ this.removed = removed;
+ this.changes = changes;
+ this.children = children;
+ }
+}
+class ReplaceText extends CustomType {
+ constructor(kind, content) {
+ super();
+ this.kind = kind;
+ this.content = content;
+ }
+}
+class ReplaceInnerHtml extends CustomType {
+ constructor(kind, inner_html) {
+ super();
+ this.kind = kind;
+ this.inner_html = inner_html;
+ }
+}
+class Update extends CustomType {
+ constructor(kind, added, removed) {
+ super();
+ this.kind = kind;
+ this.added = added;
+ this.removed = removed;
+ }
+}
+class Move extends CustomType {
+ constructor(kind, key, before) {
+ super();
+ this.kind = kind;
+ this.key = key;
+ this.before = before;
+ }
+}
+class Replace extends CustomType {
+ constructor(kind, index4, with$) {
+ super();
+ this.kind = kind;
+ this.index = index4;
+ this.with = with$;
+ }
+}
+class Remove extends CustomType {
+ constructor(kind, index4) {
+ super();
+ this.kind = kind;
+ this.index = index4;
+ }
+}
+class Insert extends CustomType {
+ constructor(kind, children, before) {
+ super();
+ this.kind = kind;
+ this.children = children;
+ this.before = before;
+ }
+}
+var replace_text_kind = 0;
+var replace_inner_html_kind = 1;
+var update_kind = 2;
+var move_kind = 3;
+var remove_kind = 4;
+var replace_kind = 5;
+var insert_kind = 6;
+function new$3(index4, removed, changes, children) {
+ return new Patch(index4, empty_list, removed, changes, children);
+}
+function replace_text(content) {
+ return new ReplaceText(replace_text_kind, content);
+}
+function replace_inner_html(inner_html) {
+ return new ReplaceInnerHtml(replace_inner_html_kind, inner_html);
+}
+function update(added, removed) {
+ return new Update(update_kind, added, removed);
+}
+function move(key, before) {
+ return new Move(move_kind, key, before);
+}
+function remove2(index4) {
+ return new Remove(remove_kind, index4);
+}
+function replace2(index4, with$) {
+ return new Replace(replace_kind, index4, with$);
+}
+function insert3(children, before) {
+ return new Insert(insert_kind, children, before);
+}
+function add_parent(child, index4) {
+ return new Patch(index4, prepend(child.index, child.path), child.removed, child.changes, child.children);
+}
+
+// build/dev/javascript/lustre/lustre/runtime/transport.mjs
+class Mount extends CustomType {
+ constructor(kind, open_shadow_root, will_adopt_styles, observed_attributes, observed_properties, requested_contexts, provided_contexts, vdom, memos) {
+ super();
+ this.kind = kind;
+ this.open_shadow_root = open_shadow_root;
+ this.will_adopt_styles = will_adopt_styles;
+ this.observed_attributes = observed_attributes;
+ this.observed_properties = observed_properties;
+ this.requested_contexts = requested_contexts;
+ this.provided_contexts = provided_contexts;
+ this.vdom = vdom;
+ this.memos = memos;
+ }
+}
+class Reconcile extends CustomType {
+ constructor(kind, patch, memos) {
+ super();
+ this.kind = kind;
+ this.patch = patch;
+ this.memos = memos;
+ }
+}
+class Emit extends CustomType {
+ constructor(kind, name2, data) {
+ super();
+ this.kind = kind;
+ this.name = name2;
+ this.data = data;
+ }
+}
+class Provide extends CustomType {
+ constructor(kind, key, value2) {
+ super();
+ this.kind = kind;
+ this.key = key;
+ this.value = value2;
+ }
+}
+class Subscribe extends CustomType {
+ constructor(kind, key) {
+ super();
+ this.kind = kind;
+ this.key = key;
+ }
+}
+class Unsubscribe extends CustomType {
+ constructor(kind, key) {
+ super();
+ this.kind = kind;
+ this.key = key;
+ }
+}
+class Batch extends CustomType {
+ constructor(kind, messages) {
+ super();
+ this.kind = kind;
+ this.messages = messages;
+ }
+}
+var ServerMessage$isBatch = (value2) => value2 instanceof Batch;
+class AttributeChanged extends CustomType {
+ constructor(kind, name2, value2) {
+ super();
+ this.kind = kind;
+ this.name = name2;
+ this.value = value2;
+ }
+}
+var ServerMessage$isAttributeChanged = (value2) => value2 instanceof AttributeChanged;
+class PropertyChanged extends CustomType {
+ constructor(kind, name2, value2) {
+ super();
+ this.kind = kind;
+ this.name = name2;
+ this.value = value2;
+ }
+}
+var ServerMessage$isPropertyChanged = (value2) => value2 instanceof PropertyChanged;
+class EventFired extends CustomType {
+ constructor(kind, path, name2, event2) {
+ super();
+ this.kind = kind;
+ this.path = path;
+ this.name = name2;
+ this.event = event2;
+ }
+}
+var ServerMessage$isEventFired = (value2) => value2 instanceof EventFired;
+class ContextProvided extends CustomType {
+ constructor(kind, key, value2) {
+ super();
+ this.kind = kind;
+ this.key = key;
+ this.value = value2;
+ }
+}
+var ServerMessage$isContextProvided = (value2) => value2 instanceof ContextProvided;
+var mount_kind = 0;
+var reconcile_kind = 1;
+var emit_kind = 2;
+var provide_kind = 3;
+var subscribe_kind = 4;
+var unsubscribe_kind = 5;
+function mount(open_shadow_root, will_adopt_styles, observed_attributes, observed_properties, requested_contexts, provided_contexts, vdom, memos) {
+ return new Mount(mount_kind, open_shadow_root, will_adopt_styles, observed_attributes, observed_properties, requested_contexts, provided_contexts, vdom, memos);
+}
+function reconcile(patch, memos) {
+ return new Reconcile(reconcile_kind, patch, memos);
+}
+function emit(name2, data) {
+ return new Emit(emit_kind, name2, data);
+}
+function provide(key, value2) {
+ return new Provide(provide_kind, key, value2);
+}
+function subscribe(key) {
+ return new Subscribe(subscribe_kind, key);
+}
+function unsubscribe(key) {
+ return new Unsubscribe(unsubscribe_kind, key);
+}
+
+// build/dev/javascript/lustre/lustre/vdom/path.mjs
+class Root extends CustomType {
+}
+var Path$Root$const = new Root;
+
+class Key extends CustomType {
+ constructor(key, parent) {
+ super();
+ this.key = key;
+ this.parent = parent;
+ }
+}
+
+class Index extends CustomType {
+ constructor(index4, parent) {
+ super();
+ this.index = index4;
+ this.parent = parent;
+ }
+}
+
+class Subtree extends CustomType {
+ constructor(parent) {
+ super();
+ this.parent = parent;
+ }
+}
+var separator_subtree = "\r";
+var separator_element = "\t";
+var separator_event = `
+`;
+var root = Path$Root$const;
+function finish_to_string(acc) {
+ if (acc instanceof Empty) {
+ return "";
+ } else {
+ let segments = acc.tail;
+ return concat2(segments);
+ }
+}
+function do_to_string(loop$full, loop$path, loop$acc) {
+ while (true) {
+ let full = loop$full;
+ let path = loop$path;
+ let acc = loop$acc;
+ if (path instanceof Root) {
+ return finish_to_string(acc);
+ } else if (path instanceof Key) {
+ let key = path.key;
+ let parent = path.parent;
+ loop$full = full;
+ loop$path = parent;
+ loop$acc = prepend(separator_element, prepend(key, acc));
+ } else if (path instanceof Index) {
+ let index4 = path.index;
+ let parent = path.parent;
+ let acc$1 = prepend(separator_element, prepend(to_string(index4), acc));
+ loop$full = full;
+ loop$path = parent;
+ loop$acc = acc$1;
+ } else if (!full) {
+ return finish_to_string(acc);
+ } else {
+ let parent = path.parent;
+ if (acc instanceof Empty) {
+ loop$full = full;
+ loop$path = parent;
+ loop$acc = acc;
+ } else {
+ let acc$1 = acc.tail;
+ loop$full = full;
+ loop$path = parent;
+ loop$acc = prepend(separator_subtree, acc$1);
+ }
+ }
+ }
+}
+function to_string4(path) {
+ return do_to_string(true, path, empty_list);
+}
+function do_matches(loop$path, loop$candidates) {
+ while (true) {
+ let path = loop$path;
+ let candidates = loop$candidates;
+ if (candidates instanceof Empty) {
+ return false;
+ } else {
+ let candidate = candidates.head;
+ let rest = candidates.tail;
+ let $ = starts_with(path, candidate);
+ if ($) {
+ return $;
+ } else {
+ loop$path = path;
+ loop$candidates = rest;
+ }
+ }
+ }
+}
+function matches(path, candidates) {
+ if (candidates instanceof Empty) {
+ return false;
+ } else {
+ return do_matches(to_string4(path), candidates);
+ }
+}
+function split_subtree_path(path) {
+ return split2(path, separator_subtree);
+}
+function add2(parent, index4, key) {
+ if (key === "") {
+ return new Index(index4, parent);
+ } else {
+ return new Key(key, parent);
+ }
+}
+function subtree(path) {
+ return new Subtree(path);
+}
+function event2(path, event3) {
+ return do_to_string(false, path, prepend(separator_event, prepend(event3, empty_list)));
+}
+function child(path) {
+ return do_to_string(false, path, empty_list);
+}
+
+// build/dev/javascript/lustre/lustre/vdom/cache.mjs
+class Cache extends CustomType {
+ constructor(events, vdoms, old_vdoms, dispatched_paths, next_dispatched_paths) {
+ super();
+ this.events = events;
+ this.vdoms = vdoms;
+ this.old_vdoms = old_vdoms;
+ this.dispatched_paths = dispatched_paths;
+ this.next_dispatched_paths = next_dispatched_paths;
+ }
+}
+
+class Events extends CustomType {
+ constructor(handlers, children) {
+ super();
+ this.handlers = handlers;
+ this.children = children;
+ }
+}
+
+class Child extends CustomType {
+ constructor(mapper, events) {
+ super();
+ this.mapper = mapper;
+ this.events = events;
+ }
+}
+
+class AddedChildren extends CustomType {
+ constructor(handlers, children, vdoms) {
+ super();
+ this.handlers = handlers;
+ this.children = children;
+ this.vdoms = vdoms;
+ }
+}
+
+class DecodedEvent extends CustomType {
+ constructor(path, handler) {
+ super();
+ this.path = path;
+ this.handler = handler;
+ }
+}
+
+class DispatchedEvent extends CustomType {
+ constructor(path) {
+ super();
+ this.path = path;
+ }
+}
+function compose_mapper(mapper, child_mapper) {
+ return (message) => {
+ return mapper(child_mapper(message));
+ };
+}
+function new_events() {
+ return new Events(empty2(), empty2());
+}
+function new$4() {
+ return new Cache(new_events(), empty2(), empty2(), empty_list, empty_list);
+}
+function do_add_event(handlers, path, name2, handler) {
+ return insert2(handlers, event2(path, name2), handler);
+}
+function add_attributes(handlers, path, attributes) {
+ return fold2(attributes, handlers, (events, attribute3) => {
+ if (attribute3 instanceof Event2) {
+ let name2 = attribute3.name;
+ let handler = attribute3.handler;
+ return do_add_event(events, path, name2, handler);
+ } else {
+ return events;
+ }
+ });
+}
+function do_add_children(loop$handlers, loop$children, loop$vdoms, loop$parent, loop$child_index, loop$nodes) {
+ while (true) {
+ let handlers = loop$handlers;
+ let children = loop$children;
+ let vdoms = loop$vdoms;
+ let parent = loop$parent;
+ let child_index = loop$child_index;
+ let nodes = loop$nodes;
+ let next = child_index + 1;
+ if (nodes instanceof Empty) {
+ return new AddedChildren(handlers, children, vdoms);
+ } else {
+ let $ = nodes.head;
+ if ($ instanceof Fragment) {
+ let rest = nodes.tail;
+ let key = $.key;
+ let nodes$1 = $.children;
+ let path = add2(parent, child_index, key);
+ let $1 = do_add_children(handlers, children, vdoms, path, 0, nodes$1);
+ let handlers$1 = $1.handlers;
+ let children$1 = $1.children;
+ let vdoms$1 = $1.vdoms;
+ loop$handlers = handlers$1;
+ loop$children = children$1;
+ loop$vdoms = vdoms$1;
+ loop$parent = parent;
+ loop$child_index = next;
+ loop$nodes = rest;
+ } else if ($ instanceof Element2) {
+ let rest = nodes.tail;
+ let key = $.key;
+ let attributes = $.attributes;
+ let nodes$1 = $.children;
+ let path = add2(parent, child_index, key);
+ let handlers$1 = add_attributes(handlers, path, attributes);
+ let $1 = do_add_children(handlers$1, children, vdoms, path, 0, nodes$1);
+ let handlers$2 = $1.handlers;
+ let children$1 = $1.children;
+ let vdoms$1 = $1.vdoms;
+ loop$handlers = handlers$2;
+ loop$children = children$1;
+ loop$vdoms = vdoms$1;
+ loop$parent = parent;
+ loop$child_index = next;
+ loop$nodes = rest;
+ } else if ($ instanceof Text) {
+ let rest = nodes.tail;
+ loop$handlers = handlers;
+ loop$children = children;
+ loop$vdoms = vdoms;
+ loop$parent = parent;
+ loop$child_index = next;
+ loop$nodes = rest;
+ } else if ($ instanceof UnsafeInnerHtml) {
+ let rest = nodes.tail;
+ let key = $.key;
+ let attributes = $.attributes;
+ let path = add2(parent, child_index, key);
+ let handlers$1 = add_attributes(handlers, path, attributes);
+ loop$handlers = handlers$1;
+ loop$children = children;
+ loop$vdoms = vdoms;
+ loop$parent = parent;
+ loop$child_index = next;
+ loop$nodes = rest;
+ } else if ($ instanceof Map2) {
+ let rest = nodes.tail;
+ let key = $.key;
+ let mapper = $.mapper;
+ let child2 = $.child;
+ let path = add2(parent, child_index, key);
+ let added = do_add_children(empty2(), empty2(), vdoms, subtree(path), 0, singleton_list(child2));
+ let vdoms$1 = added.vdoms;
+ let child_events = new Events(added.handlers, added.children);
+ let child$1 = new Child(mapper, child_events);
+ let children$1 = insert2(children, child(path), child$1);
+ loop$handlers = handlers;
+ loop$children = children$1;
+ loop$vdoms = vdoms$1;
+ loop$parent = parent;
+ loop$child_index = next;
+ loop$nodes = rest;
+ } else {
+ let rest = nodes.tail;
+ let view = $.view;
+ let child_node = view();
+ let vdoms$1 = insert2(vdoms, view, child_node);
+ let next$1 = child_index;
+ let rest$1 = prepend(child_node, rest);
+ loop$handlers = handlers;
+ loop$children = children;
+ loop$vdoms = vdoms$1;
+ loop$parent = parent;
+ loop$child_index = next$1;
+ loop$nodes = rest$1;
+ }
+ }
+ }
+}
+function add_children(cache, events, path, child_index, nodes) {
+ let vdoms = cache.vdoms;
+ let handlers = events.handlers;
+ let children = events.children;
+ let $ = do_add_children(handlers, children, vdoms, path, child_index, nodes);
+ let handlers$1 = $.handlers;
+ let children$1 = $.children;
+ let vdoms$1 = $.vdoms;
+ return [
+ new Cache(cache.events, vdoms$1, cache.old_vdoms, cache.dispatched_paths, cache.next_dispatched_paths),
+ new Events(handlers$1, children$1)
+ ];
+}
+function add_child(cache, events, parent, index4, child2) {
+ let children = singleton_list(child2);
+ return add_children(cache, events, parent, index4, children);
+}
+function from_node(root2) {
+ let cache = new$4();
+ let $ = add_child(cache, cache.events, root, 0, root2);
+ let cache$1 = $[0];
+ let events$1 = $[1];
+ return new Cache(events$1, cache$1.vdoms, cache$1.old_vdoms, cache$1.dispatched_paths, cache$1.next_dispatched_paths);
+}
+function tick(cache) {
+ return new Cache(cache.events, empty2(), cache.vdoms, cache.next_dispatched_paths, empty_list);
+}
+function events(cache) {
+ return cache.events;
+}
+function update_events(cache, events2) {
+ return new Cache(events2, cache.vdoms, cache.old_vdoms, cache.dispatched_paths, cache.next_dispatched_paths);
+}
+function memos(cache) {
+ return cache.vdoms;
+}
+function get_old_memo(cache, old, new$5) {
+ return get_or_compute(cache.old_vdoms, old, new$5);
+}
+function keep_memo(cache, old, new$5) {
+ let node = get_or_compute(cache.old_vdoms, old, new$5);
+ let vdoms = insert2(cache.vdoms, new$5, node);
+ return new Cache(cache.events, vdoms, cache.old_vdoms, cache.dispatched_paths, cache.next_dispatched_paths);
+}
+function add_memo(cache, new$5, node) {
+ let vdoms = insert2(cache.vdoms, new$5, node);
+ return new Cache(cache.events, vdoms, cache.old_vdoms, cache.dispatched_paths, cache.next_dispatched_paths);
+}
+function get_subtree(events2, path, old_mapper) {
+ let child2 = get_or_compute(events2.children, path, () => {
+ return new Child(old_mapper, new_events());
+ });
+ return child2.events;
+}
+function update_subtree(parent, path, mapper, events2) {
+ let new_child = new Child(mapper, events2);
+ let children = insert2(parent.children, path, new_child);
+ return new Events(parent.handlers, children);
+}
+function add_event(events2, path, name2, handler) {
+ let handlers = do_add_event(events2.handlers, path, name2, handler);
+ return new Events(handlers, events2.children);
+}
+function do_remove_event(handlers, path, name2) {
+ return remove(handlers, event2(path, name2));
+}
+function remove_event(events2, path, name2) {
+ let handlers = do_remove_event(events2.handlers, path, name2);
+ return new Events(handlers, events2.children);
+}
+function remove_attributes(handlers, path, attributes) {
+ return fold2(attributes, handlers, (events2, attribute3) => {
+ if (attribute3 instanceof Event2) {
+ let name2 = attribute3.name;
+ return do_remove_event(events2, path, name2);
+ } else {
+ return events2;
+ }
+ });
+}
+function do_remove_children(loop$handlers, loop$children, loop$vdoms, loop$parent, loop$index, loop$nodes) {
+ while (true) {
+ let handlers = loop$handlers;
+ let children = loop$children;
+ let vdoms = loop$vdoms;
+ let parent = loop$parent;
+ let index4 = loop$index;
+ let nodes = loop$nodes;
+ let next = index4 + 1;
+ if (nodes instanceof Empty) {
+ return new Events(handlers, children);
+ } else {
+ let $ = nodes.head;
+ if ($ instanceof Fragment) {
+ let rest = nodes.tail;
+ let key = $.key;
+ let nodes$1 = $.children;
+ let path = add2(parent, index4, key);
+ let $1 = do_remove_children(handlers, children, vdoms, path, 0, nodes$1);
+ let handlers$1 = $1.handlers;
+ let children$1 = $1.children;
+ loop$handlers = handlers$1;
+ loop$children = children$1;
+ loop$vdoms = vdoms;
+ loop$parent = parent;
+ loop$index = next;
+ loop$nodes = rest;
+ } else if ($ instanceof Element2) {
+ let rest = nodes.tail;
+ let key = $.key;
+ let attributes = $.attributes;
+ let nodes$1 = $.children;
+ let path = add2(parent, index4, key);
+ let handlers$1 = remove_attributes(handlers, path, attributes);
+ let $1 = do_remove_children(handlers$1, children, vdoms, path, 0, nodes$1);
+ let handlers$2 = $1.handlers;
+ let children$1 = $1.children;
+ loop$handlers = handlers$2;
+ loop$children = children$1;
+ loop$vdoms = vdoms;
+ loop$parent = parent;
+ loop$index = next;
+ loop$nodes = rest;
+ } else if ($ instanceof Text) {
+ let rest = nodes.tail;
+ loop$handlers = handlers;
+ loop$children = children;
+ loop$vdoms = vdoms;
+ loop$parent = parent;
+ loop$index = next;
+ loop$nodes = rest;
+ } else if ($ instanceof UnsafeInnerHtml) {
+ let rest = nodes.tail;
+ let key = $.key;
+ let attributes = $.attributes;
+ let path = add2(parent, index4, key);
+ let handlers$1 = remove_attributes(handlers, path, attributes);
+ loop$handlers = handlers$1;
+ loop$children = children;
+ loop$vdoms = vdoms;
+ loop$parent = parent;
+ loop$index = next;
+ loop$nodes = rest;
+ } else if ($ instanceof Map2) {
+ let rest = nodes.tail;
+ let key = $.key;
+ let path = add2(parent, index4, key);
+ let children$1 = remove(children, child(path));
+ loop$handlers = handlers;
+ loop$children = children$1;
+ loop$vdoms = vdoms;
+ loop$parent = parent;
+ loop$index = next;
+ loop$nodes = rest;
+ } else {
+ let rest = nodes.tail;
+ let view = $.view;
+ let $1 = has_key(vdoms, view);
+ if ($1) {
+ let child2 = get2(vdoms, view);
+ let nodes$1 = prepend(child2, rest);
+ loop$handlers = handlers;
+ loop$children = children;
+ loop$vdoms = vdoms;
+ loop$parent = parent;
+ loop$index = index4;
+ loop$nodes = nodes$1;
+ } else {
+ loop$handlers = handlers;
+ loop$children = children;
+ loop$vdoms = vdoms;
+ loop$parent = parent;
+ loop$index = next;
+ loop$nodes = rest;
+ }
+ }
+ }
+ }
+}
+function remove_child(cache, events2, parent, child_index, child2) {
+ return do_remove_children(events2.handlers, events2.children, cache.old_vdoms, parent, child_index, singleton_list(child2));
+}
+function replace_child(cache, events2, parent, child_index, prev, next) {
+ let events$1 = remove_child(cache, events2, parent, child_index, prev);
+ return add_child(cache, events$1, parent, child_index, next);
+}
+function get_handler(loop$events, loop$path, loop$mapper) {
+ while (true) {
+ let events2 = loop$events;
+ let path = loop$path;
+ let mapper = loop$mapper;
+ if (path instanceof Empty) {
+ return error_nil;
+ } else {
+ let $ = path.tail;
+ if ($ instanceof Empty) {
+ let key = path.head;
+ let $1 = has_key(events2.handlers, key);
+ if ($1) {
+ let handler = get2(events2.handlers, key);
+ return new Ok(map3(handler, (handler2) => {
+ return new Handler(handler2.prevent_default, handler2.stop_propagation, identity2(mapper)(handler2.message));
+ }));
+ } else {
+ return error_nil;
+ }
+ } else {
+ let key = path.head;
+ let path$1 = $;
+ let $1 = has_key(events2.children, key);
+ if ($1) {
+ let child2 = get2(events2.children, key);
+ let mapper$1 = compose_mapper(mapper, child2.mapper);
+ loop$events = child2.events;
+ loop$path = path$1;
+ loop$mapper = mapper$1;
+ } else {
+ return error_nil;
+ }
+ }
+ }
+ }
+}
+function decode2(cache, path, name2, event3) {
+ let parts = split_subtree_path(path + separator_event + name2);
+ let $ = get_handler(cache.events, parts, identity2);
+ if ($ instanceof Ok) {
+ let handler = $[0];
+ let $1 = run(event3, handler);
+ if ($1 instanceof Ok) {
+ let handler$1 = $1[0];
+ return new DecodedEvent(path, handler$1);
+ } else {
+ return new DispatchedEvent(path);
+ }
+ } else {
+ return new DispatchedEvent(path);
+ }
+}
+function dispatch(cache, event3) {
+ let next_dispatched_paths = prepend(event3.path, cache.next_dispatched_paths);
+ let cache$1 = new Cache(cache.events, cache.vdoms, cache.old_vdoms, cache.dispatched_paths, next_dispatched_paths);
+ if (event3 instanceof DecodedEvent) {
+ let handler = event3.handler;
+ return [cache$1, new Ok(handler)];
+ } else {
+ return [cache$1, error_nil];
+ }
+}
+function handle(cache, path, name2, event3) {
+ let _pipe = decode2(cache, path, name2, event3);
+ return ((_capture) => {
+ return dispatch(cache, _capture);
+ })(_pipe);
+}
+function has_dispatched_events(cache, path) {
+ return matches(path, cache.dispatched_paths);
+}
+
+// build/dev/javascript/lustre/lustre/runtime/server/runtime.mjs
+class ClientDispatchedMessage extends CustomType {
+ constructor(message) {
+ super();
+ this.message = message;
+ }
+}
+var Message$isClientDispatchedMessage = (value2) => value2 instanceof ClientDispatchedMessage;
+class ClientRegisteredCallback extends CustomType {
+ constructor(callback) {
+ super();
+ this.callback = callback;
+ }
+}
+var Message$isClientRegisteredCallback = (value2) => value2 instanceof ClientRegisteredCallback;
+class ClientDeregisteredCallback extends CustomType {
+ constructor(callback) {
+ super();
+ this.callback = callback;
+ }
+}
+var Message$isClientDeregisteredCallback = (value2) => value2 instanceof ClientDeregisteredCallback;
+class EffectDispatchedMessage extends CustomType {
+ constructor(message) {
+ super();
+ this.message = message;
+ }
+}
+var Message$EffectDispatchedMessage = (message) => new EffectDispatchedMessage(message);
+var Message$isEffectDispatchedMessage = (value2) => value2 instanceof EffectDispatchedMessage;
+class EffectEmitEvent extends CustomType {
+ constructor(name2, data) {
+ super();
+ this.name = name2;
+ this.data = data;
+ }
+}
+var Message$EffectEmitEvent = (name2, data) => new EffectEmitEvent(name2, data);
+var Message$isEffectEmitEvent = (value2) => value2 instanceof EffectEmitEvent;
+class EffectProvidedValue extends CustomType {
+ constructor(key, value2) {
+ super();
+ this.key = key;
+ this.value = value2;
+ }
+}
+var Message$EffectProvidedValue = (key, value2) => new EffectProvidedValue(key, value2);
+var Message$isEffectProvidedValue = (value2) => value2 instanceof EffectProvidedValue;
+class EffectRequestedContextSubscription extends CustomType {
+ constructor(key, decoder) {
+ super();
+ this.key = key;
+ this.decoder = decoder;
+ }
+}
+var Message$EffectRequestedContextSubscription = (key, decoder) => new EffectRequestedContextSubscription(key, decoder);
+var Message$isEffectRequestedContextSubscription = (value2) => value2 instanceof EffectRequestedContextSubscription;
+class EffectRemovedContextSubscription extends CustomType {
+ constructor(key) {
+ super();
+ this.key = key;
+ }
+}
+var Message$EffectRemovedContextSubscription = (key) => new EffectRemovedContextSubscription(key);
+var Message$isEffectRemovedContextSubscription = (value2) => value2 instanceof EffectRemovedContextSubscription;
+class SystemRequestedShutdown extends CustomType {
+}
+var Message$SystemRequestedShutdown$const = new SystemRequestedShutdown;
+var Message$isSystemRequestedShutdown = (value2) => value2 instanceof SystemRequestedShutdown;
+
+// build/dev/javascript/lustre/lustre/runtime/app.mjs
+class App extends CustomType {
+ constructor(name2, init, update2, view, config) {
+ super();
+ this.name = name2;
+ this.init = init;
+ this.update = update2;
+ this.view = view;
+ this.config = config;
+ }
+}
+class Config2 extends CustomType {
+ constructor(open_shadow_root, adopt_styles, delegates_focus, attributes, properties, contexts, is_form_associated, on_form_autofill, on_form_reset, on_form_restore, on_form_disabled, on_connect, on_adopt, on_disconnect) {
+ super();
+ this.open_shadow_root = open_shadow_root;
+ this.adopt_styles = adopt_styles;
+ this.delegates_focus = delegates_focus;
+ this.attributes = attributes;
+ this.properties = properties;
+ this.contexts = contexts;
+ this.is_form_associated = is_form_associated;
+ this.on_form_autofill = on_form_autofill;
+ this.on_form_reset = on_form_reset;
+ this.on_form_restore = on_form_restore;
+ this.on_form_disabled = on_form_disabled;
+ this.on_connect = on_connect;
+ this.on_adopt = on_adopt;
+ this.on_disconnect = on_disconnect;
+ }
+}
+var default_config = /* @__PURE__ */ new Config2(true, true, false, empty_list, empty_list, empty_list, false, Option$None$const, Option$None$const, Option$None$const, Option$None$const, Option$None$const, Option$None$const, Option$None$const);
+
+// build/dev/javascript/lustre/lustre/internals/equals.ffi.mjs
+var isEqual2 = (a2, b) => {
+ if (a2 === b) {
+ return true;
+ }
+ if (a2 == null || b == null) {
+ return false;
+ }
+ const type = typeof a2;
+ if (type !== typeof b) {
+ return false;
+ }
+ if (type !== "object") {
+ return false;
+ }
+ const ctor = a2.constructor;
+ if (ctor !== b.constructor) {
+ return false;
+ }
+ if (Array.isArray(a2)) {
+ return areArraysEqual(a2, b);
+ }
+ return areObjectsEqual(a2, b);
+};
+var areArraysEqual = (a2, b) => {
+ let index4 = a2.length;
+ if (index4 !== b.length) {
+ return false;
+ }
+ while (index4--) {
+ if (!isEqual2(a2[index4], b[index4])) {
+ return false;
+ }
+ }
+ return true;
+};
+var areObjectsEqual = (a2, b) => {
+ const properties = Object.keys(a2);
+ let index4 = properties.length;
+ if (Object.keys(b).length !== index4) {
+ return false;
+ }
+ while (index4--) {
+ const property3 = properties[index4];
+ if (!Object.hasOwn(b, property3)) {
+ return false;
+ }
+ if (!isEqual2(a2[property3], b[property3])) {
+ return false;
+ }
+ }
+ return true;
+};
+
+// build/dev/javascript/lustre/lustre/vdom/diff.mjs
+class Diff extends CustomType {
+ constructor(patch, cache) {
+ super();
+ this.patch = patch;
+ this.cache = cache;
+ }
+}
+class PartialDiff extends CustomType {
+ constructor(patch, cache, events2) {
+ super();
+ this.patch = patch;
+ this.cache = cache;
+ this.events = events2;
+ }
+}
+
+class AttributeChange extends CustomType {
+ constructor(added, removed, events2) {
+ super();
+ this.added = added;
+ this.removed = removed;
+ this.events = events2;
+ }
+}
+function diff_attributes(loop$controlled, loop$path, loop$events, loop$old, loop$new, loop$added, loop$removed) {
+ while (true) {
+ let controlled = loop$controlled;
+ let path = loop$path;
+ let events2 = loop$events;
+ let old = loop$old;
+ let new$5 = loop$new;
+ let added = loop$added;
+ let removed = loop$removed;
+ if (old instanceof Empty) {
+ if (new$5 instanceof Empty) {
+ return new AttributeChange(added, removed, events2);
+ } else {
+ let $ = new$5.head;
+ if ($ instanceof Event2) {
+ let next = $;
+ let new$1 = new$5.tail;
+ let name2 = $.name;
+ let handler = $.handler;
+ let events$1 = add_event(events2, path, name2, handler);
+ let added$1 = prepend(next, added);
+ loop$controlled = controlled;
+ loop$path = path;
+ loop$events = events$1;
+ loop$old = old;
+ loop$new = new$1;
+ loop$added = added$1;
+ loop$removed = removed;
+ } else {
+ let next = $;
+ let new$1 = new$5.tail;
+ let added$1 = prepend(next, added);
+ loop$controlled = controlled;
+ loop$path = path;
+ loop$events = events2;
+ loop$old = old;
+ loop$new = new$1;
+ loop$added = added$1;
+ loop$removed = removed;
+ }
+ }
+ } else if (new$5 instanceof Empty) {
+ let $ = old.head;
+ if ($ instanceof Event2) {
+ let prev = $;
+ let old$1 = old.tail;
+ let name2 = $.name;
+ let events$1 = remove_event(events2, path, name2);
+ let removed$1 = prepend(prev, removed);
+ loop$controlled = controlled;
+ loop$path = path;
+ loop$events = events$1;
+ loop$old = old$1;
+ loop$new = new$5;
+ loop$added = added;
+ loop$removed = removed$1;
+ } else {
+ let prev = $;
+ let old$1 = old.tail;
+ let removed$1 = prepend(prev, removed);
+ loop$controlled = controlled;
+ loop$path = path;
+ loop$events = events2;
+ loop$old = old$1;
+ loop$new = new$5;
+ loop$added = added;
+ loop$removed = removed$1;
+ }
+ } else {
+ let prev = old.head;
+ let remaining_old = old.tail;
+ let next = new$5.head;
+ let remaining_new = new$5.tail;
+ let $ = compare2(prev, next);
+ if ($ instanceof Lt) {
+ if (prev instanceof Event2) {
+ let name2 = prev.name;
+ loop$controlled = controlled;
+ loop$path = path;
+ loop$events = remove_event(events2, path, name2);
+ loop$old = remaining_old;
+ loop$new = new$5;
+ loop$added = added;
+ loop$removed = prepend(prev, removed);
+ } else {
+ loop$controlled = controlled;
+ loop$path = path;
+ loop$events = events2;
+ loop$old = remaining_old;
+ loop$new = new$5;
+ loop$added = added;
+ loop$removed = prepend(prev, removed);
+ }
+ } else if ($ instanceof Eq) {
+ if (prev instanceof Attribute) {
+ if (next instanceof Attribute) {
+ let _block;
+ let $1 = next.name;
+ if ($1 === "value") {
+ _block = controlled || prev.value !== next.value;
+ } else if ($1 === "checked") {
+ _block = controlled || prev.value !== next.value;
+ } else if ($1 === "selected") {
+ _block = controlled || prev.value !== next.value;
+ } else {
+ _block = prev.value !== next.value;
+ }
+ let has_changes = _block;
+ let _block$1;
+ if (has_changes) {
+ _block$1 = prepend(next, added);
+ } else {
+ _block$1 = added;
+ }
+ let added$1 = _block$1;
+ loop$controlled = controlled;
+ loop$path = path;
+ loop$events = events2;
+ loop$old = remaining_old;
+ loop$new = remaining_new;
+ loop$added = added$1;
+ loop$removed = removed;
+ } else if (next instanceof Event2) {
+ let name2 = next.name;
+ let handler = next.handler;
+ loop$controlled = controlled;
+ loop$path = path;
+ loop$events = add_event(events2, path, name2, handler);
+ loop$old = remaining_old;
+ loop$new = remaining_new;
+ loop$added = prepend(next, added);
+ loop$removed = prepend(prev, removed);
+ } else {
+ loop$controlled = controlled;
+ loop$path = path;
+ loop$events = events2;
+ loop$old = remaining_old;
+ loop$new = remaining_new;
+ loop$added = prepend(next, added);
+ loop$removed = prepend(prev, removed);
+ }
+ } else if (prev instanceof Property) {
+ if (next instanceof Property) {
+ let _block;
+ let $1 = next.name;
+ if ($1 === "scrollLeft") {
+ _block = true;
+ } else if ($1 === "scrollRight") {
+ _block = true;
+ } else if ($1 === "value") {
+ _block = controlled || !isEqual2(prev.value, next.value);
+ } else if ($1 === "checked") {
+ _block = controlled || !isEqual2(prev.value, next.value);
+ } else if ($1 === "selected") {
+ _block = controlled || !isEqual2(prev.value, next.value);
+ } else {
+ _block = !isEqual2(prev.value, next.value);
+ }
+ let has_changes = _block;
+ let _block$1;
+ if (has_changes) {
+ _block$1 = prepend(next, added);
+ } else {
+ _block$1 = added;
+ }
+ let added$1 = _block$1;
+ loop$controlled = controlled;
+ loop$path = path;
+ loop$events = events2;
+ loop$old = remaining_old;
+ loop$new = remaining_new;
+ loop$added = added$1;
+ loop$removed = removed;
+ } else if (next instanceof Event2) {
+ let name2 = next.name;
+ let handler = next.handler;
+ loop$controlled = controlled;
+ loop$path = path;
+ loop$events = add_event(events2, path, name2, handler);
+ loop$old = remaining_old;
+ loop$new = remaining_new;
+ loop$added = prepend(next, added);
+ loop$removed = prepend(prev, removed);
+ } else {
+ loop$controlled = controlled;
+ loop$path = path;
+ loop$events = events2;
+ loop$old = remaining_old;
+ loop$new = remaining_new;
+ loop$added = prepend(next, added);
+ loop$removed = prepend(prev, removed);
+ }
+ } else if (next instanceof Event2) {
+ let name2 = next.name;
+ let handler = next.handler;
+ let has_changes = prev.prevent_default.kind !== next.prevent_default.kind || prev.stop_propagation.kind !== next.stop_propagation.kind || prev.debounce !== next.debounce || prev.throttle !== next.throttle;
+ let _block;
+ if (has_changes) {
+ _block = prepend(next, added);
+ } else {
+ _block = added;
+ }
+ let added$1 = _block;
+ loop$controlled = controlled;
+ loop$path = path;
+ loop$events = add_event(events2, path, name2, handler);
+ loop$old = remaining_old;
+ loop$new = remaining_new;
+ loop$added = added$1;
+ loop$removed = removed;
+ } else {
+ let name2 = prev.name;
+ loop$controlled = controlled;
+ loop$path = path;
+ loop$events = remove_event(events2, path, name2);
+ loop$old = remaining_old;
+ loop$new = remaining_new;
+ loop$added = prepend(next, added);
+ loop$removed = prepend(prev, removed);
+ }
+ } else if (next instanceof Event2) {
+ let name2 = next.name;
+ let handler = next.handler;
+ loop$controlled = controlled;
+ loop$path = path;
+ loop$events = add_event(events2, path, name2, handler);
+ loop$old = old;
+ loop$new = remaining_new;
+ loop$added = prepend(next, added);
+ loop$removed = removed;
+ } else {
+ loop$controlled = controlled;
+ loop$path = path;
+ loop$events = events2;
+ loop$old = old;
+ loop$new = remaining_new;
+ loop$added = prepend(next, added);
+ loop$removed = removed;
+ }
+ }
+ }
+}
+function is_controlled(cache, namespace, tag, path) {
+ if (tag === "input" && namespace === "") {
+ return has_dispatched_events(cache, path);
+ } else if (tag === "select" && namespace === "") {
+ return has_dispatched_events(cache, path);
+ } else if (tag === "textarea" && namespace === "") {
+ return has_dispatched_events(cache, path);
+ } else {
+ return false;
+ }
+}
+function do_diff(loop$old, loop$old_keyed, loop$new, loop$new_keyed, loop$moved, loop$moved_offset, loop$removed, loop$node_index, loop$patch_index, loop$changes, loop$children, loop$path, loop$cache, loop$events) {
+ while (true) {
+ let old = loop$old;
+ let old_keyed = loop$old_keyed;
+ let new$5 = loop$new;
+ let new_keyed = loop$new_keyed;
+ let moved = loop$moved;
+ let moved_offset = loop$moved_offset;
+ let removed = loop$removed;
+ let node_index = loop$node_index;
+ let patch_index = loop$patch_index;
+ let changes = loop$changes;
+ let children = loop$children;
+ let path = loop$path;
+ let cache = loop$cache;
+ let events2 = loop$events;
+ if (old instanceof Empty) {
+ if (new$5 instanceof Empty) {
+ let _block;
+ let $ = is_browser();
+ if (changes instanceof Empty) {
+ if (children instanceof Empty) {
+ _block = new$3(patch_index, removed, changes, children);
+ } else if (!$) {
+ let $1 = children.tail;
+ if ($1 instanceof Empty && removed === 0) {
+ let child2 = children.head;
+ _block = add_parent(child2, patch_index);
+ } else {
+ _block = new$3(patch_index, removed, changes, children);
+ }
+ } else {
+ _block = new$3(patch_index, removed, changes, children);
+ }
+ } else {
+ _block = new$3(patch_index, removed, changes, children);
+ }
+ let patch = _block;
+ return new PartialDiff(patch, cache, events2);
+ } else {
+ let $ = add_children(cache, events2, path, node_index, new$5);
+ let cache$1 = $[0];
+ let events$1 = $[1];
+ let insert4 = insert3(new$5, node_index - moved_offset);
+ let changes$1 = prepend(insert4, changes);
+ let patch = new$3(patch_index, removed, changes$1, children);
+ return new PartialDiff(patch, cache$1, events$1);
+ }
+ } else if (new$5 instanceof Empty) {
+ let prev = old.head;
+ let old$1 = old.tail;
+ let $ = prev.key === "" || !has_key(moved, prev.key);
+ if ($) {
+ let events$1 = remove_child(cache, events2, path, node_index, prev);
+ loop$old = old$1;
+ loop$old_keyed = old_keyed;
+ loop$new = new$5;
+ loop$new_keyed = new_keyed;
+ loop$moved = moved;
+ loop$moved_offset = moved_offset;
+ loop$removed = removed + 1;
+ loop$node_index = node_index;
+ loop$patch_index = patch_index;
+ loop$changes = changes;
+ loop$children = children;
+ loop$path = path;
+ loop$cache = cache;
+ loop$events = events$1;
+ } else {
+ loop$old = old$1;
+ loop$old_keyed = old_keyed;
+ loop$new = new$5;
+ loop$new_keyed = new_keyed;
+ loop$moved = moved;
+ loop$moved_offset = moved_offset;
+ loop$removed = removed;
+ loop$node_index = node_index;
+ loop$patch_index = patch_index;
+ loop$changes = changes;
+ loop$children = children;
+ loop$path = path;
+ loop$cache = cache;
+ loop$events = events2;
+ }
+ } else {
+ let prev = old.head;
+ let next = new$5.head;
+ if (prev.key !== next.key) {
+ let old_remaining = old.tail;
+ let new_remaining = new$5.tail;
+ let next_did_exist = has_key(old_keyed, next.key);
+ let prev_does_exist = has_key(new_keyed, prev.key);
+ if (prev_does_exist) {
+ if (next_did_exist) {
+ let $ = has_key(moved, prev.key);
+ if ($) {
+ loop$old = old_remaining;
+ loop$old_keyed = old_keyed;
+ loop$new = new$5;
+ loop$new_keyed = new_keyed;
+ loop$moved = moved;
+ loop$moved_offset = moved_offset - 1;
+ loop$removed = removed;
+ loop$node_index = node_index;
+ loop$patch_index = patch_index;
+ loop$changes = changes;
+ loop$children = children;
+ loop$path = path;
+ loop$cache = cache;
+ loop$events = events2;
+ } else {
+ let match = get2(old_keyed, next.key);
+ let before = node_index - moved_offset;
+ let changes$1 = prepend(move(next.key, before), changes);
+ let moved$1 = insert2(moved, next.key, undefined);
+ loop$old = prepend(match, old);
+ loop$old_keyed = old_keyed;
+ loop$new = new$5;
+ loop$new_keyed = new_keyed;
+ loop$moved = moved$1;
+ loop$moved_offset = moved_offset + 1;
+ loop$removed = removed;
+ loop$node_index = node_index;
+ loop$patch_index = patch_index;
+ loop$changes = changes$1;
+ loop$children = children;
+ loop$path = path;
+ loop$cache = cache;
+ loop$events = events2;
+ }
+ } else {
+ let before = node_index - moved_offset;
+ let $ = add_child(cache, events2, path, node_index, next);
+ let cache$1 = $[0];
+ let events$1 = $[1];
+ let insert4 = insert3(singleton_list(next), before);
+ let changes$1 = prepend(insert4, changes);
+ loop$old = old;
+ loop$old_keyed = old_keyed;
+ loop$new = new_remaining;
+ loop$new_keyed = new_keyed;
+ loop$moved = moved;
+ loop$moved_offset = moved_offset + 1;
+ loop$removed = removed;
+ loop$node_index = node_index + 1;
+ loop$patch_index = patch_index;
+ loop$changes = changes$1;
+ loop$children = children;
+ loop$path = path;
+ loop$cache = cache$1;
+ loop$events = events$1;
+ }
+ } else if (next_did_exist) {
+ let index4 = node_index - moved_offset;
+ let changes$1 = prepend(remove2(index4), changes);
+ let events$1 = remove_child(cache, events2, path, node_index, prev);
+ loop$old = old_remaining;
+ loop$old_keyed = old_keyed;
+ loop$new = new$5;
+ loop$new_keyed = new_keyed;
+ loop$moved = moved;
+ loop$moved_offset = moved_offset - 1;
+ loop$removed = removed;
+ loop$node_index = node_index;
+ loop$patch_index = patch_index;
+ loop$changes = changes$1;
+ loop$children = children;
+ loop$path = path;
+ loop$cache = cache;
+ loop$events = events$1;
+ } else {
+ let change = replace2(node_index - moved_offset, next);
+ let $ = replace_child(cache, events2, path, node_index, prev, next);
+ let cache$1 = $[0];
+ let events$1 = $[1];
+ loop$old = old_remaining;
+ loop$old_keyed = old_keyed;
+ loop$new = new_remaining;
+ loop$new_keyed = new_keyed;
+ loop$moved = moved;
+ loop$moved_offset = moved_offset;
+ loop$removed = removed;
+ loop$node_index = node_index + 1;
+ loop$patch_index = patch_index;
+ loop$changes = prepend(change, changes);
+ loop$children = children;
+ loop$path = path;
+ loop$cache = cache$1;
+ loop$events = events$1;
+ }
+ } else {
+ let $ = old.head;
+ if ($ instanceof Fragment) {
+ let $1 = new$5.head;
+ if ($1 instanceof Fragment) {
+ let prev2 = $;
+ let old$1 = old.tail;
+ let next2 = $1;
+ let new$1 = new$5.tail;
+ let $2 = do_diff(prev2.children, prev2.keyed_children, next2.children, next2.keyed_children, empty2(), 0, 0, 0, node_index, empty_list, empty_list, add2(path, node_index, next2.key), cache, events2);
+ let patch = $2.patch;
+ let cache$1 = $2.cache;
+ let events$1 = $2.events;
+ let _block;
+ let $3 = patch.changes;
+ if ($3 instanceof Empty) {
+ let $4 = patch.children;
+ if ($4 instanceof Empty) {
+ let $5 = patch.removed;
+ if ($5 === 0) {
+ _block = children;
+ } else {
+ _block = prepend(patch, children);
+ }
+ } else {
+ _block = prepend(patch, children);
+ }
+ } else {
+ _block = prepend(patch, children);
+ }
+ let children$1 = _block;
+ loop$old = old$1;
+ loop$old_keyed = old_keyed;
+ loop$new = new$1;
+ loop$new_keyed = new_keyed;
+ loop$moved = moved;
+ loop$moved_offset = moved_offset;
+ loop$removed = removed;
+ loop$node_index = node_index + 1;
+ loop$patch_index = patch_index;
+ loop$changes = changes;
+ loop$children = children$1;
+ loop$path = path;
+ loop$cache = cache$1;
+ loop$events = events$1;
+ } else {
+ let prev2 = $;
+ let old_remaining = old.tail;
+ let next2 = $1;
+ let new_remaining = new$5.tail;
+ let change = replace2(node_index - moved_offset, next2);
+ let $2 = replace_child(cache, events2, path, node_index, prev2, next2);
+ let cache$1 = $2[0];
+ let events$1 = $2[1];
+ loop$old = old_remaining;
+ loop$old_keyed = old_keyed;
+ loop$new = new_remaining;
+ loop$new_keyed = new_keyed;
+ loop$moved = moved;
+ loop$moved_offset = moved_offset;
+ loop$removed = removed;
+ loop$node_index = node_index + 1;
+ loop$patch_index = patch_index;
+ loop$changes = prepend(change, changes);
+ loop$children = children;
+ loop$path = path;
+ loop$cache = cache$1;
+ loop$events = events$1;
+ }
+ } else if ($ instanceof Element2) {
+ let $1 = new$5.head;
+ if ($1 instanceof Element2) {
+ let prev2 = $;
+ let next2 = $1;
+ if (prev2.namespace === next2.namespace && prev2.tag === next2.tag) {
+ let old$1 = old.tail;
+ let new$1 = new$5.tail;
+ let child_path = add2(path, node_index, next2.key);
+ let controlled = is_controlled(cache, next2.namespace, next2.tag, child_path);
+ let $2 = diff_attributes(controlled, child_path, events2, prev2.attributes, next2.attributes, empty_list, empty_list);
+ let added_attrs = $2.added;
+ let removed_attrs = $2.removed;
+ let events$1 = $2.events;
+ let _block;
+ if (added_attrs instanceof Empty && removed_attrs instanceof Empty) {
+ _block = empty_list;
+ } else {
+ _block = singleton_list(update(added_attrs, removed_attrs));
+ }
+ let initial_child_changes = _block;
+ let $3 = do_diff(prev2.children, prev2.keyed_children, next2.children, next2.keyed_children, empty2(), 0, 0, 0, node_index, initial_child_changes, empty_list, child_path, cache, events$1);
+ let patch = $3.patch;
+ let cache$1 = $3.cache;
+ let events$2 = $3.events;
+ let _block$1;
+ let $4 = patch.changes;
+ if ($4 instanceof Empty) {
+ let $5 = patch.children;
+ if ($5 instanceof Empty) {
+ let $6 = patch.removed;
+ if ($6 === 0) {
+ _block$1 = children;
+ } else {
+ _block$1 = prepend(patch, children);
+ }
+ } else {
+ _block$1 = prepend(patch, children);
+ }
+ } else {
+ _block$1 = prepend(patch, children);
+ }
+ let children$1 = _block$1;
+ loop$old = old$1;
+ loop$old_keyed = old_keyed;
+ loop$new = new$1;
+ loop$new_keyed = new_keyed;
+ loop$moved = moved;
+ loop$moved_offset = moved_offset;
+ loop$removed = removed;
+ loop$node_index = node_index + 1;
+ loop$patch_index = patch_index;
+ loop$changes = changes;
+ loop$children = children$1;
+ loop$path = path;
+ loop$cache = cache$1;
+ loop$events = events$2;
+ } else {
+ let prev3 = $;
+ let old_remaining = old.tail;
+ let next3 = $1;
+ let new_remaining = new$5.tail;
+ let change = replace2(node_index - moved_offset, next3);
+ let $2 = replace_child(cache, events2, path, node_index, prev3, next3);
+ let cache$1 = $2[0];
+ let events$1 = $2[1];
+ loop$old = old_remaining;
+ loop$old_keyed = old_keyed;
+ loop$new = new_remaining;
+ loop$new_keyed = new_keyed;
+ loop$moved = moved;
+ loop$moved_offset = moved_offset;
+ loop$removed = removed;
+ loop$node_index = node_index + 1;
+ loop$patch_index = patch_index;
+ loop$changes = prepend(change, changes);
+ loop$children = children;
+ loop$path = path;
+ loop$cache = cache$1;
+ loop$events = events$1;
+ }
+ } else {
+ let prev2 = $;
+ let old_remaining = old.tail;
+ let next2 = $1;
+ let new_remaining = new$5.tail;
+ let change = replace2(node_index - moved_offset, next2);
+ let $2 = replace_child(cache, events2, path, node_index, prev2, next2);
+ let cache$1 = $2[0];
+ let events$1 = $2[1];
+ loop$old = old_remaining;
+ loop$old_keyed = old_keyed;
+ loop$new = new_remaining;
+ loop$new_keyed = new_keyed;
+ loop$moved = moved;
+ loop$moved_offset = moved_offset;
+ loop$removed = removed;
+ loop$node_index = node_index + 1;
+ loop$patch_index = patch_index;
+ loop$changes = prepend(change, changes);
+ loop$children = children;
+ loop$path = path;
+ loop$cache = cache$1;
+ loop$events = events$1;
+ }
+ } else if ($ instanceof Text) {
+ let $1 = new$5.head;
+ if ($1 instanceof Text) {
+ let prev2 = $;
+ let next2 = $1;
+ if (prev2.content === next2.content) {
+ let old$1 = old.tail;
+ let new$1 = new$5.tail;
+ loop$old = old$1;
+ loop$old_keyed = old_keyed;
+ loop$new = new$1;
+ loop$new_keyed = new_keyed;
+ loop$moved = moved;
+ loop$moved_offset = moved_offset;
+ loop$removed = removed;
+ loop$node_index = node_index + 1;
+ loop$patch_index = patch_index;
+ loop$changes = changes;
+ loop$children = children;
+ loop$path = path;
+ loop$cache = cache;
+ loop$events = events2;
+ } else {
+ let old$1 = old.tail;
+ let next3 = $1;
+ let new$1 = new$5.tail;
+ let child2 = new$3(node_index, 0, singleton_list(replace_text(next3.content)), empty_list);
+ loop$old = old$1;
+ loop$old_keyed = old_keyed;
+ loop$new = new$1;
+ loop$new_keyed = new_keyed;
+ loop$moved = moved;
+ loop$moved_offset = moved_offset;
+ loop$removed = removed;
+ loop$node_index = node_index + 1;
+ loop$patch_index = patch_index;
+ loop$changes = changes;
+ loop$children = prepend(child2, children);
+ loop$path = path;
+ loop$cache = cache;
+ loop$events = events2;
+ }
+ } else {
+ let prev2 = $;
+ let old_remaining = old.tail;
+ let next2 = $1;
+ let new_remaining = new$5.tail;
+ let change = replace2(node_index - moved_offset, next2);
+ let $2 = replace_child(cache, events2, path, node_index, prev2, next2);
+ let cache$1 = $2[0];
+ let events$1 = $2[1];
+ loop$old = old_remaining;
+ loop$old_keyed = old_keyed;
+ loop$new = new_remaining;
+ loop$new_keyed = new_keyed;
+ loop$moved = moved;
+ loop$moved_offset = moved_offset;
+ loop$removed = removed;
+ loop$node_index = node_index + 1;
+ loop$patch_index = patch_index;
+ loop$changes = prepend(change, changes);
+ loop$children = children;
+ loop$path = path;
+ loop$cache = cache$1;
+ loop$events = events$1;
+ }
+ } else if ($ instanceof UnsafeInnerHtml) {
+ let $1 = new$5.head;
+ if ($1 instanceof UnsafeInnerHtml) {
+ let prev2 = $;
+ let old$1 = old.tail;
+ let next2 = $1;
+ let new$1 = new$5.tail;
+ let child_path = add2(path, node_index, next2.key);
+ let $2 = diff_attributes(false, child_path, events2, prev2.attributes, next2.attributes, empty_list, empty_list);
+ let added_attrs = $2.added;
+ let removed_attrs = $2.removed;
+ let events$1 = $2.events;
+ let _block;
+ if (added_attrs instanceof Empty && removed_attrs instanceof Empty) {
+ _block = empty_list;
+ } else {
+ _block = singleton_list(update(added_attrs, removed_attrs));
+ }
+ let child_changes = _block;
+ let _block$1;
+ let $3 = prev2.inner_html === next2.inner_html;
+ if ($3) {
+ _block$1 = child_changes;
+ } else {
+ _block$1 = prepend(replace_inner_html(next2.inner_html), child_changes);
+ }
+ let child_changes$1 = _block$1;
+ let _block$2;
+ if (child_changes$1 instanceof Empty) {
+ _block$2 = children;
+ } else {
+ _block$2 = prepend(new$3(node_index, 0, child_changes$1, empty_list), children);
+ }
+ let children$1 = _block$2;
+ loop$old = old$1;
+ loop$old_keyed = old_keyed;
+ loop$new = new$1;
+ loop$new_keyed = new_keyed;
+ loop$moved = moved;
+ loop$moved_offset = moved_offset;
+ loop$removed = removed;
+ loop$node_index = node_index + 1;
+ loop$patch_index = patch_index;
+ loop$changes = changes;
+ loop$children = children$1;
+ loop$path = path;
+ loop$cache = cache;
+ loop$events = events$1;
+ } else {
+ let prev2 = $;
+ let old_remaining = old.tail;
+ let next2 = $1;
+ let new_remaining = new$5.tail;
+ let change = replace2(node_index - moved_offset, next2);
+ let $2 = replace_child(cache, events2, path, node_index, prev2, next2);
+ let cache$1 = $2[0];
+ let events$1 = $2[1];
+ loop$old = old_remaining;
+ loop$old_keyed = old_keyed;
+ loop$new = new_remaining;
+ loop$new_keyed = new_keyed;
+ loop$moved = moved;
+ loop$moved_offset = moved_offset;
+ loop$removed = removed;
+ loop$node_index = node_index + 1;
+ loop$patch_index = patch_index;
+ loop$changes = prepend(change, changes);
+ loop$children = children;
+ loop$path = path;
+ loop$cache = cache$1;
+ loop$events = events$1;
+ }
+ } else if ($ instanceof Map2) {
+ let $1 = new$5.head;
+ if ($1 instanceof Map2) {
+ let prev2 = $;
+ let old$1 = old.tail;
+ let next2 = $1;
+ let new$1 = new$5.tail;
+ let child_path = add2(path, node_index, next2.key);
+ let child_key = child(child_path);
+ let $2 = do_diff(singleton_list(prev2.child), empty2(), singleton_list(next2.child), empty2(), empty2(), 0, 0, 0, node_index, empty_list, empty_list, subtree(child_path), cache, get_subtree(events2, child_key, prev2.mapper));
+ let patch = $2.patch;
+ let cache$1 = $2.cache;
+ let child_events = $2.events;
+ let events$1 = update_subtree(events2, child_key, next2.mapper, child_events);
+ let _block;
+ let $3 = patch.changes;
+ if ($3 instanceof Empty) {
+ let $4 = patch.children;
+ if ($4 instanceof Empty) {
+ let $5 = patch.removed;
+ if ($5 === 0) {
+ _block = children;
+ } else {
+ _block = prepend(patch, children);
+ }
+ } else {
+ _block = prepend(patch, children);
+ }
+ } else {
+ _block = prepend(patch, children);
+ }
+ let children$1 = _block;
+ loop$old = old$1;
+ loop$old_keyed = old_keyed;
+ loop$new = new$1;
+ loop$new_keyed = new_keyed;
+ loop$moved = moved;
+ loop$moved_offset = moved_offset;
+ loop$removed = removed;
+ loop$node_index = node_index + 1;
+ loop$patch_index = patch_index;
+ loop$changes = changes;
+ loop$children = children$1;
+ loop$path = path;
+ loop$cache = cache$1;
+ loop$events = events$1;
+ } else {
+ let prev2 = $;
+ let old_remaining = old.tail;
+ let next2 = $1;
+ let new_remaining = new$5.tail;
+ let change = replace2(node_index - moved_offset, next2);
+ let $2 = replace_child(cache, events2, path, node_index, prev2, next2);
+ let cache$1 = $2[0];
+ let events$1 = $2[1];
+ loop$old = old_remaining;
+ loop$old_keyed = old_keyed;
+ loop$new = new_remaining;
+ loop$new_keyed = new_keyed;
+ loop$moved = moved;
+ loop$moved_offset = moved_offset;
+ loop$removed = removed;
+ loop$node_index = node_index + 1;
+ loop$patch_index = patch_index;
+ loop$changes = prepend(change, changes);
+ loop$children = children;
+ loop$path = path;
+ loop$cache = cache$1;
+ loop$events = events$1;
+ }
+ } else {
+ let $1 = new$5.head;
+ if ($1 instanceof Memo) {
+ let prev2 = $;
+ let old$1 = old.tail;
+ let next2 = $1;
+ let new$1 = new$5.tail;
+ let $2 = equal_lists(prev2.dependencies, next2.dependencies);
+ if ($2) {
+ let cache$1 = keep_memo(cache, prev2.view, next2.view);
+ loop$old = old$1;
+ loop$old_keyed = old_keyed;
+ loop$new = new$1;
+ loop$new_keyed = new_keyed;
+ loop$moved = moved;
+ loop$moved_offset = moved_offset;
+ loop$removed = removed;
+ loop$node_index = node_index + 1;
+ loop$patch_index = patch_index;
+ loop$changes = changes;
+ loop$children = children;
+ loop$path = path;
+ loop$cache = cache$1;
+ loop$events = events2;
+ } else {
+ let prev_node = get_old_memo(cache, prev2.view, prev2.view);
+ let next_node = next2.view();
+ let cache$1 = add_memo(cache, next2.view, next_node);
+ loop$old = prepend(prev_node, old$1);
+ loop$old_keyed = old_keyed;
+ loop$new = prepend(next_node, new$1);
+ loop$new_keyed = new_keyed;
+ loop$moved = moved;
+ loop$moved_offset = moved_offset;
+ loop$removed = removed;
+ loop$node_index = node_index;
+ loop$patch_index = patch_index;
+ loop$changes = changes;
+ loop$children = children;
+ loop$path = path;
+ loop$cache = cache$1;
+ loop$events = events2;
+ }
+ } else {
+ let prev2 = $;
+ let old_remaining = old.tail;
+ let next2 = $1;
+ let new_remaining = new$5.tail;
+ let change = replace2(node_index - moved_offset, next2);
+ let $2 = replace_child(cache, events2, path, node_index, prev2, next2);
+ let cache$1 = $2[0];
+ let events$1 = $2[1];
+ loop$old = old_remaining;
+ loop$old_keyed = old_keyed;
+ loop$new = new_remaining;
+ loop$new_keyed = new_keyed;
+ loop$moved = moved;
+ loop$moved_offset = moved_offset;
+ loop$removed = removed;
+ loop$node_index = node_index + 1;
+ loop$patch_index = patch_index;
+ loop$changes = prepend(change, changes);
+ loop$children = children;
+ loop$path = path;
+ loop$cache = cache$1;
+ loop$events = events$1;
+ }
+ }
+ }
+ }
+ }
+}
+function diff(cache, old, new$5) {
+ let cache$1 = tick(cache);
+ let $ = do_diff(singleton_list(old), empty2(), singleton_list(new$5), empty2(), empty2(), 0, 0, 0, 0, empty_list, empty_list, root, cache$1, events(cache$1));
+ let patch = $.patch;
+ let cache$2 = $.cache;
+ let events2 = $.events;
+ return new Diff(patch, update_events(cache$2, events2));
+}
+
+// build/dev/javascript/lustre/lustre/internals/list.ffi.mjs
+var toList2 = (arr) => arr.reduceRight((xs, x) => List$NonEmpty(x, xs), empty_list);
+var iterate = (list4, callback) => {
+ if (Array.isArray(list4)) {
+ for (let i = 0;i < list4.length; i++) {
+ callback(list4[i]);
+ }
+ } else if (list4) {
+ for (list4;List$NonEmpty$rest(list4); list4 = List$NonEmpty$rest(list4)) {
+ callback(List$NonEmpty$first(list4));
+ }
+ }
+};
+var append4 = (a2, b) => {
+ if (!List$NonEmpty$rest(a2)) {
+ return b;
+ } else if (!List$NonEmpty$rest(b)) {
+ return a2;
+ } else {
+ return append(a2, b);
+ }
+};
+
+// build/dev/javascript/lustre/lustre/internals/constants.ffi.mjs
+var NAMESPACE_HTML = "http://www.w3.org/1999/xhtml";
+var ELEMENT_NODE = 1;
+var TEXT_NODE = 3;
+var COMMENT_NODE = 8;
+var SUPPORTS_MOVE_BEFORE = !!globalThis.HTMLElement?.prototype?.moveBefore;
+
+// build/dev/javascript/lustre/lustre/vdom/reconciler.ffi.mjs
+var setTimeout = globalThis.setTimeout;
+var clearTimeout = globalThis.clearTimeout;
+var createElementNS = (ns, name2) => globalThis.document.createElementNS(ns, name2);
+var createTextNode = (data) => globalThis.document.createTextNode(data);
+var createComment = (data) => globalThis.document.createComment(data);
+var createDocumentFragment = () => globalThis.document.createDocumentFragment();
+var insertBefore = (parent, node, reference) => parent.insertBefore(node, reference);
+var moveBefore = SUPPORTS_MOVE_BEFORE ? (parent, node, reference) => parent.moveBefore(node, reference) : insertBefore;
+var removeChild = (parent, child2) => parent.removeChild(child2);
+var getAttribute = (node, name2) => node.getAttribute(name2);
+var setAttribute = (node, name2, value2) => node.setAttribute(name2, value2);
+var removeAttribute = (node, name2) => node.removeAttribute(name2);
+var addEventListener = (node, name2, handler, options) => node.addEventListener(name2, handler, options);
+var removeEventListener = (node, name2, handler) => node.removeEventListener(name2, handler);
+var setInnerHtml = (node, innerHtml) => node.innerHTML = innerHtml;
+var setData = (node, data) => node.data = data;
+var meta = Symbol("lustre");
+
+class MetadataNode {
+ constructor(kind, parent, node, key) {
+ this.kind = kind;
+ this.key = key;
+ this.parent = parent;
+ this.children = [];
+ this.node = node;
+ this.endNode = null;
+ this.handlers = new Map;
+ this.throttles = new Map;
+ this.debouncers = new Map;
+ }
+ get isVirtual() {
+ return this.kind === fragment_kind || this.kind === map_kind;
+ }
+ get parentNode() {
+ return this.isVirtual ? this.node.parentNode : this.node;
+ }
+}
+var insertMetadataChild = (kind, parent, node, index4, key) => {
+ const child2 = new MetadataNode(kind, parent, node, key);
+ node[meta] = child2;
+ parent?.children.splice(index4, 0, child2);
+ return child2;
+};
+var getPath = (node) => {
+ let path = "";
+ for (let current = node[meta];current.parent; current = current.parent) {
+ const separator = current.parent && current.parent.kind === map_kind ? separator_subtree : separator_element;
+ if (current.key) {
+ path = `${separator}${current.key}${path}`;
+ } else {
+ const index4 = current.parent.children.indexOf(current);
+ path = `${separator}${index4}${path}`;
+ }
+ }
+ return path.slice(1);
+};
+
+class Reconciler {
+ #root = null;
+ #decodeEvent;
+ #dispatch;
+ #debug = false;
+ constructor(root2, decodeEvent, dispatch2, { debug = false } = {}) {
+ this.#root = root2;
+ this.#decodeEvent = decodeEvent;
+ this.#dispatch = dispatch2;
+ this.#debug = debug;
+ }
+ mount(vdom) {
+ insertMetadataChild(element_kind, null, this.#root, 0, null);
+ this.#insertChild(this.#root, null, this.#root[meta], 0, vdom);
+ }
+ push(patch, memos2 = null) {
+ this.#memos = memos2;
+ this.#stack.push({ node: this.#root[meta], patch });
+ this.#reconcile();
+ }
+ #memos;
+ #stack = [];
+ #reconcile() {
+ const stack = this.#stack;
+ while (stack.length) {
+ let { node, patch } = stack.pop();
+ const { path, changes, removed, children: childPatches } = patch;
+ iterate(path, (index4) => {
+ node = node.children[index4];
+ });
+ const { children: childNodes } = node;
+ iterate(changes, (change) => this.#patch(node, change));
+ if (removed) {
+ this.#removeChildren(node, childNodes.length - removed, removed);
+ }
+ iterate(childPatches, (childPatch) => {
+ const child2 = childNodes[childPatch.index | 0];
+ this.#stack.push({ node: child2, patch: childPatch });
+ });
+ }
+ }
+ #patch(node, change) {
+ switch (change.kind) {
+ case replace_text_kind:
+ this.#replaceText(node, change);
+ break;
+ case replace_inner_html_kind:
+ this.#replaceInnerHtml(node, change);
+ break;
+ case update_kind:
+ this.#update(node, change);
+ break;
+ case move_kind:
+ this.#move(node, change);
+ break;
+ case remove_kind:
+ this.#remove(node, change);
+ break;
+ case replace_kind:
+ this.#replace(node, change);
+ break;
+ case insert_kind:
+ this.#insert(node, change);
+ break;
+ }
+ }
+ #insert(parent, { children, before }) {
+ const fragment2 = createDocumentFragment();
+ const beforeEl = this.#getReference(parent, before);
+ this.#insertChildren(fragment2, null, parent, before | 0, children);
+ insertBefore(parent.parentNode, fragment2, beforeEl);
+ }
+ #replace(parent, { index: index4, with: child2 }) {
+ this.#removeChildren(parent, index4 | 0, 1);
+ const beforeEl = this.#getReference(parent, index4);
+ this.#insertChild(parent.parentNode, beforeEl, parent, index4 | 0, child2);
+ }
+ #getReference(node, index4) {
+ index4 = index4 | 0;
+ const { children } = node;
+ const childCount = children.length;
+ if (index4 < childCount)
+ return children[index4].node;
+ if (node.endNode)
+ return node.endNode;
+ if (!node.isVirtual)
+ return null;
+ while (node.isVirtual && node.children.length) {
+ if (node.endNode)
+ return node.endNode.nextSibling;
+ node = node.children[node.children.length - 1];
+ }
+ return node.node.nextSibling;
+ }
+ #move(parent, { key, before }) {
+ before = before | 0;
+ const { children, parentNode } = parent;
+ const beforeEl = children[before].node;
+ let prev = children[before];
+ for (let i = before + 1;i < children.length; ++i) {
+ const next = children[i];
+ children[i] = prev;
+ prev = next;
+ if (next.key === key) {
+ children[before] = next;
+ break;
+ }
+ }
+ this.#moveChild(parentNode, prev, beforeEl);
+ }
+ #moveChildren(domParent, children, beforeEl) {
+ for (let i = 0;i < children.length; ++i) {
+ this.#moveChild(domParent, children[i], beforeEl);
+ }
+ }
+ #moveChild(domParent, child2, beforeEl) {
+ moveBefore(domParent, child2.node, beforeEl);
+ if (child2.isVirtual) {
+ this.#moveChildren(domParent, child2.children, beforeEl);
+ }
+ if (child2.endNode) {
+ moveBefore(domParent, child2.endNode, beforeEl);
+ }
+ }
+ #remove(parent, { index: index4 }) {
+ this.#removeChildren(parent, index4, 1);
+ }
+ #removeChildren(parent, index4, count) {
+ const { children, parentNode } = parent;
+ const deleted = children.splice(index4, count);
+ for (let i = 0;i < deleted.length; ++i) {
+ const child2 = deleted[i];
+ const { node, endNode, isVirtual, children: nestedChildren } = child2;
+ removeChild(parentNode, node);
+ if (endNode) {
+ removeChild(parentNode, endNode);
+ }
+ this.#removeDebouncers(child2);
+ if (isVirtual) {
+ deleted.push(...nestedChildren);
+ }
+ }
+ }
+ #removeDebouncers(node) {
+ const { debouncers, children } = node;
+ for (const { timeout } of debouncers.values()) {
+ if (timeout) {
+ clearTimeout(timeout);
+ }
+ }
+ debouncers.clear();
+ iterate(children, (child2) => this.#removeDebouncers(child2));
+ }
+ #update({ node, handlers, throttles, debouncers }, { added, removed }) {
+ iterate(removed, ({ name: name2 }) => {
+ if (handlers.delete(name2)) {
+ removeEventListener(node, name2, handleEvent);
+ this.#updateDebounceThrottle(throttles, name2, 0);
+ this.#updateDebounceThrottle(debouncers, name2, 0);
+ } else {
+ removeAttribute(node, name2);
+ SYNCED_ATTRIBUTES[name2]?.removed?.(node, name2);
+ }
+ });
+ iterate(added, (attribute3) => this.#createAttribute(node, attribute3));
+ }
+ #replaceText({ node }, { content }) {
+ setData(node, content ?? "");
+ }
+ #replaceInnerHtml({ node }, { inner_html }) {
+ setInnerHtml(node, inner_html ?? "");
+ }
+ #insertChildren(domParent, beforeEl, metaParent, index4, children) {
+ iterate(children, (child2) => this.#insertChild(domParent, beforeEl, metaParent, index4++, child2));
+ }
+ #insertChild(domParent, beforeEl, metaParent, index4, vnode) {
+ switch (vnode.kind) {
+ case element_kind: {
+ const node = this.#createElement(metaParent, index4, vnode);
+ this.#insertChildren(node, null, node[meta], 0, vnode.children);
+ insertBefore(domParent, node, beforeEl);
+ break;
+ }
+ case text_kind: {
+ const node = this.#createTextNode(metaParent, index4, vnode);
+ insertBefore(domParent, node, beforeEl);
+ break;
+ }
+ case fragment_kind: {
+ const marker = "lustre:fragment";
+ const head = this.#createHead(marker, metaParent, index4, vnode);
+ insertBefore(domParent, head, beforeEl);
+ this.#insertChildren(domParent, beforeEl, head[meta], 0, vnode.children);
+ if (this.#debug) {
+ head[meta].endNode = createComment(` /${marker} `);
+ insertBefore(domParent, head[meta].endNode, beforeEl);
+ }
+ break;
+ }
+ case unsafe_inner_html_kind: {
+ const node = this.#createElement(metaParent, index4, vnode);
+ this.#replaceInnerHtml({ node }, vnode);
+ insertBefore(domParent, node, beforeEl);
+ break;
+ }
+ case map_kind: {
+ const head = this.#createHead("lustre:map", metaParent, index4, vnode);
+ insertBefore(domParent, head, beforeEl);
+ this.#insertChild(domParent, beforeEl, head[meta], 0, vnode.child);
+ break;
+ }
+ case memo_kind: {
+ const child2 = this.#memos?.get(vnode.view) ?? vnode.view();
+ this.#insertChild(domParent, beforeEl, metaParent, index4, child2);
+ break;
+ }
+ }
+ }
+ #createElement(parent, index4, { kind, key, tag, namespace, attributes }) {
+ const node = createElementNS(namespace || NAMESPACE_HTML, tag);
+ insertMetadataChild(kind, parent, node, index4, key);
+ if (this.#debug && key) {
+ setAttribute(node, "data-lustre-key", key);
+ }
+ iterate(attributes, (attribute3) => this.#createAttribute(node, attribute3));
+ return node;
+ }
+ #createTextNode(parent, index4, { kind, key, content }) {
+ const node = createTextNode(content ?? "");
+ insertMetadataChild(kind, parent, node, index4, key);
+ return node;
+ }
+ #createHead(marker, parent, index4, { kind, key }) {
+ const node = this.#debug ? createComment(markerComment(marker, key)) : createTextNode("");
+ insertMetadataChild(kind, parent, node, index4, key);
+ return node;
+ }
+ #createAttribute(node, attribute3) {
+ const { debouncers, handlers, throttles } = node[meta];
+ const {
+ kind,
+ name: name2,
+ value: value2,
+ prevent_default: prevent,
+ debounce: debounceDelay,
+ throttle: throttleDelay
+ } = attribute3;
+ switch (kind) {
+ case attribute_kind: {
+ const valueOrDefault = value2 ?? "";
+ if (name2 === "virtual:defaultValue") {
+ node.defaultValue = valueOrDefault;
+ return;
+ } else if (name2 === "virtual:defaultChecked") {
+ node.defaultChecked = true;
+ return;
+ } else if (name2 === "virtual:defaultSelected") {
+ node.defaultSelected = true;
+ return;
+ }
+ if (valueOrDefault !== getAttribute(node, name2)) {
+ setAttribute(node, name2, valueOrDefault);
+ }
+ SYNCED_ATTRIBUTES[name2]?.added?.(node, valueOrDefault);
+ break;
+ }
+ case property_kind:
+ node[name2] = value2;
+ break;
+ case event_kind: {
+ if (handlers.has(name2)) {
+ removeEventListener(node, name2, handleEvent);
+ }
+ const passive = prevent.kind === never_kind;
+ addEventListener(node, name2, handleEvent, { passive });
+ this.#updateDebounceThrottle(throttles, name2, throttleDelay);
+ this.#updateDebounceThrottle(debouncers, name2, debounceDelay);
+ handlers.set(name2, (event3) => this.#handleEvent(attribute3, event3));
+ break;
+ }
+ }
+ }
+ #updateDebounceThrottle(map7, name2, delay) {
+ const debounceOrThrottle = map7.get(name2);
+ if (delay > 0) {
+ if (debounceOrThrottle) {
+ debounceOrThrottle.delay = delay;
+ } else {
+ map7.set(name2, { delay });
+ }
+ } else if (debounceOrThrottle) {
+ const { timeout } = debounceOrThrottle;
+ if (timeout) {
+ clearTimeout(timeout);
+ }
+ map7.delete(name2);
+ }
+ }
+ #handleEvent(attribute3, event3) {
+ const { currentTarget, type } = event3;
+ const { debouncers, throttles } = currentTarget[meta];
+ const path = getPath(currentTarget);
+ const {
+ prevent_default: prevent,
+ stop_propagation: stop,
+ include
+ } = attribute3;
+ if (prevent.kind === always_kind)
+ event3.preventDefault();
+ if (stop.kind === always_kind)
+ event3.stopPropagation();
+ if (type === "submit") {
+ event3.detail ??= {};
+ event3.detail.formData = [
+ ...new FormData(event3.target, event3.submitter).entries()
+ ];
+ }
+ const data = this.#decodeEvent(event3, path, type, include);
+ const throttle = throttles.get(type);
+ if (throttle) {
+ const now = Date.now();
+ const last = throttle.last || 0;
+ if (now > last + throttle.delay) {
+ throttle.last = now;
+ throttle.lastEvent = event3;
+ this.#dispatch(event3, data);
+ }
+ }
+ const debounce = debouncers.get(type);
+ if (debounce) {
+ clearTimeout(debounce.timeout);
+ debounce.timeout = setTimeout(() => {
+ if (event3 === throttles.get(type)?.lastEvent)
+ return;
+ this.#dispatch(event3, data);
+ }, debounce.delay);
+ }
+ if (!throttle && !debounce) {
+ this.#dispatch(event3, data);
+ }
+ }
+}
+var markerComment = (marker, key) => {
+ if (key) {
+ return ` ${marker} key="${escape(key)}" `;
+ } else {
+ return ` ${marker} `;
+ }
+};
+var handleEvent = (event3) => {
+ const { currentTarget, type } = event3;
+ const handler = currentTarget[meta].handlers.get(type);
+ handler(event3);
+};
+var syncedBooleanAttribute = (name2) => {
+ return {
+ added(node) {
+ node[name2] = true;
+ },
+ removed(node) {
+ node[name2] = false;
+ }
+ };
+};
+var syncedAttribute = (name2) => {
+ return {
+ added(node, value2) {
+ node[name2] = value2;
+ }
+ };
+};
+var SYNCED_ATTRIBUTES = {
+ checked: syncedBooleanAttribute("checked"),
+ selected: syncedBooleanAttribute("selected"),
+ value: syncedAttribute("value"),
+ autofocus: {
+ added(node) {
+ queueMicrotask(() => {
+ node.focus?.();
+ });
+ }
+ },
+ autoplay: {
+ added(node) {
+ try {
+ node.play?.();
+ } catch (e) {
+ console.error(e);
+ }
+ }
+ }
+};
+
+// build/dev/javascript/lustre/lustre/element/keyed.mjs
+function do_extract_keyed_children(loop$key_children_pairs, loop$keyed_children, loop$children) {
+ while (true) {
+ let key_children_pairs = loop$key_children_pairs;
+ let keyed_children = loop$keyed_children;
+ let children = loop$children;
+ if (key_children_pairs instanceof Empty) {
+ return [keyed_children, reverse(children)];
+ } else {
+ let rest = key_children_pairs.tail;
+ let key = key_children_pairs.head[0];
+ let element$1 = key_children_pairs.head[1];
+ let keyed_element = to_keyed(key, element$1);
+ let _block;
+ if (key === "") {
+ _block = keyed_children;
+ } else {
+ _block = insert2(keyed_children, key, keyed_element);
+ }
+ let keyed_children$1 = _block;
+ let children$1 = prepend(keyed_element, children);
+ loop$key_children_pairs = rest;
+ loop$keyed_children = keyed_children$1;
+ loop$children = children$1;
+ }
+ }
+}
+function extract_keyed_children(children) {
+ return do_extract_keyed_children(children, empty2(), empty_list);
+}
+function element3(tag, attributes, children) {
+ let $ = extract_keyed_children(children);
+ let keyed_children = $[0];
+ let children$1 = $[1];
+ return element("", "", tag, attributes, children$1, keyed_children, false, is_void_html_element(tag, ""));
+}
+function namespaced2(namespace, tag, attributes, children) {
+ let $ = extract_keyed_children(children);
+ let keyed_children = $[0];
+ let children$1 = $[1];
+ return element("", namespace, tag, attributes, children$1, keyed_children, false, is_void_html_element(tag, namespace));
+}
+function fragment2(children) {
+ let $ = extract_keyed_children(children);
+ let keyed_children = $[0];
+ let children$1 = $[1];
+ return fragment("", children$1, keyed_children);
+}
+
+// build/dev/javascript/lustre/lustre/vdom/virtualise.ffi.mjs
+var virtualise = (root2) => {
+ const rootMeta = insertMetadataChild(element_kind, null, root2, 0, null);
+ const { children } = virtualiseChildren(rootMeta, root2, root2.firstChild);
+ if (children.length > 1) {
+ const rootNodeMeta = insertMetadataChild(element_kind, null, root2, 0, null);
+ rootMeta.kind = fragment_kind;
+ rootMeta.node = globalThis.document.createTextNode("");
+ rootMeta.parent = rootNodeMeta;
+ rootNodeMeta.children.push(rootMeta);
+ root2.insertBefore(rootMeta.node, root2.firstChild);
+ return fragment2(toList3(children));
+ }
+ if (children.length === 1) {
+ return children[0][1];
+ }
+ const placeholder2 = globalThis.document.createTextNode("");
+ insertMetadataChild(text_kind, rootMeta, placeholder2, 0, null);
+ root2.insertBefore(placeholder2, root2.firstChild);
+ return none2();
+};
+var virtualiseChild = (meta2, domParent, child2, index4) => {
+ if (child2.nodeType === COMMENT_NODE) {
+ const data = child2.data.trim();
+ if (data.startsWith("lustre:fragment")) {
+ return virtualiseFragment(meta2, domParent, child2, index4);
+ }
+ if (data.startsWith("lustre:map")) {
+ return virtualiseMap(meta2, domParent, child2, index4);
+ }
+ if (data.startsWith("lustre:memo")) {
+ return virtualiseMemo(meta2, domParent, child2, index4);
+ }
+ return null;
+ }
+ if (child2.nodeType === ELEMENT_NODE) {
+ return virtualiseElement(meta2, child2, index4);
+ }
+ if (child2.nodeType === TEXT_NODE) {
+ return virtualiseText(meta2, child2, index4);
+ }
+ return null;
+};
+var virtualiseElement = (metaParent, node, index4) => {
+ const key = node.getAttribute("data-lustre-key") ?? "";
+ if (key) {
+ node.removeAttribute("data-lustre-key");
+ }
+ const meta2 = insertMetadataChild(element_kind, metaParent, node, index4, key);
+ const tag = node.localName;
+ const namespace = node.namespaceURI;
+ const isHtmlElement = !namespace || namespace === NAMESPACE_HTML;
+ if (isHtmlElement && INPUT_ELEMENTS.includes(tag)) {
+ virtualiseInputEvents(tag, node);
+ }
+ const attributes = virtualiseAttributes(node);
+ const { children } = virtualiseChildren(meta2, node, node.firstChild);
+ const vnode = isHtmlElement ? element3(tag, attributes, toList3(children)) : namespaced2(namespace, tag, attributes, toList3(children));
+ return childResult(key, vnode, node.nextSibling);
+};
+var virtualiseChildren = (meta2, domParent, childNode) => {
+ const children = [];
+ while (childNode && (childNode.nodeType !== COMMENT_NODE || childNode.data.trim() !== "/lustre:fragment")) {
+ const child2 = virtualiseChild(meta2, domParent, childNode, children.length);
+ if (child2) {
+ children.push([child2.key, child2.vnode]);
+ childNode = child2.next;
+ } else {
+ childNode = childNode.nextSibling;
+ }
+ }
+ return { children, end: childNode };
+};
+var virtualiseText = (meta2, node, index4) => {
+ insertMetadataChild(text_kind, meta2, node, index4, null);
+ return childResult("", text2(node.data), node.nextSibling);
+};
+var virtualiseFragment = (metaParent, domParent, node, index4) => {
+ const key = parseKey(node.data);
+ const meta2 = insertMetadataChild(fragment_kind, metaParent, node, index4, key);
+ const { children, end } = virtualiseChildren(meta2, domParent, node.nextSibling);
+ meta2.endNode = end;
+ const vnode = fragment2(toList3(children));
+ return childResult(key, vnode, end?.nextSibling);
+};
+var virtualiseMap = (metaParent, domParent, node, index4) => {
+ const key = parseKey(node.data);
+ const meta2 = insertMetadataChild(map_kind, metaParent, node, index4, key);
+ const child2 = virtualiseNextChild(meta2, domParent, node, 0);
+ if (!child2)
+ return null;
+ const vnode = map6(child2.vnode, (x) => x);
+ return childResult(key, vnode, child2.next);
+};
+var virtualiseMemo = (meta2, domParent, node, index4) => {
+ const key = parseKey(node.data);
+ const child2 = virtualiseNextChild(meta2, domParent, node, index4);
+ if (!child2)
+ return null;
+ domParent.removeChild(node);
+ const vnode = memo2(toList3([ref({})]), () => child2.vnode);
+ return childResult(key, vnode, child2.next);
+};
+var virtualiseNextChild = (meta2, domParent, node, index4) => {
+ while (true) {
+ node = node.nextSibling;
+ if (!node)
+ return null;
+ const child2 = virtualiseChild(meta2, domParent, node, index4);
+ if (child2)
+ return child2;
+ }
+};
+var childResult = (key, vnode, next) => {
+ return { key, vnode, next };
+};
+var virtualiseAttributes = (node) => {
+ const attributes = [];
+ for (let i = 0;i < node.attributes.length; i++) {
+ const attr = node.attributes[i];
+ if (attr.name !== "xmlns") {
+ attributes.push(attribute2(attr.localName, attr.value));
+ }
+ }
+ return toList3(attributes);
+};
+var INPUT_ELEMENTS = ["input", "select", "textarea"];
+var virtualiseInputEvents = (tag, node) => {
+ const value2 = node.value;
+ const checked = node.checked;
+ if (tag === "input" && node.type === "checkbox" && !checked)
+ return;
+ if (tag === "input" && node.type === "radio" && !checked)
+ return;
+ if (node.type !== "checkbox" && node.type !== "radio" && !value2)
+ return;
+ queueMicrotask(() => {
+ node.value = value2;
+ node.checked = checked;
+ node.dispatchEvent(new Event("input", { bubbles: true }));
+ node.dispatchEvent(new Event("change", { bubbles: true }));
+ if (globalThis.document.activeElement !== node) {
+ node.dispatchEvent(new Event("blur", { bubbles: true }));
+ }
+ });
+};
+var parseKey = (data) => {
+ const keyMatch = data.match(/key="([^"]*)"/);
+ if (!keyMatch)
+ return "";
+ return unescapeKey(keyMatch[1]);
+};
+var unescapeKey = (key) => {
+ return key.replace(/</g, "<").replace(/>/g, ">").replace(/"/g, '"').replace(/&/g, "&").replace(/'/g, "'");
+};
+var toList3 = (arr) => arr.reduceRight((xs, x) => List$NonEmpty(x, xs), empty_list);
+
+// build/dev/javascript/lustre/lustre/runtime/client/runtime.ffi.mjs
+var is_browser = () => !!globalThis.document;
+class Runtime {
+ constructor(root2, [model, effects], view, update2, options) {
+ this.root = root2;
+ this.#model = model;
+ this.#view = view;
+ this.#update = update2;
+ this.root.addEventListener("context-request", (event3) => {
+ if (!(event3.context && event3.callback))
+ return;
+ if (!this.#contexts.has(event3.context))
+ return;
+ event3.stopImmediatePropagation();
+ const context = this.#contexts.get(event3.context);
+ if (event3.subscribe) {
+ const unsubscribe2 = () => {
+ context.subscribers = context.subscribers.filter((subscriber) => subscriber !== event3.callback);
+ };
+ context.subscribers.push([event3.callback, unsubscribe2]);
+ event3.callback(context.value, unsubscribe2);
+ } else {
+ event3.callback(context.value);
+ }
+ });
+ const decodeEvent = (event3, path, name2) => decode2(this.#cache, path, name2, event3);
+ const dispatch2 = (event3, data) => {
+ const [cache, result] = dispatch(this.#cache, data);
+ this.#cache = cache;
+ if (Result$isOk(result)) {
+ const handler = Result$Ok$0(result);
+ if (handler.stop_propagation)
+ event3.stopPropagation();
+ if (handler.prevent_default)
+ event3.preventDefault();
+ this.dispatch(handler.message, false);
+ }
+ };
+ this.#reconciler = new Reconciler(this.root, decodeEvent, dispatch2, options);
+ this.#vdom = virtualise(this.root);
+ this.#cache = new$4();
+ this.#handleEffects(effects);
+ this.#render();
+ }
+ root = null;
+ dispatch(message, shouldFlush = false) {
+ if (this.#shouldQueue) {
+ this.#queue.push(message);
+ } else {
+ const [model, effects] = this.#update(this.#model, message);
+ this.#model = model;
+ this.#scheduleRender(shouldFlush);
+ this.#handleEffects(effects);
+ }
+ }
+ emit(event3, data) {
+ const target = this.root.host ?? this.root;
+ target.dispatchEvent(new LustreEvent(event3, data));
+ }
+ provide(key, value2) {
+ if (!this.#contexts.has(key)) {
+ this.#contexts.set(key, { value: value2, subscribers: [] });
+ } else {
+ const context = this.#contexts.get(key);
+ if (isEqual2(context.value, value2)) {
+ return;
+ }
+ context.value = value2;
+ for (let i = context.subscribers.length - 1;i >= 0; i--) {
+ const [subscriber, unsubscribe2] = context.subscribers[i];
+ if (!subscriber) {
+ context.subscribers.splice(i, 1);
+ continue;
+ }
+ subscriber(value2, unsubscribe2);
+ }
+ }
+ }
+ subscribe(key, decoder) {
+ if (!key)
+ return;
+ this.#contextSubscriptions.get(key)?.();
+ const target = this.root.host ?? this.root;
+ target.dispatchEvent(new ContextRequestEvent(key, (value2, unsubscribe2) => {
+ const previousUnsubscribe = this.#contextSubscriptions.get(key);
+ if (previousUnsubscribe !== unsubscribe2) {
+ previousUnsubscribe?.();
+ }
+ const decoded = run(value2, decoder);
+ this.#contextSubscriptions.set(key, unsubscribe2);
+ if (Result$isOk(decoded)) {
+ this.dispatch(Result$Ok$0(decoded), true);
+ }
+ }, true));
+ }
+ unsubscribe(key) {
+ const unsubscribe2 = this.#contextSubscriptions.get(key);
+ if (unsubscribe2) {
+ unsubscribe2();
+ this.#contextSubscriptions.delete(key);
+ }
+ }
+ unsubscribeAll() {
+ for (const [_, unsubscribe2] of this.#contextSubscriptions) {
+ unsubscribe2?.();
+ }
+ this.#contextSubscriptions.clear();
+ }
+ #model;
+ #view;
+ #update;
+ #vdom;
+ #cache;
+ #reconciler;
+ #contexts = new Map;
+ #contextSubscriptions = new Map;
+ #shouldQueue = false;
+ #queue = [];
+ #beforePaint = empty_list;
+ #afterPaint = empty_list;
+ #renderTimer = null;
+ #actions = {
+ dispatch: (message) => this.dispatch(message),
+ emit: (event3, data) => this.emit(event3, data),
+ select: () => {},
+ root: () => this.root,
+ provide: (key, value2) => this.provide(key, value2),
+ subscribe: (key, decoder) => this.subscribe(key, decoder),
+ unsubscribe: (key) => this.unsubscribe(key)
+ };
+ #scheduleRender(shouldFlush = false) {
+ if (this.#renderTimer)
+ return;
+ if (shouldFlush) {
+ this.#renderTimer = "sync";
+ queueMicrotask(() => this.#render());
+ } else {
+ this.#renderTimer = window.requestAnimationFrame(() => this.#render());
+ }
+ }
+ #handleEffects(effects) {
+ this.#shouldQueue = true;
+ let updateCalledDuringEffects = false;
+ while (true) {
+ iterate(effects.synchronous, (effect) => effect(this.#actions));
+ this.#beforePaint = append4(this.#beforePaint, effects.before_paint);
+ this.#afterPaint = append4(this.#afterPaint, effects.after_paint);
+ if (!this.#queue.length)
+ break;
+ const message = this.#queue.shift();
+ [this.#model, effects] = this.#update(this.#model, message);
+ updateCalledDuringEffects = true;
+ }
+ this.#shouldQueue = false;
+ return updateCalledDuringEffects;
+ }
+ #handleAsyncEffects(effects) {
+ if (this.#handleEffects(effects)) {
+ this.#scheduleRender(true);
+ }
+ }
+ #render() {
+ this.#renderTimer = null;
+ const next = this.#view(this.#model);
+ const { patch, cache } = diff(this.#cache, this.#vdom, next);
+ this.#cache = cache;
+ this.#vdom = next;
+ this.#reconciler.push(patch, memos(cache));
+ if (List$isNonEmpty(this.#beforePaint)) {
+ const effects = makeEffect(this.#beforePaint);
+ this.#beforePaint = empty_list;
+ queueMicrotask(() => this.#handleAsyncEffects(effects));
+ }
+ if (List$isNonEmpty(this.#afterPaint)) {
+ const effects = makeEffect(this.#afterPaint);
+ this.#afterPaint = empty_list;
+ window.requestAnimationFrame(() => this.#handleAsyncEffects(effects));
+ }
+ }
+}
+function makeEffect(synchronous) {
+ return {
+ synchronous,
+ after_paint: empty_list,
+ before_paint: empty_list
+ };
+}
+var copiedStyleSheets = new WeakMap;
+class ContextRequestEvent extends Event {
+ constructor(context, callback, subscribe2) {
+ super("context-request", { bubbles: true, composed: true });
+ this.context = context;
+ this.callback = callback;
+ this.subscribe = subscribe2;
+ }
+}
+
+class LustreEvent extends CustomEvent {
+ isLustreEvent = true;
+ constructor(name2, detail) {
+ super(name2, { detail, bubbles: true, composed: true });
+ }
+}
+
+// build/dev/javascript/lustre/lustre/runtime/client/spa.ffi.mjs
+class Spa {
+ #runtime;
+ constructor(root2, [init, effects], update2, view) {
+ this.#runtime = new Runtime(root2, [init, effects], view, update2);
+ }
+ send(message) {
+ if (Message$isEffectDispatchedMessage(message)) {
+ this.dispatch(message.message, false);
+ } else if (Message$isEffectEmitEvent(message)) {
+ this.emit(message.name, message.data);
+ } else if (Message$isSystemRequestedShutdown(message)) {}
+ }
+ dispatch(message) {
+ this.#runtime.dispatch(message);
+ }
+ emit(event3, data) {
+ this.#runtime.emit(event3, data);
+ }
+}
+var start = ({ init, update: update2, view }, selector, flags) => {
+ if (!is_browser())
+ return Result$Error(Error$NotABrowser());
+ const root2 = selector instanceof HTMLElement ? selector : globalThis.document.querySelector(selector);
+ if (!root2)
+ return Result$Error(Error$ElementNotFound(selector));
+ return Result$Ok(new Spa(root2, init(flags), update2, view));
+};
+
+// build/dev/javascript/lustre/lustre/runtime/server/runtime.ffi.mjs
+class Runtime2 {
+ #model;
+ #update;
+ #view;
+ #config;
+ #vdom;
+ #cache;
+ #providers = make();
+ #callbacks = /* @__PURE__ */ new Set;
+ constructor(_, init, update2, view, config, start_arguments) {
+ const [model, effects] = init(start_arguments);
+ this.#model = model;
+ this.#update = update2;
+ this.#view = view;
+ this.#config = config;
+ this.#vdom = this.#view(this.#model);
+ this.#cache = from_node(this.#vdom);
+ this.#handle_effect(effects);
+ }
+ send(message) {
+ if (Message$isClientDispatchedMessage(message)) {
+ const { message: message2 } = message2;
+ const next = this.#handle_client_message(message2);
+ const diff2 = diff(this.#cache, this.#vdom, next);
+ this.#vdom = next;
+ this.#cache = diff2.cache;
+ this.broadcast(reconcile(diff2.patch, memos(diff2.cache)));
+ } else if (Message$isClientRegisteredCallback(message)) {
+ const { callback } = message;
+ this.#callbacks.add(callback);
+ callback(mount(this.#config.open_shadow_root, this.#config.adopt_styles, keys(this.#config.attributes), keys(this.#config.properties), keys(this.#config.contexts), this.#providers, this.#vdom, memos(this.#cache)));
+ if (Option$isSome(this.#config.on_connect)) {
+ this.#dispatch(Option$Some$0(this.#config.on_connect));
+ }
+ } else if (Message$isClientDeregisteredCallback(message)) {
+ const { callback } = message;
+ this.#callbacks.delete(callback);
+ if (Option$isSome(this.#config.on_disconnect)) {
+ this.#dispatch(Option$Some$0(this.#config.on_disconnect));
+ }
+ } else if (Message$isEffectDispatchedMessage(message)) {
+ const { message: message2 } = message2;
+ const [model, effect] = this.#update(this.#model, message2);
+ const next = this.#view(model);
+ const diff2 = diff(this.#cache, this.#vdom, next);
+ this.#handle_effect(effect);
+ this.#model = model;
+ this.#vdom = next;
+ this.#cache = diff2.cache;
+ this.broadcast(reconcile(diff2.patch, memos(diff2.cache)));
+ } else if (Message$isEffectEmitEvent(message)) {
+ const { name: name2, data } = message;
+ this.broadcast(emit(name2, data));
+ } else if (Message$isEffectProvidedValue(message)) {
+ const { key, value: value2 } = message;
+ const existing = get(this.#providers, key);
+ if (Result$isOk(existing) && isEqual2(Result$Ok$0(existing), value2)) {
+ return;
+ }
+ this.#providers = insert(this.#providers, key, value2);
+ this.broadcast(provide(key, value2));
+ } else if (Message$isEffectRequestedContextSubscription(message)) {
+ const { key, decoder } = message;
+ this.broadcast(subscribe(key));
+ this.#config.contexts = insert(this.#config.contexts, key, decoder);
+ } else if (Message$isEffectRemovedContextSubscription(message)) {
+ const { key } = message;
+ this.broadcast(unsubscribe(key));
+ this.#config.contexts = delete$(this.#config.contexts, key);
+ } else if (Message$isSystemRequestedShutdown(message)) {
+ this.#model = null;
+ this.#update = null;
+ this.#view = null;
+ this.#config = null;
+ this.#vdom = null;
+ this.#cache = null;
+ this.#providers = null;
+ this.#callbacks.clear();
+ }
+ }
+ broadcast(message) {
+ for (const callback of this.#callbacks) {
+ callback(message);
+ }
+ }
+ #handle_client_message(message) {
+ if (ServerMessage$isBatch(message)) {
+ const { messages } = message;
+ let model = this.#model;
+ let effect = none();
+ for (let list4 = messages;List$NonEmpty$rest(list4); list4 = List$NonEmpty$rest(list4)) {
+ const result = this.#handle_client_message(List$NonEmpty$first(list4));
+ if (Result$isOk(result)) {
+ model = Result$Ok$0(result)[0];
+ effect = batch(toList2([effect, Result$Ok$0(result)[1]]));
+ break;
+ }
+ }
+ this.#handle_effect(effect);
+ this.#model = model;
+ return this.#view(model);
+ } else if (ServerMessage$isAttributeChanged(message)) {
+ const { name: name2, value: value2 } = message;
+ const result = this.#handle_attribute_change(name2, value2);
+ if (!Result$isOk(result)) {
+ return this.#vdom;
+ }
+ return this.#dispatch(Result$Ok$0(result));
+ } else if (ServerMessage$isPropertyChanged(message)) {
+ const { name: name2, value: value2 } = message;
+ const result = this.#handle_properties_change(name2, value2);
+ if (!Result$isOk(result)) {
+ return this.#vdom;
+ }
+ return this.#dispatch(Result$Ok$0(result));
+ } else if (ServerMessage$isEventFired(message)) {
+ const { path, name: name2, event: event3 } = message2;
+ const [cache, result] = handle(this.#cache, path, name2, event3);
+ this.#cache = cache;
+ if (!Result$isOk(result)) {
+ return this.#vdom;
+ }
+ const { message: message2 } = Result$Ok$0(result);
+ return this.#dispatch(message2);
+ } else if (ServerMessage$isContextProvided(message)) {
+ const { key, value: value2 } = message;
+ let result = get(this.#config.contexts, key);
+ if (!Result$isOk(result)) {
+ return this.#vdom;
+ }
+ result = run(value2, Result$Ok$0(result));
+ if (!Result$isOk(result)) {
+ return this.#vdom;
+ }
+ return this.#dispatch(Result$Ok$0(result));
+ }
+ }
+ #dispatch(message) {
+ const [model, effects] = this.#update(this.#model, message);
+ this.#handle_effect(effects);
+ this.#model = model;
+ return this.#view(this.#model);
+ }
+ #handle_attribute_change(name2, value2) {
+ const result = get(this.#config.attributes, name2);
+ if (!Result$isOk(result)) {
+ return result;
+ }
+ return Result$Ok$0(result)(value2);
+ }
+ #handle_properties_change(name2, value2) {
+ const result = get(this.#config.properties, name2);
+ if (!Result$isOk(result)) {
+ return result;
+ }
+ return Result$Ok$0(result)(value2);
+ }
+ #handle_effect(effect) {
+ const dispatch2 = (message) => this.send(Message$EffectDispatchedMessage(message));
+ const emit2 = (name2, data) => this.send(Message$EffectEmitEvent(name2, data));
+ const select = () => {
+ return;
+ };
+ const internals = () => {
+ return;
+ };
+ const provide2 = (key, value2) => this.send(Message$EffectProvidedValue(key, value2));
+ const subscribe2 = (key, decoder) => this.send(Message$EffectRequestedContextSubscription(key, decoder));
+ const unsubscribe2 = (key) => this.send(Message$EffectRemovedContextSubscription(key));
+ globalThis.queueMicrotask(() => {
+ perform(effect, dispatch2, emit2, select, internals, provide2, subscribe2, unsubscribe2);
+ });
+ }
+}
+
+// build/dev/javascript/lustre/lustre.mjs
+class ElementNotFound extends CustomType {
+ constructor(selector) {
+ super();
+ this.selector = selector;
+ }
+}
+var Error$ElementNotFound = (selector) => new ElementNotFound(selector);
+class NotABrowser extends CustomType {
+}
+var Error$NotABrowser$const = new NotABrowser;
+var Error$NotABrowser = () => Error$NotABrowser$const;
+function application(init, update2, view) {
+ return new App(Option$None$const, init, update2, view, default_config);
+}
+function start4(app, selector, arguments$) {
+ return guard(!is_browser(), new Error2(Error$NotABrowser$const), () => {
+ return start(app, selector, arguments$);
+ });
+}
+
+// build/dev/javascript/gleam_stdlib/gleam/pair.mjs
+function new$5(first, second) {
+ return [first, second];
+}
+
+// build/dev/javascript/lustre/lustre/event.mjs
+function on(name2, handler) {
+ return event(name2, map3(handler, (message) => {
+ return new Handler(false, false, message);
+ }), empty_list, never, never, 0, 0);
+}
+function prevent_default(event4) {
+ if (event4 instanceof Event2) {
+ return new Event2(event4.kind, event4.name, event4.handler, event4.include, always, event4.stop_propagation, event4.debounce, event4.throttle);
+ } else {
+ return event4;
+ }
+}
+function on_click(message) {
+ return on("click", success(message));
+}
+function on_input(message) {
+ return on("input", subfield(toList(["target", "value"]), string3, (value2) => {
+ return success(message(value2));
+ }));
+}
+function formdata_decoder() {
+ let string_value_decoder = field(0, string3, (key) => {
+ return field(1, one_of(map3(string3, (var0) => {
+ return new Ok(var0);
+ }), toList([success(error_nil)])), (value2) => {
+ let _pipe2 = value2;
+ let _pipe$12 = map4(_pipe2, (_capture) => {
+ return new$5(key, _capture);
+ });
+ return success(_pipe$12);
+ });
+ });
+ let _pipe = string_value_decoder;
+ let _pipe$1 = list2(_pipe);
+ return map3(_pipe$1, values2);
+}
+function on_submit(message) {
+ let _pipe = on("submit", subfield(toList(["detail", "formData"]), formdata_decoder(), (formdata) => {
+ let _pipe2 = formdata;
+ let _pipe$1 = message(_pipe2);
+ return success(_pipe$1);
+ }));
+ return prevent_default(_pipe);
+}
+// build/dev/javascript/plinth/location_ffi.mjs
+function pathname(location) {
+ return location.pathname;
+}
+// build/dev/javascript/gleam_javascript/gleam_javascript_ffi.mjs
+class PromiseLayer {
+ constructor(promise) {
+ this.promise = promise;
+ }
+ static wrap(value2) {
+ return value2 instanceof Promise ? new PromiseLayer(value2) : value2;
+ }
+ static unwrap(value2) {
+ return value2 instanceof PromiseLayer ? value2.promise : value2;
+ }
+}
+function resolve(value2) {
+ return Promise.resolve(PromiseLayer.wrap(value2));
+}
+function then_await(promise, fn) {
+ return promise.then((value2) => fn(PromiseLayer.unwrap(value2)));
+}
+function map_promise(promise, fn) {
+ return promise.then((value2) => PromiseLayer.wrap(fn(PromiseLayer.unwrap(value2))));
+}
+function rescue(promise, fn) {
+ return promise.catch((error) => fn(error));
+}
+
+// build/dev/javascript/gleam_javascript/gleam/javascript/promise.mjs
+function tap(promise, callback) {
+ let _pipe = promise;
+ return map_promise(_pipe, (a2) => {
+ callback(a2);
+ return a2;
+ });
+}
+function try_await(promise, callback) {
+ let _pipe = promise;
+ return then_await(_pipe, (result) => {
+ if (result instanceof Ok) {
+ let a2 = result[0];
+ return callback(a2);
+ } else {
+ let e = result[0];
+ return resolve(new Error2(e));
+ }
+ });
+}
+
+// build/dev/javascript/plinth/plinth/browser/element.mjs
+class BeforeBegin extends CustomType {
+}
+var Position$BeforeBegin$const = new BeforeBegin;
+class AfterBegin extends CustomType {
+}
+var Position$AfterBegin$const = new AfterBegin;
+class BeforeEnd extends CustomType {
+}
+var Position$BeforeEnd$const = new BeforeEnd;
+class AfterEnd extends CustomType {
+}
+var Position$AfterEnd$const = new AfterEnd;
+
+// build/dev/javascript/plinth/window_ffi.mjs
+function crypto(self) {
+ const crypto2 = self.crypto;
+ if (crypto2 && crypto2 instanceof globalThis.Crypto) {
+ return Result$Ok(crypto2);
+ }
+ return Result$Error();
+}
+function self() {
+ return globalThis;
+}
+function alert(message) {
+ window.alert(message);
+}
+function confirm(message) {
+ return window.confirm(message);
+}
+function prompt(message, defaultValue) {
+ let text4 = window.prompt(message, defaultValue);
+ if (text4 !== null) {
+ return Result$Ok(text4);
+ } else {
+ return Result$Error();
+ }
+}
+function addEventListener4(type, listener) {
+ return window.addEventListener(type, listener);
+}
+function document2(window2) {
+ return window2.document;
+}
+async function requestWakeLock() {
+ try {
+ return Result$Ok(await window.navigator.wakeLock.request("screen"));
+ } catch (error) {
+ return Result$Error(error.toString());
+ }
+}
+function location(window2) {
+ return window2.location;
+}
+function focus2(w) {
+ return w.focus();
+}
+function innerHeight(w) {
+ return w.innerHeight;
+}
+function innerWidth(w) {
+ return w.innerWidth;
+}
+function outerHeight(w) {
+ return w.outerHeight;
+}
+function outerWidth(w) {
+ return w.outerWidth;
+}
+function screenX(w) {
+ return w.screenX;
+}
+function screenY(w) {
+ return w.screenY;
+}
+function screenTop(w) {
+ return w.screenTop;
+}
+function screenLeft(w) {
+ return w.screenLeft;
+}
+function scrollX(w) {
+ return w.scrollX;
+}
+function scrollY(w) {
+ return w.scrollY;
+}
+function opener(window2) {
+ const opener2 = window2.opener;
+ if (opener2) {
+ return Result$Ok(opener2);
+ } else {
+ return Result$Error();
+ }
+}
+function postMessage(window2, message, targetOrigin) {
+ window2.postMessage(message, targetOrigin);
+}
+function onMessage(worker2, callback) {
+ worker2.addEventListener("message", function(message) {
+ callback(message);
+ });
+}
+function open(url, target2, features) {
+ try {
+ return Result$Ok(window.open(url, target2, features));
+ } catch (error) {
+ return Result$Error(error.toString());
+ }
+}
+function close(w) {
+ w.close();
+}
+function closed(w) {
+ return w.closed;
+}
+function queueMicrotask2(callback) {
+ return window.queueMicrotask(callback);
+}
+function requestAnimationFrame(callback) {
+ return window.requestAnimationFrame(callback);
+}
+function cancelAnimationFrame(callback) {
+ return window.cancelAnimationFrame(callback);
+}
+function eval_(string) {
+ try {
+ return Result$Ok(eval(string));
+ } catch (error) {
+ return Result$Error(error.toString());
+ }
+}
+async function import_(string6) {
+ try {
+ return Result$Ok(await import(string6));
+ } catch (error) {
+ return Result$Error(error.toString());
+ }
+}
+
+// build/dev/javascript/gleam_stdlib/gleam/uri.mjs
+class Uri extends CustomType {
+ constructor(scheme, userinfo, host, port, path, query, fragment3) {
+ super();
+ this.scheme = scheme;
+ this.userinfo = userinfo;
+ this.host = host;
+ this.port = port;
+ this.path = path;
+ this.query = query;
+ this.fragment = fragment3;
+ }
+}
+var empty3 = /* @__PURE__ */ new Uri(Option$None$const, Option$None$const, Option$None$const, Option$None$const, "", Option$None$const, Option$None$const);
+function parse_fragment(rest, pieces) {
+ return new Ok(new Uri(pieces.scheme, pieces.userinfo, pieces.host, pieces.port, pieces.path, pieces.query, new Some(rest)));
+}
+function parse_query_with_question_mark_loop(loop$original, loop$uri_string, loop$pieces, loop$size) {
+ while (true) {
+ let original = loop$original;
+ let uri_string = loop$uri_string;
+ let pieces = loop$pieces;
+ let size3 = loop$size;
+ if (uri_string.charCodeAt(0) === 35) {
+ if (size3 === 0) {
+ let rest = uri_string.slice(1);
+ return parse_fragment(rest, pieces);
+ } else {
+ let rest = uri_string.slice(1);
+ let query = string_codeunit_slice(original, 0, size3);
+ let pieces$1 = new Uri(pieces.scheme, pieces.userinfo, pieces.host, pieces.port, pieces.path, new Some(query), pieces.fragment);
+ return parse_fragment(rest, pieces$1);
+ }
+ } else if (uri_string === "") {
+ return new Ok(new Uri(pieces.scheme, pieces.userinfo, pieces.host, pieces.port, pieces.path, new Some(original), pieces.fragment));
+ } else {
+ let $ = pop_codeunit(uri_string);
+ let rest = $[1];
+ loop$original = original;
+ loop$uri_string = rest;
+ loop$pieces = pieces;
+ loop$size = size3 + 1;
+ }
+ }
+}
+function parse_query_with_question_mark(uri_string, pieces) {
+ return parse_query_with_question_mark_loop(uri_string, uri_string, pieces, 0);
+}
+function parse_path_loop(loop$original, loop$uri_string, loop$pieces, loop$size) {
+ while (true) {
+ let original = loop$original;
+ let uri_string = loop$uri_string;
+ let pieces = loop$pieces;
+ let size3 = loop$size;
+ let $ = uri_string.charCodeAt(0);
+ if ($ === 63) {
+ let rest = uri_string.slice(1);
+ let path = string_codeunit_slice(original, 0, size3);
+ let pieces$1 = new Uri(pieces.scheme, pieces.userinfo, pieces.host, pieces.port, path, pieces.query, pieces.fragment);
+ return parse_query_with_question_mark(rest, pieces$1);
+ } else if ($ === 35) {
+ let rest = uri_string.slice(1);
+ let path = string_codeunit_slice(original, 0, size3);
+ let pieces$1 = new Uri(pieces.scheme, pieces.userinfo, pieces.host, pieces.port, path, pieces.query, pieces.fragment);
+ return parse_fragment(rest, pieces$1);
+ } else if (uri_string === "") {
+ return new Ok(new Uri(pieces.scheme, pieces.userinfo, pieces.host, pieces.port, original, pieces.query, pieces.fragment));
+ } else {
+ let $1 = pop_codeunit(uri_string);
+ let rest = $1[1];
+ loop$original = original;
+ loop$uri_string = rest;
+ loop$pieces = pieces;
+ loop$size = size3 + 1;
+ }
+ }
+}
+function parse_path(uri_string, pieces) {
+ return parse_path_loop(uri_string, uri_string, pieces, 0);
+}
+function parse_port_loop(loop$uri_string, loop$pieces, loop$port) {
+ while (true) {
+ let uri_string = loop$uri_string;
+ let pieces = loop$pieces;
+ let port = loop$port;
+ let $ = uri_string.charCodeAt(0);
+ if ($ === 48) {
+ let rest = uri_string.slice(1);
+ loop$uri_string = rest;
+ loop$pieces = pieces;
+ loop$port = port * 10;
+ } else if ($ === 49) {
+ let rest = uri_string.slice(1);
+ loop$uri_string = rest;
+ loop$pieces = pieces;
+ loop$port = port * 10 + 1;
+ } else if ($ === 50) {
+ let rest = uri_string.slice(1);
+ loop$uri_string = rest;
+ loop$pieces = pieces;
+ loop$port = port * 10 + 2;
+ } else if ($ === 51) {
+ let rest = uri_string.slice(1);
+ loop$uri_string = rest;
+ loop$pieces = pieces;
+ loop$port = port * 10 + 3;
+ } else if ($ === 52) {
+ let rest = uri_string.slice(1);
+ loop$uri_string = rest;
+ loop$pieces = pieces;
+ loop$port = port * 10 + 4;
+ } else if ($ === 53) {
+ let rest = uri_string.slice(1);
+ loop$uri_string = rest;
+ loop$pieces = pieces;
+ loop$port = port * 10 + 5;
+ } else if ($ === 54) {
+ let rest = uri_string.slice(1);
+ loop$uri_string = rest;
+ loop$pieces = pieces;
+ loop$port = port * 10 + 6;
+ } else if ($ === 55) {
+ let rest = uri_string.slice(1);
+ loop$uri_string = rest;
+ loop$pieces = pieces;
+ loop$port = port * 10 + 7;
+ } else if ($ === 56) {
+ let rest = uri_string.slice(1);
+ loop$uri_string = rest;
+ loop$pieces = pieces;
+ loop$port = port * 10 + 8;
+ } else if ($ === 57) {
+ let rest = uri_string.slice(1);
+ loop$uri_string = rest;
+ loop$pieces = pieces;
+ loop$port = port * 10 + 9;
+ } else if ($ === 63) {
+ let rest = uri_string.slice(1);
+ let pieces$1 = new Uri(pieces.scheme, pieces.userinfo, pieces.host, new Some(port), pieces.path, pieces.query, pieces.fragment);
+ return parse_query_with_question_mark(rest, pieces$1);
+ } else if ($ === 35) {
+ let rest = uri_string.slice(1);
+ let pieces$1 = new Uri(pieces.scheme, pieces.userinfo, pieces.host, new Some(port), pieces.path, pieces.query, pieces.fragment);
+ return parse_fragment(rest, pieces$1);
+ } else if ($ === 47) {
+ let pieces$1 = new Uri(pieces.scheme, pieces.userinfo, pieces.host, new Some(port), pieces.path, pieces.query, pieces.fragment);
+ return parse_path(uri_string, pieces$1);
+ } else if (uri_string === "") {
+ return new Ok(new Uri(pieces.scheme, pieces.userinfo, pieces.host, new Some(port), pieces.path, pieces.query, pieces.fragment));
+ } else {
+ return new Error2(undefined);
+ }
+ }
+}
+function parse_port(uri_string, pieces) {
+ let $ = uri_string.charCodeAt(0);
+ if (uri_string.startsWith(":0")) {
+ let rest = uri_string.slice(2);
+ return parse_port_loop(rest, pieces, 0);
+ } else if (uri_string.startsWith(":1")) {
+ let rest = uri_string.slice(2);
+ return parse_port_loop(rest, pieces, 1);
+ } else if (uri_string.startsWith(":2")) {
+ let rest = uri_string.slice(2);
+ return parse_port_loop(rest, pieces, 2);
+ } else if (uri_string.startsWith(":3")) {
+ let rest = uri_string.slice(2);
+ return parse_port_loop(rest, pieces, 3);
+ } else if (uri_string.startsWith(":4")) {
+ let rest = uri_string.slice(2);
+ return parse_port_loop(rest, pieces, 4);
+ } else if (uri_string.startsWith(":5")) {
+ let rest = uri_string.slice(2);
+ return parse_port_loop(rest, pieces, 5);
+ } else if (uri_string.startsWith(":6")) {
+ let rest = uri_string.slice(2);
+ return parse_port_loop(rest, pieces, 6);
+ } else if (uri_string.startsWith(":7")) {
+ let rest = uri_string.slice(2);
+ return parse_port_loop(rest, pieces, 7);
+ } else if (uri_string.startsWith(":8")) {
+ let rest = uri_string.slice(2);
+ return parse_port_loop(rest, pieces, 8);
+ } else if (uri_string.startsWith(":9")) {
+ let rest = uri_string.slice(2);
+ return parse_port_loop(rest, pieces, 9);
+ } else if (uri_string === ":") {
+ return new Ok(pieces);
+ } else if (uri_string === "") {
+ return new Ok(pieces);
+ } else if ($ === 63) {
+ let rest = uri_string.slice(1);
+ return parse_query_with_question_mark(rest, pieces);
+ } else if (uri_string.startsWith(":?")) {
+ let rest = uri_string.slice(2);
+ return parse_query_with_question_mark(rest, pieces);
+ } else if ($ === 35) {
+ let rest = uri_string.slice(1);
+ return parse_fragment(rest, pieces);
+ } else if (uri_string.startsWith(":#")) {
+ let rest = uri_string.slice(2);
+ return parse_fragment(rest, pieces);
+ } else if ($ === 47) {
+ return parse_path(uri_string, pieces);
+ } else if ($ === 58) {
+ let rest = uri_string.slice(1);
+ if (rest.charCodeAt(0) === 47) {
+ return parse_path(rest, pieces);
+ } else {
+ return new Error2(undefined);
+ }
+ } else {
+ return new Error2(undefined);
+ }
+}
+function parse_host_outside_of_brackets_loop(loop$original, loop$uri_string, loop$pieces, loop$size) {
+ while (true) {
+ let original = loop$original;
+ let uri_string = loop$uri_string;
+ let pieces = loop$pieces;
+ let size3 = loop$size;
+ let $ = uri_string.charCodeAt(0);
+ if (uri_string === "") {
+ return new Ok(new Uri(pieces.scheme, pieces.userinfo, new Some(original), pieces.port, pieces.path, pieces.query, pieces.fragment));
+ } else if ($ === 58) {
+ let host = string_codeunit_slice(original, 0, size3);
+ let pieces$1 = new Uri(pieces.scheme, pieces.userinfo, new Some(host), pieces.port, pieces.path, pieces.query, pieces.fragment);
+ return parse_port(uri_string, pieces$1);
+ } else if ($ === 47) {
+ let host = string_codeunit_slice(original, 0, size3);
+ let pieces$1 = new Uri(pieces.scheme, pieces.userinfo, new Some(host), pieces.port, pieces.path, pieces.query, pieces.fragment);
+ return parse_path(uri_string, pieces$1);
+ } else if ($ === 63) {
+ let rest = uri_string.slice(1);
+ let host = string_codeunit_slice(original, 0, size3);
+ let pieces$1 = new Uri(pieces.scheme, pieces.userinfo, new Some(host), pieces.port, pieces.path, pieces.query, pieces.fragment);
+ return parse_query_with_question_mark(rest, pieces$1);
+ } else if ($ === 35) {
+ let rest = uri_string.slice(1);
+ let host = string_codeunit_slice(original, 0, size3);
+ let pieces$1 = new Uri(pieces.scheme, pieces.userinfo, new Some(host), pieces.port, pieces.path, pieces.query, pieces.fragment);
+ return parse_fragment(rest, pieces$1);
+ } else {
+ let $1 = pop_codeunit(uri_string);
+ let rest = $1[1];
+ loop$original = original;
+ loop$uri_string = rest;
+ loop$pieces = pieces;
+ loop$size = size3 + 1;
+ }
+ }
+}
+function parse_host_outside_of_brackets(uri_string, pieces) {
+ return parse_host_outside_of_brackets_loop(uri_string, uri_string, pieces, 0);
+}
+function is_valid_host_within_brackets_char(char) {
+ return 48 >= char && char <= 57 || 65 >= char && char <= 90 || 97 >= char && char <= 122 || char === 58 || char === 46;
+}
+function parse_host_within_brackets_loop(loop$original, loop$uri_string, loop$pieces, loop$size) {
+ while (true) {
+ let original = loop$original;
+ let uri_string = loop$uri_string;
+ let pieces = loop$pieces;
+ let size3 = loop$size;
+ let $ = uri_string.charCodeAt(0);
+ if (uri_string === "") {
+ return new Ok(new Uri(pieces.scheme, pieces.userinfo, new Some(uri_string), pieces.port, pieces.path, pieces.query, pieces.fragment));
+ } else if ($ === 93) {
+ if (size3 === 0) {
+ let rest = uri_string.slice(1);
+ return parse_port(rest, pieces);
+ } else {
+ let rest = uri_string.slice(1);
+ let host = string_codeunit_slice(original, 0, size3 + 1);
+ let pieces$1 = new Uri(pieces.scheme, pieces.userinfo, new Some(host), pieces.port, pieces.path, pieces.query, pieces.fragment);
+ return parse_port(rest, pieces$1);
+ }
+ } else if ($ === 47) {
+ if (size3 === 0) {
+ return parse_path(uri_string, pieces);
+ } else {
+ let host = string_codeunit_slice(original, 0, size3);
+ let pieces$1 = new Uri(pieces.scheme, pieces.userinfo, new Some(host), pieces.port, pieces.path, pieces.query, pieces.fragment);
+ return parse_path(uri_string, pieces$1);
+ }
+ } else if ($ === 63) {
+ if (size3 === 0) {
+ let rest = uri_string.slice(1);
+ return parse_query_with_question_mark(rest, pieces);
+ } else {
+ let rest = uri_string.slice(1);
+ let host = string_codeunit_slice(original, 0, size3);
+ let pieces$1 = new Uri(pieces.scheme, pieces.userinfo, new Some(host), pieces.port, pieces.path, pieces.query, pieces.fragment);
+ return parse_query_with_question_mark(rest, pieces$1);
+ }
+ } else if ($ === 35) {
+ if (size3 === 0) {
+ let rest = uri_string.slice(1);
+ return parse_fragment(rest, pieces);
+ } else {
+ let rest = uri_string.slice(1);
+ let host = string_codeunit_slice(original, 0, size3);
+ let pieces$1 = new Uri(pieces.scheme, pieces.userinfo, new Some(host), pieces.port, pieces.path, pieces.query, pieces.fragment);
+ return parse_fragment(rest, pieces$1);
+ }
+ } else {
+ let $1 = pop_codeunit(uri_string);
+ let char = $1[0];
+ let rest = $1[1];
+ let $2 = is_valid_host_within_brackets_char(char);
+ if ($2) {
+ loop$original = original;
+ loop$uri_string = rest;
+ loop$pieces = pieces;
+ loop$size = size3 + 1;
+ } else {
+ return parse_host_outside_of_brackets_loop(original, original, pieces, 0);
+ }
+ }
+ }
+}
+function parse_host_within_brackets(uri_string, pieces) {
+ return parse_host_within_brackets_loop(uri_string, uri_string, pieces, 0);
+}
+function parse_host(uri_string, pieces) {
+ let $ = uri_string.charCodeAt(0);
+ if ($ === 91) {
+ return parse_host_within_brackets(uri_string, pieces);
+ } else if ($ === 58) {
+ let pieces$1 = new Uri(pieces.scheme, pieces.userinfo, new Some(""), pieces.port, pieces.path, pieces.query, pieces.fragment);
+ return parse_port(uri_string, pieces$1);
+ } else if (uri_string === "") {
+ return new Ok(new Uri(pieces.scheme, pieces.userinfo, new Some(""), pieces.port, pieces.path, pieces.query, pieces.fragment));
+ } else {
+ return parse_host_outside_of_brackets(uri_string, pieces);
+ }
+}
+function parse_userinfo_loop(loop$original, loop$uri_string, loop$pieces, loop$size) {
+ while (true) {
+ let original = loop$original;
+ let uri_string = loop$uri_string;
+ let pieces = loop$pieces;
+ let size3 = loop$size;
+ let $ = uri_string.charCodeAt(0);
+ if ($ === 64) {
+ if (size3 === 0) {
+ let rest = uri_string.slice(1);
+ return parse_host(rest, pieces);
+ } else {
+ let rest = uri_string.slice(1);
+ let userinfo = string_codeunit_slice(original, 0, size3);
+ let pieces$1 = new Uri(pieces.scheme, new Some(userinfo), pieces.host, pieces.port, pieces.path, pieces.query, pieces.fragment);
+ return parse_host(rest, pieces$1);
+ }
+ } else if (uri_string === "") {
+ return parse_host(original, pieces);
+ } else if ($ === 47) {
+ return parse_host(original, pieces);
+ } else if ($ === 63) {
+ return parse_host(original, pieces);
+ } else if ($ === 35) {
+ return parse_host(original, pieces);
+ } else {
+ let $1 = pop_codeunit(uri_string);
+ let rest = $1[1];
+ loop$original = original;
+ loop$uri_string = rest;
+ loop$pieces = pieces;
+ loop$size = size3 + 1;
+ }
+ }
+}
+function parse_authority_pieces(string6, pieces) {
+ return parse_userinfo_loop(string6, string6, pieces, 0);
+}
+function parse_authority_with_slashes(uri_string, pieces) {
+ if (uri_string === "//") {
+ return new Ok(new Uri(pieces.scheme, pieces.userinfo, new Some(""), pieces.port, pieces.path, pieces.query, pieces.fragment));
+ } else if (uri_string.startsWith("//")) {
+ let rest = uri_string.slice(2);
+ return parse_authority_pieces(rest, pieces);
+ } else {
+ return parse_path(uri_string, pieces);
+ }
+}
+function parse_scheme_loop(loop$original, loop$uri_string, loop$pieces, loop$size) {
+ while (true) {
+ let original = loop$original;
+ let uri_string = loop$uri_string;
+ let pieces = loop$pieces;
+ let size3 = loop$size;
+ let $ = uri_string.charCodeAt(0);
+ if ($ === 47) {
+ if (size3 === 0) {
+ return parse_authority_with_slashes(uri_string, pieces);
+ } else {
+ let scheme = string_codeunit_slice(original, 0, size3);
+ let pieces$1 = new Uri(new Some(lowercase(scheme)), pieces.userinfo, pieces.host, pieces.port, pieces.path, pieces.query, pieces.fragment);
+ return parse_authority_with_slashes(uri_string, pieces$1);
+ }
+ } else if ($ === 63) {
+ if (size3 === 0) {
+ let rest = uri_string.slice(1);
+ return parse_query_with_question_mark(rest, pieces);
+ } else {
+ let rest = uri_string.slice(1);
+ let scheme = string_codeunit_slice(original, 0, size3);
+ let pieces$1 = new Uri(new Some(lowercase(scheme)), pieces.userinfo, pieces.host, pieces.port, pieces.path, pieces.query, pieces.fragment);
+ return parse_query_with_question_mark(rest, pieces$1);
+ }
+ } else if ($ === 35) {
+ if (size3 === 0) {
+ let rest = uri_string.slice(1);
+ return parse_fragment(rest, pieces);
+ } else {
+ let rest = uri_string.slice(1);
+ let scheme = string_codeunit_slice(original, 0, size3);
+ let pieces$1 = new Uri(new Some(lowercase(scheme)), pieces.userinfo, pieces.host, pieces.port, pieces.path, pieces.query, pieces.fragment);
+ return parse_fragment(rest, pieces$1);
+ }
+ } else if ($ === 58) {
+ if (size3 === 0) {
+ return new Error2(undefined);
+ } else {
+ let rest = uri_string.slice(1);
+ let scheme = string_codeunit_slice(original, 0, size3);
+ let pieces$1 = new Uri(new Some(lowercase(scheme)), pieces.userinfo, pieces.host, pieces.port, pieces.path, pieces.query, pieces.fragment);
+ return parse_authority_with_slashes(rest, pieces$1);
+ }
+ } else if (uri_string === "") {
+ return new Ok(new Uri(pieces.scheme, pieces.userinfo, pieces.host, pieces.port, original, pieces.query, pieces.fragment));
+ } else {
+ let $1 = pop_codeunit(uri_string);
+ let rest = $1[1];
+ loop$original = original;
+ loop$uri_string = rest;
+ loop$pieces = pieces;
+ loop$size = size3 + 1;
+ }
+ }
+}
+function parse2(uri_string) {
+ return parse_scheme_loop(uri_string, uri_string, empty3, 0);
+}
+function to_string5(uri) {
+ let _block;
+ let $ = uri.scheme;
+ if ($ instanceof Some) {
+ let scheme = $[0];
+ _block = scheme + ":";
+ } else {
+ _block = "";
+ }
+ let out = _block;
+ let _block$1;
+ let $1 = uri.host;
+ if ($1 instanceof Some) {
+ let host = $1[0];
+ let out$12 = out + "//";
+ let _block$22;
+ let $22 = uri.userinfo;
+ if ($22 instanceof Some) {
+ let userinfo = $22[0];
+ _block$22 = out$12 + userinfo + "@";
+ } else {
+ _block$22 = out$12;
+ }
+ let out$22 = _block$22;
+ let out$32 = out$22 + host;
+ let _block$32;
+ let $32 = uri.port;
+ if ($32 instanceof Some) {
+ let port = $32[0];
+ _block$32 = out$32 + ":" + to_string(port);
+ } else {
+ _block$32 = out$32;
+ }
+ let out$4 = _block$32;
+ let _block$4;
+ let $4 = uri.path;
+ if ($4 === "") {
+ _block$4 = out$4;
+ } else if ($4.charCodeAt(0) === 47) {
+ _block$4 = out$4 + uri.path;
+ } else {
+ _block$4 = out$4 + "/" + uri.path;
+ }
+ let out$5 = _block$4;
+ _block$1 = out$5;
+ } else {
+ _block$1 = out + uri.path;
+ }
+ let out$1 = _block$1;
+ let _block$2;
+ let $2 = uri.query;
+ if ($2 instanceof Some) {
+ let query = $2[0];
+ _block$2 = out$1 + "?" + query;
+ } else {
+ _block$2 = out$1;
+ }
+ let out$2 = _block$2;
+ let _block$3;
+ let $3 = uri.fragment;
+ if ($3 instanceof Some) {
+ let fragment3 = $3[0];
+ _block$3 = out$2 + "#" + fragment3;
+ } else {
+ _block$3 = out$2;
+ }
+ let out$3 = _block$3;
+ return out$3;
+}
+// build/dev/javascript/gleam_http/gleam/http.mjs
+class Get extends CustomType {
+}
+var Method$Get$const = new Get;
+class Post extends CustomType {
+}
+var Method$Post$const = new Post;
+class Head extends CustomType {
+}
+var Method$Head$const = new Head;
+class Put extends CustomType {
+}
+var Method$Put$const = new Put;
+class Delete extends CustomType {
+}
+var Method$Delete$const = new Delete;
+class Trace extends CustomType {
+}
+var Method$Trace$const = new Trace;
+class Connect extends CustomType {
+}
+var Method$Connect$const = new Connect;
+class Options extends CustomType {
+}
+var Method$Options$const = new Options;
+class Patch2 extends CustomType {
+}
+var Method$Patch$const = new Patch2;
+class Http extends CustomType {
+}
+var Scheme$Http$const = new Http;
+class Https extends CustomType {
+}
+var Scheme$Https$const = new Https;
+function method_to_string(method) {
+ if (method instanceof Get) {
+ return "GET";
+ } else if (method instanceof Post) {
+ return "POST";
+ } else if (method instanceof Head) {
+ return "HEAD";
+ } else if (method instanceof Put) {
+ return "PUT";
+ } else if (method instanceof Delete) {
+ return "DELETE";
+ } else if (method instanceof Trace) {
+ return "TRACE";
+ } else if (method instanceof Connect) {
+ return "CONNECT";
+ } else if (method instanceof Options) {
+ return "OPTIONS";
+ } else if (method instanceof Patch2) {
+ return "PATCH";
+ } else {
+ let method$1 = method[0];
+ return method$1;
+ }
+}
+function scheme_to_string(scheme) {
+ if (scheme instanceof Http) {
+ return "http";
+ } else {
+ return "https";
+ }
+}
+function scheme_from_string(scheme) {
+ let $ = lowercase(scheme);
+ if ($ === "http") {
+ return new Ok(Scheme$Http$const);
+ } else if ($ === "https") {
+ return new Ok(Scheme$Https$const);
+ } else {
+ return new Error2(undefined);
+ }
+}
+
+// build/dev/javascript/gleam_http/gleam/http/cookie.mjs
+class Lax extends CustomType {
+}
+var SameSitePolicy$Lax$const = new Lax;
+class Strict extends CustomType {
+}
+var SameSitePolicy$Strict$const = new Strict;
+class None2 extends CustomType {
+}
+var SameSitePolicy$None$const = new None2;
+
+// build/dev/javascript/gleam_http/gleam/http/request.mjs
+class Request extends CustomType {
+ constructor(method, headers, body2, scheme, host, port, path, query) {
+ super();
+ this.method = method;
+ this.headers = headers;
+ this.body = body2;
+ this.scheme = scheme;
+ this.host = host;
+ this.port = port;
+ this.path = path;
+ this.query = query;
+ }
+}
+function to_uri(request) {
+ return new Uri(new Some(scheme_to_string(request.scheme)), Option$None$const, new Some(request.host), request.port, request.path, request.query, Option$None$const);
+}
+function from_uri(uri) {
+ return try$((() => {
+ let _pipe = uri.scheme;
+ let _pipe$1 = unwrap(_pipe, "");
+ return scheme_from_string(_pipe$1);
+ })(), (scheme) => {
+ return try$((() => {
+ let _pipe = uri.host;
+ return to_result(_pipe, undefined);
+ })(), (host) => {
+ let req = new Request(Method$Get$const, List$Empty$const, "", scheme, host, uri.port, uri.path, uri.query);
+ return new Ok(req);
+ });
+ });
+}
+function set_header(request, key2, value3) {
+ let headers = key_set(request.headers, lowercase(key2), value3);
+ return new Request(request.method, headers, request.body, request.scheme, request.host, request.port, request.path, request.query);
+}
+function set_body(req, body2) {
+ return new Request(req.method, req.headers, body2, req.scheme, req.host, req.port, req.path, req.query);
+}
+function set_method(req, method) {
+ return new Request(method, req.headers, req.body, req.scheme, req.host, req.port, req.path, req.query);
+}
+
+// build/dev/javascript/gleam_http/gleam/http/response.mjs
+class Response extends CustomType {
+ constructor(status, headers, body2) {
+ super();
+ this.status = status;
+ this.headers = headers;
+ this.body = body2;
+ }
+}
+var Response$Response = (status, headers, body2) => new Response(status, headers, body2);
+function set_body2(response, body2) {
+ return new Response(response.status, response.headers, body2);
+}
+function get_header(response, key2) {
+ return key_find(response.headers, lowercase(key2));
+}
+function map9(response, transform) {
+ let _pipe = response.body;
+ let _pipe$1 = transform(_pipe);
+ return ((_capture) => {
+ return set_body2(response, _capture);
+ })(_pipe$1);
+}
+// build/dev/javascript/gleam_fetch/gleam_fetch_ffi.mjs
+async function raw_send(request) {
+ try {
+ return Result$Ok(await fetch(request));
+ } catch (error) {
+ return Result$Error(FetchError$NetworkError(error.toString()));
+ }
+}
+function from_fetch_response(response) {
+ let headers = [...response.headers].reverse();
+ return Response$Response(response.status, arrayToList2(headers), response);
+}
+function request_common(request) {
+ let url = to_string5(to_uri(request));
+ let method = method_to_string(request.method).toUpperCase();
+ let options = {
+ headers: make_headers(request.headers),
+ method
+ };
+ return [url, options];
+}
+function to_fetch_request(request) {
+ let [url, options] = request_common(request);
+ if (options.method !== "GET" && options.method !== "HEAD")
+ options.body = request.body;
+ return new globalThis.Request(url, options);
+}
+function make_headers(headersList) {
+ let headers = new globalThis.Headers;
+ for (let [k, v] of headersList)
+ headers.append(k.toLowerCase(), v);
+ return headers;
+}
+async function read_text_body(response) {
+ let body2;
+ try {
+ body2 = await response.body.text();
+ } catch (error) {
+ return Result$Error(FetchError$UnableToReadBody());
+ }
+ return Result$Ok(map9(response, () => body2));
+}
+function arrayToList2(array3) {
+ let list4 = List$Empty();
+ for (const element4 of array3) {
+ list4 = List$NonEmpty(element4, list4);
+ }
+ return list4;
+}
+
+// build/dev/javascript/gleam_fetch/gleam/fetch.mjs
+class NetworkError extends CustomType {
+ constructor($0) {
+ super();
+ this[0] = $0;
+ }
+}
+var FetchError$NetworkError = ($0) => new NetworkError($0);
+class UnableToReadBody extends CustomType {
+}
+var FetchError$UnableToReadBody$const = new UnableToReadBody;
+var FetchError$UnableToReadBody = () => FetchError$UnableToReadBody$const;
+class InvalidJsonBody extends CustomType {
+}
+var FetchError$InvalidJsonBody$const = new InvalidJsonBody;
+function send2(request) {
+ let _pipe = request;
+ let _pipe$1 = to_fetch_request(_pipe);
+ let _pipe$2 = raw_send(_pipe$1);
+ return try_await(_pipe$2, (resp) => {
+ return resolve(new Ok(from_fetch_response(resp)));
+ });
+}
+// build/dev/javascript/rsvp/rsvp.ffi.mjs
+var from_relative_url = (url_string) => {
+ if (!globalThis.location)
+ return new Error2(undefined);
+ const url = new URL(url_string, globalThis.location.href);
+ const uri = uri_from_url(url);
+ return new Ok(uri);
+};
+var uri_from_url = (url) => {
+ const optional = (value3) => value3 ? new Some(value3) : new None;
+ return new Uri(optional(url.protocol?.slice(0, -1)), new None, optional(url.hostname), optional(url.port && Number(url.port)), url.pathname, optional(url.search?.slice(1)), optional(url.hash?.slice(1)));
+};
+
+// build/dev/javascript/rsvp/rsvp.mjs
+class BadBody extends CustomType {
+}
+var Error$BadBody$const = new BadBody;
+class BadUrl extends CustomType {
+ constructor($0) {
+ super();
+ this[0] = $0;
+ }
+}
+class HttpError extends CustomType {
+ constructor($0) {
+ super();
+ this[0] = $0;
+ }
+}
+class JsonError extends CustomType {
+ constructor($0) {
+ super();
+ this[0] = $0;
+ }
+}
+class NetworkError2 extends CustomType {
+}
+var Error$NetworkError$const = new NetworkError2;
+class UnhandledResponse extends CustomType {
+ constructor($0) {
+ super();
+ this[0] = $0;
+ }
+}
+class Handler2 extends CustomType {
+ constructor(run2) {
+ super();
+ this.run = run2;
+ }
+}
+function decode_json_body(response, decoder) {
+ let _pipe = response.body;
+ let _pipe$1 = parse(_pipe, decoder);
+ return map_error(_pipe$1, (var0) => {
+ return new JsonError(var0);
+ });
+}
+function expect_ok_response(handler) {
+ return new Handler2((result) => {
+ return handler(try$(result, (response) => {
+ let $ = response.status;
+ let code2 = $;
+ if (code2 >= 200 && code2 < 300) {
+ return new Ok(response);
+ } else {
+ let code3 = $;
+ if (code3 >= 400 && code3 < 600) {
+ return new Error2(new HttpError(response));
+ } else {
+ return new Error2(new UnhandledResponse(response));
+ }
+ }
+ }));
+ });
+}
+function expect_json_response(handler) {
+ return expect_ok_response((result) => {
+ return handler(try$(result, (response) => {
+ let $ = get_header(response, "content-type");
+ if ($ instanceof Ok) {
+ let $1 = $[0];
+ if ($1 === "application/json") {
+ return new Ok(response);
+ } else if ($1.startsWith("application/json;")) {
+ return new Ok(response);
+ } else {
+ return new Error2(new UnhandledResponse(response));
+ }
+ } else {
+ return new Error2(new UnhandledResponse(response));
+ }
+ }));
+ });
+}
+function expect_json(decoder, handler) {
+ return expect_json_response((result) => {
+ let _pipe = result;
+ let _pipe$1 = try$(_pipe, (_capture) => {
+ return decode_json_body(_capture, decoder);
+ });
+ return handler(_pipe$1);
+ });
+}
+function expect_any_response(handler) {
+ return new Handler2(handler);
+}
+function reject(err, handler) {
+ return from2((dispatch2) => {
+ let _pipe = new Error2(err);
+ let _pipe$1 = handler.run(_pipe);
+ return dispatch2(_pipe$1);
+ });
+}
+function do_send(request, handler) {
+ return from2((dispatch2) => {
+ let _pipe = send2(request);
+ let _pipe$1 = try_await(_pipe, read_text_body);
+ let _pipe$2 = map_promise(_pipe$1, (_capture) => {
+ return map_error(_capture, (error) => {
+ if (error instanceof NetworkError) {
+ return Error$NetworkError$const;
+ } else if (error instanceof UnableToReadBody) {
+ return Error$BadBody$const;
+ } else {
+ return Error$BadBody$const;
+ }
+ });
+ });
+ let _pipe$3 = rescue(_pipe$2, (_) => {
+ return new Error2(Error$NetworkError$const);
+ });
+ let _pipe$4 = map_promise(_pipe$3, handler.run);
+ tap(_pipe$4, dispatch2);
+ return;
+ });
+}
+function send3(request, handler) {
+ return do_send(request, handler);
+}
+function to_uri2(uri_string) {
+ let _block;
+ if (uri_string.startsWith("./")) {
+ _block = from_relative_url(uri_string);
+ } else if (uri_string.charCodeAt(0) === 47) {
+ _block = from_relative_url(uri_string);
+ } else {
+ _block = parse2(uri_string);
+ }
+ let _pipe = _block;
+ return replace_error(_pipe, new BadUrl(uri_string));
+}
+function get3(url, handler) {
+ let $ = to_uri2(url);
+ if ($ instanceof Ok) {
+ let uri = $[0];
+ let $1 = from_uri(uri);
+ if ($1 instanceof Ok) {
+ let request = $1[0];
+ return send3(request, handler);
+ } else {
+ return reject(new BadUrl(url), handler);
+ }
+ } else {
+ let err = $[0];
+ return reject(err, handler);
+ }
+}
+function post(url, body2, handler) {
+ let $ = to_uri2(url);
+ if ($ instanceof Ok) {
+ let uri = $[0];
+ let $1 = from_uri(uri);
+ if ($1 instanceof Ok) {
+ let request = $1[0];
+ let _pipe = request;
+ let _pipe$1 = set_method(_pipe, Method$Post$const);
+ let _pipe$2 = set_header(_pipe$1, "content-type", "application/json");
+ let _pipe$3 = set_body(_pipe$2, to_string2(body2));
+ return send3(_pipe$3, handler);
+ } else {
+ return reject(new BadUrl(url), handler);
+ }
+ } else {
+ let err = $[0];
+ return reject(err, handler);
+ }
+}
+// build/dev/javascript/shared/shared.mjs
+class Project extends CustomType {
+ constructor(id, name2, description, tasks) {
+ super();
+ this.id = id;
+ this.name = name2;
+ this.description = description;
+ this.tasks = tasks;
+ }
+}
+class Task extends CustomType {
+ constructor(id, project_id, title2, description, status, assignee, assignees, due_date) {
+ super();
+ this.id = id;
+ this.project_id = project_id;
+ this.title = title2;
+ this.description = description;
+ this.status = status;
+ this.assignee = assignee;
+ this.assignees = assignees;
+ this.due_date = due_date;
+ }
+}
+class Dashboard extends CustomType {
+ constructor(username, projects) {
+ super();
+ this.username = username;
+ this.projects = projects;
+ }
+}
+class Credentials extends CustomType {
+ constructor(username, password) {
+ super();
+ this.username = username;
+ this.password = password;
+ }
+}
+class NewProject extends CustomType {
+ constructor(name2, description) {
+ super();
+ this.name = name2;
+ this.description = description;
+ }
+}
+class NewTask extends CustomType {
+ constructor(title2, description, assignee, assignees, due_date) {
+ super();
+ this.title = title2;
+ this.description = description;
+ this.assignee = assignee;
+ this.assignees = assignees;
+ this.due_date = due_date;
+ }
+}
+class StatusChange extends CustomType {
+ constructor(status) {
+ super();
+ this.status = status;
+ }
+}
+function task_decoder() {
+ return field("id", int2, (id) => {
+ return field("project_id", int2, (project_id) => {
+ return field("title", string3, (title2) => {
+ return field("description", string3, (description) => {
+ return field("status", string3, (status) => {
+ return field("assignee", string3, (assignee) => {
+ return field("assignees", string3, (assignees) => {
+ return field("due_date", string3, (due_date) => {
+ return success(new Task(id, project_id, title2, description, status, assignee, assignees, due_date));
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+}
+function project_decoder() {
+ return field("id", int2, (id) => {
+ return field("name", string3, (name2) => {
+ return field("description", string3, (description) => {
+ return field("tasks", list2(task_decoder()), (tasks) => {
+ return success(new Project(id, name2, description, tasks));
+ });
+ });
+ });
+ });
+}
+function dashboard_decoder() {
+ return field("username", string3, (username) => {
+ return field("projects", list2(project_decoder()), (projects) => {
+ return success(new Dashboard(username, projects));
+ });
+ });
+}
+function credentials_json(value3) {
+ return object2(toList([
+ ["username", string4(value3.username)],
+ ["password", string4(value3.password)]
+ ]));
+}
+function new_project_json(value3) {
+ return object2(toList([
+ ["name", string4(value3.name)],
+ ["description", string4(value3.description)]
+ ]));
+}
+function new_task_json(value3) {
+ return object2(toList([
+ ["title", string4(value3.title)],
+ ["description", string4(value3.description)],
+ ["assignee", string4(value3.assignee)],
+ ["assignees", string4(value3.assignees)],
+ ["due_date", string4(value3.due_date)]
+ ]));
+}
+function status_change_json(value3) {
+ return object2(toList([["status", string4(value3.status)]]));
+}
+// build/dev/javascript/client/client.mjs
+var FILEPATH = "src/client.gleam";
+
+class Model extends CustomType {
+ constructor(page, dashboard, error, username, password, project_name, project_description, task_title, task_description, task_assignee, task_assignees, task_due_date) {
+ super();
+ this.page = page;
+ this.dashboard = dashboard;
+ this.error = error;
+ this.username = username;
+ this.password = password;
+ this.project_name = project_name;
+ this.project_description = project_description;
+ this.task_title = task_title;
+ this.task_description = task_description;
+ this.task_assignee = task_assignee;
+ this.task_assignees = task_assignees;
+ this.task_due_date = task_due_date;
+ }
+}
+
+class DashboardLoaded extends CustomType {
+ constructor($0) {
+ super();
+ this[0] = $0;
+ }
+}
+class LoginSubmitted extends CustomType {
+ constructor($0) {
+ super();
+ this[0] = $0;
+ }
+}
+class RegisterSubmitted extends CustomType {
+ constructor($0) {
+ super();
+ this[0] = $0;
+ }
+}
+class ProjectSubmitted extends CustomType {
+ constructor($0) {
+ super();
+ this[0] = $0;
+ }
+}
+class TaskSubmitted extends CustomType {
+ constructor($0, $1) {
+ super();
+ this[0] = $0;
+ this[1] = $1;
+ }
+}
+class StatusSubmitted extends CustomType {
+ constructor($0, $1) {
+ super();
+ this[0] = $0;
+ this[1] = $1;
+ }
+}
+class Authenticated extends CustomType {
+ constructor($0) {
+ super();
+ this[0] = $0;
+ }
+}
+class Saved extends CustomType {
+ constructor($0) {
+ super();
+ this[0] = $0;
+ }
+}
+class UsernameChanged extends CustomType {
+ constructor($0) {
+ super();
+ this[0] = $0;
+ }
+}
+class PasswordChanged extends CustomType {
+ constructor($0) {
+ super();
+ this[0] = $0;
+ }
+}
+class ProjectNameChanged extends CustomType {
+ constructor($0) {
+ super();
+ this[0] = $0;
+ }
+}
+class ProjectDescriptionChanged extends CustomType {
+ constructor($0) {
+ super();
+ this[0] = $0;
+ }
+}
+class TaskTitleChanged extends CustomType {
+ constructor($0) {
+ super();
+ this[0] = $0;
+ }
+}
+class TaskDescriptionChanged extends CustomType {
+ constructor($0) {
+ super();
+ this[0] = $0;
+ }
+}
+class TaskAssigneeChanged extends CustomType {
+ constructor($0) {
+ super();
+ this[0] = $0;
+ }
+}
+class TaskAssigneesChanged extends CustomType {
+ constructor($0) {
+ super();
+ this[0] = $0;
+ }
+}
+class TaskDueDateChanged extends CustomType {
+ constructor($0) {
+ super();
+ this[0] = $0;
+ }
+}
+class LogOut extends CustomType {
+}
+var Message$LogOut$const = new LogOut;
+class Nothing extends CustomType {
+}
+var Message$Nothing$const = new Nothing;
+function text_input(name2, placeholder2) {
+ return input(toList([name(name2), placeholder(placeholder2)]));
+}
+function task_view(task) {
+ let _block;
+ let $ = task.status;
+ if ($ === "todo") {
+ _block = "doing";
+ } else if ($ === "doing") {
+ _block = "done";
+ } else {
+ _block = "todo";
+ }
+ let next = _block;
+ return div(toList([class$("task")]), toList([
+ div(List$Empty$const, toList([
+ strong(List$Empty$const, toList([text3(task.title)])),
+ p(List$Empty$const, toList([text3(task.description)]))
+ ])),
+ div(toList([class$("task-meta")]), toList([
+ span(List$Empty$const, toList([text3(task.status)])),
+ text3("Owner: " + task.assignee),
+ text3("Assignees: " + task.assignees),
+ form(toList([
+ on_submit((fields) => {
+ return new StatusSubmitted(task.id, fields);
+ })
+ ]), toList([
+ input(toList([
+ type_("hidden"),
+ name("status"),
+ value(next)
+ ])),
+ button(List$Empty$const, toList([text3("Move to " + next)]))
+ ]))
+ ]))
+ ]));
+}
+function project_view(_, project) {
+ return article(toList([class$("panel")]), append(toList([
+ text3("PROJECT"),
+ h2(List$Empty$const, toList([text3(project.name)])),
+ p(List$Empty$const, toList([text3(project.description)]))
+ ]), append(map2(project.tasks, task_view), toList([
+ form(toList([
+ on_submit((fields) => {
+ return new TaskSubmitted(project.id, fields);
+ })
+ ]), toList([
+ text_input("title", "Task title"),
+ text_input("assignee", "Owner"),
+ text_input("assignees", "Assignees"),
+ text_input("due_date", "Due date"),
+ text_input("description", "Details"),
+ button(List$Empty$const, toList([text3("Add task")]))
+ ]))
+ ]))));
+}
+function styles() {
+ return style(List$Empty$const, "body{margin:0;background:#f4f0e8;color:#28231e;font-family:Inter,ui-sans-serif,system-ui,sans-serif}.page{max-width:1120px;margin:auto;padding:28px 22px 72px}.auth{max-width:430px;margin:10vh auto;padding:42px;background:#fff;border:1px solid #e2d9cc;border-radius:22px;box-shadow:0 20px 60px #2d241414}.auth h1{font-size:clamp(2.4rem,8vw,4.8rem);line-height:.95;letter-spacing:-.06em;margin:14px 0}.auth form{display:grid;gap:12px;margin:26px 0 14px}.auth a{color:#b53b24;font-weight:700}.eyebrow{font-size:.72rem;letter-spacing:.16em;color:#b53b24;font-weight:800}header{display:flex;justify-content:space-between;gap:24px;align-items:start;margin-bottom:42px}header h1{font-size:clamp(2.7rem,7vw,5.5rem);line-height:.9;letter-spacing:-.07em;margin:12px 0}.hero{padding:42px;border-radius:22px;background:linear-gradient(120deg,#29241f,#594538);color:#fff;margin-bottom:20px;font-size:clamp(1.5rem,3vw,2.5rem);font-weight:800;letter-spacing:-.04em}.panel{background:#fff;border:1px solid #e2d9cc;border-radius:18px;padding:24px;margin:18px 0;box-shadow:0 12px 30px #2d24140b}.panel h2{margin:5px 0 8px;letter-spacing:-.03em}.panel>p{color:#796f64}.task{display:flex;justify-content:space-between;gap:20px;padding:17px 0;border-top:1px solid #eee8df}.task p{margin:5px 0 0;color:#796f64}.task-meta{display:flex;align-items:center;justify-content:flex-end;gap:9px;flex-wrap:wrap;color:#796f64;font-size:.82rem}.task-meta span{padding:5px 9px;border-radius:99px;background:#f0ebe3}.task-meta button{padding:7px 10px;font-size:.78rem}form{display:flex;gap:10px;flex-wrap:wrap;margin-top:22px}input{min-width:150px;flex:1;padding:12px 13px;border:1px solid #d9cfc2;border-radius:10px;background:#fffcf8;color:#28231e;font:inherit}button{border:0;border-radius:10px;background:#b53b24;color:#fff;padding:12px 17px;font:inherit;font-weight:800;cursor:pointer}button:hover{background:#902e1d}.error{color:#b53b24;font-weight:700}a{color:inherit;text-decoration:none}@media(max-width:650px){.task{display:block}.task-meta{justify-content:flex-start;margin-top:12px}header{display:block}.hero{padding:28px}}");
+}
+function error_view(error) {
+ if (error instanceof Some) {
+ let message2 = error[0];
+ return p(toList([class$("error")]), toList([text3(message2)]));
+ } else {
+ return none2();
+ }
+}
+function dashboard_view(model) {
+ let $ = model.dashboard;
+ if ($ instanceof Some) {
+ let board = $[0];
+ return main(toList([class$("page")]), append(toList([
+ styles(),
+ header(List$Empty$const, toList([
+ div(List$Empty$const, toList([
+ text3("FRC 972 · IRON CLAW"),
+ h1(List$Empty$const, toList([text3("Team board")]))
+ ])),
+ button(toList([on_click(Message$LogOut$const)]), toList([text3("Sign out")]))
+ ])),
+ section(toList([class$("hero")]), toList([text3("wassup")])),
+ section(toList([class$("panel")]), toList([
+ h2(List$Empty$const, toList([text3("New project")])),
+ form(toList([
+ on_submit((var0) => {
+ return new ProjectSubmitted(var0);
+ })
+ ]), toList([
+ text_input("name", "Project name"),
+ text_input("description", "What does success look like?"),
+ button(List$Empty$const, toList([text3("Add project")]))
+ ]))
+ ]))
+ ]), map2(board.projects, (project) => {
+ return project_view(model, project);
+ })));
+ } else {
+ return main(toList([class$("auth")]), toList([
+ h1(List$Empty$const, toList([text3("Loading Iron Claw...")])),
+ error_view(model.error)
+ ]));
+ }
+}
+function auth_view(model, title2, submit, on_submit2) {
+ let _block;
+ let $ = submit === "Log in";
+ if ($) {
+ _block = "/register";
+ } else {
+ _block = "/login";
+ }
+ let link = _block;
+ let _block$1;
+ let $1 = submit === "Log in";
+ if ($1) {
+ _block$1 = "Need an account?";
+ } else {
+ _block$1 = "Already registered?";
+ }
+ let link_text = _block$1;
+ return main(toList([class$("auth")]), toList([
+ styles(),
+ text3("FRC 972 · IRON CLAW"),
+ h1(List$Empty$const, toList([text3(title2)])),
+ p(List$Empty$const, toList([text3("google sheets, more like shmoogle shits")])),
+ error_view(model.error),
+ form(toList([on_submit(on_submit2)]), toList([
+ input(toList([
+ name("username"),
+ placeholder("Username"),
+ on_input((var0) => {
+ return new UsernameChanged(var0);
+ })
+ ])),
+ input(toList([
+ name("password"),
+ type_("password"),
+ placeholder("Password"),
+ on_input((var0) => {
+ return new PasswordChanged(var0);
+ })
+ ])),
+ button(List$Empty$const, toList([text3(submit)]))
+ ])),
+ a(toList([href(link)]), toList([text3(link_text)]))
+ ]));
+}
+function view(model) {
+ let $ = model.page;
+ if ($ === "login") {
+ return auth_view(model, "Welcome back", "Log in", (var0) => {
+ return new LoginSubmitted(var0);
+ });
+ } else if ($ === "register") {
+ return auth_view(model, "Create your account", "Create account", (var0) => {
+ return new RegisterSubmitted(var0);
+ });
+ } else {
+ return dashboard_view(model);
+ }
+}
+function field2(fields, name2) {
+ let _pipe = key_find(fields, name2);
+ return unwrap2(_pipe, "");
+}
+function auth_request(model, fields, url, _) {
+ let _block;
+ let _pipe = new Credentials(field2(fields, "username"), field2(fields, "password"));
+ _block = credentials_json(_pipe);
+ let body2 = _block;
+ return [
+ model,
+ post(url, body2, expect_any_response((result) => {
+ return new Authenticated((() => {
+ let _pipe$1 = result;
+ return map4(_pipe$1, (response) => {
+ return response.body;
+ });
+ })());
+ }))
+ ];
+}
+function update2(model, message2) {
+ if (message2 instanceof DashboardLoaded) {
+ let $ = message2[0];
+ if ($ instanceof Ok) {
+ let value3 = $[0];
+ echo("dashload good", undefined, "src/client.gleam", 103);
+ return [
+ new Model(model.page, new Some(value3), Option$None$const, model.username, model.password, model.project_name, model.project_description, model.task_title, model.task_description, model.task_assignee, model.task_assignees, model.task_due_date),
+ none()
+ ];
+ } else {
+ echo("dashload err", undefined, "src/client.gleam", 107);
+ return [
+ new Model("login", model.dashboard, new Some("Please sign in to continue."), model.username, model.password, model.project_name, model.project_description, model.task_title, model.task_description, model.task_assignee, model.task_assignees, model.task_due_date),
+ none()
+ ];
+ }
+ } else if (message2 instanceof LoginSubmitted) {
+ let fields = message2[0];
+ return auth_request(model, fields, "/api/login", "/");
+ } else if (message2 instanceof RegisterSubmitted) {
+ let fields = message2[0];
+ return auth_request(model, fields, "/api/register", "/");
+ } else if (message2 instanceof ProjectSubmitted) {
+ let fields = message2[0];
+ let _block;
+ let _pipe = new NewProject(field2(fields, "name"), field2(fields, "description"));
+ _block = new_project_json(_pipe);
+ let body2 = _block;
+ return [
+ model,
+ post("/api/projects", body2, expect_any_response((result) => {
+ return new Saved((() => {
+ let _pipe$1 = result;
+ return map4(_pipe$1, (response) => {
+ return response.body;
+ });
+ })());
+ }))
+ ];
+ } else if (message2 instanceof TaskSubmitted) {
+ let project_id = message2[0];
+ let fields = message2[1];
+ let _block;
+ let _pipe = new NewTask(field2(fields, "title"), field2(fields, "description"), field2(fields, "assignee"), field2(fields, "assignees"), field2(fields, "due_date"));
+ _block = new_task_json(_pipe);
+ let body2 = _block;
+ return [
+ model,
+ post("/api/projects/" + to_string(project_id) + "/tasks", body2, expect_any_response((result) => {
+ return new Saved((() => {
+ let _pipe$1 = result;
+ return map4(_pipe$1, (response) => {
+ return response.body;
+ });
+ })());
+ }))
+ ];
+ } else if (message2 instanceof StatusSubmitted) {
+ let task_id = message2[0];
+ let fields = message2[1];
+ let status = field2(fields, "status");
+ let _block;
+ let _pipe = new StatusChange(status);
+ _block = status_change_json(_pipe);
+ let body2 = _block;
+ return [
+ model,
+ post("/api/tasks/" + to_string(task_id) + "/status", body2, expect_any_response((result) => {
+ return new Saved((() => {
+ let _pipe$1 = result;
+ return map4(_pipe$1, (response) => {
+ return response.body;
+ });
+ })());
+ }))
+ ];
+ } else if (message2 instanceof Authenticated) {
+ let $ = message2[0];
+ if ($ instanceof Ok) {
+ return [
+ new Model("dashboard", model.dashboard, model.error, model.username, model.password, model.project_name, model.project_description, model.task_title, model.task_description, model.task_assignee, model.task_assignees, model.task_due_date),
+ get3("/api/dashboard", expect_json(dashboard_decoder(), (var0) => {
+ return new DashboardLoaded(var0);
+ }))
+ ];
+ } else {
+ return [
+ new Model(model.page, model.dashboard, new Some("Invalid username or password."), model.username, model.password, model.project_name, model.project_description, model.task_title, model.task_description, model.task_assignee, model.task_assignees, model.task_due_date),
+ none()
+ ];
+ }
+ } else if (message2 instanceof Saved) {
+ let $ = message2[0];
+ if ($ instanceof Ok) {
+ return [
+ new Model(model.page, model.dashboard, model.error, model.username, model.password, "", "", "", "", "", "", ""),
+ get3("/api/dashboard", expect_json(dashboard_decoder(), (var0) => {
+ return new DashboardLoaded(var0);
+ }))
+ ];
+ } else {
+ return [
+ new Model(model.page, model.dashboard, new Some("The request could not be saved."), model.username, model.password, model.project_name, model.project_description, model.task_title, model.task_description, model.task_assignee, model.task_assignees, model.task_due_date),
+ none()
+ ];
+ }
+ } else if (message2 instanceof UsernameChanged) {
+ let value3 = message2[0];
+ return [
+ new Model(model.page, model.dashboard, model.error, value3, model.password, model.project_name, model.project_description, model.task_title, model.task_description, model.task_assignee, model.task_assignees, model.task_due_date),
+ none()
+ ];
+ } else if (message2 instanceof PasswordChanged) {
+ let value3 = message2[0];
+ return [
+ new Model(model.page, model.dashboard, model.error, model.username, value3, model.project_name, model.project_description, model.task_title, model.task_description, model.task_assignee, model.task_assignees, model.task_due_date),
+ none()
+ ];
+ } else if (message2 instanceof ProjectNameChanged) {
+ let value3 = message2[0];
+ return [
+ new Model(model.page, model.dashboard, model.error, model.username, model.password, value3, model.project_description, model.task_title, model.task_description, model.task_assignee, model.task_assignees, model.task_due_date),
+ none()
+ ];
+ } else if (message2 instanceof ProjectDescriptionChanged) {
+ let value3 = message2[0];
+ return [
+ new Model(model.page, model.dashboard, model.error, model.username, model.password, model.project_name, value3, model.task_title, model.task_description, model.task_assignee, model.task_assignees, model.task_due_date),
+ none()
+ ];
+ } else if (message2 instanceof TaskTitleChanged) {
+ let value3 = message2[0];
+ return [
+ new Model(model.page, model.dashboard, model.error, model.username, model.password, model.project_name, model.project_description, value3, model.task_description, model.task_assignee, model.task_assignees, model.task_due_date),
+ none()
+ ];
+ } else if (message2 instanceof TaskDescriptionChanged) {
+ let value3 = message2[0];
+ return [
+ new Model(model.page, model.dashboard, model.error, model.username, model.password, model.project_name, model.project_description, model.task_title, value3, model.task_assignee, model.task_assignees, model.task_due_date),
+ none()
+ ];
+ } else if (message2 instanceof TaskAssigneeChanged) {
+ let value3 = message2[0];
+ return [
+ new Model(model.page, model.dashboard, model.error, model.username, model.password, model.project_name, model.project_description, model.task_title, model.task_description, value3, model.task_assignees, model.task_due_date),
+ none()
+ ];
+ } else if (message2 instanceof TaskAssigneesChanged) {
+ let value3 = message2[0];
+ return [
+ new Model(model.page, model.dashboard, model.error, model.username, model.password, model.project_name, model.project_description, model.task_title, model.task_description, model.task_assignee, value3, model.task_due_date),
+ none()
+ ];
+ } else if (message2 instanceof TaskDueDateChanged) {
+ let value3 = message2[0];
+ return [
+ new Model(model.page, model.dashboard, model.error, model.username, model.password, model.project_name, model.project_description, model.task_title, model.task_description, model.task_assignee, model.task_assignees, value3),
+ none()
+ ];
+ } else if (message2 instanceof LogOut) {
+ return [
+ new Model("login", model.dashboard, model.error, model.username, model.password, model.project_name, model.project_description, model.task_title, model.task_description, model.task_assignee, model.task_assignees, model.task_due_date),
+ get3("/api/logout", expect_ok_response((_) => {
+ return Message$Nothing$const;
+ }))
+ ];
+ } else {
+ return [model, none()];
+ }
+}
+function current_path() {
+ let _pipe = self();
+ let _pipe$1 = location(_pipe);
+ return pathname(_pipe$1);
+}
+function init(_) {
+ let _block;
+ let $ = current_path();
+ if ($ === "/login") {
+ _block = "login";
+ } else if ($ === "/register") {
+ _block = "register";
+ } else {
+ _block = "dashboard";
+ }
+ let page = _block;
+ echo(page, undefined, "src/client.gleam", 68);
+ let model = new Model(page, Option$None$const, Option$None$const, "", "", "", "", "", "", "", "", "");
+ return auth_request(model, List$Empty$const, "/api/login", "/");
+}
+function main2() {
+ let app = application(init, update2, view);
+ let $ = start4(app, "#app", Option$None$const);
+ if (!($ instanceof Ok)) {
+ throw makeError("let_assert", FILEPATH, "client", 18, "main", "Pattern match failed, no pattern matched the value.", { value: $, start: 421, end: 471, pattern_start: 432, pattern_end: 437 });
+ }
+ return;
+}
+function echo(value3, message2, file, line) {
+ const grey = "\x1B[90m";
+ const reset_color = "\x1B[39m";
+ const file_line = `${file}:${line}`;
+ const inspector = new Echo$Inspector;
+ const string_value = inspector.inspect(value3);
+ const string_message = message2 === undefined ? "" : " " + message2;
+ if (globalThis.process?.stderr?.write) {
+ const string6 = `${grey}${file_line}${reset_color}${string_message}
+${string_value}
+`;
+ globalThis.process.stderr.write(string6);
+ } else if (globalThis.Deno) {
+ const string6 = `${grey}${file_line}${reset_color}${string_message}
+${string_value}
+`;
+ globalThis.Deno.stderr.writeSync(new TextEncoder().encode(string6));
+ } else {
+ const string6 = `${file_line}${string_message}
+${string_value}`;
+ globalThis.console.log(string6);
+ }
+ return value3;
+}
+
+class Echo$Inspector {
+ #references = new globalThis.Set;
+ #isDict(value3) {
+ try {
+ const empty_dict = make();
+ const dict_class = empty_dict.constructor;
+ return value3 instanceof dict_class;
+ } catch {
+ return false;
+ }
+ }
+ #float(float3) {
+ const string6 = float3.toString().replace("+", "");
+ if (string6.indexOf(".") >= 0) {
+ return string6;
+ } else {
+ const index5 = string6.indexOf("e");
+ if (index5 >= 0) {
+ return string6.slice(0, index5) + ".0" + string6.slice(index5);
+ } else {
+ return string6 + ".0";
+ }
+ }
+ }
+ inspect(v) {
+ const t = typeof v;
+ if (v === true)
+ return "True";
+ if (v === false)
+ return "False";
+ if (v === null)
+ return "//js(null)";
+ if (v === undefined)
+ return "Nil";
+ if (t === "string")
+ return this.#string(v);
+ if (t === "bigint" || globalThis.Number.isInteger(v))
+ return v.toString();
+ if (t === "number")
+ return this.#float(v);
+ if (v instanceof UtfCodepoint)
+ return this.#utfCodepoint(v);
+ if (v instanceof BitArray)
+ return this.#bit_array(v);
+ if (v instanceof globalThis.RegExp)
+ return `//js(${v})`;
+ if (v instanceof globalThis.Date)
+ return `//js(Date("${v.toISOString()}"))`;
+ if (v instanceof globalThis.Error)
+ return `//js(${v.toString()})`;
+ if (v instanceof globalThis.Function) {
+ const args = [];
+ for (const i of globalThis.Array(v.length).keys())
+ args.push(globalThis.String.fromCharCode(i + 97));
+ return `//fn(${args.join(", ")}) { ... }`;
+ }
+ if (this.#references.size === this.#references.add(v).size) {
+ return "//js(circular reference)";
+ }
+ let printed;
+ if (globalThis.Array.isArray(v)) {
+ printed = `#(${v.map((v2) => this.inspect(v2)).join(", ")})`;
+ } else if (v instanceof List) {
+ printed = this.#list(v);
+ } else if (v instanceof CustomType) {
+ printed = this.#customType(v);
+ } else if (this.#isDict(v)) {
+ printed = this.#dict(v);
+ } else if (v instanceof Set) {
+ return `//js(Set(${[...v].map((v2) => this.inspect(v2)).join(", ")}))`;
+ } else {
+ printed = this.#object(v);
+ }
+ this.#references.delete(v);
+ return printed;
+ }
+ #object(v) {
+ const name2 = globalThis.Object.getPrototypeOf(v)?.constructor?.name || "Object";
+ const props = [];
+ for (const k of globalThis.Object.keys(v)) {
+ props.push(`${this.inspect(k)}: ${this.inspect(v[k])}`);
+ }
+ const body2 = props.length ? " " + props.join(", ") + " " : "";
+ const head = name2 === "Object" ? "" : name2 + " ";
+ return `//js(${head}{${body2}})`;
+ }
+ #dict(map10) {
+ let body2 = "dict.from_list([";
+ let first = true;
+ let key_value_pairs = fold(map10, [], (pairs, key2, value3) => {
+ pairs.push([key2, value3]);
+ return pairs;
+ });
+ key_value_pairs.sort();
+ key_value_pairs.forEach(([key2, value3]) => {
+ if (!first)
+ body2 = body2 + ", ";
+ body2 = body2 + "#(" + this.inspect(key2) + ", " + this.inspect(value3) + ")";
+ first = false;
+ });
+ return body2 + "])";
+ }
+ #customType(record) {
+ const props = globalThis.Object.keys(record).map((label) => {
+ const value3 = this.inspect(record[label]);
+ return isNaN(parseInt(label)) ? `${label}: ${value3}` : value3;
+ }).join(", ");
+ return props ? `${record.constructor.name}(${props})` : record.constructor.name;
+ }
+ #list(list4) {
+ if (list4 instanceof Empty) {
+ return "[]";
+ }
+ let char_out = 'charlist.from_string("';
+ let list_out = "[";
+ let current = list4;
+ while (current instanceof NonEmpty) {
+ let element4 = current.head;
+ current = current.tail;
+ if (list_out !== "[") {
+ list_out += ", ";
+ }
+ list_out += this.inspect(element4);
+ if (char_out) {
+ if (globalThis.Number.isInteger(element4) && element4 >= 32 && element4 <= 126) {
+ char_out += globalThis.String.fromCharCode(element4);
+ } else {
+ char_out = null;
+ }
+ }
+ }
+ if (char_out) {
+ return char_out + '")';
+ } else {
+ return list_out + "]";
+ }
+ }
+ #string(str) {
+ let new_str = '"';
+ for (let i = 0;i < str.length; i++) {
+ const char = str[i];
+ switch (char) {
+ case `
+`:
+ new_str += "\\n";
+ break;
+ case "\r":
+ new_str += "\\r";
+ break;
+ case "\t":
+ new_str += "\\t";
+ break;
+ case "\f":
+ new_str += "\\f";
+ break;
+ case "\\":
+ new_str += "\\\\";
+ break;
+ case '"':
+ new_str += "\\\"";
+ break;
+ default:
+ if (char < " " || char > "~" && char < " ") {
+ new_str += "\\u{" + char.charCodeAt(0).toString(16).toUpperCase().padStart(4, "0") + "}";
+ } else {
+ new_str += char;
+ }
+ }
+ }
+ new_str += '"';
+ return new_str;
+ }
+ #utfCodepoint(codepoint2) {
+ return `//utfcodepoint(${globalThis.String.fromCodePoint(codepoint2.value)})`;
+ }
+ #bit_array(bits2) {
+ if (bits2.bitSize === 0) {
+ return "<<>>";
+ }
+ let acc = "<<";
+ for (let i = 0;i < bits2.byteSize - 1; i++) {
+ acc += bits2.byteAt(i).toString();
+ acc += ", ";
+ }
+ if (bits2.byteSize * 8 === bits2.bitSize) {
+ acc += bits2.byteAt(bits2.byteSize - 1).toString();
+ } else {
+ const trailingBitsCount = bits2.bitSize % 8;
+ acc += bits2.byteAt(bits2.byteSize - 1) >> 8 - trailingBitsCount;
+ acc += `:size(${trailingBitsCount})`;
+ }
+ acc += ">>";
+ return acc;
+ }
+}
+
+// .lustre/build/client.mjs
+main2();
--- /dev/null
+import gleeunit
+
+pub fn main() -> Nil {
+ gleeunit.main()
+}
+
+// gleeunit test functions end in `_test`
+pub fn hello_world_test() {
+ let name = "Joe"
+ let greeting = "Hello, " <> name <> "!"
+
+ assert greeting == "Hello, Joe!"
+}
--- /dev/null
+*.beam
+*.ez
+/build
+erl_crash.dump
--- /dev/null
+# shared
+
+[](https://hex.pm/packages/shared)
+[](https://shared.hexdocs.pm/)
+
+```sh
+gleam add shared@1
+```
+```gleam
+import shared
+
+pub fn main() -> Nil {
+ // TODO: An example of the project in use
+}
+```
+
+Further documentation can be found at <https://shared.hexdocs.pm/>.
+
+## Development
+
+```sh
+gleam run # Run the project
+gleam test # Run the tests
+```
--- /dev/null
+name = "shared"
+version = "1.0.0"
+
+# Fill out these fields if you intend to generate HTML documentation or publish
+# your project to the Hex package manager.
+#
+# description = ""
+# licences = ["Apache-2.0"]
+# repository = { type = "github", user = "", repo = "" }
+# links = [{ title = "Website", href = "" }]
+#
+# For a full reference of all the available options, you can have a look at
+# https://gleam.run/writing-gleam/gleam-toml/.
+
+[dependencies]
+gleam_stdlib = ">= 1.0.0 and < 2.0.0"
+gleam_json = ">= 3.1.0 and < 4.0.0"
+simplifile = ">= 2.7.0 and < 3.0.0"
+
+[dev_dependencies]
+gleeunit = ">= 1.0.0 and < 2.0.0"
--- /dev/null
+# Do not manually edit this file, it is managed by Gleam.
+#
+# This file locks the dependency versions used, to make your build
+# deterministic and to prevent unexpected versions from being included
+# in your application.
+#
+# You should check this file into your source control repository.
+
+packages = [
+ { name = "filepath", version = "1.1.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "B06A9AF0BF10E51401D64B98E4B627F1D2E48C154967DA7AF4D0914780A6D40A" },
+ { name = "gleam_json", version = "3.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_json", source = "hex", outer_checksum = "44FDAA8847BE8FC48CA7A1C089706BD54BADCC4C45B237A992EDDF9F2CDB2836" },
+ { name = "gleam_stdlib", version = "1.0.5", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "CEE5B6C076A85B45F60C585F4316C63EC8B7127C119D5738C3958A9C4D50404E" },
+ { name = "gleeunit", version = "1.11.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "EC31ABA74256AEA531EDF8169931D775BBB384FED0A8A1BDC4DD9354E3E21826" },
+ { name = "simplifile", version = "2.7.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "A2727627B063E87351934C7F7F008F2D1FDB16F6DE0B8C79F9E46459CFC9C164" },
+]
+
+[requirements]
+gleam_json = { version = ">= 3.1.0 and < 4.0.0" }
+gleam_stdlib = { version = ">= 1.0.0 and < 2.0.0" }
+gleeunit = { version = ">= 1.0.0 and < 2.0.0" }
+simplifile = { version = ">= 2.7.0 and < 3.0.0" }
--- /dev/null
+import gleam/dynamic/decode
+import gleam/json
+
+pub type Project {
+ Project(id: Int, name: String, description: String, tasks: List(Task))
+}
+
+pub type Task {
+ Task(
+ id: Int,
+ project_id: Int,
+ title: String,
+ description: String,
+ status: String,
+ assignee: String,
+ assignees: String,
+ due_date: String,
+ )
+}
+
+pub type Dashboard {
+ Dashboard(username: String, projects: List(Project))
+}
+
+pub type Credentials {
+ Credentials(username: String, password: String)
+}
+
+pub type NewProject {
+ NewProject(name: String, description: String)
+}
+
+pub type NewTask {
+ NewTask(
+ title: String,
+ description: String,
+ assignee: String,
+ assignees: String,
+ due_date: String,
+ )
+}
+
+pub type StatusChange {
+ StatusChange(status: String)
+}
+
+pub fn dashboard_decoder() -> decode.Decoder(Dashboard) {
+ use username <- decode.field("username", decode.string)
+ use projects <- decode.field("projects", decode.list(project_decoder()))
+ decode.success(Dashboard(username:, projects:))
+}
+
+fn project_decoder() -> decode.Decoder(Project) {
+ use id <- decode.field("id", decode.int)
+ use name <- decode.field("name", decode.string)
+ use description <- decode.field("description", decode.string)
+ use tasks <- decode.field("tasks", decode.list(task_decoder()))
+ decode.success(Project(id:, name:, description:, tasks:))
+}
+
+fn task_decoder() -> decode.Decoder(Task) {
+ use id <- decode.field("id", decode.int)
+ use project_id <- decode.field("project_id", decode.int)
+ use title <- decode.field("title", decode.string)
+ use description <- decode.field("description", decode.string)
+ use status <- decode.field("status", decode.string)
+ use assignee <- decode.field("assignee", decode.string)
+ use assignees <- decode.field("assignees", decode.string)
+ use due_date <- decode.field("due_date", decode.string)
+ decode.success(Task(id:, project_id:, title:, description:, status:, assignee:, assignees:, due_date:))
+}
+
+pub fn credentials_decoder() -> decode.Decoder(Credentials) {
+ use username <- decode.field("username", decode.string)
+ use password <- decode.field("password", decode.string)
+ decode.success(Credentials(username:, password:))
+}
+
+pub fn new_project_decoder() -> decode.Decoder(NewProject) {
+ use name <- decode.field("name", decode.string)
+ use description <- decode.field("description", decode.string)
+ decode.success(NewProject(name:, description:))
+}
+
+pub fn new_task_decoder() -> decode.Decoder(NewTask) {
+ use title <- decode.field("title", decode.string)
+ use description <- decode.field("description", decode.string)
+ use assignee <- decode.field("assignee", decode.string)
+ use assignees <- decode.field("assignees", decode.string)
+ use due_date <- decode.field("due_date", decode.string)
+ decode.success(NewTask(title:, description:, assignee:, assignees:, due_date:))
+}
+
+pub fn status_change_decoder() -> decode.Decoder(StatusChange) {
+ use status <- decode.field("status", decode.string)
+ decode.success(StatusChange(status:))
+}
+
+pub fn dashboard_json(value: Dashboard) -> json.Json {
+ let Dashboard(username:, projects:) = value
+ json.object([
+ #("username", json.string(username)),
+ #("projects", json.array(projects, project_json)),
+ ])
+}
+
+fn project_json(value: Project) -> json.Json {
+ json.object([
+ #("id", json.int(value.id)),
+ #("name", json.string(value.name)),
+ #("description", json.string(value.description)),
+ #("tasks", json.array(value.tasks, task_json)),
+ ])
+}
+
+fn task_json(value: Task) -> json.Json {
+ json.object([
+ #("id", json.int(value.id)),
+ #("project_id", json.int(value.project_id)),
+ #("title", json.string(value.title)),
+ #("description", json.string(value.description)),
+ #("status", json.string(value.status)),
+ #("assignee", json.string(value.assignee)),
+ #("assignees", json.string(value.assignees)),
+ #("due_date", json.string(value.due_date)),
+ ])
+}
+
+pub fn credentials_json(value: Credentials) -> json.Json {
+ json.object([
+ #("username", json.string(value.username)),
+ #("password", json.string(value.password)),
+ ])
+}
+
+pub fn new_project_json(value: NewProject) -> json.Json {
+ json.object([
+ #("name", json.string(value.name)),
+ #("description", json.string(value.description)),
+ ])
+}
+
+pub fn new_task_json(value: NewTask) -> json.Json {
+ json.object([
+ #("title", json.string(value.title)),
+ #("description", json.string(value.description)),
+ #("assignee", json.string(value.assignee)),
+ #("assignees", json.string(value.assignees)),
+ #("due_date", json.string(value.due_date)),
+ ])
+}
+
+pub fn status_change_json(value: StatusChange) -> json.Json {
+ json.object([#("status", json.string(value.status))])
+}
--- /dev/null
+import gleeunit
+
+pub fn main() -> Nil {
+ gleeunit.main()
+}
+
+// gleeunit test functions end in `_test`
+pub fn hello_world_test() {
+ let name = "Joe"
+ let greeting = "Hello, " <> name <> "!"
+
+ assert greeting == "Hello, Joe!"
+}