Yuki Takei hace 2 semanas
padre
commit
254e75f24f

+ 0 - 58
.kiro/specs/optimize-presentation/requirements.md

@@ -1,58 +0,0 @@
-# Requirements Document
-
-## Introduction
-
-The GROWI presentation feature (`@growi/presentation` package) statically imports `@marp-team/marp-core` (~524KB) and `@marp-team/marpit` (~372KB) whenever any slide component loads, even when Marp rendering is not needed. This is because both `MarpSlides` and `GrowiSlides` components statically import `growi-marpit.ts`, which instantiates Marp objects at module scope.
-
-The goal is to decouple heavy Marp dependencies so they are only loaded when a page explicitly uses `marp: true` in its frontmatter, reducing the async chunk size for the common non-Marp slide rendering path and improving overall bundle efficiency.
-
-## Requirements
-
-### Requirement 1: Decouple GrowiSlides from Marp Runtime Dependencies
-
-**Objective:** As a developer, I want GrowiSlides to render without loading `@marp-team/marp-core` or `@marp-team/marpit`, so that non-Marp slide pages do not incur unnecessary module loading overhead.
-
-#### Acceptance Criteria
-1. The `@growi/presentation` build output for GrowiSlides shall not contain import references to `@marp-team/marp-core` or `@marp-team/marpit`.
-2. When a slide page without `marp: true` is rendered, the Presentation module shall render GrowiSlides without loading `@marp-team/marp-core` or `@marp-team/marpit` modules.
-3. The Presentation module shall provide the Marp base CSS (previously generated by `marpit.render('')`) as pre-extracted static string constants, so that GrowiSlides can apply Marp container styling without a runtime Marp dependency.
-4. The `MARP_CONTAINER_CLASS_NAME` constant shall be defined in a shared constants module, not in `growi-marpit.ts`, to avoid transitive Marp imports.
-
-### Requirement 2: Dynamic Loading of MarpSlides
-
-**Objective:** As a developer, I want MarpSlides to be loaded dynamically (on demand), so that the Marp rendering engine is only fetched when a page actually uses Marp.
-
-#### Acceptance Criteria
-1. When a slide page with `marp: true` is rendered, the Presentation module shall dynamically load MarpSlides and render Marp content correctly.
-2. While MarpSlides is loading, the Presentation module shall display a loading indicator (Suspense fallback).
-3. When a slide page without `marp: true` is rendered, the Presentation module shall not trigger the dynamic import of MarpSlides.
-
-### Requirement 3: Build-Time CSS Extraction
-
-**Objective:** As a developer, I want the Marp base CSS to be extracted at build time via an automated script, so that the pre-extracted CSS stays synchronized with the installed `@marp-team/marp-core` version.
-
-#### Acceptance Criteria
-1. The `@growi/presentation` package shall include a build-time script that generates Marp base CSS constants by invoking `slideMarpit.render('')` and `presentationMarpit.render('')`.
-2. When `pnpm run build` is executed for `@growi/presentation`, the build pipeline shall regenerate the CSS constants before compiling source files.
-3. The generated CSS constants file shall be committed to the repository so that `dev` mode works without running the extraction script first.
-
-### Requirement 4: Functional Equivalence
-
-**Objective:** As a user, I want the presentation feature to behave identically after optimization, so that existing Marp and non-Marp presentations continue to work without regression.
-
-#### Acceptance Criteria
-1. When a page with `marp: true` frontmatter is viewed inline, the Presentation module shall render Marp slides with correct styling.
-2. When a page with `slide: true` frontmatter (without `marp: true`) is viewed inline, the Presentation module shall render GrowiSlides with correct styling.
-3. When the presentation modal is opened for a Marp page, the Presentation module shall render Marp slides in the modal with correct fullscreen behavior.
-4. When the presentation modal is opened for a non-Marp slide page, the Presentation module shall render GrowiSlides in the modal with correct fullscreen behavior.
-5. When a non-slide page is viewed, the Presentation module shall not load any slide rendering components (existing lazy-loading behavior preserved).
-
-### Requirement 5: Build Verification
-
-**Objective:** As a developer, I want to verify that the optimization achieves its goal, so that Marp module separation can be confirmed in CI and during development.
-
-#### Acceptance Criteria
-1. The `@growi/presentation` package shall build successfully with `pnpm run build`.
-2. The `@growi/app` package shall build successfully with `turbo run build --filter @growi/app`.
-3. The built `GrowiSlides.js` output shall contain no references to `@marp-team/marp-core` or `@marp-team/marpit`.
-4. The built `Slides.js` output shall contain a dynamic `import()` expression for `MarpSlides`.

