diff --git a/.github/workflows/firebase-hosting-merge.yml b/.github/workflows/firebase-hosting-merge.yml index 460544d0..e5484675 100644 --- a/.github/workflows/firebase-hosting-merge.yml +++ b/.github/workflows/firebase-hosting-merge.yml @@ -39,7 +39,7 @@ jobs: - uses: subosito/flutter-action@v2 with: flutter-version: ${{ steps.fvm-config-action.outputs.FLUTTER_VERSION }} - channel: ${{ steps.fvm-config-action.outputs.FLUTTER_CHANNEL }} + channel: stable - name: Align Melos SDK path run: | diff --git a/.github/workflows/firebase-hosting-pull-request.yml b/.github/workflows/firebase-hosting-pull-request.yml index 476533f6..dc239a44 100644 --- a/.github/workflows/firebase-hosting-pull-request.yml +++ b/.github/workflows/firebase-hosting-pull-request.yml @@ -38,7 +38,7 @@ jobs: - uses: subosito/flutter-action@v2 with: flutter-version: ${{ steps.fvm-config-action.outputs.FLUTTER_VERSION }} - channel: ${{ steps.fvm-config-action.outputs.FLUTTER_CHANNEL }} + channel: stable - name: Align Melos SDK path run: | diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 22b0a5bf..0a9a0a45 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -28,7 +28,7 @@ jobs: - uses: subosito/flutter-action@v2 with: flutter-version: ${{ steps.fvm-config-action.outputs.FLUTTER_VERSION }} - channel: ${{ steps.fvm-config-action.outputs.FLUTTER_CHANNEL }} + channel: stable - name: Align Melos SDK path run: | @@ -81,7 +81,7 @@ jobs: - uses: subosito/flutter-action@v2 with: flutter-version: ${{ steps.fvm-config-action.outputs.FLUTTER_VERSION }} - channel: ${{ steps.fvm-config-action.outputs.FLUTTER_CHANNEL }} + channel: stable - name: Align Melos SDK path run: | @@ -135,7 +135,7 @@ jobs: - uses: subosito/flutter-action@v2 with: flutter-version: ${{ steps.fvm-config-action.outputs.FLUTTER_VERSION }} - channel: ${{ steps.fvm-config-action.outputs.FLUTTER_CHANNEL }} + channel: stable - name: Align Melos SDK path run: | diff --git a/.planning/feature-templates.md b/.planning/feature-templates.md index 094d8c08..dd67918a 100644 --- a/.planning/feature-templates.md +++ b/.planning/feature-templates.md @@ -2,9 +2,9 @@ ## Executive Summary -Templates provide reusable **chrome configurations** (background, header, footer) bundled with **isolated style systems** for consistent slide presentation. Templates are like Keynote master slides - they define the visual frame and default styling, while users continue writing markdown content using `@section`/`@column` directives normally. +Templates provide reusable **chrome configurations** (background, header, footer) bundled with **isolated style systems** for consistent slide presentation. Templates are like Keynote master slides - they define the visual frame and default styling, while users continue writing markdown content using `@section`/`@block` directives normally. -**Key Principle:** Templates control the **decorative layer** (chrome + styling), not the content layout. The existing `@section`/`@column` system remains unchanged. +**Key Principle:** Templates control the **decorative layer** (chrome + styling), not the content layout. The existing `@section`/`@block` system remains unchanged. --- @@ -12,7 +12,7 @@ Templates provide reusable **chrome configurations** (background, header, footer ### 1. Template Scope: Chrome Only - **Chrome Elements:** Background, header, footer (via `SlideParts`) -- **NOT in scope:** Slot definitions, layout restructuring, replacing `@section`/`@column` +- **NOT in scope:** Slot definitions, layout restructuring, replacing `@section`/`@block` - **Rationale:** Keep templates simple, focused, and non-invasive to existing markdown authoring ### 2. Isolated Style Systems @@ -257,7 +257,7 @@ SlideConfiguration SlideView ├─ config.parts.background (from template or deck) ├─ config.parts.header (from template or deck) - ├─ @section/@column content (styled with config.style) + ├─ @section/@block content (styled with config.style) └─ config.parts.footer (from template or deck) ``` @@ -634,7 +634,7 @@ Available styles: announcement, quote, emphasis **1. Keep Templates Focused** - Templates should define chrome (visual frame) -- Let content flow naturally using `@section`/`@column` +- Let content flow naturally using `@section`/`@block` - Don't try to control content layout from templates **2. Provide Sensible Defaults** @@ -737,7 +737,7 @@ Available styles: announcement, quote, emphasis ## Open Questions (Resolved) ### ~~Q1: Slot mapping strategy?~~ -**Resolved:** Templates do NOT define slots. Users continue using `@section`/`@column` normally. Templates only affect chrome (background, header, footer). +**Resolved:** Templates do NOT define slots. Users continue using `@section`/`@block` normally. Templates only affect chrome (background, header, footer). ### ~~Q2: Template helper return type?~~ **Resolved:** Not applicable - templates are simple data classes, not helpers/builders. diff --git a/AGENTS.md b/AGENTS.md index a1cb8d37..47840ad4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -130,7 +130,7 @@ The project uses Signals for reactive state management. `DeckController` is the ### Block System Slides are composed of "blocks" defined by `@blockname` annotations in Markdown: -- `@column` - Layout columns +- `@block` - Markdown content blocks - `@image` - Image blocks - `@code` - Syntax-highlighted code - `@mermaid` - Mermaid diagrams diff --git a/README.md b/README.md index c30bc789..59df8410 100644 --- a/README.md +++ b/README.md @@ -55,10 +55,10 @@ Create a `slides.md` file in your project root. Separate slides with `---`. ```md --- -@column +@block # Welcome -@column +@block - Write slides in Markdown - Use blocks for layout diff --git a/demo/lib/src/templates.dart b/demo/lib/src/templates.dart index a918d7e3..e5ab365a 100644 --- a/demo/lib/src/templates.dart +++ b/demo/lib/src/templates.dart @@ -22,10 +22,7 @@ SlideTemplate corporateTemplate() { ), ), p: TextStyler().style( - TextStyleMix( - fontFamily: GoogleFonts.inter().fontFamily, - fontSize: 24, - ), + TextStyleMix(fontFamily: GoogleFonts.inter().fontFamily, fontSize: 24), ), ), styles: { @@ -107,10 +104,7 @@ class _CorporateHeader extends StatelessWidget implements PreferredSizeWidget { const Spacer(), Text( '${slide.slideIndex + 1}', - style: GoogleFonts.poppins( - fontSize: 16, - color: Colors.white38, - ), + style: GoogleFonts.poppins(fontSize: 16, color: Colors.white38), ), ], ), diff --git a/demo/showcase.md b/demo/showcase.md index 7b979935..2996f8ad 100644 --- a/demo/showcase.md +++ b/demo/showcase.md @@ -3,7 +3,7 @@ @section { flex: 2 } -@column { +@block { align: center } # SuperDeck {.heading} @@ -13,7 +13,7 @@ ## What is SuperDeck? {.heading} -@column +@block SuperDeck is a presentation framework that transforms how developers create slides. @@ -24,13 +24,13 @@ SuperDeck is a presentation framework that transforms how developers create slid --- -@column { +@block { flex: 2 align: centerLeft } ### Traditional Tools {.heading} -@column { +@block { flex: 3 } @@ -53,7 +53,7 @@ SuperDeck is a presentation framework that transforms how developers create slid @section { flex: 2 } -@column { +@block { align: center } ## "Write once, present anywhere. Version control everything." {.heading} @@ -62,7 +62,7 @@ SuperDeck is a presentation framework that transforms how developers create slid --- -@column { +@block { flex: 2 align: centerLeft } @@ -70,7 +70,7 @@ SuperDeck is a presentation framework that transforms how developers create slid Edit your slides and see changes instantly - no rebuild needed. -@column { +@block { flex: 3 } @@ -83,7 +83,7 @@ Edit your slides and see changes instantly - no rebuild needed. ### Markdown Syntax {.heading} -@column { +@block { flex: 2 } @@ -92,7 +92,7 @@ Edit your slides and see changes instantly - no rebuild needed. ## Slide Title {.heading} -@column +@block Your content here with **bold** and *italic* text. @@ -108,7 +108,7 @@ and *italic* text. @section -@column { +@block { flex: 1 } ## Layout System {.heading} @@ -120,7 +120,7 @@ How SuperDeck organizes content on slides. align: topLeft } -@column { +@block { flex: 1 } #### Sections @@ -133,7 +133,7 @@ Horizontal rows that divide the slide vertically. } ``` -@column { +@block { flex: 1 } #### Columns @@ -141,13 +141,13 @@ Horizontal rows that divide the slide vertically. Vertical divisions within sections. ```markdown -@column { +@block { flex: 3 align: center } ``` -@column { +@block { flex: 1 } #### Blocks @@ -164,7 +164,7 @@ Content containers with markdown or widgets. ## Layout Types {.heading} -@column +@block | Layout | Structure | Best For | |--------|-----------|----------| @@ -180,11 +180,11 @@ Content containers with markdown or widgets. ### The Block System {.heading} -@column +@block SuperDeck uses three core block types: -- **Content Blocks** (`@column`) - Render markdown text, lists, tables +- **Content Blocks** (`@block`) - Render markdown text, lists, tables - **Widget Blocks** (`@widget`) - Embed custom Flutter components - **Built-in Widgets** (`@image`, `@dartpad`, `@qrcode`) - Pre-configured widgets @@ -197,7 +197,7 @@ Each block supports: ### Build Pipeline {.heading} -@column +@block ```mermaid flowchart LR @@ -220,13 +220,13 @@ The CLI processes your markdown through multiple stages: --- -@column { +@block { flex: 2 align: centerLeft } ### Getting Started {.heading} -@column { +@block { flex: 3 } @@ -257,7 +257,7 @@ flutter run -d macos # or chrome, windows, linux flex: 3 } -@column { +@block { flex: 1 } @@ -272,7 +272,7 @@ styles: primaryColor: '#4CAF50' ``` -@column { +@block { flex: 1 } @@ -292,7 +292,7 @@ style: quote ## Advanced Features {.heading} -@column +@block - **Mermaid Diagrams** - Flowcharts, sequences, mind maps - **Code Highlighting** - Syntax-aware formatting @@ -306,7 +306,7 @@ style: quote @section { flex: 2 } -@column { +@block { align: center } ## "The best presentation tool is the one that gets out of your way." {.heading} @@ -324,7 +324,7 @@ style: quote @section -@column { +@block { align: center } MIT License | Flutter & Dart diff --git a/demo/slides.md b/demo/slides.md index ef2a9df4..a44e0985 100644 --- a/demo/slides.md +++ b/demo/slides.md @@ -3,7 +3,7 @@ @section { flex: 2 } -@column { +@block { align: center } # SuperDeck {.heading} @@ -11,14 +11,14 @@ --- -@column { +@block { align: center } #### Leo Farias {.heading} #### @leoafarias {.subheading} -@column { +@block { align: centerLeft } - Founder/CEO/CTO @@ -30,7 +30,7 @@ ## What is SuperDeck? {.heading} -@column +@block - Write slides in **Markdown** - Render with **Flutter** @@ -39,14 +39,14 @@ --- -@column -@column { +@block +@block { flex: 5 align: center } ### A developer-first presentation framework that combines the simplicity of Markdown with the power of Flutter. {.heading} -@column +@block --- @@ -54,7 +54,7 @@ @section -@column { +@block { align: topCenter } ```mermaid @@ -82,7 +82,7 @@ mindmap ### Markdown-First {.heading} -@column +@block Write your presentations in familiar Markdown syntax: @@ -100,22 +100,22 @@ SuperDeck supports flexible layouts using sections and columns. --- -@column { +@block { flex: 2 align: centerRight } ### Two Columns {.heading} -@column { +@block { flex: 3 } ```markdown -@column { +@block { flex: 2 } Left content here -@column { +@block { flex: 3 } Right content here @@ -124,7 +124,7 @@ Right content here --- @section -@column { +@block { align: center } ### Top Section @@ -132,13 +132,13 @@ Right content here @section { flex: 2 } -@column { +@block { align: center } ### Middle Section (flex: 2) @section -@column { +@block { align: center } ### Bottom Section @@ -147,7 +147,7 @@ Right content here ### Code Blocks {.heading} -@column { +@block { flex: 2 } @@ -171,7 +171,7 @@ void main() { ### Mermaid Diagrams {.heading} -@column +@block ```mermaid flowchart LR @@ -187,7 +187,7 @@ flowchart LR ### Sequence Diagrams {.heading} -@column +@block ```mermaid sequenceDiagram @@ -205,7 +205,7 @@ sequenceDiagram ## Custom Widgets {.heading} -@column +@block Embed interactive Flutter widgets directly in your slides! @@ -213,7 +213,7 @@ Embed interactive Flutter widgets directly in your slides! ### Mix Box Example {.heading} -@column { +@block { flex: 2 } @@ -221,7 +221,7 @@ Embed interactive Flutter widgets directly in your slides! @mix-simple-box ``` -@column { +@block { flex: 3 align: center } @@ -232,13 +232,13 @@ Embed interactive Flutter widgets directly in your slides! ### Interactive Variants {.heading} -@column { +@block { flex: 2 } Hover and press interactions using Mix variants. -@column { +@block { flex: 3 align: center } @@ -249,13 +249,13 @@ Hover and press interactions using Mix variants. ### Remix Buttons {.heading} -@column { +@block { flex: 2 } Design system components with Remix. -@column { +@block { flex: 3 align: center } @@ -266,13 +266,13 @@ Design system components with Remix. ### Animations {.heading} -@column { +@block { flex: 2 } Implicit and keyframe animations with Mix. -@column { +@block { flex: 3 align: center } @@ -283,13 +283,13 @@ Implicit and keyframe animations with Mix. ## Styling Options {.heading} -@column +@block SuperDeck supports custom themes and per-slide styling. --- -@column { +@block { scrollable: true } @@ -313,7 +313,7 @@ styles: ### Per-Slide Styles -@column +@block ```markdown --- @@ -333,7 +333,7 @@ style: quote ## Architecture {.heading} -@column +@block ```mermaid graph TB @@ -365,7 +365,7 @@ graph TB ## Getting Started {.heading} -@column { +@block { flex: 2 } @@ -374,7 +374,7 @@ graph TB 3. Run the CLI 4. Present! -@column { +@block { flex: 3 } @@ -393,7 +393,7 @@ flutter run ### Project Structure {.heading} -@column +@block ``` my_presentation/ @@ -408,7 +408,7 @@ my_presentation/ ## Export Options {.heading} -@column +@block - **PDF Export** - Generate PDF for sharing - **Thumbnails** - Auto-generated slide previews @@ -416,8 +416,8 @@ my_presentation/ --- -@column -@column { +@block +@block { flex: 3 align: center } @@ -429,13 +429,13 @@ my_presentation/ - Hot reload while editing - Cross-platform output -@column +@block --- ## Slide Templates {.heading} -@column +@block Templates bundle **chrome** (header, footer, background) with an **isolated style system** — like Keynote master slides. @@ -443,7 +443,7 @@ Templates bundle **chrome** (header, footer, background) with an **isolated styl template: corporate --- -@column { +@block { align: center } # Corporate Template {.heading} @@ -455,7 +455,7 @@ template: corporate style: highlight --- -@column { +@block { align: center } # Highlight Style {.heading} @@ -466,7 +466,7 @@ Templates can have their own named style variants. template: minimal --- -@column { +@block { align: center } # Minimal Template {.heading} @@ -486,7 +486,7 @@ Leo Farias @leoafarias (GitHub, Twitter/X) -@column +@block #### Source Code https://github.com/leoafarias/superdeck diff --git a/docs/examples.mdx b/docs/examples.mdx index 1041734f..2f8740d3 100644 --- a/docs/examples.mdx +++ b/docs/examples.mdx @@ -18,7 +18,7 @@ Use this for opening slides, section dividers, or any slide where you want the t flex: 2 } -@column { +@block { align: center } @@ -40,18 +40,18 @@ Use this for comparisons, pros/cons lists, or showing two related concepts side- ```markdown @section -@column { +@block { flex: 2 align: centerLeft } ### Generative UI -@column +@block ### VS -@column { +@block { flex: 2 } @@ -72,7 +72,7 @@ Use this for comparisons, pros/cons lists, or showing two related concepts side- Use this when demonstrating code snippets, API usage, or implementation details. ````markdown -@column +@block ```dart Column( @@ -99,7 +99,7 @@ Column( ### Complex schema definition ````markdown -@column +@block ```dart final schema = Schema.object(properties: { @@ -128,7 +128,7 @@ final schema = Schema.object(properties: { ### Image with cover fit ```markdown -@column +@block ![Screenshot](https://picsum.photos/800/1400) {.cover} @@ -145,7 +145,7 @@ final schema = Schema.object(properties: { ````markdown @section -@column +@block ```mermaid graph TD @@ -155,7 +155,7 @@ graph TD D --> E[End] ``` -@column +@block ![Screenshot](https://picsum.photos/800/1400) {.cover} @@ -172,7 +172,7 @@ graph TD ### DartPad integration ```markdown -@column +@block ![Screenshot](https://picsum.photos/800/1400) {.cover} @@ -182,7 +182,7 @@ graph TD run: true } -@column +@block ## Interactive Demo @@ -222,7 +222,7 @@ graph TD flex: 2 } -@column { +@block { align: center flex: 1 } @@ -241,7 +241,7 @@ Column( ) ``` -@column +@block ![Screenshot](https://picsum.photos/800/1400) {.cover} @@ -258,14 +258,14 @@ Column( ```markdown @section -@column { +@block { align: centerRight } #### Leo Farias @leoafarias -@column { +@block { align: centerLeft } @@ -287,7 +287,7 @@ Column( ### GitHub-style alerts ```markdown -@column { +@block { align: centerLeft flex: 2 } @@ -324,10 +324,10 @@ Column( ```markdown @section -@column +@block Try the interactive counter: -@column +@block @widget { name: "counter" @@ -347,7 +347,7 @@ Try the interactive counter: ### Process flow ````markdown -@column +@block ```mermaid graph TD @@ -398,7 +398,7 @@ void main() { ### Feature announcement ```markdown -@column { +@block { flex: 3 align: center } @@ -409,7 +409,7 @@ void main() { Built for any screen: Ideal for generating adaptive UIs across devices and platforms. -@column +@block --- ``` @@ -419,11 +419,11 @@ adaptive UIs across devices and platforms. ````markdown @section -@column +@block ### Structured Output -@column +@block ```dart final schema = Schema.array( diff --git a/docs/getting-started.mdx b/docs/getting-started.mdx index d53bfc5f..ea40d25a 100644 --- a/docs/getting-started.mdx +++ b/docs/getting-started.mdx @@ -92,13 +92,13 @@ Create beautiful presentations using: @section -@column +@block ### Left Column - Point one - Point two - Point three -@column +@block ### Right Column ![Flutter Logo](https://storage.googleapis.com/cms-storage-bucket/4fd5520fe28ebf839174.svg) diff --git a/docs/guides/markdown-authoring.mdx b/docs/guides/markdown-authoring.mdx index e65f4fa7..c0855e37 100644 --- a/docs/guides/markdown-authoring.mdx +++ b/docs/guides/markdown-authoring.mdx @@ -18,7 +18,7 @@ A basic slide with a title and content: title: My First Slide --- -@column +@block # Welcome to SuperDeck @@ -51,7 +51,7 @@ style: overview Use these block types when you compose slides: - `@section` for horizontal layout containers. -- `@column` for markdown content. +- `@block` for markdown content. - `@widget` for custom Flutter widgets. For the full syntax and argument reference, see the [Markdown syntax reference](../reference/markdown-syntax). @@ -71,12 +71,12 @@ Groups blocks horizontally. Use sections to create multi-column layouts. } ```` -### `@column` +### `@block` Renders markdown content. Most slides use one or more columns. ````markdown -@column { +@block { flex: 2 align: topLeft } @@ -154,7 +154,7 @@ The widget name becomes the block type (`@metricCard`), and all properties are p Use headings, lists, tables, and code blocks as you normally would: ````markdown -@column +@block # Slide Title diff --git a/docs/guides/superdeck-overview.mdx b/docs/guides/superdeck-overview.mdx index a2806cbd..2385ff52 100644 --- a/docs/guides/superdeck-overview.mdx +++ b/docs/guides/superdeck-overview.mdx @@ -32,14 +32,14 @@ SuperDeck uses a powerful `@block` syntax for organizing slide content into flex flex: 2 } -@column { +@block { align: center } # Welcome to SuperDeck Build presentations with Markdown and Flutter -@column { +@block { align: center flex: 1 } @@ -50,7 +50,7 @@ Build presentations with Markdown and Flutter **Core block types** - `@section` – multi-column container with configurable flex ratios -- `@column` – display markdown content with alignment and scrolling +- `@block` – display markdown content with alignment and scrolling - `@widget` – custom registered Flutter widgets **Built-in widgets** (use shorthand syntax like `@image { ... }`): diff --git a/docs/index.mdx b/docs/index.mdx index 27373984..3b5a39c3 100644 --- a/docs/index.mdx +++ b/docs/index.mdx @@ -25,7 +25,7 @@ SuperDeck is a Flutter presentation framework that combines Markdown simplicity ## Core features -- **3 Block Types** - `@column` (content), `@section` (layout), `@widget` (custom components) +- **3 Block Types** - `@block` (content), `@section` (layout), `@widget` (custom components) - **Built-in Widgets** - `image`, `dartpad`, `qrcode` - **Mermaid Diagrams** - Use ` ```mermaid` code blocks (rendered to images at build time) - **CLI Commands** - `setup`, `build`, `publish`, `version` diff --git a/docs/reference/block-types.mdx b/docs/reference/block-types.mdx index 85757048..4a9ed36e 100644 --- a/docs/reference/block-types.mdx +++ b/docs/reference/block-types.mdx @@ -29,12 +29,12 @@ Controls relative sizing (`flex: 2` takes twice the space of `flex: 1`). Enables scrolling for overflow content. -## @column +## @block Renders markdown content. ```markdown -@column { +@block { align: center flex: 2 scrollable: true @@ -60,10 +60,10 @@ Arranges child blocks horizontally. flex: 1 } -@column +@block Left content -@column +@block Right content ``` @@ -76,13 +76,13 @@ Use for multi-column layouts and side-by-side content. ```markdown @section -@column +@block Column 1 -@column +@block Column 2 -@column +@block Column 3 ``` @@ -228,7 +228,7 @@ graph TD **Centered content:** ```markdown -@column { +@block { align: center } ``` @@ -237,11 +237,11 @@ graph TD ```markdown @section -@column { +@block { flex: 1 } -@column { +@block { flex: 1 } ``` @@ -275,7 +275,7 @@ graph TD ## Best practices -1. Use `@column` for most content +1. Use `@block` for most content 2. Combine blocks in `@section` for rich layouts 3. Set explicit image dimensions to prevent shifts 4. Test DartPad IDs before presenting diff --git a/docs/reference/markdown-syntax.mdx b/docs/reference/markdown-syntax.mdx index 7adfe597..3d637bde 100644 --- a/docs/reference/markdown-syntax.mdx +++ b/docs/reference/markdown-syntax.mdx @@ -34,7 +34,7 @@ SuperDeck supports three core block types. | Block | Purpose | Key properties | |---|---|---| | `@section` | Container for horizontal layout | `flex`, `align`, `scrollable` | -| `@column` | Render markdown content | `flex`, `align`, `scrollable` | +| `@block` | Render markdown content | `flex`, `align`, `scrollable` | | `@widget` | Embed custom Flutter widgets | `name` + custom args | Built-in widgets (`image`, `dartpad`, `qrcode`) use the same widget syntax as `@widget`. diff --git a/docs/tutorials/block-layouts.mdx b/docs/tutorials/block-layouts.mdx index d76dd542..a27e197f 100644 --- a/docs/tutorials/block-layouts.mdx +++ b/docs/tutorials/block-layouts.mdx @@ -18,7 +18,7 @@ Blocks automatically arrange themselves: ## Common blocks ```markdown -@column # Markdown content (most common) +@block # Markdown content (most common) @section # Container for horizontal layouts @image # Images with fit options @dartpad # Interactive code examples @@ -41,10 +41,10 @@ More content below. ```markdown @section -@column +@block Left side content -@column +@block Right side content ``` @@ -52,12 +52,12 @@ Right side content ```markdown @section -@column { +@block { flex: 2 } Takes 2/3 of the space -@column { +@block { flex: 1 } Takes 1/3 of the space @@ -67,7 +67,7 @@ Takes 1/3 of the space ```markdown @section -@column +@block ## Text Content - Point one - Point two @@ -87,7 +87,7 @@ All blocks support these properties: - **`scrollable`** - Enable scrolling (default: false) ```markdown -@column { +@block { flex: 2 align: center scrollable: true @@ -100,7 +100,7 @@ All blocks support these properties: ```markdown @section -@column { +@block { align: center } # Big Title @@ -111,13 +111,13 @@ All blocks support these properties: ```markdown @section -@column { +@block { flex: 2 } ## Feature Description Detailed explanation... -@column +@block ![Feature Screenshot](image.png) ``` @@ -125,19 +125,19 @@ Detailed explanation... ```markdown @section -@column +@block ### Option A -@column +@block ### Option B -@column +@block ### Option C ``` ## Key takeaways -- Start with `@column` blocks +- Start with `@block` blocks - Use `@section` for side-by-side layouts - Control sizing with `flex` - Mix content types freely diff --git a/docs/tutorials/first-presentation.mdx b/docs/tutorials/first-presentation.mdx index 9f2b238e..c0a0d295 100644 --- a/docs/tutorials/first-presentation.mdx +++ b/docs/tutorials/first-presentation.mdx @@ -32,7 +32,7 @@ title: Flutter Development Essentials @section -@column { +@block { align: center } @@ -61,7 +61,7 @@ Add slides introducing Flutter concepts: @section -@column { +@block { flex: 2 } @@ -72,7 +72,7 @@ Flutter is Google's **UI toolkit** for building natively compiled applications f - 🖥️ Desktop (Windows, macOS, Linux) - 📺 Embedded devices -@column +@block ![Flutter Architecture](https://docs.flutter.dev/assets/images/docs/arch-overview/archdiagram.png) @@ -86,7 +86,7 @@ Flutter is Google's **UI toolkit** for building natively compiled applications f @section -@column +@block ### ⚡ Performance - Native performance @@ -98,7 +98,7 @@ Flutter is Google's **UI toolkit** for building natively compiled applications f - Cupertino widgets - Custom styling -@column +@block ### 🔥 Hot Reload - Instant updates @@ -122,7 +122,7 @@ Include syntax-highlighted code: @section -@column +@block Here's a simple Flutter app: @@ -148,7 +148,7 @@ class MyApp extends StatelessWidget { } ``` -@column +@block ### Key Concepts: - **Widgets** - Everything is a widget @@ -168,7 +168,7 @@ Add a DartPad for live coding: @section -@column +@block Experiment with this Flutter code: @@ -176,7 +176,7 @@ Experiment with this Flutter code: - Change colors - Add more widgets -@column { +@block { flex: 2 } @@ -198,7 +198,7 @@ Replace `your_dartpad_id` with an ID from [dartpad.dev](https://dartpad.dev). @section -@column +@block ### Popular Apps Built with Flutter: @@ -224,7 +224,7 @@ Replace `your_dartpad_id` with an ID from [dartpad.dev](https://dartpad.dev). @section -@column { +@block { align: center } @@ -256,7 +256,7 @@ title: Flutter Development Essentials @section -@column { +@block { align: center } @@ -272,7 +272,7 @@ title: Flutter Development Essentials @section -@column { +@block { flex: 2 } @@ -283,7 +283,7 @@ Flutter is Google's **UI toolkit** for building natively compiled applications f - Desktop (Windows, macOS, Linux) - Embedded devices -@column +@block ![Flutter Architecture](https://docs.flutter.dev/assets/images/docs/arch-overview/archdiagram.png) @@ -293,7 +293,7 @@ Flutter is Google's **UI toolkit** for building natively compiled applications f @section -@column +@block ### Performance - Native performance @@ -305,7 +305,7 @@ Flutter is Google's **UI toolkit** for building natively compiled applications f - Cupertino widgets - Custom styling -@column +@block ### Hot Reload - Instant updates @@ -323,7 +323,7 @@ Flutter is Google's **UI toolkit** for building natively compiled applications f @section -@column { +@block { align: center } diff --git a/packages/builder/lib/src/parsers/block_parser.dart b/packages/builder/lib/src/parsers/block_parser.dart index f8b9c6b0..a1c49275 100644 --- a/packages/builder/lib/src/parsers/block_parser.dart +++ b/packages/builder/lib/src/parsers/block_parser.dart @@ -14,29 +14,20 @@ class ParsedBlock { }) : _data = data; Map get data { - // Normalize legacy @column to the current ContentBlock key. - final normalizedType = - type == ContentBlock.legacyKey || type == ContentBlock.key - ? ContentBlock.key - : type; - - return switch (normalizedType) { + return switch (type) { SectionBlock.key || ContentBlock.key || - WidgetBlock.key => {..._data, 'type': normalizedType}, + WidgetBlock.key => {..._data, 'type': type}, _ => {..._data, 'name': type, 'type': WidgetBlock.key}, }; } } -/// Parses build-time layout directives (@section, @column, @block) with YAML-style options. +/// Parses build-time layout directives (@section, @block) with YAML-style options. /// /// Extracts custom directives like: /// - `@section` or `@section{flex: 1}` -/// - `@column{align: center, flex: 2}` or `@block{align: center, flex: 2}` -/// -/// Both `@column` and `@block` tags create [ContentBlock] instances. -/// The `@column` tag is legacy and normalized to `@block` for backward compatibility. +/// - `@block{align: center, flex: 2}` /// /// **Why regex instead of markdown package BlockSyntax?** /// - These are build-time directives, not markdown syntax @@ -52,15 +43,21 @@ class BlockParser { List parse(String text) { final tokens = const TagTokenizer().tokenize(text); - return tokens - .map( - (token) => ParsedBlock( - type: token.name, - data: token.options, - startIndex: token.startIndex, - endIndex: token.endIndex, - ), - ) - .toList(); + return tokens.map((token) { + if (token.name == 'column') { + throw DeckFormatException( + 'Unsupported @column directive. Use @block instead.', + text, + token.startIndex, + ); + } + + return ParsedBlock( + type: token.name, + data: token.options, + startIndex: token.startIndex, + endIndex: token.endIndex, + ); + }).toList(); } } diff --git a/packages/builder/lib/src/parsers/markdown_parser.dart b/packages/builder/lib/src/parsers/markdown_parser.dart index d5833c67..763ac75c 100644 --- a/packages/builder/lib/src/parsers/markdown_parser.dart +++ b/packages/builder/lib/src/parsers/markdown_parser.dart @@ -29,7 +29,7 @@ String _uniquifyKey( /// runtime by flutter_markdown_plus, not during the build phase. /// /// See also: -/// - [SectionParser] - Stage 2: Parses @section/@column directives into layout structure +/// - [SectionParser] - Stage 2: Parses @section/@block directives into layout structure class MarkdownParser { const MarkdownParser(); diff --git a/packages/builder/lib/src/parsers/section_parser.dart b/packages/builder/lib/src/parsers/section_parser.dart index 909cbf32..2af6a270 100644 --- a/packages/builder/lib/src/parsers/section_parser.dart +++ b/packages/builder/lib/src/parsers/section_parser.dart @@ -4,13 +4,13 @@ import 'block_parser.dart'; /// Stage 2 of 3-stage parsing: Converts slide markdown into structured layout. /// -/// Parses custom @section/@column directives to create a tree of [SectionBlock] +/// Parses custom @section/@block directives to create a tree of [SectionBlock] /// objects representing the slide's layout structure. This is build-time processing /// specific to SuperDeck's layout DSL. /// /// See also: /// - [MarkdownParser] - Stage 1: Splits presentation into slides -/// - [BlockParser] - Parses individual @section/@column directives +/// - [BlockParser] - Parses individual @section/@block directives class SectionParser { const SectionParser(); diff --git a/packages/builder/test/src/parsers/block_parser_test.dart b/packages/builder/test/src/parsers/block_parser_test.dart index 15cc7d4f..be776c04 100644 --- a/packages/builder/test/src/parsers/block_parser_test.dart +++ b/packages/builder/test/src/parsers/block_parser_test.dart @@ -345,11 +345,11 @@ Test content 2 ), ], }, - // does not match {@column} + // does not match {@block} { - 'description': 'Test Case 10: Does not match @column', + 'description': 'Test Case 10: Does not match @block', 'input': ''' -{@column} +{@block} ''', 'expectedBlocks': [], }, @@ -448,7 +448,7 @@ void main() { ); }); - test('normalizes @block tag to ContentBlock key', () { + test('@block produces a ContentBlock', () { const text = ''' @block Some markdown content @@ -464,30 +464,29 @@ More content expect(blocks.length, 2); - // First @block block - expect(blocks[0].type, 'block'); // Original type - expect(blocks[0].data['type'], 'block'); // Normalized to ContentBlock.key - - // Second @block block with options + expect(blocks[0].type, 'block'); + expect(blocks[0].data['type'], 'block'); expect(blocks[1].type, 'block'); expect(blocks[1].data['type'], 'block'); expect(blocks[1].data['align'], 'center'); expect(blocks[1].data['flex'], 2); }); - test('both @column and @block produce same ContentBlock type', () { - const textColumn = '@column{flex: 1}'; - const textBlock = '@block{flex: 1}'; - - final blocksColumn = const BlockParser().parse(textColumn); - final blocksBlock = const BlockParser().parse(textBlock); + test('rejects legacy @column directives', () { + const text = '@column{flex: 1}'; - expect(blocksColumn[0].data['type'], blocksBlock[0].data['type']); expect( - blocksColumn[0].data['type'], - 'block', - ); // Both normalize to ContentBlock.key - expect(blocksColumn[0].data['flex'], blocksBlock[0].data['flex']); + () => const BlockParser().parse(text), + throwsA( + isA() + .having( + (e) => e.message, + 'message', + contains('Unsupported @column directive'), + ) + .having((e) => e.offset, 'offset', 0), + ), + ); }); }); } diff --git a/packages/builder/test/src/parsers/section_parser_test.dart b/packages/builder/test/src/parsers/section_parser_test.dart index 1d1c9385..6dadb776 100644 --- a/packages/builder/test/src/parsers/section_parser_test.dart +++ b/packages/builder/test/src/parsers/section_parser_test.dart @@ -1,4 +1,3 @@ -import 'package:superdeck_builder/src/parsers/section_parser.dart'; import 'package:superdeck_builder/superdeck_builder.dart'; import 'package:superdeck_core/superdeck_core.dart'; import 'package:test/test.dart'; @@ -38,10 +37,10 @@ void main() { @section # Title -@column +@block content column 1. -@column +@block content column 2. '''; @@ -67,10 +66,10 @@ content column 2. test('Only columns without sections', () { const markdown = ''' -@column +@block Content column 1. -@column +@block Content column 2. '''; @@ -81,6 +80,24 @@ Content column 2. expect(sections[0].blocks[1].content.trim(), 'Content column 2.'); }); + test('Legacy @column directives fail loudly', () { + const markdown = ''' +@column +Legacy content. +'''; + + expect( + () => sectionParser.parse(markdown), + throwsA( + isA().having( + (e) => e.message, + 'message', + contains('Unsupported @column directive'), + ), + ), + ); + }); + test('Columns then sections', () { const markdown = ''' # Regular Markdown @@ -90,7 +107,7 @@ This is some regular markdown content. @section ## Header Title -@column +@block Content inside the header. '''; @@ -116,18 +133,18 @@ Content inside the header. @section # Header Title -@column +@block Header content column. @section -@column +@block Body content column 1. -@column +@block Body content column 2. @section -@column +@block Footer content column. '''; @@ -151,12 +168,12 @@ Footer content column. test('Header with columns and flex attribute', () { const markdown = ''' @section -@column{ +@block{ flex: 1 } Header content column 1. -@column{ +@block{ flex: 2 } Header content column 2. @@ -188,12 +205,12 @@ Header content column 2. test('Section with columns and alignment attribute', () { const markdown = ''' @section -@column{ +@block{ align: center } Body content column 1. -@column{ +@block{ align: bottomRight } Body content column 2. @@ -214,12 +231,12 @@ Body content column 2. test('Section with columns, flex, and alignment attributes', () { const markdown = ''' @section -@column{ +@block{ flex: 3 align: topLeft } Footer content column 1. -@column{ +@block{ flex: 1 align: centerRight } @@ -251,27 +268,27 @@ Footer content column 2. test('Sections with columns and attributes', () { const markdown = ''' @section -@column{ +@block{ flex: 1 align: center } Header content. @section -@column{ +@block{ flex: 2 align: centerLeft } Body content column 1. -@column{ +@block{ flex: 1 align: centerRight } Body content column 2. @section -@column{ +@block{ flex: 1 align: bottomCenter } @@ -316,14 +333,14 @@ Footer content. test('Columns inherit options from the parent', () { const markdown = ''' @section {align: center} -@column +@block Header content. @section{ align: topLeft flex: 2 } -@column{ +@block{ flex: 3 } Body content. @@ -332,7 +349,7 @@ Body content. align: bottomRight flex: 1 } -@column{ align: bottomRight} +@block{ align: bottomRight} Footer content. '''; @@ -383,7 +400,7 @@ Footer content. test('Invalid flex attribute format', () { const markdown = ''' @section -@column{ flex: invalid} +@block{ flex: invalid} Header content. '''; @@ -397,7 +414,7 @@ Header content. test('Invalid alignment attribute value', () { const markdown = ''' @section -@column{ +@block{ align: invalid_alignment } Header content. diff --git a/packages/builder/test/src/parsers/tag_tokenizer_test.dart b/packages/builder/test/src/parsers/tag_tokenizer_test.dart index 9c072ad3..4a63fe16 100644 --- a/packages/builder/test/src/parsers/tag_tokenizer_test.dart +++ b/packages/builder/test/src/parsers/tag_tokenizer_test.dart @@ -97,14 +97,14 @@ class User { } ``` -@column +@block '''; final tokens = const TagTokenizer().tokenize(text); expect(tokens, hasLength(2)); expect(tokens[0].name, 'section'); - expect(tokens[1].name, 'column'); + expect(tokens[1].name, 'block'); // @AckType should be ignored because it's inside the code block }); diff --git a/packages/builder/test/src/slide_processor_test.dart b/packages/builder/test/src/slide_processor_test.dart index 8613ae10..50bd4ac2 100644 --- a/packages/builder/test/src/slide_processor_test.dart +++ b/packages/builder/test/src/slide_processor_test.dart @@ -415,7 +415,7 @@ void main() { @section # Header -@column +@block Column content ''', 'frontmatter': {}, @@ -549,7 +549,7 @@ Symbols: ← → ↑ ↓ @section Normal section -@column +@block Normal column Some content without tag @@ -696,13 +696,13 @@ More content. @section ## Section 1 -@column{ +@block{ flex: 1 align: center } Column 1 content -@column{ +@block{ flex: 2 align: topLeft } diff --git a/packages/cli/lib/src/commands/publish_command.dart b/packages/cli/lib/src/commands/publish_command.dart index 36e2a1c1..899f600a 100644 --- a/packages/cli/lib/src/commands/publish_command.dart +++ b/packages/cli/lib/src/commands/publish_command.dart @@ -648,11 +648,7 @@ class PublishCommand extends Command { if (worktreeCreated && tempDir != null) { try { final removeWorktreeArgs = ['worktree', 'remove', '--force', tempDir]; - await _runGitCommand( - currentDir, - removeWorktreeArgs, - dryRun: dryRun, - ); + await _runGitCommand(currentDir, removeWorktreeArgs, dryRun: dryRun); } catch (e) { _logger.warn('Failed to clean up temporary git worktree: $e'); } diff --git a/packages/cli/lib/src/commands/setup_command.dart b/packages/cli/lib/src/commands/setup_command.dart index 4a5c7fc6..6194dd52 100644 --- a/packages/cli/lib/src/commands/setup_command.dart +++ b/packages/cli/lib/src/commands/setup_command.dart @@ -46,13 +46,13 @@ class SetupCommand extends SuperDeckCommand { try { const content = '''--- -@column +@block # Welcome to SuperDeck Your awesome slides start here! -@column +@block - Create beautiful slides using markdown - Arrange content using the block-based system @@ -60,14 +60,14 @@ Your awesome slides start here! --- -@column +@block ## Example of a multi-column slide - This content appears in the left column - Add more items here -@column { +@block { align: centerRight } @@ -77,7 +77,7 @@ This content appears in the right column. --- -@column { +@block { align: center } diff --git a/packages/core/lib/src/deck_configuration.dart b/packages/core/lib/src/deck_configuration.dart index b4d2eaf4..5f8dc5fd 100644 --- a/packages/core/lib/src/deck_configuration.dart +++ b/packages/core/lib/src/deck_configuration.dart @@ -28,9 +28,8 @@ final class DeckConfiguration with DeckConfigurationMappable { String get _assets => assetsPath ?? 'assets'; String get _slides => slidesPath ?? 'slides.md'; - late final superdeckDir = Directory( - p.normalize(p.join(_baseDir, _outputDir)), - ); + Directory get superdeckDir => + Directory(p.normalize(p.join(_baseDir, _outputDir))); File get deckJson => File(p.join(superdeckDir.path, 'superdeck.json')); File get deckFullJson => diff --git a/packages/core/lib/src/models/block_model.dart b/packages/core/lib/src/models/block_model.dart index 2d63a4b7..3e835fc0 100644 --- a/packages/core/lib/src/models/block_model.dart +++ b/packages/core/lib/src/models/block_model.dart @@ -1,15 +1,13 @@ import 'package:dart_mappable/dart_mappable.dart'; import 'package:superdeck_core/superdeck_core.dart'; -import 'mappers.dart'; - part 'block_model.mapper.dart'; /// Base class for all content blocks in a slide. /// /// Blocks are the fundamental building units of slide content. They can be /// arranged in sections and support alignment, flexible sizing, and scrolling. -@MappableClass(discriminatorKey: 'type', hook: BlockDiscriminatorHook()) +@MappableClass(discriminatorKey: 'type') sealed class Block with BlockMappable { /// The type identifier for this block. final String type; @@ -52,7 +50,6 @@ sealed class Block with BlockMappable { discriminatorKey: 'type', schemas: { ContentBlock.key: ContentBlock.schema, - ContentBlock.legacyKey: ContentBlock.schema, // Backward compatibility WidgetBlock.key: WidgetBlock.schema, }, ); @@ -63,7 +60,7 @@ sealed class Block with BlockMappable { final type = map['type'] as String; return switch (type) { SectionBlock.key => SectionBlock.fromMap(map), - ContentBlock.key || ContentBlock.legacyKey => ContentBlock.fromMap(map), + ContentBlock.key => ContentBlock.fromMap(map), WidgetBlock.key => WidgetBlock.fromMap(map), _ => throw ArgumentError('Unknown block type: $type'), }; @@ -118,7 +115,7 @@ class SectionBlock extends Block with SectionBlockMappable { static SectionBlock parse(Map map) => fromMap(schema.parse(map)!); - /// Creates a section block with a single text column. + /// Creates a section block with a single text block. static SectionBlock text(String content) { return SectionBlock([ContentBlock(content)]); } @@ -143,9 +140,6 @@ class ContentBlock extends Block with ContentBlockMappable { /// The type identifier for content blocks. static const key = 'block'; - /// Legacy key for backward compatibility with existing slides. - static const legacyKey = 'column'; - /// The markdown content to display. final String content; @@ -165,6 +159,11 @@ class ContentBlock extends Block with ContentBlockMappable { } static ContentBlock fromMap(Map map) { + final type = map['type']; + if (type != null && type != key) { + throw ArgumentError('Unknown block type: $type'); + } + return ContentBlock( map['content'] as String?, align: map['align'] != null @@ -177,6 +176,7 @@ class ContentBlock extends Block with ContentBlockMappable { /// Validation schema for content blocks. static final schema = Ack.object({ + 'type': Ack.literal(key).optional(), 'align': ContentAlignment.schema.optional(), 'flex': Ack.integer().optional(), 'scrollable': Ack.boolean().optional(), diff --git a/packages/core/lib/src/models/block_model.mapper.dart b/packages/core/lib/src/models/block_model.mapper.dart index 518edd06..74cd376d 100644 --- a/packages/core/lib/src/models/block_model.mapper.dart +++ b/packages/core/lib/src/models/block_model.mapper.dart @@ -243,8 +243,6 @@ class BlockMapper extends ClassMapperBase { #scrollable: _f$scrollable, }; - @override - final MappingHook hook = const BlockDiscriminatorHook(); static Block _instantiate(DecodingData data) { throw MapperException.missingSubclass( 'Block', @@ -340,9 +338,6 @@ class SectionBlockMapper extends SubClassMapperBase { @override late final ClassMapperBase superMapper = BlockMapper.ensureInitialized(); - @override - final MappingHook superHook = const BlockDiscriminatorHook(); - static SectionBlock _instantiate(DecodingData data) { return SectionBlock( data.dec(_f$blocks), @@ -520,9 +515,6 @@ class ContentBlockMapper extends SubClassMapperBase { @override late final ClassMapperBase superMapper = BlockMapper.ensureInitialized(); - @override - final MappingHook superHook = const BlockDiscriminatorHook(); - static ContentBlock _instantiate(DecodingData data) { return ContentBlock( data.dec(_f$content), @@ -698,9 +690,6 @@ class WidgetBlockMapper extends SubClassMapperBase { @override final MappingHook hook = const UnmappedPropertiesHook('args'); - @override - final MappingHook superHook = const BlockDiscriminatorHook(); - static WidgetBlock _instantiate(DecodingData data) { return WidgetBlock( name: data.dec(_f$name), diff --git a/packages/core/lib/src/models/deck_build_status.dart b/packages/core/lib/src/models/deck_build_status.dart index 6ba349de..af41c245 100644 --- a/packages/core/lib/src/models/deck_build_status.dart +++ b/packages/core/lib/src/models/deck_build_status.dart @@ -3,12 +3,7 @@ import 'package:dart_mappable/dart_mappable.dart'; part 'deck_build_status.mapper.dart'; @MappableEnum() -enum DeckBuildPhase { - unknown, - building, - success, - failure, -} +enum DeckBuildPhase { unknown, building, success, failure } @MappableClass() final class DeckBuildError with DeckBuildErrorMappable { diff --git a/packages/core/lib/src/models/mappers.dart b/packages/core/lib/src/models/mappers.dart deleted file mode 100644 index 64159326..00000000 --- a/packages/core/lib/src/models/mappers.dart +++ /dev/null @@ -1,15 +0,0 @@ -import 'package:dart_mappable/dart_mappable.dart'; - -/// Normalizes the legacy `column` discriminator to `block`. -class BlockDiscriminatorHook extends MappingHook { - const BlockDiscriminatorHook(); - - @override - Object? beforeDecode(Object? value) { - if (value case {'type': 'column'}) { - return {...value, 'type': 'block'}; - } - - return value; - } -} diff --git a/packages/core/schema/superdeck.deck.schema.json b/packages/core/schema/superdeck.deck.schema.json index 9449a668..ff78c437 100644 --- a/packages/core/schema/superdeck.deck.schema.json +++ b/packages/core/schema/superdeck.deck.schema.json @@ -107,42 +107,6 @@ ], "type": "object" }, - { - "additionalProperties": {}, - "properties": { - "align": { - "enum": [ - "topLeft", - "topCenter", - "topRight", - "centerLeft", - "center", - "centerRight", - "bottomLeft", - "bottomCenter", - "bottomRight" - ], - "type": "string" - }, - "content": { - "type": "string" - }, - "flex": { - "type": "integer" - }, - "scrollable": { - "type": "boolean" - }, - "type": { - "const": "column", - "type": "string" - } - }, - "required": [ - "type" - ], - "type": "object" - }, { "additionalProperties": {}, "properties": { diff --git a/packages/core/test/src/models/block_model_test.dart b/packages/core/test/src/models/block_model_test.dart index 8ce17d02..fb077efe 100644 --- a/packages/core/test/src/models/block_model_test.dart +++ b/packages/core/test/src/models/block_model_test.dart @@ -365,7 +365,7 @@ void main() { group('fromMap', () { test('deserializes minimal map', () { - final map = {'type': 'column'}; + final map = {'type': 'block'}; final block = ContentBlock.fromMap(map); expect(block.content, ''); @@ -376,7 +376,7 @@ void main() { test('deserializes full map', () { final map = { - 'type': 'column', + 'type': 'block', 'content': 'Content', 'align': 'center', 'flex': 2, @@ -399,14 +399,20 @@ void main() { }); test('handles numeric flex as double', () { - final map = {'type': 'column', 'flex': 2.0}; + final map = {'type': 'block', 'flex': 2.0}; final block = ContentBlock.fromMap(map); expect(block.flex, 2); }); test('throws on invalid alignment', () { - final map = {'type': 'column', 'align': 'invalid'}; + final map = {'type': 'block', 'align': 'invalid'}; + expect(() => ContentBlock.fromMap(map), throwsArgumentError); + }); + + test('rejects legacy column type', () { + final map = {'type': 'column', 'content': 'Legacy'}; + expect(() => ContentBlock.fromMap(map), throwsArgumentError); }); }); @@ -454,7 +460,7 @@ void main() { test('validates minimal block', () { // Note: 'content' is required to satisfy Google AI schema requirements final result = ContentBlock.schema.safeParse({ - 'type': 'column', + 'type': 'block', 'content': '', }); expect(result.isOk, isTrue); @@ -462,7 +468,7 @@ void main() { test('validates full block', () { final result = ContentBlock.schema.safeParse({ - 'type': 'column', + 'type': 'block', 'content': 'Content', 'align': 'center', 'flex': 2, @@ -470,6 +476,15 @@ void main() { }); expect(result.isOk, isTrue); }); + + test('rejects legacy column type', () { + final result = ContentBlock.schema.safeParse({ + 'type': 'column', + 'content': 'Content', + }); + + expect(result.isOk, isFalse); + }); }); }); @@ -586,7 +601,7 @@ void main() { final map = { 'type': 'section', 'blocks': [ - {'type': 'column', 'content': 'Test'}, + {'type': 'block', 'content': 'Test'}, ], }; final section = SectionBlock.fromMap(map); @@ -835,14 +850,20 @@ void main() { group('Block', () { group('fromMap', () { - test('creates ContentBlock from column type', () { - final map = {'type': 'column', 'content': 'Test'}; + test('creates ContentBlock from block type', () { + final map = {'type': 'block', 'content': 'Test'}; final block = Block.fromMap(map); expect(block, isA()); expect((block as ContentBlock).content, 'Test'); }); + test('rejects legacy column type', () { + final map = {'type': 'column', 'content': 'Test'}; + + expect(() => Block.fromMap(map), throwsArgumentError); + }); + test('creates SectionBlock from section type', () { final map = {'type': 'section', 'blocks': []}; final block = Block.fromMap(map); @@ -866,12 +887,18 @@ void main() { group('parse', () { test('parses ContentBlock', () { - final map = {'type': 'column', 'content': 'Parsed'}; + final map = {'type': 'block', 'content': 'Parsed'}; final block = Block.parse(map); expect(block, isA()); }); + test('rejects legacy column type', () { + final map = {'type': 'column', 'content': 'Parsed'}; + + expect(() => Block.parse(map), throwsA(anything)); + }); + test('parses WidgetBlock', () { final map = {'type': 'widget', 'name': 'ParsedWidget'}; final block = Block.parse(map); @@ -881,9 +908,9 @@ void main() { }); group('schema', () { - test('validates column block', () { + test('validates content block', () { final result = Block.schema.safeParse({ - 'type': 'column', + 'type': 'block', 'content': 'Test', }); expect(result.isOk, isTrue); diff --git a/packages/core/test/src/models/deck_model_test.dart b/packages/core/test/src/models/deck_model_test.dart index 801b9e9e..cc664156 100644 --- a/packages/core/test/src/models/deck_model_test.dart +++ b/packages/core/test/src/models/deck_model_test.dart @@ -194,7 +194,7 @@ void main() { 'type': 'section', 'flex': 2, 'blocks': [ - {'type': 'column', 'content': 'Block 1', 'flex': 1}, + {'type': 'block', 'content': 'Block 1', 'flex': 1}, {'type': 'widget', 'name': 'image', 'src': 'test.png'}, ], }, diff --git a/packages/core/test/src/models/slide_model_test.dart b/packages/core/test/src/models/slide_model_test.dart index e4fa44d5..af9de76d 100644 --- a/packages/core/test/src/models/slide_model_test.dart +++ b/packages/core/test/src/models/slide_model_test.dart @@ -184,7 +184,7 @@ void main() { { 'type': 'section', 'blocks': [ - {'type': 'column', 'content': 'Block content'}, + {'type': 'block', 'content': 'Block content'}, ], }, ], diff --git a/packages/superdeck/README.md b/packages/superdeck/README.md index a8c613b0..aae6c746 100644 --- a/packages/superdeck/README.md +++ b/packages/superdeck/README.md @@ -45,7 +45,7 @@ SuperDeck reads slide content from `slides.md` and build output from `.superdeck Separate slides with `---`. Use blocks to control layout: - `@section` groups blocks horizontally. -- `@column` renders Markdown content. +- `@block` renders Markdown content. - `@widget` renders a registered Flutter widget. ```md @@ -53,10 +53,10 @@ Separate slides with `---`. Use blocks to control layout: @section -@column +@block # Title -@column +@block - Point one - Point two diff --git a/packages/superdeck/lib/src/deck/deck_loader.dart b/packages/superdeck/lib/src/deck/deck_loader.dart index 8e1dbe96..0b206ffb 100644 --- a/packages/superdeck/lib/src/deck/deck_loader.dart +++ b/packages/superdeck/lib/src/deck/deck_loader.dart @@ -47,9 +47,7 @@ class FileDeckLoader extends DeckLoader { _controller.add(DeckRebuildingEvent()); case DeckBuildPhase.failure: final message = status.error?.message ?? 'Deck build failed'; - _controller.add( - DeckErrorEvent(message, error: Exception(message)), - ); + _controller.add(DeckErrorEvent(message, error: Exception(message))); case DeckBuildPhase.success: try { final deckJson = jsonDecode(await _deckFile.readAsString()); @@ -68,10 +66,12 @@ class FileDeckLoader extends DeckLoader { } } on Object catch (error) { if (_isActive) { - _controller.add(DeckErrorEvent( - 'Superdeck reference error', - error: _asException(error), - )); + _controller.add( + DeckErrorEvent( + 'Superdeck reference error', + error: _asException(error), + ), + ); } } case DeckBuildPhase.unknown: @@ -79,10 +79,9 @@ class FileDeckLoader extends DeckLoader { } } on Object catch (error) { if (_isActive) { - _controller.add(DeckErrorEvent( - 'Build status error', - error: _asException(error), - )); + _controller.add( + DeckErrorEvent('Build status error', error: _asException(error)), + ); } } } @@ -101,20 +100,22 @@ class FileDeckLoader extends DeckLoader { StreamSubscription? sub; try { - sub = dir.watch(events: events, recursive: recursive).listen( - (event) { - if (_disposed || wait.isCompleted) return; - if (!matcher(event)) return; - matched = true; - if (!wait.isCompleted) wait.complete(); - }, - onError: (_, __) { - if (!wait.isCompleted) wait.complete(); - }, - onDone: () { - if (!wait.isCompleted) wait.complete(); - }, - ); + sub = dir + .watch(events: events, recursive: recursive) + .listen( + (event) { + if (_disposed || wait.isCompleted) return; + if (!matcher(event)) return; + matched = true; + if (!wait.isCompleted) wait.complete(); + }, + onError: (_, __) { + if (!wait.isCompleted) wait.complete(); + }, + onDone: () { + if (!wait.isCompleted) wait.complete(); + }, + ); await Future.any([wait.future, _disposeSignal.future]); return matched; @@ -178,10 +179,9 @@ class FileDeckLoader extends DeckLoader { if (_runTask == null && !_disposed) { _runTask = _run().catchError((Object error) { if (_isActive) { - _controller.add(DeckErrorEvent( - 'Build status error', - error: _asException(error), - )); + _controller.add( + DeckErrorEvent('Build status error', error: _asException(error)), + ); } }); } diff --git a/packages/superdeck/test/deck/slide_template_test.dart b/packages/superdeck/test/deck/slide_template_test.dart index ddcbdc10..b3b38b73 100644 --- a/packages/superdeck/test/deck/slide_template_test.dart +++ b/packages/superdeck/test/deck/slide_template_test.dart @@ -115,10 +115,7 @@ void main() { test('templates with different baseStyles are not equal', () { final parts = SlideParts(); - final a = SlideTemplate( - parts: parts, - baseStyle: SlideStyle(), - ); + final a = SlideTemplate(parts: parts, baseStyle: SlideStyle()); final b = SlideTemplate(parts: parts); expect(a, isNot(equals(b))); @@ -135,10 +132,7 @@ void main() { test('templates with different styles maps are not equal', () { final parts = SlideParts(); - final a = SlideTemplate( - parts: parts, - styles: {'dark': SlideStyle()}, - ); + final a = SlideTemplate(parts: parts, styles: {'dark': SlideStyle()}); final b = SlideTemplate(parts: parts, styles: {}); expect(a, isNot(equals(b))); diff --git a/packages/superdeck/test/fixtures/deck_reference.json b/packages/superdeck/test/fixtures/deck_reference.json index 649e9520..1a1b68d7 100644 --- a/packages/superdeck/test/fixtures/deck_reference.json +++ b/packages/superdeck/test/fixtures/deck_reference.json @@ -11,7 +11,7 @@ "options": { "style": "custom" }, - "markdown": "{@section}\n{@column}\n## This is an example of a widgets\n\n{@widget name: demo}\n\n{@column}\n\n```dart\nimport 'package:flutter/material.dart';\n\nvoid main() {\n final style = Style(\n $box.padding.all(),\n $box.border.all(),\n );\n}\n\n```", + "markdown": "{@section}\n{@block}\n## This is an example of a widgets\n\n{@widget name: demo}\n\n{@block}\n\n```dart\nimport 'package:flutter/material.dart';\n\nvoid main() {\n final style = Style(\n $box.padding.all(),\n $box.border.all(),\n );\n}\n\n```", "sections": [ { "options": null, @@ -19,7 +19,7 @@ { "content": "\n## This is an example of a widgets", "options": null, - "type": "column" + "type": "block" }, { "options": { @@ -32,7 +32,7 @@ { "content": "\n```dart\nimport 'package:flutter/material.dart';\nvoid main() {\n final style = Style(\n $box.padding.all(),\n $box.border.all(),\n );\n}\n```", "options": null, - "type": "column" + "type": "block" } ] } @@ -40,20 +40,20 @@ }, { "key": "rHLJMgwc", - "markdown": "```mermaid\ngraph TD\n A[Enter Chart Definition] --> B(Preview)\n B --> C{decide}\n C --> D[Keep]\n C --> E[Edit Definition]\n E --> B\n D --> F[Save Image and Car]\n F --> B \n```\n\n{@column flex: 3}\n\n```mermaid\nsequenceDiagram\n participant Customer as 🧑 Customer\n participant Barista as ☕ Barista\n participant CoffeeMachine as 🏭 Coffee Machine\n```\n\n\n", + "markdown": "```mermaid\ngraph TD\n A[Enter Chart Definition] --> B(Preview)\n B --> C{decide}\n C --> D[Keep]\n C --> E[Edit Definition]\n E --> B\n D --> F[Save Image and Car]\n F --> B \n```\n\n{@block flex: 3}\n\n```mermaid\nsequenceDiagram\n participant Customer as 🧑 Customer\n participant Barista as ☕ Barista\n participant CoffeeMachine as 🏭 Coffee Machine\n```\n\n\n", "sections": [ { "sub_sections": [ { "content": "![Mermaid Diagram](.superdeck/generated/mermaid_llAVsepR.png)", - "type": "column" + "type": "block" }, { "content": "\n![Mermaid Diagram](.superdeck/generated/mermaid_BTVEzSEg.png)\n", "options": { "flex": 3 }, - "type": "column" + "type": "block" } ] } @@ -64,7 +64,7 @@ "options": { "style": "quote" }, - "markdown": "{@section}\n{@column align: bottomRight flex: 3}\n# This presentation will be great\n\n{@column}\n\n{@section}\n\n\n{@column }\n{@column flex: 2 align: topRight}\n> Create your Flutter presentations faster and easier than ever.\n> You can quote me on that\n> ### Leo", + "markdown": "{@section}\n{@block align: bottomRight flex: 3}\n# This presentation will be great\n\n{@block}\n\n{@section}\n\n\n{@block }\n{@block flex: 2 align: topRight}\n> Create your Flutter presentations faster and easier than ever.\n> You can quote me on that\n> ### Leo", "sections": [ { "options": null, @@ -75,12 +75,12 @@ "flex": 3, "align": "bottomRight" }, - "type": "column" + "type": "block" }, { "content": "", "options": null, - "type": "column" + "type": "block" } ] }, @@ -90,7 +90,7 @@ { "content": "", "options": null, - "type": "column" + "type": "block" }, { "content": "\n> Create your Flutter presentations faster and easier than ever.\n> You can quote me on that\n> ### Leo", @@ -98,7 +98,7 @@ "flex": 2, "align": "topRight" }, - "type": "column" + "type": "block" } ] } @@ -109,7 +109,7 @@ "options": { "style": "show_sections" }, - "markdown": "{@section}\n{@image src: https://picsum.photos/1200/1200?waves align: topLeft fit: cover}\n\n{@section flex: 2}\n{@column flex: 2}\n# Two Column HGoes here\n\nThis is a two-column layout. You can use it to compare two different concepts or ideas.\n\n\n{@column}\n\n### Section Options\n\nEasily customize the content of each section to suit your needs.\n\nUse front matter to define the layout of each section", + "markdown": "{@section}\n{@image src: https://picsum.photos/1200/1200?waves align: topLeft fit: cover}\n\n{@section flex: 2}\n{@block flex: 2}\n# Two Column HGoes here\n\nThis is a two-column layout. You can use it to compare two different concepts or ideas.\n\n\n{@block}\n\n### Section Options\n\nEasily customize the content of each section to suit your needs.\n\nUse front matter to define the layout of each section", "sections": [ { "options": null, @@ -136,12 +136,12 @@ "options": { "flex": 2 }, - "type": "column" + "type": "block" }, { "content": "\n### Section Options\nEasily customize the content of each section to suit your needs.\nUse front matter to define the layout of each section", "options": null, - "type": "column" + "type": "block" } ] } @@ -152,7 +152,7 @@ "options": { "style": "show_sections" }, - "markdown": "{@section}\n{@column align: bottomRight}\n\n## First\n\n{@column} \n\n\n## Header\n\n{@section flex: 2}\n\n### Left Section\nEasily customize the content of each section to suit your needs.\n\nUse front matter to define the layout of each section\n\n{@column}\n\n#### Section Options\n\n```yaml\nsections:\n left:\n alignment: bottomRight\n flex: 2\n right:\n alignment: bottomLeft\n header:\n alignment: bottomLeft\n```", + "markdown": "{@section}\n{@block align: bottomRight}\n\n## First\n\n{@block} \n\n\n## Header\n\n{@section flex: 2}\n\n### Left Section\nEasily customize the content of each section to suit your needs.\n\nUse front matter to define the layout of each section\n\n{@block}\n\n#### Section Options\n\n```yaml\nsections:\n left:\n alignment: bottomRight\n flex: 2\n right:\n alignment: bottomLeft\n header:\n alignment: bottomLeft\n```", "sections": [ { "options": null, @@ -162,12 +162,12 @@ "options": { "align": "bottomRight" }, - "type": "column" + "type": "block" }, { "content": "\n## Header", "options": null, - "type": "column" + "type": "block" } ] }, @@ -178,12 +178,12 @@ "sub_sections": [ { "content": "### Left Section\nEasily customize the content of each section to suit your needs.\nUse front matter to define the layout of each section", - "type": "column" + "type": "block" }, { "content": "\n#### Section Options\n```yaml\nsections:\n left:\n alignment: bottomRight\n flex: 2\n right:\n alignment: bottomLeft\n header:\n alignment: bottomLeft\n```", "options": null, - "type": "column" + "type": "block" } ] }