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 diff --git a/Dockerfile b/Dockerfile index 7243e52..e2b34a2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,12 +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 -COPY --from=build /build/dist/comfy-recipes-*-py3-none-any.whl / -RUN apk add --no-cache python3 py3-pip && \ - pip install /comfy-recipes-*-py3-none-any.whl && \ - apk del py3-pip -ENTRYPOINT ["/usr/bin/recipes-cli"] +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/local/bin/recipes-cli"] diff --git a/README.md b/README.md index aa2dec4..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 -## 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 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 -v ./recipes:/recipes git.comfy.city/Emi/comfy-recipes:local build /recipes ``` -## Building the documentation +### Building the documentation ```sh cd docs mdbook build diff --git a/comfyrecipes/parsing.py b/comfyrecipes/parsing.py index 7f73140..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( @@ -289,7 +290,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 +318,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 +336,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 +601,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 cf3a0b6..b85b929 100644 --- a/comfyrecipes/templates/base.html +++ b/comfyrecipes/templates/base.html @@ -1,12 +1,24 @@ {% 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 %} {% block title %}{% endblock %} + {% block body %}{% endblock %} 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 %}

Recipes

{% for recipe in recipes %} -
  • {% if recipe.price != None %}{{price(recipe.price)}} {%endif%}{{ recipe.title }}
  • +
  • {% if recipe.price != None %}{{multiprice(recipe.price, true)}} {%endif%}{{ recipe.title }}
  • {% 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 %}
  • {{ingredient(ing)}}
  • {% endfor %} -{% if rec.price != None %}price: {{price(rec.price)}}{%endif%} +{% if rec.price != None %} +
    +price: {{multiprice(rec.price)}} +{%endif%} {% endif %} {% if rec.stepsections|length != 0 %}

    Steps

    diff --git a/pyproject.toml b/pyproject.toml index 99e6d9f..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", @@ -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]