From 08fce0ae1602e2b4d44f22210b123921ba458a97 Mon Sep 17 00:00:00 2001
From: Emi Vasilek <emi.vasilek@gmail.com>
Date: Tue, 12 Dec 2023 02:32:04 +0000
Subject: [PATCH 01/10] update package name in dockerfile

---
 Dockerfile | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/Dockerfile b/Dockerfile
index 7243e52..a4621d8 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -5,8 +5,9 @@ RUN apk add --no-cache python3 py3-build py3-hatchling && \
     python3 -m build .
 
 FROM alpine:3.18
-COPY --from=build /build/dist/comfy-recipes-*-py3-none-any.whl /
+COPY --from=build /build/dist/ /mnt
 RUN apk add --no-cache python3 py3-pip && \
-    pip install /comfy-recipes-*-py3-none-any.whl && \
-    apk del py3-pip
+    pip install /mnt/comfy_recipes-*-py3-none-any.whl && \
+    apk del py3-pip && \
+    rm -r /mnt
 ENTRYPOINT ["/usr/bin/recipes-cli"]

From 8046f0d237c3cae18cb5be64ecd8b8b85c6f3cc3 Mon Sep 17 00:00:00 2001
From: Emi Vasilek <emi.vasilek@gmail.com>
Date: Tue, 12 Dec 2023 02:33:12 +0000
Subject: [PATCH 02/10] responsive website

---
 comfyrecipes/templates/base.html | 1 +
 1 file changed, 1 insertion(+)

diff --git a/comfyrecipes/templates/base.html b/comfyrecipes/templates/base.html
index cf3a0b6..720c2a8 100644
--- a/comfyrecipes/templates/base.html
+++ b/comfyrecipes/templates/base.html
@@ -7,6 +7,7 @@
     <title>{% block title %}{% endblock %}</title>
     <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/water.css@2/out/water.css">
     <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1" />
 </head>
 <body>
     {% block body %}{% endblock %}

From 88f801cadbe176ef06fb790757612b39dd3d5e54 Mon Sep 17 00:00:00 2001
From: Emi Vasilek <emi.vasilek@gmail.com>
Date: Sun, 12 May 2024 22:18:45 +0000
Subject: [PATCH 03/10] show full recipe price every time with a clarification
 if necessary

---
 comfyrecipes/parsing.py            | 27 +++++++++++++++++++++++----
 comfyrecipes/templates/base.html   | 11 +++++++++++
 comfyrecipes/templates/index.html  |  2 +-
 comfyrecipes/templates/recipe.html |  7 +++++--
 4 files changed, 40 insertions(+), 7 deletions(-)

diff --git a/comfyrecipes/parsing.py b/comfyrecipes/parsing.py
index 7f73140..6778e05 100644
--- a/comfyrecipes/parsing.py
+++ b/comfyrecipes/parsing.py
@@ -289,7 +289,7 @@ class Recipe(Element):
         source: Optional[SafeHTML],
         ingredients: List[IngredientInstance],
         subrecipes: List["Recipe"],
-        price: Optional["PriceDB"],
+        price: Optional["MultiPriceDB"],
         stepsections: List[StepSection],
     ) -> None:
         super().__init__(ctx)
@@ -317,7 +317,7 @@ class Recipe(Element):
                 rp = Recipe.from_dict(ctx, partdct)
                 subrecipes.append(rp)
 
-        price: Optional[PriceDB] = None
+        price: Optional[MultiPriceDB] = None
         pricex: float = 0
         ingswithprice = 0
         ingswithoutprice = 0
@@ -335,16 +335,22 @@ class Recipe(Element):
                 # we don't know how to convert currencies yet
                 currency = None
                 break
-        if currency is None or ingswithoutprice != 0 or len(ingredients) == 0:
+        if currency is None or len(ingredients) == 0:
             price = None
         else:
