Skip to content

Commit

Permalink
Merge branch 'main' into yaml_frontmatter
Browse files Browse the repository at this point in the history
  • Loading branch information
dubadub authored Dec 4, 2024
2 parents b638d06 + 5aef19f commit 97dd329
Show file tree
Hide file tree
Showing 17 changed files with 1,679 additions and 143 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ target/
.DS_Store
out/
.idea
.build
43 changes: 43 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// swift-tools-version: 5.7
import PackageDescription
import class Foundation.ProcessInfo

var package = Package(
name: "cooklang-rs",
platforms: [
.macOS(.v10_15),
.iOS(.v15),
],
products: [
.library(
name: "CooklangParser",
targets: ["CooklangParser"]),
],
dependencies: [
],
targets: [
.target(
name: "CooklangParser",
path: "swift/Sources/CooklangParser"),
.testTarget(
name: "CooklangParserTests",
dependencies: ["CooklangParser"],
path: "swift/Tests/CooklangParserTests"),
.binaryTarget(
name: "CooklangParserFFI",
url: "https://github.com/cooklang/cooklang-rs/releases/download/v0.13.3/CooklangParserFFI.xcframework.zip",
checksum: "b64965748b82f8ef55019b25416c2908f0c88e7e1b85af4c7cb53b7233b38e6d"),
]
)

let cooklangParserTarget = package.targets.first(where: { $0.name == "CooklangParser" })