+ 0 - 49
.kiro/specs/optimize-presentation/tasks.md

@@ -1,49 +0,0 @@
-# Implementation Plan
-
-- [x] 1. Set up shared constants and build-time CSS extraction infrastructure
-- [x] 1.1 Move the Marp container class name constant to the shared constants module and update growi-marpit to import from there
-  - Add the `MARP_CONTAINER_CLASS_NAME` string constant to the existing shared constants module in the presentation package
-  - Update growi-marpit to import the constant from the shared module instead of defining it locally
-  - Re-export the constant from growi-marpit for backward compatibility with MarpSlides
-  - _Requirements: 1.4_
-
-- [x] 1.2 Create the build-time CSS extraction script
-  - Write a Node.js ESM script that instantiates Marp with the same configuration as growi-marpit (container classes, inlineSVG, emoji/html/math disabled)
-  - The script renders empty strings through both slide and presentation Marp instances to extract their CSS output
-  - Write the CSS strings as exported TypeScript constants to the constants directory
-  - Include a file header comment indicating the file is auto-generated and how to regenerate it
-  - Validate that extracted CSS is non-empty before writing
-  - _Requirements: 3.1_
-
-- [x] 1.3 Wire the extraction script into the build pipeline and generate the initial CSS file
-  - Add a `pre:build:src` script entry in the presentation package's package.json that runs the extraction script before the main Vite build
-  - Execute the script once to generate the initial pre-extracted CSS constants file
-  - Commit the generated file so that dev mode works without running extraction first
-  - _Requirements: 3.2, 3.3_
-
-- [x] 2. (P) Decouple GrowiSlides from Marp runtime dependencies
-  - Replace the growi-marpit import in GrowiSlides with imports from the shared constants module and the pre-extracted CSS constants
-  - Replace the runtime `marpit.render('')` call with a lookup of the pre-extracted CSS constant based on the presentation mode flag
-  - After this change, GrowiSlides must have no import path leading to `@marp-team/marp-core` or `@marp-team/marpit`
-  - Depends on task 1 (shared constants and CSS file must exist)
-  - _Requirements: 1.1, 1.2, 1.3_
-
-- [x] 3. (P) Add dynamic import for MarpSlides in the Slides routing component
-  - Replace the static import of MarpSlides with a React.lazy dynamic import that resolves the named export
-  - Wrap the MarpSlides rendering branch in a Suspense boundary with a simple loading fallback
-  - Keep GrowiSlides as a static import (the common, lightweight path)
-  - The dynamic import ensures MarpSlides and its transitive Marp dependencies are only loaded when `hasMarpFlag` is true
-  - Depends on task 1 (shared constants must exist); parallel-safe with task 2 (different file)
-  - _Requirements: 2.1, 2.2, 2.3_
-
-- [x] 4. Build verification and functional validation
-- [x] 4.1 Build the presentation package and verify module separation in the output
-  - Run the presentation package build and confirm it succeeds
-  - Inspect the built GrowiSlides output file to confirm it contains no references to `@marp-team/marp-core` or `@marp-team/marpit`
-  - Inspect the built Slides output file to confirm it contains a dynamic `import()` expression for MarpSlides
-  - _Requirements: 5.1, 5.3, 5.4_
-
-- [x] 4.2 Build the main GROWI application and verify successful compilation
-  - Run the full app build to confirm no regressions from the presentation package changes
-  - Verify that both Marp and non-Marp slide rendering paths are intact by checking the build completes without type errors
-  - _Requirements: 4.1, 4.2, 4.3, 4.4, 4.5, 5.2_

+ 1 - 41
.kiro/specs/optimize-presentation/design.md → .kiro/specs/presentation/design.md

@@ -1,4 +1,4 @@
-# Design Document: optimize-presentation
+# Design Document: presentation
 
 ## Overview
 
