Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
841 changes: 795 additions & 46 deletions README.md

Large diffs are not rendered by default.

780 changes: 780 additions & 0 deletions content/about.md

Large diffs are not rendered by default.

736 changes: 736 additions & 0 deletions content/animations.md

Large diffs are not rendered by default.

730 changes: 730 additions & 0 deletions content/animations.txt

Large diffs are not rendered by default.

730 changes: 730 additions & 0 deletions content/animations_css.txt

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions content/badges.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[![Current Crates.io Version](https://img.shields.io/crates/v/grimoire_css.svg)](https://crates.io/crates/grimoire_css)
[![Crates.io Downloads](https://img.shields.io/crates/d/grimoire_css.svg)](https://crates.io/crates/grimoire_css)
[![Test Status](https://github.com/persevie/grimoire-css/actions/workflows/quality.yml/badge.svg)](https://github.com/persevie/grimoire-css/actions/workflows/quality.yml)
[![codecov](https://codecov.io/github/persevie/grimoire-css/graph/badge.svg?token=3QE08UYS3S)](https://codecov.io/github/persevie/grimoire-css)
![license](https://shields.io/badge/license-MIT-blue)

---
19 changes: 19 additions & 0 deletions content/circle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# The Arcane Circle

Grimoire CSS gives you the freedom to create styles that work exactly the way you want them to - no rigid rules or constraints. Whether you’re crafting dynamic interactions or fine-tuning layouts, Grimoire adapts to your needs, making each step straightforward and rewarding.

So, come join us. Share your work, exchange your thoughts, and help us keep pushing CSS to be more flexible and enjoyable.

The Arcane Circle, or simply the Circle, is a place where you can share your configs, scrolls, variables, components, or UI kits. It’s where you can catch the latest news, follow development, influence the project, and interact with other members of the Circle.

> The Circle is currently under development.

## The First Member

Hello! My name is [Dmitrii Shatokhin](https://dmtrshat.github.io/), and I am the creator of Grimoire CSS. I invented the Spell concept and all the other ideas behind the project. Grimoire CSS is the result of countless hours of work and dedication, and I am proud to have made it open source.

But this is just the beginning. I am committed to the ongoing development of Grimoire CSS and its entire ecosystem - there are many plans and tasks ahead, which I strive to manage transparently on GitHub. My vision is to grow the Arcane Circle community and bring all these ideas to life.

I would be truly grateful for any support you can offer - whether it’s starring the project on GitHub, leaving feedback, recommending it to others, contributing to its development, helping to promote Grimoire CSS, or even sponsoring the project or my work.

Thank you!
1 change: 1 addition & 0 deletions content/desk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
> For the best experience and access to online playground and transmutator (aka **Desk**), please visit the [Grimoire CSS site](https://grimoirecss.com). The documentation is the same in both places.
5 changes: 5 additions & 0 deletions content/hero_image.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<div align="center">
<img height="128" alt="Grimoire CSS logo" src="./assets/grimoire-css-logo.svg">
</div>

---
1 change: 1 addition & 0 deletions content/note.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
> For the best experience and access to advanced features like playgrounds and interactive previews, please visit the [Grimoire CSS site](https://grimoirecss.com). The documentation is the same in both places.
9 changes: 9 additions & 0 deletions content/release_info.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Release Information

## Release Notes

For detailed information about each release, including new features, improvements, and breaking changes, see our [Release Notes](https://github.com/persevie/grimoire-css/blob/main/RELEASES.md).

### Changelog

A concise list of version-specific changes can be found in our [Changelog](https://github.com/persevie/grimoire-css/blob/main/CHANGELOG.md).
1 change: 1 addition & 0 deletions content/slogan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Craft Your Code, Cast Your Spells
115 changes: 115 additions & 0 deletions scripts/pre_publish.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
#!/usr/bin/env bash

# Pre-publish helper: generate animations list and compose README.md from content blocks.

set -euo pipefail

SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "${BASH_SOURCE[0]:-$0}")" && pwd)
REPO_ROOT=$(cd "$SCRIPT_DIR/.." && pwd)
CONTENT_DIR="$REPO_ROOT/content"
ANIM_CSS_DIR="$REPO_ROOT/src/core/animations/css"

echo "[pre_publish] repo_root=$REPO_ROOT"

# 1) Create content/animations.txt from src/core/animations/css using ls (remove .css)
# Keep it sorted and handle the case when no files exist.
animations_txt="$CONTENT_DIR/animations.txt"
{
shopt -s nullglob
css_files=("$ANIM_CSS_DIR"/*.css)
if ((${#css_files[@]})); then
for f in "${css_files[@]}"; do
bname=$(basename "$f")
printf '%s\n' "${bname%.css}"
done | LC_ALL=C sort
fi
} > "$animations_txt"
echo "[pre_publish] generated $(wc -l < "$animations_txt") entries in content/animations.txt"

# 2) Insert animations from content/animations.txt into content/animations.md
# between the markers, adding "- " at the beginning of each line.
animations_md="$CONTENT_DIR/animations.md"
tmp_file="$animations_md.tmp"

awk -v list_file="$animations_txt" '
BEGIN {
i = 0
while ((getline l < list_file) > 0) { list[i++] = l }
close(list_file)
}
{
if (state == 1) {
# Skip lines until END marker, then print the new block and the END marker.
if ($0 ~ /<!--[[:space:]]*END[[:space:]]+ANIMATIONS[[:space:]]+LIST[[:space:]]*-->/) {
for (j=0; j<i; j++) print "- " list[j]
print
state = 0
}
next
}
print
if ($0 ~ /<!--[[:space:]]*START[[:space:]]+ANIMATIONS[[:space:]]+LIST[[:space:]]*-->/) {
state = 1
}
}
' "$animations_md" > "$tmp_file" && mv "$tmp_file" "$animations_md"
echo "[pre_publish] updated content/animations.md with bulleted list"

# 3) Build README.md by inserting content files into blocks in content/about.md
about_md="$CONTENT_DIR/about.md"
readme_md="$REPO_ROOT/README.md"

awk \
-v hero="$CONTENT_DIR/hero_image.md" \
-v note="$CONTENT_DIR/note.md" \
-v badges="$CONTENT_DIR/badges.md" \
-v animsec="$CONTENT_DIR/animations.md" \
-v desk="$CONTENT_DIR/desk.md" \
-v circle="$CONTENT_DIR/circle.md" \
-v release="$CONTENT_DIR/release_info.md" \
-v slogan="$CONTENT_DIR/slogan.md" '
function print_file(path, line, opened) {
# Print file only if it exists and is readable.
if ((getline line < path) <= 0) { close(path); return }
print line
while ((getline line < path) > 0) print line
close(path)
}
{
if (skip) {
# Pass through until any END marker for safety (sections are not nested).
if ($0 ~ /<!--[[:space:]]*END[[:space:]]+[A-Z][A-Z ]*[[:space:]]*-->/) {
print
skip = 0
}
next
}

# Section handlers: print START, inject file content, then skip until END.
if ($0 ~ /<!--[[:space:]]*START[[:space:]]+HERO[[:space:]]+IMAGE[[:space:]]*-->/) { print; print_file(hero); skip=1; next }
if ($0 ~ /<!--[[:space:]]*START[[:space:]]+NOTE[[:space:]]*-->/) { print; print_file(note); skip=1; next }
if ($0 ~ /<!--[[:space:]]*START[[:space:]]+BADGES[[:space:]]*-->/) { print; print_file(badges); skip=1; next }
if ($0 ~ /<!--[[:space:]]*START[[:space:]]+ANIMATIONS[[:space:]]+SECTION[[:space:]]*-->/) { print; print_file(animsec); skip=1; next }
if ($0 ~ /<!--[[:space:]]*START[[:space:]]+DESK[[:space:]]*-->/) { print; print_file(desk); skip=1; next }
if ($0 ~ /<!--[[:space:]]*START[[:space:]]+CIRCLE[[:space:]]*-->/) { print; print_file(circle); skip=1; next }
if ($0 ~ /<!--[[:space:]]*START[[:space:]]+RELEASE[[:space:]]+INFO[[:space:]]*-->/) { print; print_file(release); skip=1; next }
if ($0 ~ /<!--[[:space:]]*START[[:space:]]+SLOGAN[[:space:]]*-->/) { print; print_file(slogan); skip=1; next }

print
}
' "$about_md" > "$readme_md"

echo "[pre_publish] generated README.md from content/about.md"

# 4) Update Table of Contents in README.md using doctoc (if available)
if command -v doctoc >/dev/null 2>&1; then
echo "[pre_publish] running doctoc on README.md"
doctoc --github "$readme_md" || echo "[pre_publish] doctoc encountered an error but continuing"
elif command -v npx >/dev/null 2>&1; then
echo "[pre_publish] running npx doctoc on README.md"
npx -y doctoc --github "$readme_md" || echo "[pre_publish] npx doctoc encountered an error but continuing"
else
echo "[pre_publish] doctoc not found. Skipping TOC update. Install with: npm i -g doctoc" >&2
fi

echo "[pre_publish] done."
15 changes: 7 additions & 8 deletions src/commands/shorten.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,14 @@ pub fn shorten(current_dir: &Path) -> Result<(), GrimoireCssError> {
}
} else if let Ok(Some(spell)) =
Spell::new(raw_spell, &config.shared_spells, &config.scrolls)
&& let Some(short) = get_shorten_component(&spell.component)
{
if let Some(short) = get_shorten_component(&spell.component) {
let short_spell = raw_spell.replacen(&spell.component, short, 1);
if raw_spell != &short_spell && new_content.contains(raw_spell) {
let count = new_content.matches(raw_spell).count();
new_content = new_content.replace(raw_spell, &short_spell);
replaced_any = true;
replaced_count += count;
}
let short_spell = raw_spell.replacen(&spell.component, short, 1);
if raw_spell != &short_spell && new_content.contains(raw_spell) {
let count = new_content.matches(raw_spell).count();
new_content = new_content.replace(raw_spell, &short_spell);
replaced_any = true;
replaced_count += count;
}
}
}
Expand Down
12 changes: 6 additions & 6 deletions src/core/css_generator/css_generator_base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -457,12 +457,12 @@ impl<'a> CssGenerator<'a> {
/// * `Ok(None)` - If no matching keyframes are found.
/// * `Err(GrimoireCSSError)` - If an error occurs during processing.
fn get_additional_css(&self, adapted_target: &str) -> Result<Option<String>, GrimoireCssError> {
if let Some(grimoire_animation_name) = Self::find_grimoire_animation_name(adapted_target) {
if let Some(animation) = ANIMATIONS.get(grimoire_animation_name) {
let (keyframes, _) =
self.get_keyframe_class_from_animation(animation, grimoire_animation_name)?;
return Ok(Some(keyframes));
}
if let Some(grimoire_animation_name) = Self::find_grimoire_animation_name(adapted_target)
&& let Some(animation) = ANIMATIONS.get(grimoire_animation_name)
{
let (keyframes, _) =
self.get_keyframe_class_from_animation(animation, grimoire_animation_name)?;
return Ok(Some(keyframes));
};

for adapted_target_item in adapted_target.split_whitespace() {
Expand Down
30 changes: 15 additions & 15 deletions src/core/parser/parser_base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,27 +56,27 @@ impl Parser {
match ch {
'(' | '[' | '{' => stack.push((ch, i)),
')' => {
if let Some((open, open_idx)) = stack.pop() {
if open == '(' {
keep[open_idx] = true;
keep[i] = true;
}
if let Some((open, open_idx)) = stack.pop()
&& open == '('
{
keep[open_idx] = true;
keep[i] = true;
}
}
']' => {
if let Some((open, open_idx)) = stack.pop() {
if open == '[' {
keep[open_idx] = true;
keep[i] = true;
}
if let Some((open, open_idx)) = stack.pop()
&& open == '['
{
keep[open_idx] = true;
keep[i] = true;
}
}
'}' => {
if let Some((open, open_idx)) = stack.pop() {
if open == '{' {
keep[open_idx] = true;
keep[i] = true;
}
if let Some((open, open_idx)) = stack.pop()
&& open == '{'
{
keep[open_idx] = true;
keep[i] = true;
}
}
_ => {}
Expand Down
8 changes: 4 additions & 4 deletions src/core/spell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,10 +221,10 @@ impl Spell {
let mut spells = Vec::with_capacity(css_classes.len());

for cs in css_classes {
if !shared_spells.contains(&cs) {
if let Some(spell) = Spell::new(&cs, shared_spells, scrolls)? {
spells.push(spell);
}
if !shared_spells.contains(&cs)
&& let Some(spell) = Spell::new(&cs, shared_spells, scrolls)?
{
spells.push(spell);
}
}

Expand Down
Loading