if ProcessInfo.processInfo.environment["USE_LOCAL_XCFRAMEWORK"] == nil {
cooklangParserTarget?.dependencies.append("CooklangParserFFI")
} else {
package.targets.append(.binaryTarget(
name: "CooklangParserFFI_local",
path: "bindings/out/CooklangParserFFI.xcframework"))

cooklangParserTarget?.dependencies.append("CooklangParserFFI_local")
}
49 changes: 49 additions & 0 deletions bindings/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,3 +142,52 @@ Biuld foreight language bindings (this will output Kotlin code into `./out` dir:
--out-dir out

See example of a Gradle config [here](https://github.com/cooklang/cooklang-android/blob/main/app/build.gradle#L77-L132) with all required tasks.



## Building for iOS

### Prepare

Install `rustup` https://www.rust-lang.org/tools/install.

Then add iOS targets.

rustup target add aarch64-apple-ios
rustup target add x86_64-apple-ios

Install iOS SDK https://developer.apple.com/xcode/resources/.

Add ndk linkers to the PATH variable. Example for ~/.zshrc:

export PATH=$PATH:/Users/dubadub/Library/Android/sdk/ndk/25.2.9519653/toolchains/llvm/prebuilt/darwin-x86_64/bin/

### Build

Build library:

cargo build --lib --target=x86_64-apple-ios --release

Biuld foreight language bindings (this will output Swift code into `./out` dir:

cargo run --features="uniffi/cli" \
--bin uniffi-bindgen generate \
--config uniffi.toml \
--library ../target/x86_64-apple-ios/release/libcooklang_bindings.a \
--language swift \
--out-dir out

See example of a Xcode project [here](https://github.com/cooklang/cooklang-ios/blob/main/Cooklang.xcodeproj).

Combine into universal library:

mkdir -p ../target/universal/release
lipo -create -output ../target/universal/release/libcooklang_bindings.a \
../target/x86_64-apple-ios/release/libcooklang_bindings.a \
../target/aarch64-apple-ios/release/libcooklang_bindings.a


xcodebuild -create-xcframework \
-library ../target/aarch64-apple-ios/release/libcooklang_bindings.a \
-library ../target/x86_64-apple-ios/release/libcooklang_bindings.a \
-output CooklangParserFFI.xcframework
129 changes: 129 additions & 0 deletions bindings/build-swift.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
#!/bin/sh

set -eo pipefail

pushd `dirname $0`
trap popd EXIT

NAME="CooklangParser"
VERSION=${1:-"1.0"} # first arg or "1.0"
BUNDLE_IDENTIFIER="org.cooklang.$NAME"
LIBRARY_NAME="libcooklang_bindings.a"
FRAMEWORK_LIBRARY_NAME=${NAME}FFI
FRAMEWORK_NAME="$FRAMEWORK_LIBRARY_NAME.framework"
XC_FRAMEWORK_NAME="$FRAMEWORK_LIBRARY_NAME.xcframework"
HEADER_NAME="${NAME}FFI.h"
OUT_PATH="out"
MIN_IOS_VERSION="15.0"
WRAPPER_PATH="../swift/Sources/CooklangParser"

AARCH64_APPLE_IOS_PATH="../target/aarch64-apple-ios/release"
AARCH64_APPLE_IOS_SIM_PATH="../target/aarch64-apple-ios-sim/release"
X86_64_APPLE_IOS_PATH="../target/x86_64-apple-ios/release"
AARCH64_APPLE_DARWIN_PATH="../target/aarch64-apple-darwin/release"
X86_64_APPLE_DARWIN_PATH="../target/x86_64-apple-darwin/release"

targets=("aarch64-apple-ios" "aarch64-apple-ios-sim" "x86_64-apple-ios" "aarch64-apple-darwin" "x86_64-apple-darwin")

# Build for all targets
for target in "${targets[@]}"; do
echo "Building for $target..."
rustup target add $target
cargo build --release --target $target
done

# Generate swift wrapper
echo "Generating swift wrapper..."
mkdir -p $OUT_PATH
mkdir -p $WRAPPER_PATH
CURRENT_ARCH=$(rustc --version --verbose | grep host | cut -f2 -d' ')

cargo run --features="uniffi/cli" \
--bin uniffi-bindgen generate \
--config uniffi.toml \
--library ../target/$CURRENT_ARCH/release/$LIBRARY_NAME \
--language swift \
--out-dir $OUT_PATH

# Merge libraries with lipo
echo "Merging libraries with lipo..."
lipo -create $AARCH64_APPLE_IOS_SIM_PATH/$LIBRARY_NAME \
$X86_64_APPLE_IOS_PATH/$LIBRARY_NAME \
-output $OUT_PATH/sim-$LIBRARY_NAME
lipo -create $AARCH64_APPLE_DARWIN_PATH/$LIBRARY_NAME \
$X86_64_APPLE_DARWIN_PATH/$LIBRARY_NAME \
-output $OUT_PATH/macos-$LIBRARY_NAME

# Create framework template
rm -rf $OUT_PATH/$FRAMEWORK_NAME
mkdir -p $OUT_PATH/$FRAMEWORK_NAME/Headers
mkdir -p $OUT_PATH/$FRAMEWORK_NAME/Modules
cp $OUT_PATH/$HEADER_NAME $OUT_PATH/$FRAMEWORK_NAME/Headers
cat <<EOT > $OUT_PATH/$FRAMEWORK_NAME/Modules/module.modulemap
framework module $FRAMEWORK_LIBRARY_NAME {
umbrella header "$HEADER_NAME"
export *
module * { export * }
}
EOT

cat <<EOT > $OUT_PATH/$FRAMEWORK_NAME/Info.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$FRAMEWORK_LIBRARY_NAME</string>
<key>CFBundleIdentifier</key>
<string>$BUNDLE_IDENTIFIER</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$FRAMEWORK_LIBRARY_NAME</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>$VERSION</string>
<key>NSPrincipalClass</key>
<string></string>
<key>MinimumOSVersion</key>
<string>$MIN_IOS_VERSION</string>
</dict>
</plist>
EOT

# Prepare frameworks for each platform
rm -rf $OUT_PATH/frameworks
mkdir -p $OUT_PATH/frameworks/sim
mkdir -p $OUT_PATH/frameworks/ios
mkdir -p $OUT_PATH/frameworks/macos
cp -r $OUT_PATH/$FRAMEWORK_NAME $OUT_PATH/frameworks/sim/
cp -r $OUT_PATH/$FRAMEWORK_NAME $OUT_PATH/frameworks/ios/
cp -r $OUT_PATH/$FRAMEWORK_NAME $OUT_PATH/frameworks/macos/
mv $OUT_PATH/sim-$LIBRARY_NAME $OUT_PATH/frameworks/sim/$FRAMEWORK_NAME/$FRAMEWORK_LIBRARY_NAME
mv $OUT_PATH/macos-$LIBRARY_NAME $OUT_PATH/frameworks/macos/$FRAMEWORK_NAME/$FRAMEWORK_LIBRARY_NAME
cp $AARCH64_APPLE_IOS_PATH/$LIBRARY_NAME $OUT_PATH/frameworks/ios/$FRAMEWORK_NAME/$FRAMEWORK_LIBRARY_NAME

# Create xcframework
echo "Creating xcframework..."
rm -rf $OUT_PATH/$XC_FRAMEWORK_NAME
xcodebuild -create-xcframework \
-framework $OUT_PATH/frameworks/sim/$FRAMEWORK_NAME \
-framework $OUT_PATH/frameworks/ios/$FRAMEWORK_NAME \
-framework $OUT_PATH/frameworks/macos/$FRAMEWORK_NAME \
-output $OUT_PATH/$XC_FRAMEWORK_NAME

# Copy swift wrapper
# Need some temporary workarounds to compile swift wrapper
# https://github.com/rust-lang/cargo/issues/11953
cat <<EOT > $OUT_PATH/import.txt
#if os(macOS)
import SystemConfiguration
#endif
EOT
cat $OUT_PATH/import.txt $OUT_PATH/$NAME.swift > $WRAPPER_PATH/$NAME.swift
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`
8 changes: 2 additions & 6 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 @@ -330,15 +330,11 @@ <h1>cooklang-rs playground</h1>

const extensionsContainer = document.getElementById("extensions-container");
const extensions = [
"MULTILINE_STEPS",
"COMPONENT_MODIFIERS",
"COMPONENT_NOTE",
"COMPONENT_ALIAS",
"SECTIONS",
"ADVANCED_UNITS",
"MODES",
"TEMPERATURE",
"TEXT_STEPS",
"RANGE_VALUES",
"TIMER_REQUIRES_TIME",
"INTERMEDIATE_PREPARATIONS",
Expand Down Expand Up @@ -418,4 +414,4 @@ <h1>cooklang-rs playground</h1>
</script>
</body>

</html>
</html>
6 changes: 0 additions & 6 deletions src/analysis/event_consumer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,12 +375,6 @@ impl<'i, 'c> RecipeCollector<'i, 'c> {

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

let check_result = crate::metadata::check_std_entry(
sp_key,
self.content.metadata.map.get(key_t.as_ref()).unwrap(),
Expand Down
Loading

0 comments on commit 97dd329

Please sign in to comment.