-            price = PriceDB(
+            pricedb = PriceDB(
                 ctx=ctx,
                 price=pricex,
                 amount=1,
                 unit=ctx.default_unit,
                 currency=currency,
             )
+            price = MultiPriceDB(
+                ctx=ctx,
+                pricedb=pricedb,
+                item_count=len(ingredients),
+                item_prices_missing=ingswithoutprice,
+            )
 
         stepsections: List[StepSection] = []
         if "steps" in dct:
@@ -594,3 +600,16 @@ class PriceDB(Element):
         if currency is None:
             raise RuntimeError("currency not specified and default_currency is also not set")
         return cls(ctx=ctx, price=price, amount=amount, unit=unit, currency=currency)
+
+class MultiPriceDB(Element):
+    def __init__(
+        self,
+        ctx: Context,
+        pricedb: PriceDB,
+        item_count: int,
+        item_prices_missing: int,
+    ) -> None:
+        super().__init__(ctx)
+        self.pricedb = pricedb
+        self.item_count = item_count
+        self.item_prices_missing = item_prices_missing
diff --git a/comfyrecipes/templates/base.html b/comfyrecipes/templates/base.html
index 720c2a8..b85b929 100644
--- a/comfyrecipes/templates/base.html
+++ b/comfyrecipes/templates/base.html
@@ -1,6 +1,17 @@
 {% macro price(price) -%}
 {% if price != None and price is defined and price.price is defined %}{{price.price|round(1)|numprint}}{%else%}?{% endif %} {{price.currency}}
 {%- endmacro %}
+{% macro multiprice(multiprice, shortform) -%}
+{% if multiprice != None and multiprice.pricedb != None and multiprice.pricedb is defined and multiprice.pricedb.price is defined -%}
+{{multiprice.pricedb.price|round(1)|numprint}}
+{%else%}
+?
+{%- endif %}
+ {{multiprice.pricedb.currency}}
+{%if multiprice.item_prices_missing != 0 and not shortform%}
+({{multiprice.item_prices_missing}}/{{multiprice.item_count}} prices missing)
+{%endif%}
+{%- endmacro %}
 <!DOCTYPE html>
 <html lang="en">
 <head>
diff --git a/comfyrecipes/templates/index.html b/comfyrecipes/templates/index.html
index 9a38e25..eaccdb5 100644
--- a/comfyrecipes/templates/index.html
+++ b/comfyrecipes/templates/index.html
@@ -3,6 +3,6 @@
 {%block body %}
     <h1>Recipes</h1>
     {% for recipe in recipes %}
-    <li>{% if recipe.price != None %}{{price(recipe.price)}} {%endif%}<a href="{{ recipe.outpath }}">{{ recipe.title }}</a></li>
+    <li>{% if recipe.price != None %}{{multiprice(recipe.price, true)}} {%endif%}<a href="{{ recipe.outpath }}">{{ recipe.title }}</a></li>
     {% endfor %}
 {%endblock%}
diff --git a/comfyrecipes/templates/recipe.html b/comfyrecipes/templates/recipe.html
index 2ffc5b1..81e7591 100644
--- a/comfyrecipes/templates/recipe.html
+++ b/comfyrecipes/templates/recipe.html
@@ -1,6 +1,6 @@
 {% extends "base.html" %}
 {% macro ingredientpart(ing) -%}
-{% if recipe.price != None %}{{price(ing.price)}} {%endif%}
+{% if ing.price != None %}{{price(ing.price)}} {%endif%}
 {% if ing.amount != None %} {{ing.amount|amountprint}}
 {% if ing.unit != None %} {{ing.unit.name}}{% endif %}
 {%endif%}
@@ -29,7 +29,10 @@
 {% for ing in rec.ingredients %}
     <li>{{ingredient(ing)}}</li>
 {% endfor %}
-{% if rec.price != None %}price: {{price(rec.price)}}{%endif%}
+{% if rec.price != None %}
+<br>
+price: {{multiprice(rec.price)}}
+{%endif%}
 {% endif %}
 {% if rec.stepsections|length != 0 %}
     <h3>Steps</h3>

From 7b3aa25c955dd7456a4ecee9a0fac080d7010029 Mon Sep 17 00:00:00 2001
From: Emi Vasilek <emi.vasilek@gmail.com>
Date: Fri, 11 Oct 2024 22:20:08 +0200
Subject: [PATCH 04/10] Dockerfile: use python image instead of alpine, update

---
 Dockerfile | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/Dockerfile b/Dockerfile
index a4621d8..c9bddac 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,13 +1,11 @@
-FROM alpine:3.18 AS build
+FROM python:3.13-alpine AS build
 COPY . /build
 WORKDIR /build
-RUN apk add --no-cache python3 py3-build py3-hatchling && \
+RUN pip install build hatchling && \
     python3 -m build .
 
-FROM alpine:3.18
+FROM python:3.13-alpine
 COPY --from=build /build/dist/ /mnt
-RUN apk add --no-cache python3 py3-pip && \
-    pip install /mnt/comfy_recipes-*-py3-none-any.whl && \
-    apk del py3-pip && \
+RUN pip install /mnt/comfy_recipes-*-py3-none-any.whl && \
     rm -r /mnt
 ENTRYPOINT ["/usr/bin/recipes-cli"]

From e35bc3852b47dfd70286f5210eb7a893c1389aa6 Mon Sep 17 00:00:00 2001
From: Emi Vasilek <emi.vasilek@gmail.com>
Date: Fri, 11 Oct 2024 22:21:30 +0200
Subject: [PATCH 05/10] update URLs

---
 README.md      | 4 ++--
 pyproject.toml | 6 +++---
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/README.md b/README.md
index aa2dec4..3e886c8 100644
--- a/README.md
+++ b/README.md
@@ -17,12 +17,12 @@ pip install dist/comfy-recipes-*-py3-none-any.whl
 
 ## Building the docker container
 ```sh
-docker build -t codeberg.org/comfy.city/comfy-recipes .
+docker buildx build -t git.comfy.city/Emi/comfy-recipes:local .
 ```
 
 The container can now be ran
 ```sh
-docker run --rm codeberg.org/comfy.city/comfy-recipes
+docker run --rm git.comfy.city/Emi/comfy-recipes:local
 ```
 
 ## Building the documentation
diff --git a/pyproject.toml b/pyproject.toml
index 99e6d9f..7cedace 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -17,9 +17,9 @@ classifiers = [
 license = { file = "LICENSE" }
 
 [project.urls]
-Homepage = "https://codeberg.org/comfy.city/comfy-recipes"
-Repository = "https://codeberg.org/comfy.city/comfy-recipes.git"
-Issues = "https://codeberg.org/comfy.city/comfy-recipes/issues"
+Homepage = "https://git.comfy.city/Emi/comfy-recipes"
+Repository = "https://git.comfy.city/Emi/comfy-recipes.git"
+Issues = "https://git.comfy.city/Emi/comfy-recipes/issues"
 Documentation = "https://comfy.city/comfy-recipes/docs"
 
 [project.scripts]

From 3e3de7ea597a6ee4d804b08beca567162d4065d9 Mon Sep 17 00:00:00 2001
From: Emi Vasilek <emi.vasilek@gmail.com>
Date: Sat, 12 Oct 2024 00:04:40 +0200
Subject: [PATCH 06/10] pyproject.toml: add dependency required with newer lxml

---
 pyproject.toml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pyproject.toml b/pyproject.toml
index 7cedace..e6bf155 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -9,7 +9,7 @@ description = "Smart recipe static site generator"
 authors = [{ name = "Emi Vasilek", email = "emi.vasilek@gmail.com" }]
 keywords = ["recipes", "recipe", "static site generator"]
 requires-python = ">= 3.8"
-dependencies = ["jsonschema", "jinja2", "PyYAML", "mistune", "lxml"]
+dependencies = ["jsonschema", "jinja2", "PyYAML", "mistune", "lxml", "lxml_html_clean"]
 classifiers = [
   "Development Status :: 3 - Alpha",
   "Programming Language :: Python",

From cc9206306ab3c771a0fdc2bd6dc876d050e4abe1 Mon Sep 17 00:00:00 2001
From: Emi Vasilek <emi.vasilek@gmail.com>
Date: Sat, 12 Oct 2024 00:05:45 +0200
Subject: [PATCH 07/10] parsing: also accept short ingredients without amounts

for example 'oil' will now be allowed, previously it would have to be `1
spoon oil` when sometimes people don't know the amount
---
 comfyrecipes/parsing.py | 31 ++++++++++++++++---------------
 1 file changed, 16 insertions(+), 15 deletions(-)

diff --git a/comfyrecipes/parsing.py b/comfyrecipes/parsing.py
index 6778e05..fd61440 100644
--- a/comfyrecipes/parsing.py
+++ b/comfyrecipes/parsing.py
@@ -197,23 +197,24 @@ class IngredientInstance(Element):
     def from_dict(cls, ctx: Context, dct: str | Dict[str, Any]) -> Self:
         if isinstance(dct, str):
             string = dct.strip()
-            p = re.compile(r"^(?:([0-9\.]+) ([a-zA-Z]+) )?([\w ]+)(?: \((.*)\))?$")
+            p = re.compile(r"^(?:([0-9\.]+) ([a-zA-Z]+) )+([\w ]+)(?: \((.*)\))?$")
             match = p.match(string)
-            if match is None:
-                raise RuntimeError(
-                    "ingredient {string} regex not matched, it should be in the format [amount(num) unit(string, one word)] name(string, any number of words) [(note(string))]"
-                )
-            amount = float(match.group(1))
-            unitstr = match.group(2)
+
+            amount = float(1)
             unit = ctx.default_unit
-            if unit is not None:
-                unitx = ctx.units.get(unitstr)
-                if unitx is None:
-                    ctx.issues.error(issues.ISSUE_UNKNOWN_UNIT, "unknown unit {unitstr}")
-                else:
-                    unit = unitx
-            name = match.group(3)
-            note = match.group(4)
+            name = string
+            note = None
+            if match is not None:
+                amount = float(match.group(1))
+                unitstr = match.group(2)
+                if unit is not None:
+                    unitx = ctx.units.get(unitstr)
+                    if unitx is None:
+                        ctx.issues.error(issues.ISSUE_UNKNOWN_UNIT, f"unknown unit {unitstr}")
+                    else:
+                        unit = unitx
+                name = match.group(3)
+                note = match.group(4)
             if note is None:
                 note = ""
             return cls(

From 8a9ae16ad344876e17926b654b9db0f8b390fdfb Mon Sep 17 00:00:00 2001
From: Emi Vasilek <emi.vasilek@gmail.com>
Date: Sat, 12 Oct 2024 00:12:20 +0200
Subject: [PATCH 08/10] .woodpecker: add

---
 .woodpecker/containers.yaml | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
 create mode 100644 .woodpecker/containers.yaml

diff --git a/.woodpecker/containers.yaml b/.woodpecker/containers.yaml
new file mode 100644
index 0000000..3a83407
--- /dev/null
+++ b/.woodpecker/containers.yaml
@@ -0,0 +1,15 @@
+when:
+  - event: push
+    branch: main
+
+steps:
+  - name: publish
+    image: woodpeckerci/plugin-docker-buildx
+    settings:
+      platforms: linux/amd64,linux/arm64/v8
+      repo: git.comfy.city/emi/comfy-recipes
+      registry: git.comfy.city
+      tags: latest
+      username: ${CI_REPO_OWNER}
+      password:
+        from_secret: registry_token

From ae3ee28ab441b88a00addddb4b6fd9dfe8ff11fd Mon Sep 17 00:00:00 2001
From: Emi Vasilek <emi.vasilek@gmail.com>
Date: Sat, 12 Oct 2024 00:20:05 +0200
Subject: [PATCH 09/10] README.md: update

---
 README.md | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index 3e886c8..15c3e4b 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,13 @@ Comfy Recipes is a simple application that renders your recipes into HTML.
 
 Documentation is available at <https://comfy.city/comfy-recipes/docs>
 
-## Building the python package
+## Running
+```sh
+docker run -v ./recipes:/recipes git.comfy.city/Emi/comfy-recipes:latest build /recipes
+```
+
+## Building
+### Building the python package
 Make sure you have hatchling and build modules installed.
 ```sh
 python3 -m build
@@ -15,17 +21,17 @@ The package can now be installed with
 pip install dist/comfy-recipes-*-py3-none-any.whl
 ```
 
-## Building the docker container
+### Building the docker container
 ```sh
 docker buildx build -t git.comfy.city/Emi/comfy-recipes:local .
 ```
 
 The container can now be ran
 ```sh
-docker run --rm git.comfy.city/Emi/comfy-recipes:local
+docker run -v ./recipes:/recipes git.comfy.city/Emi/comfy-recipes:local build /recipes
 ```
 
-## Building the documentation
+### Building the documentation
 ```sh
 cd docs
 mdbook build

From 2e5859342d3734dc4749ff988a7a33ec1dca95c1 Mon Sep 17 00:00:00 2001
From: Emi Vasilek <emi.vasilek@gmail.com>
Date: Sat, 12 Oct 2024 00:20:25 +0200
Subject: [PATCH 10/10] Dockerfile: fix entrypoint

---
 Dockerfile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Dockerfile b/Dockerfile
index c9bddac..e2b34a2 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -8,4 +8,4 @@ FROM python:3.13-alpine
 COPY --from=build /build/dist/ /mnt
 RUN pip install /mnt/comfy_recipes-*-py3-none-any.whl && \
     rm -r /mnt
-ENTRYPOINT ["/usr/bin/recipes-cli"]
+ENTRYPOINT ["/usr/local/bin/recipes-cli"]