Skip to content

Commit

Permalink
Merge pull request #20 from cooklang/feat/proposals-0006-0007-0008
Browse files Browse the repository at this point in the history
  • Loading branch information
dubadub authored Nov 30, 2024
2 parents 2ca0861 + 10c5419 commit 5aef19f
Show file tree
Hide file tree
Showing 7 changed files with 15 additions and 106 deletions.
71 changes: 5 additions & 66 deletions extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ are 5 modifiers:
- `@` **Recipe**. References another recipe by it's name.
```cooklang
Add @@tomato sauce{200%ml}.
```
```
- `&` **Reference**. References another ingredient with the same name. If a
quantity is given, the amount can be added. The ingredient must be defined
before. If there are multiple definitions, use the last one.
Expand All @@ -21,7 +21,7 @@ are 5 modifiers:
```cooklang
Now you can add @?thyme.
```
- `+` **New**. Forces to create a new ingredient. This works with the
- `+` **New**. Forces to create a new ingredient. This works with the
[modes](#modes) extension.

This also works (except recipe) for cookware.
Expand All @@ -47,18 +47,7 @@ There are more syntax variations:
Only past steps from the current section can be referenced. It can only be
combined with the optional (`?`) modifier. Text steps can't be referenced. In
relative references, text steps are ignored. Enabling this extension
automatically enables the [modifiers](#modifiers) extension.

## Component note
Simple, add small notes to ingredients. The notes in between parenthesis.

```coklang
@flour{}(all purpose)
@flour(all purpose) -- can omit the close brackets
@flour{} (all purpose) -- ❌ no space between the ingredient and the note
```

This also works for cookware.
automatically enables the [modifiers](#modifiers) extension.

## Component alias
Add an alias to an ingredient to display a different name.
Expand All @@ -78,43 +67,6 @@ Add more @&tipo zero flour|flour{}

This also works for cookware.

## Sections
Divide the steps. Sections can have a name or not.

```cooklang
= Cooking -- this
== Cooking == -- many before and after is also supported
==== -- without name
```

To add images to steps inside a section, add another index to the image name:
```txt
Recipe.0.jpeg -- First section, first step
Recipe.0.0.jpeg -- The same
Recipe.1.0.jpeg -- Second section, first, step
```

## Multiline steps
In regular cooklang each line is a step. With this extension, the recipe is
divided into blocks by a blank line in between, so:
```cooklang
A step,
the same step.
A different step.
```

## Text blocks
Some people like to write a couple of paragraphs in the recipe that don't are steps.

It can also be used as notes that are not instructions.

```cooklang
> Text block.
Regular step.
```

## Advanced units
Maybe confusing name. Tweaks a little bit the parsing and behaviour of units
inside quantities.
Expand Down Expand Up @@ -205,29 +157,16 @@ Just an extra rule that makes timers like `~name` invalid.
[^2]: Currently this is done in the analysis pass. So in the AST there is no
concept of inline quantities.

## Special metadata
This extension enables extra parsing for some special metadata keys. These are:

- `tags`. Comma separated list of tags.
- `emoji`. Emoji or emoji shortcode, checked that it's an actual emoji.
- `author`. Name, URL or [both](#Name-with-URL) with the format `name <URL>`.
- `source`. Same as `author`.
- `time`. Time string with unit support. Like `2 hour 30 min`. This overrides past `prep_time`/`cook_time`.
- `prep_time`. Same format as `time`. Overrides past `time` but not `prep_time`.
- `cook_time`. Same format as `time`. Overrides past `time` but not `cook_time`.

_(`servings` is always parsed)_

### Name with URL

Example: `Mom's Cookbook <https://moms-cookbook.url>` -> name: `Mom's Cookbook` url: `https://moms-cookbook.url/`

The interpretations of the key value will be:
The interpretations of the key value will be:

- `name <valid url>` -> as `name` & `url`
- `name <invalid url>` -> as `name`
- `name` -> as `name`
- `invalid url` -> as `name`
- `<invalid url>` -> as `name`
- `valid url` -> as `url`
- `<valid url>` -> as `url`
- `<valid url>` -> as `url`
4 changes: 1 addition & 3 deletions playground/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ <h1>cooklang-rs playground</h1>
<input type="checkbox" name="loadUnits" id="loadUnits">
<label for="loadUnits">Load units</label>
</div>

