Repository navigation
Conversation
"Save as Menu" on the shopping list page writes the recipes on the list to a new `.menu`, so the same list can be put together again another week with the menu's "Add All to Shopping List" (cooklang#380, carried into cooklang#385). - One `- @./Path/Recipe{factor}` bullet per recipe, in list order, `{}` at x1, joined with ` \` so they stay one list. `add_menu` reads a unitless factor back unchanged, so adding the saved menu stores the same recipes at the same factors. - A menu on the list is written as its recipes. Which sub-recipes a recipe was added without is dropped: a menu cannot say it. - `POST /api/shopping_list/save_as_menu {name}` → 201 `{path, skipped}`, 400 for an empty list or name, 409 when the menu exists. It writes a file, so it needs `EditRecipes`: listed before `/api/shopping_list` in the auth WRITES table, whose prefix would otherwise make it a list edit for shoppers. - The dialog (name, Escape, focus kept inside and handed back) is shown to those who may edit recipes; the new menu opens once saved. - `/new`'s file creation (name clean-up, containment check through symlinks from cooklang#549, create_new + flush) moves to `server::new_file::create`, shared by both. Clean-up now also trims each path segment: " /// " no longer makes a folder named " " holding " .menu". - Strings in all 9 locales; docs/server.md and the API reference. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RXA3hAKY9Q8hLCZGeokLPK
Member
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Part of #671 (the #380 request in the comments of #385).
What changes
Save as Menu on the shopping list page writes the recipes on the list to a new
.menu. Open the menu another week and Add All to Shopping List puts the same list together again, against whatever the pantry holds then.{}at ×1).add_menustores a unitless factor unchanged, so the saved menu round-trips to the same entries and scales. An integration test checks this, including a menu on the list whose{4%servings}reference became ×4.\continuation keeps the bullets one list, as the menu editor writes them. Without it, Cooklang joins the lines of a paragraph.@./sub-recipes) are dropped: a menu cannot say "this recipe, but not its dough". Adding the saved menu back includes them all. The dialog and the docs say so.Design
POST /api/shopping_list/save_as_menu {name}:201 {path, skipped}400for an empty list or a name with nothing left in it409when the menu existsskippedlists paths a reference cannot spell, e.g. a file name containing{./api/shopping_list, whose prefix maps toEditLists. It is listed first in theWRITEStable atEditRecipes, so a shopper can still change the list but cannot create files. A middleware unit test and the per-role integration test cover it./new's creation logic moves toserver::new_file::create, used by both routes. It covers the name clean-up, the containment check through symlinks fromcreate_recipedeletes a pre-existing directory when the parent resolves outside the recipe folder through a symlink #549/fix(server): never delete a folder when refusing a new recipe path #582,create_newand the flush before redirecting." /// "made a folder called" "holding" .menu"; this affects the New Recipe/Menu form as well.role="dialog",aria-modal, labelled and described. Focus starts on the name and stays inside the dialog. Escape or Cancel hands focus back to the button. Errors are announced withrole="alert"andaria-invalid.docs/server.md; the endpoint in the API reference anddocs/api.md.Screenshots
Tests
tests/save_as_menu_test.rs:add_menuand the menu page's links;../..in the name;server_auth_test.rs: reader and shopper get403, editor and admin get through, and the button only shows for the latter two.shopping-list-save-menu.spec.ts:cargo fmt,cargo clippy --all-targets(also--no-default-features: no new warnings),cargo testall clean.seed/.shopping-list(shopping-list-copy/-live, recipe-scaling, this one) can trip over each other locally. They pass with--workers=1.🤖 Generated with Claude Code
https://claude.ai/code/session_01RXA3hAKY9Q8hLCZGeokLPK