@@ -118,23 +118,6 @@ flowchart TD
   F --> G[vite build compiles all sources]
 ```
 
-## Requirements Traceability
-
-| Requirement | Summary | Components | Interfaces | Flows |
-|-------------|---------|------------|------------|-------|
-| 1.1 | No marp-core references in GrowiSlides build output | GrowiSlides, marpit-base-css | — | — |
-| 1.2 | Non-Marp slides render without loading Marp | Slides, GrowiSlides | — | Slide Rendering Decision |
-| 1.3 | Pre-extracted CSS constants for container styling | marpit-base-css | MarpitBaseCss | CSS Extraction |
-| 1.4 | MARP_CONTAINER_CLASS_NAME in shared consts | consts/index.ts | — | — |
-| 2.1 | Dynamic load MarpSlides for marp:true pages | Slides | — | Slide Rendering Decision |
-| 2.2 | Loading indicator during MarpSlides load | Slides | — | Slide Rendering Decision |
-| 2.3 | No MarpSlides import triggered for non-Marp | Slides | — | Slide Rendering Decision |
-| 3.1 | Build-time CSS extraction script | extract-marpit-css.mjs | ExtractScript | CSS Extraction |
-| 3.2 | Extraction runs before source compilation | package.json pre:build:src | — | CSS Extraction |
-| 3.3 | Generated file committed for dev mode | marpit-base-css.ts | — | — |
-| 4.1–4.5 | Functional equivalence across all render paths | All components | — | Both flows |
-| 5.1–5.4 | Build verification of module separation | Build outputs | — | — |
-
 ## Components and Interfaces
 
 | Component | Domain | Intent | Req Coverage | Key Dependencies | Contracts |
@@ -299,26 +282,3 @@ export const presentationMarpit: Marp;
 - Validation: Script exits with error if CSS extraction produces empty output
 - Risks: Marp options must stay synchronized with `growi-marpit.ts`
 
-## Testing Strategy
-
-### Unit Tests
-- Verify `GrowiSlides` renders correctly with pre-extracted CSS constants (no Marp imports in test)
-- Verify `Slides` renders `GrowiSlides` when `hasMarpFlag` is false/undefined
-- Verify `Slides` renders `MarpSlides` (via Suspense) when `hasMarpFlag` is true
-
-### Build Verification Tests
-- `GrowiSlides.js` build output contains no references to `@marp-team/marp-core` or `@marp-team/marpit`
-- `Slides.js` build output contains dynamic `import()` for MarpSlides
-- `@growi/presentation` builds without errors
-- `@growi/app` builds without errors
-
-### Integration Tests
-- Marp slide page (`marp: true`) renders correctly in inline view
-- Non-Marp slide page (`slide: true`) renders correctly in inline view
-- Presentation modal works for both Marp and non-Marp content
-
-## Performance & Scalability
-
-**Target**: Eliminate ~896KB of Marp-related JavaScript from the async chunk loaded for non-Marp slide rendering.
-
-**Measurement**: Compare the chunk contents before and after optimization using the existing `ChunkModuleStatsPlugin` or manual inspection of build output. The `initial` module count (primary KPI from build-optimization skill) is not directly affected since slides are already in async chunks, but the async chunk size is reduced.

+ 26 - 0
.kiro/specs/presentation/requirements.md

@@ -0,0 +1,26 @@
+# Presentation Feature — Requirements Overview
+
+## Introduction
+
+The GROWI presentation feature (`@growi/presentation` package) provides slide rendering for wiki pages using frontmatter flags. It supports two rendering modes:
+
+- **GrowiSlides** (`slide: true`): Lightweight slide rendering using ReactMarkdown with Marp container styling applied via pre-extracted CSS constants. Does not load Marp runtime dependencies.
+- **MarpSlides** (`marp: true`): Full Marp-powered slide rendering using `@marp-team/marp-core`, loaded dynamically only when needed.
+
+## Key Requirements
+
+### 1. Module Separation
+
+GrowiSlides renders without loading `@marp-team/marp-core` or `@marp-team/marpit`. Marp dependencies are isolated behind a dynamic import boundary (`React.lazy`) and only loaded for pages with `marp: true`.
+
+### 2. Build-Time CSS Extraction
+
+Marp base CSS is pre-extracted at build time via `extract-marpit-css.mjs`. The generated constants file (`consts/marpit-base-css.ts`) is committed to the repository so that dev mode works without running the extraction script first. The extraction runs automatically before source compilation via the `pre:build:src` script.
+
+### 3. Functional Equivalence
+
+Both Marp and non-Marp slide pages render correctly in inline view and presentation modal. No behavioral differences from the user's perspective.
+
+### 4. Build Integrity
+
+Both `@growi/presentation` and `@growi/app` build successfully. The GrowiSlides build output contains no Marp module references, and the Slides build output contains a dynamic `import()` for MarpSlides.

+ 0 - 0
.kiro/specs/optimize-presentation/research.md → .kiro/specs/presentation/research.md


+ 3 - 2
.kiro/specs/optimize-presentation/spec.json → .kiro/specs/presentation/spec.json

@@ -1,9 +1,10 @@
 {
-  "feature_name": "optimize-presentation",
+  "feature_name": "presentation",
   "created_at": "2026-03-05T12:00:00Z",
-  "updated_at": "2026-03-05T13:30:00Z",
+  "updated_at": "2026-03-23T00:00:00Z",
   "language": "en",
   "phase": "implementation-complete",
+  "cleanup_completed": true,
   "approvals": {
     "requirements": {
       "generated": true,