<fieldset>
<legend>Extensions</legend>
<div id="extensions-container"></div>
Expand Down Expand Up @@ -331,9 +331,7 @@ <h1>cooklang-rs playground</h1>
const extensionsContainer = document.getElementById("extensions-container");
const extensions = [
"COMPONENT_MODIFIERS",
"COMPONENT_NOTE",
"COMPONENT_ALIAS",
"SECTIONS",
"ADVANCED_UNITS",
"MODES",
"TEMPERATURE",
Expand Down
7 changes: 0 additions & 7 deletions src/analysis/event_consumer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,13 +288,6 @@ impl<'i, 'c> RecipeCollector<'i, 'c> {

// check if it's a special key
if let Ok(sp_key) = SpecialKey::from_str(&key_t) {
// always parse servings
if sp_key != SpecialKey::Servings
&& !self.extensions.contains(Extensions::SPECIAL_METADATA)
{
return;
}

// try to insert it
let res =
self.content
Expand Down
8 changes: 1 addition & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,8 @@ bitflags! {
pub struct Extensions: u32 {
/// Enables the [`Modifiers`](crate::ast::Modifiers)
const COMPONENT_MODIFIERS = 1 << 1;
/// Notes with `@igr(note)`
const COMPONENT_NOTE = 1 << 2;
/// Alias with `@igr|alias{}`
const COMPONENT_ALIAS = 1 << 3;
/// Sections with `== Section ==` or `= Section`
const SECTIONS = 1 << 4;
/// Enable extra checks with units and allows to omit the `%` in simple
/// cases like `@igr{10 kg}`
const ADVANCED_UNITS = 1 << 5;
Expand All @@ -144,9 +140,7 @@ bitflags! {
///
/// **ADDITIONS TO THE EXTENSIONS THIS ENABLES WILL NOT BE CONSIDERED A BREAKING CHANGE**
const COMPAT = Self::COMPONENT_MODIFIERS.bits()
| Self::COMPONENT_NOTE.bits()
| Self::COMPONENT_ALIAS.bits()
| Self::SECTIONS.bits()
| Self::ADVANCED_UNITS.bits()
| Self::MODES.bits()
| Self::TEMPERATURE.bits()
Expand Down Expand Up @@ -257,7 +251,7 @@ impl CooklangParser {
analysis::parse_events(
meta_events,
input,
Extensions::SPECIAL_METADATA & self.extensions,
self.extensions,
&self.converter,
options,
)
Expand Down
4 changes: 0 additions & 4 deletions src/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,6 @@ use crate::{
/// The raw key/value pairs from the recipe are in the `map` field. Many methods
/// on this struct are the parsed values with some special meaning. They return
/// `None` if the key is missing or the value failed to parse.
///
/// Also, most of these values will not have been parsed if the
/// [`SPECIAL_METADATA`](crate::Extensions::SPECIAL_METADATA) extension is not
/// enabled.
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Default)]
pub struct Metadata {
special: HashMap<SpecialKey, SpecialValue>,
Expand Down
6 changes: 1 addition & 5 deletions src/parser/section.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
use crate::{error::label, lexer::T, Extensions};
use crate::{error::label, lexer::T};

use super::{tokens_span, warning, BlockParser, Event};

pub(crate) fn section<'i>(block: &mut BlockParser<'_, 'i>) -> Option<Event<'i>> {
if !block.extension(Extensions::SECTIONS) {
return None;
}

block.consume(T![=])?;
block.consume_while(|t| t == T![=]);
let name_pos = block.current_offset();
Expand Down
21 changes: 7 additions & 14 deletions src/parser/step.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,17 +116,13 @@ fn modifiers<'t>(bp: &mut BlockParser<'t, '_>) -> &'t [Token] {
}

fn note<'i>(bp: &mut BlockParser<'_, 'i>) -> Option<Text<'i>> {
bp.extension(Extensions::COMPONENT_NOTE)
.then(|| {
bp.with_recover(|line| {
line.consume(T!['('])?;
let offset = line.current_offset();
let note = line.until(|t| t == T![')'])?;
line.bump(T![')']);
Some(line.text(offset, note))
})
})
.flatten()
bp.with_recover(|line| {
line.consume(T!['('])?;
let offset = line.current_offset();
let note = line.until(|t| t == T![')'])?;
line.bump(T![')']);
Some(line.text(offset, note))
})
}

struct ParsedModifiers {
Expand Down Expand Up @@ -577,9 +573,6 @@ fn check_alias(bp: &mut BlockParser, name_tokens: &[Token], container: &'static
fn check_note(bp: &mut BlockParser, container: &'static str) {
assert_ne!(container, INGREDIENT);
assert_ne!(container, COOKWARE);
if !bp.extension(Extensions::COMPONENT_NOTE) {
return;
}

assert!(bp
.with_recover(|bp| {
Expand Down

0 comments on commit 5aef19f

Please sign in to comment.