@peter.naydenov/morph 3.1.5 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.mocharc.json +1 -0
- package/.opencode/command/speckit.analyze.md +184 -0
- package/.opencode/command/speckit.checklist.md +294 -0
- package/.opencode/command/speckit.clarify.md +181 -0
- package/.opencode/command/speckit.constitution.md +82 -0
- package/.opencode/command/speckit.implement.md +135 -0
- package/.opencode/command/speckit.plan.md +89 -0
- package/.opencode/command/speckit.specify.md +257 -0
- package/.opencode/command/speckit.tasks.md +137 -0
- package/.opencode/command/speckit.taskstoissues.md +28 -0
- package/.specify/memory/constitution.md +43 -0
- package/.specify/scripts/bash/check-prerequisites.sh +166 -0
- package/.specify/scripts/bash/common.sh +156 -0
- package/.specify/scripts/bash/create-new-feature.sh +305 -0
- package/.specify/scripts/bash/setup-plan.sh +61 -0
- package/.specify/scripts/bash/update-agent-context.sh +790 -0
- package/.specify/templates/agent-file-template.md +28 -0
- package/.specify/templates/checklist-template.md +40 -0
- package/.specify/templates/plan-template.md +104 -0
- package/.specify/templates/spec-template.md +115 -0
- package/.specify/templates/tasks-template.md +251 -0
- package/Changelog.md +12 -0
- package/README.md +154 -3
- package/dist/morph.cjs +1 -1
- package/dist/morph.esm.mjs +1 -1
- package/dist/morph.umd.js +1 -1
- package/morph.png +0 -0
- package/package.json +3 -2
- package/simple.js +17 -0
- package/specs/001-extend-templates/checklists/requirements.md +35 -0
- package/specs/001-extend-templates/contracts/set-method.json +39 -0
- package/specs/001-extend-templates/data-model.md +76 -0
- package/specs/001-extend-templates/plan.md +90 -0
- package/specs/001-extend-templates/quickstart.md +56 -0
- package/specs/001-extend-templates/research.md +18 -0
- package/specs/001-extend-templates/spec.md +139 -0
- package/specs/001-extend-templates/tasks.md +255 -0
- package/src/methods/_readTemplate.js +22 -46
- package/src/methods/_setupActions.js +1 -8
- package/src/methods/build.js +98 -43
- package/src/methods/render.js +14 -11
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Implementation Plan: Extend Templates
|
|
2
|
+
|
|
3
|
+
**Branch**: `001-extend-templates` | **Date**: 2025-11-30 | **Spec**: specs/001-extend-templates/spec.md
|
|
4
|
+
**Input**: Feature specification from /specs/001-extend-templates/spec.md
|
|
5
|
+
|
|
6
|
+
**Note**: This template is filled in by the `/speckit.plan` command. See `.specify/templates/commands/plan.md` for the execution workflow.
|
|
7
|
+
|
|
8
|
+
## Summary
|
|
9
|
+
|
|
10
|
+
Extend Morph templates with 'set' command to modify placeholders, helpers, handshake without altering originals. Technical approach: Add 'set' method to template functions, merge extensions with originals, remove routing actions.
|
|
11
|
+
|
|
12
|
+
## Technical Context
|
|
13
|
+
|
|
14
|
+
**Language/Version**: JavaScript (ES6+)
|
|
15
|
+
|
|
16
|
+
**Primary Dependencies**: None (existing library)
|
|
17
|
+
|
|
18
|
+
**Storage**: N/A
|
|
19
|
+
|
|
20
|
+
**Testing**: Existing test suite
|
|
21
|
+
|
|
22
|
+
**Target Platform**: Browser and Node.js
|
|
23
|
+
|
|
24
|
+
**Project Type**: Library
|
|
25
|
+
|
|
26
|
+
**Performance Goals**: Template extensions created and tested in under 5 minutes
|
|
27
|
+
|
|
28
|
+
**Constraints**: Maintain backward compatibility, no breaking changes
|
|
29
|
+
|
|
30
|
+
**Scale/Scope**: Small feature addition to existing library
|
|
31
|
+
|
|
32
|
+
## Constitution Check
|
|
33
|
+
|
|
34
|
+
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
|
|
35
|
+
|
|
36
|
+
- I. Logic-Less Templating: PASS - Extensions maintain logic-less syntax.
|
|
37
|
+
- II. Builtin Storage: PASS - No impact.
|
|
38
|
+
- III. Action System (NON-NEGOTIABLE): PASS - 'set' is a command, not action; removing inconsistent routing actions improves system.
|
|
39
|
+
- IV. Demo and Handshake: PASS - Extending handshake aligns.
|
|
40
|
+
- V. Extensibility: PASS - Adds extensibility via 'set'.
|
|
41
|
+
- VI. Debuggability: PASS - Empty placeholders support partial render principle.
|
|
42
|
+
|
|
43
|
+
## Project Structure
|
|
44
|
+
|
|
45
|
+
### Documentation (this feature)
|
|
46
|
+
|
|
47
|
+
```text
|
|
48
|
+
specs/[###-feature]/
|
|
49
|
+
├── plan.md # This file (/speckit.plan command output)
|
|
50
|
+
├── research.md # Phase 0 output (/speckit.plan command)
|
|
51
|
+
├── data-model.md # Phase 1 output (/speckit.plan command)
|
|
52
|
+
├── quickstart.md # Phase 1 output (/speckit.plan command)
|
|
53
|
+
├── contracts/ # Phase 1 output (/speckit.plan command)
|
|
54
|
+
└── tasks.md # Phase 2 output (/speckit.tasks command - NOT created by /speckit.plan)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Source Code (repository root)
|
|
58
|
+
|
|
59
|
+
```text
|
|
60
|
+
src/
|
|
61
|
+
├── methods/
|
|
62
|
+
│ ├── _actionSupply.js
|
|
63
|
+
│ ├── _chopTemplates.js
|
|
64
|
+
│ ├── _defineData.js
|
|
65
|
+
│ ├── _defineType.js
|
|
66
|
+
│ ├── _readTemplate.js
|
|
67
|
+
│ ├── _renderHolder.js
|
|
68
|
+
│ ├── _setupActions.js
|
|
69
|
+
│ ├── build.js
|
|
70
|
+
│ ├── render.js
|
|
71
|
+
│ └── settings.js
|
|
72
|
+
├── main.js
|
|
73
|
+
└── ...
|
|
74
|
+
|
|
75
|
+
tests/
|
|
76
|
+
├── 01-chop.test.js
|
|
77
|
+
├── 02-build.test.js
|
|
78
|
+
├── 03-storage.test.js
|
|
79
|
+
├── 04-commands.js
|
|
80
|
+
├── 05-data.test.js
|
|
81
|
+
├── 06-deps-injection.js
|
|
82
|
+
├── 07-errors.test.js
|
|
83
|
+
└── ...
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Structure Decision**: Single project library structure. Source in src/, tests in test/. Feature will modify build.js and render.js primarily.
|
|
87
|
+
|
|
88
|
+
## Complexity Tracking
|
|
89
|
+
|
|
90
|
+
No constitution violations to justify.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Quickstart: Extend Templates
|
|
2
|
+
|
|
3
|
+
**Feature**: Extend Templates
|
|
4
|
+
**Date**: 2025-11-30
|
|
5
|
+
|
|
6
|
+
## Overview
|
|
7
|
+
|
|
8
|
+
The `set` command allows you to create extended versions of existing templates by modifying placeholders, adding helpers, and providing alternative handshake data.
|
|
9
|
+
|
|
10
|
+
## Basic Usage
|
|
11
|
+
|
|
12
|
+
```javascript
|
|
13
|
+
import morph from '@peter.naydenov/morph';
|
|
14
|
+
|
|
15
|
+
// Create a base template
|
|
16
|
+
const baseTemplate = morph.build({
|
|
17
|
+
template: `Hello {{ name }}!`,
|
|
18
|
+
helpers: {},
|
|
19
|
+
handshake: { name: 'World' }
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// Extend with new placeholder and helper
|
|
23
|
+
const extendedTemplate = baseTemplate('set', {
|
|
24
|
+
placeholders: {
|
|
25
|
+
0: '{{ greeting: formatGreeting }}' // Replace position 0
|
|
26
|
+
},
|
|
27
|
+
helpers: {
|
|
28
|
+
formatGreeting: (data) => data.toUpperCase()
|
|
29
|
+
},
|
|
30
|
+
handshake: {
|
|
31
|
+
greeting: 'Hello'
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// Render the extended template
|
|
36
|
+
const result = extendedTemplate('render', { greeting: 'Hi' });
|
|
37
|
+
console.log(result); // "HI!"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Key Points
|
|
41
|
+
|
|
42
|
+
- `set` creates a new template function, leaving the original unchanged
|
|
43
|
+
- Placeholders can be identified by position (number) or name (string)
|
|
44
|
+
- New helpers overwrite existing ones with the same name
|
|
45
|
+
- Handshake data is merged
|
|
46
|
+
- Empty placeholders `{{}}` remain untouched if no data provided
|
|
47
|
+
|
|
48
|
+
## Error Handling
|
|
49
|
+
|
|
50
|
+
If a required helper is missing during render:
|
|
51
|
+
|
|
52
|
+
```javascript
|
|
53
|
+
// Will return: "Helper 'missingHelper' is not available"
|
|
54
|
+
const result = template('render', { data: 'value' });
|
|
55
|
+
```</content>
|
|
56
|
+
<parameter name="filePath">specs/001-extend-templates/quickstart.md
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Research: Extend Templates
|
|
2
|
+
|
|
3
|
+
**Feature**: Extend Templates
|
|
4
|
+
**Date**: 2025-11-30
|
|
5
|
+
|
|
6
|
+
No unknowns identified in technical context. All implementation details known from existing Morph library codebase.
|
|
7
|
+
|
|
8
|
+
- Language/Version: JavaScript (ES6+) - already in use
|
|
9
|
+
- Dependencies: None new - extending existing library
|
|
10
|
+
- Storage: N/A - in-memory operations
|
|
11
|
+
- Testing: Existing test suite - will extend
|
|
12
|
+
- Platform: Browser/Node.js - already supported
|
|
13
|
+
- Performance: Under 5 minutes - developer time, no system perf impact
|
|
14
|
+
- Constraints: Backward compatibility - standard for library updates
|
|
15
|
+
- Scale: Small feature - fits within existing architecture
|
|
16
|
+
|
|
17
|
+
**Decision**: No research required, proceed to design phase.</content>
|
|
18
|
+
<parameter name="filePath">specs/001-extend-templates/research.md
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Feature Specification: Extend Templates
|
|
2
|
+
|
|
3
|
+
**Feature Branch**: `001-extend-templates`
|
|
4
|
+
**Created**: 2025-11-30
|
|
5
|
+
**Status**: Draft
|
|
6
|
+
**Input**: User description: "- Empty placeholders - {{}}
|
|
7
|
+
- Extend templates: Change of placeholder definitions, add/overwrite helpers, provide alternative handshake data. template ('set',{ plachholders:{nameOrPosition: newPlaceholderDefinition}, helpers: { helpers}, handshake:{ new Handshake}},). Result is a new function(template), ready to receive data;
|
|
8
|
+
- Building templates - will not have 'fail' response, because we could build templates without having all helpers available. They can come latter.
|
|
9
|
+
- 'Set' creates a new template. Current template is not changed;
|
|
10
|
+
- What if we trying to render a template that don't have a helper? - it will return error as a render result. Will explain that renderFunction isn't available;
|
|
11
|
+
- Routing actions will be removed. Too unconsistant with other actions. It's can be solved with normal render functions by providing a list of possible templates. It's something that is possible even now;
|
|
12
|
+
- Update 'tests' according new features;
|
|
13
|
+
- Check jsdoc and update it according code changes. Extend jsdoc where possible. Update .d.ts type definitions; "
|
|
14
|
+
|
|
15
|
+
## Out of Scope
|
|
16
|
+
|
|
17
|
+
- Modifying the original template in place; 'set' always creates a new template.
|
|
18
|
+
- Adding new action types to the system beyond 'set' and existing ones.
|
|
19
|
+
|
|
20
|
+
## Clarifications
|
|
21
|
+
|
|
22
|
+
### Session 2025-11-30
|
|
23
|
+
|
|
24
|
+
- Q: What should happen with empty placeholders {{}}? → A: Leave empty placeholders {{}} untouched in output when no data is provided.
|
|
25
|
+
- Q: What should be the exact error message format when a helper is missing? → A: Helper '<name>' is not available
|
|
26
|
+
- Q: How are placeholders identified in the 'set' command? → A: By position (number) or name (string); new placeholders replace old ones at that position/name.
|
|
27
|
+
|
|
28
|
+
## User Scenarios & Testing *(mandatory)*
|
|
29
|
+
|
|
30
|
+
### User Story 1 - Create Template Variants (Priority: P1)
|
|
31
|
+
|
|
32
|
+
As a developer using the Morph library, I want to modify placeholder definitions in an existing template so I can create variants for different data structures without duplicating template code.
|
|
33
|
+
|
|
34
|
+
**Why this priority**: Enables template reuse and reduces code duplication.
|
|
35
|
+
|
|
36
|
+
**Independent Test**: Can be tested by creating a base template, extending it with modified placeholders, and rendering with different data structures.
|
|
37
|
+
|
|
38
|
+
**Acceptance Scenarios**:
|
|
39
|
+
|
|
40
|
+
1. **Given** a template with placeholders, **When** I use 'set' command to change placeholder definitions, **Then** the new template renders with modified behavior.
|
|
41
|
+
2. **Given** a template, **When** I extend it with new placeholders, **Then** the new template includes both original and new placeholders.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
### User Story 2 - Add/Overwrite Helpers (Priority: P1)
|
|
46
|
+
|
|
47
|
+
As a developer, I want to add new helpers or overwrite existing ones in a template so I can extend functionality dynamically.
|
|
48
|
+
|
|
49
|
+
**Why this priority**: Allows dynamic extension of template capabilities. Mixing templates with different sets of helpers. Extend templates without breaking existing functionality and minimal adiditional code.
|
|
50
|
+
|
|
51
|
+
**Independent Test**: Can be tested by extending a template with new helpers and verifying they are used in rendering.
|
|
52
|
+
|
|
53
|
+
**Acceptance Scenarios**:
|
|
54
|
+
|
|
55
|
+
1. **Given** a template with helpers, **When** I use 'set' to add new helpers, **Then** the new template includes the additional helpers.
|
|
56
|
+
2. **Given** a template, **When** I overwrite an existing helper, **Then** the new template uses the updated helper.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
### User Story 3 - Provide Alternative Handshake Data (Priority: P2)
|
|
61
|
+
|
|
62
|
+
As a developer, I want to provide alternative demo data for a template so I can test different scenarios. Helpfull for testing component behavior with different data.
|
|
63
|
+
|
|
64
|
+
**Why this priority**: Improves testing and prototyping capabilities.
|
|
65
|
+
|
|
66
|
+
**Independent Test**: Can be tested by extending a template with new handshake data and rendering in demo mode.
|
|
67
|
+
|
|
68
|
+
**Acceptance Scenarios**:
|
|
69
|
+
|
|
70
|
+
1. **Given** a template with handshake data, **When** I use 'set' to provide new handshake, **Then** demo rendering uses the new data.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
### User Story 4 - Handle Missing Helpers Gracefully (Priority: P2)
|
|
75
|
+
|
|
76
|
+
As a developer, I want clear error messages when trying to render a template with missing helpers so I can debug issues easily.
|
|
77
|
+
|
|
78
|
+
**Why this priority**: Improves developer experience and debugging.
|
|
79
|
+
|
|
80
|
+
**Independent Test**: Can be tested by attempting to render with missing helpers and verifying error message.
|
|
81
|
+
|
|
82
|
+
**Acceptance Scenarios**:
|
|
83
|
+
|
|
84
|
+
1. **Given** a template requiring a helper, **When** I render without the helper, **Then** I receive an error explaining the missing function.
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
### User Story 5 - Remove Routing Actions (Priority: P3)
|
|
89
|
+
|
|
90
|
+
As a developer, I want routing actions removed so I can use consistent action patterns with normal render functions.
|
|
91
|
+
|
|
92
|
+
**Why this priority**: Simplifies the action system and removes inconsistency.
|
|
93
|
+
|
|
94
|
+
**Independent Test**: Can be tested by verifying routing actions are no longer available and alternatives work.
|
|
95
|
+
|
|
96
|
+
**Acceptance Scenarios**:
|
|
97
|
+
|
|
98
|
+
1. **Given** the library, **When** I check available actions, **Then** routing actions are not present.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Edge Cases
|
|
103
|
+
|
|
104
|
+
- Rendering with empty placeholders {{}} should produce {{}} - no touched placeholder, as when data is not provided;
|
|
105
|
+
- Building templates with partial helpers should succeed. If helpers are not available we getting an error as a render result.
|
|
106
|
+
- Extending templates with invalid placeholder definitions should fail gracefully.
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
## Requirements *(mandatory)*
|
|
111
|
+
|
|
112
|
+
### Functional Requirements
|
|
113
|
+
|
|
114
|
+
- **FR-001**: System MUST support empty placeholders {{}} that remain untouched when no data is provided.
|
|
115
|
+
- **FR-002**: System MUST support 'set' command for extending templates with new placeholders, helpers, and handshake data. Placeholders identified by position (number) or name (string); new placeholders replace existing ones. Helpers from original template preserved, new helpers can overwrite. Handshake data merged similarly.
|
|
116
|
+
- **FR-003**: System MUST return a new template function from 'set' command that incorporates existing elements with the extensions. Where extensions have higher priority.
|
|
117
|
+
- **FR-004**: System MUST allow building templates without all required helpers present.
|
|
118
|
+
- **FR-005**: System MUST return error messages in the format "Helper '<name>' is not available" when rendering with missing helpers (can list multiple if applicable).
|
|
119
|
+
- **FR-006**: System MUST remove routing actions from the action system.
|
|
120
|
+
- **FR-007**: Tests MUST be updated to cover new template extension features.
|
|
121
|
+
- **FR-008**: JSDoc comments MUST be updated and extended according to code changes.
|
|
122
|
+
- **FR-009**: TypeScript .d.ts definitions MUST be updated to reflect new features.
|
|
123
|
+
|
|
124
|
+
### Key Entities *(include if feature involves data)*
|
|
125
|
+
|
|
126
|
+
- **Template**: The core template object with placeholders, helpers, and handshake.
|
|
127
|
+
- **Helper**: Functions or sub-templates used in actions.
|
|
128
|
+
- **Handshake**: Demo data for testing templates.
|
|
129
|
+
- **Placeholder**: Dynamic parts of the template defined by {{ }}.
|
|
130
|
+
|
|
131
|
+
## Success Criteria *(mandatory)*
|
|
132
|
+
|
|
133
|
+
### Measurable Outcomes
|
|
134
|
+
|
|
135
|
+
- **SC-001**: Developers can create and test template extensions in under 5 minutes.
|
|
136
|
+
- **SC-002**: 100% of template extension operations complete without errors.
|
|
137
|
+
- **SC-003**: Error messages for missing helpers are clear and include the helper name.
|
|
138
|
+
- **SC-004**: All routing actions are successfully removed without breaking existing functionality.
|
|
139
|
+
- **SC-005**: Test coverage for new features reaches 90%.
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
---
|
|
2
|
+
|
|
3
|
+
description: "Task list template for feature implementation"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Tasks: Extend Templates
|
|
7
|
+
|
|
8
|
+
**Input**: Design documents from `/specs/001-extend-templates/`
|
|
9
|
+
**Prerequisites**: plan.md (required), spec.md (required for user stories), research.md, data-model.md, contracts/
|
|
10
|
+
|
|
11
|
+
**Tests**: Tests are required per feature requirements (FR-007, FR-008, FR-009)
|
|
12
|
+
|
|
13
|
+
**Organization**: Tasks are grouped by user story to enable independent implementation and testing of each story.
|
|
14
|
+
|
|
15
|
+
## Format: `[ID] [P?] [Story] Description`
|
|
16
|
+
|
|
17
|
+
- **[P]**: Can run in parallel (different files, no dependencies)
|
|
18
|
+
- **[Story]**: Which user story this task belongs to (e.g., US1, US2, US3)
|
|
19
|
+
- Include exact file paths in descriptions
|
|
20
|
+
|
|
21
|
+
## Path Conventions
|
|
22
|
+
|
|
23
|
+
- **Single project**: `src/`, `test/` at repository root
|
|
24
|
+
- Paths shown below assume single project - adjust based on plan.md structure
|
|
25
|
+
|
|
26
|
+
## Phase 1: Setup (Shared Infrastructure)
|
|
27
|
+
|
|
28
|
+
**Purpose**: Project initialization and basic structure
|
|
29
|
+
|
|
30
|
+
- [X] T001 [P] Review existing code structure in src/ and test/
|
|
31
|
+
- [ ] T002 [P] Identify files to modify for 'set' command support
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Phase 2: Foundational (Blocking Prerequisites)
|
|
36
|
+
|
|
37
|
+
**Purpose**: Core infrastructure that MUST be complete before ANY user story can be implemented
|
|
38
|
+
|
|
39
|
+
**⚠️ CRITICAL**: No user story work can begin until this phase is complete
|
|
40
|
+
|
|
41
|
+
- [ ] T003 Add 'set' command support to src/methods/render.js
|
|
42
|
+
- [ ] T004 Update src/methods/build.js to handle template extensions
|
|
43
|
+
- [ ] T005 Implement placeholder replacement logic in src/methods/_chopTemplates.js
|
|
44
|
+
- [ ] T006 Implement helper merging logic in src/methods/_defineData.js
|
|
45
|
+
- [ ] T007 Implement handshake merging logic in src/methods/_defineData.js
|
|
46
|
+
|
|
47
|
+
**Checkpoint**: Foundation ready - user story implementation can now begin in parallel
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Phase 3: User Story 1 - Create Template Variants (Priority: P1) 🎯 MVP
|
|
52
|
+
|
|
53
|
+
**Goal**: Enable modification of placeholder definitions in existing templates to create variants
|
|
54
|
+
|
|
55
|
+
**Independent Test**: Create a base template, use 'set' to modify placeholders, render and verify changes
|
|
56
|
+
|
|
57
|
+
### Tests for User Story 1 ⚠️
|
|
58
|
+
|
|
59
|
+
> **NOTE: Write these tests FIRST, ensure they FAIL before implementation**
|
|
60
|
+
|
|
61
|
+
- [ ] T008 [P] [US1] Contract test for 'set' command in test/08-set-contract.test.js
|
|
62
|
+
- [ ] T009 [P] [US1] Integration test for placeholder replacement in test/09-placeholder-integration.test.js
|
|
63
|
+
|
|
64
|
+
### Implementation for User Story 1
|
|
65
|
+
|
|
66
|
+
- [ ] T010 [US1] Implement placeholder identification by position/name in src/methods/_chopTemplates.js
|
|
67
|
+
- [ ] T011 [US1] Implement placeholder replacement in 'set' command in src/methods/render.js
|
|
68
|
+
- [ ] T012 [US1] Add validation for placeholder definitions in src/methods/_chopTemplates.js
|
|
69
|
+
|
|
70
|
+
**Checkpoint**: At this point, User Story 1 should be fully functional and testable independently
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Phase 4: User Story 2 - Add/Overwrite Helpers (Priority: P1)
|
|
75
|
+
|
|
76
|
+
**Goal**: Allow adding new helpers or overwriting existing ones in templates dynamically
|
|
77
|
+
|
|
78
|
+
**Independent Test**: Extend a template with new helpers, render and verify helper execution
|
|
79
|
+
|
|
80
|
+
### Tests for User Story 2 ⚠️
|
|
81
|
+
|
|
82
|
+
- [ ] T013 [P] [US2] Contract test for helper merging in test/10-helper-contract.test.js
|
|
83
|
+
- [ ] T014 [P] [US2] Integration test for helper overwriting in test/11-helper-integration.test.js
|
|
84
|
+
|
|
85
|
+
### Implementation for User Story 2
|
|
86
|
+
|
|
87
|
+
- [ ] T015 [US2] Implement helper merging logic in src/methods/_defineData.js
|
|
88
|
+
- [ ] T016 [US2] Ensure new helpers overwrite existing ones in src/methods/build.js
|
|
89
|
+
- [ ] T017 [US2] Preserve original helpers in extended templates in src/methods/build.js
|
|
90
|
+
|
|
91
|
+
**Checkpoint**: At this point, User Stories 1 AND 2 should both work independently
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Phase 5: User Story 3 - Provide Alternative Handshake Data (Priority: P2)
|
|
96
|
+
|
|
97
|
+
**Goal**: Enable providing alternative demo data for template testing
|
|
98
|
+
|
|
99
|
+
**Independent Test**: Extend template with new handshake, render in demo mode with new data
|
|
100
|
+
|
|
101
|
+
### Tests for User Story 3 ⚠️
|
|
102
|
+
|
|
103
|
+
- [ ] T018 [P] [US3] Contract test for handshake merging in test/12-handshake-contract.test.js
|
|
104
|
+
- [ ] T019 [P] [US3] Integration test for demo rendering with new handshake in test/13-handshake-integration.test.js
|
|
105
|
+
|
|
106
|
+
### Implementation for User Story 3
|
|
107
|
+
|
|
108
|
+
- [ ] T020 [US3] Implement handshake merging logic in src/methods/_defineData.js
|
|
109
|
+
- [ ] T021 [US3] Update demo rendering to use merged handshake in src/methods/render.js
|
|
110
|
+
|
|
111
|
+
**Checkpoint**: At this point, User Stories 1, 2 AND 3 should all work independently
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Phase 6: User Story 4 - Handle Missing Helpers Gracefully (Priority: P2)
|
|
116
|
+
|
|
117
|
+
**Goal**: Provide clear error messages when rendering with missing helpers
|
|
118
|
+
|
|
119
|
+
**Independent Test**: Attempt to render template with missing helper, verify error message
|
|
120
|
+
|
|
121
|
+
### Tests for User Story 4 ⚠️
|
|
122
|
+
|
|
123
|
+
- [ ] T022 [P] [US4] Contract test for error handling in test/14-error-contract.test.js
|
|
124
|
+
- [ ] T023 [P] [US4] Integration test for missing helper errors in test/15-error-integration.test.js
|
|
125
|
+
|
|
126
|
+
### Implementation for User Story 4
|
|
127
|
+
|
|
128
|
+
- [ ] T024 [US4] Implement missing helper detection in src/methods/_actionSupply.js
|
|
129
|
+
- [ ] T025 [US4] Add error message formatting "Helper '<name>' is not available" in src/methods/render.js
|
|
130
|
+
- [ ] T026 [US4] Support listing multiple missing helpers in error messages in src/methods/render.js
|
|
131
|
+
|
|
132
|
+
**Checkpoint**: At this point, User Stories 1-4 should all work independently
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Phase 7: User Story 5 - Remove Routing Actions (Priority: P3)
|
|
137
|
+
|
|
138
|
+
**Goal**: Remove inconsistent routing actions from the action system
|
|
139
|
+
|
|
140
|
+
**Independent Test**: Verify routing actions are no longer available, alternatives work
|
|
141
|
+
|
|
142
|
+
### Tests for User Story 5 ⚠️
|
|
143
|
+
|
|
144
|
+
- [ ] T027 [P] [US5] Contract test for removed routing actions in test/16-routing-contract.test.js
|
|
145
|
+
- [ ] T028 [P] [US5] Integration test for alternative action patterns in test/17-routing-integration.test.js
|
|
146
|
+
|
|
147
|
+
### Implementation for User Story 5
|
|
148
|
+
|
|
149
|
+
- [ ] T029 [US5] Remove routing action implementations from src/methods/_setupActions.js
|
|
150
|
+
- [ ] T030 [US5] Update action validation to reject routing actions in src/methods/_setupActions.js
|
|
151
|
+
|
|
152
|
+
**Checkpoint**: All user stories should now be independently functional
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Phase 8: Polish & Cross-Cutting Concerns
|
|
157
|
+
|
|
158
|
+
**Purpose**: Improvements that affect multiple user stories
|
|
159
|
+
|
|
160
|
+
- [ ] T031 [P] Update JSDoc comments in src/methods/*.js
|
|
161
|
+
- [ ] T032 [P] Update TypeScript definitions in morph.d.ts
|
|
162
|
+
- [ ] T033 [P] Update tests for new features in test/*.js
|
|
163
|
+
- [ ] T034 [P] Update README.md with 'set' command documentation
|
|
164
|
+
- [ ] T035 Run npm test to validate all changes
|
|
165
|
+
- [ ] T036 Run npm run lint to check code quality
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Dependencies & Execution Order
|
|
170
|
+
|
|
171
|
+
### Phase Dependencies
|
|
172
|
+
|
|
173
|
+
- **Setup (Phase 1)**: No dependencies - can start immediately
|
|
174
|
+
- **Foundational (Phase 2)**: Depends on Setup completion - BLOCKS all user stories
|
|
175
|
+
- **User Stories (Phase 3-7)**: All depend on Foundational phase completion
|
|
176
|
+
- User stories can then proceed in parallel (if staffed)
|
|
177
|
+
- Or sequentially in priority order (P1 → P2 → P3)
|
|
178
|
+
- **Polish (Phase 8)**: Depends on all user stories being complete
|
|
179
|
+
|
|
180
|
+
### User Story Dependencies
|
|
181
|
+
|
|
182
|
+
- **User Story 1 (P1)**: Can start after Foundational (Phase 2) - No dependencies on other stories
|
|
183
|
+
- **User Story 2 (P1)**: Can start after Foundational (Phase 2) - No dependencies on other stories
|
|
184
|
+
- **User Story 3 (P2)**: Can start after Foundational (Phase 2) - No dependencies on other stories
|
|
185
|
+
- **User Story 4 (P2)**: Can start after Foundational (Phase 2) - No dependencies on other stories
|
|
186
|
+
- **User Story 5 (P3)**: Can start after Foundational (Phase 2) - No dependencies on other stories
|
|
187
|
+
|
|
188
|
+
### Within Each User Story
|
|
189
|
+
|
|
190
|
+
- Tests (if included) MUST be written and FAIL before implementation
|
|
191
|
+
- Core implementation before integration
|
|
192
|
+
- Story complete before moving to next priority
|
|
193
|
+
|
|
194
|
+
### Parallel Opportunities
|
|
195
|
+
|
|
196
|
+
- All Setup tasks marked [P] can run in parallel
|
|
197
|
+
- All Foundational tasks marked [P] can run in parallel (within Phase 2)
|
|
198
|
+
- Once Foundational phase completes, all user stories can start in parallel (if team capacity allows)
|
|
199
|
+
- All tests for a user story marked [P] can run in parallel
|
|
200
|
+
- Different user stories can be worked on in parallel by different team members
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## Parallel Example: User Story 1
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
# Launch all tests for User Story 1 together:
|
|
208
|
+
Task: "Contract test for 'set' command in test/08-set-contract.test.js"
|
|
209
|
+
Task: "Integration test for placeholder replacement in test/09-placeholder-integration.test.js"
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## Implementation Strategy
|
|
215
|
+
|
|
216
|
+
### MVP First (User Story 1 Only)
|
|
217
|
+
|
|
218
|
+
1. Complete Phase 1: Setup
|
|
219
|
+
2. Complete Phase 2: Foundational (CRITICAL - blocks all stories)
|
|
220
|
+
3. Complete Phase 3: User Story 1
|
|
221
|
+
4. **STOP and VALIDATE**: Test User Story 1 independently
|
|
222
|
+
5. Deploy/demo if ready
|
|
223
|
+
|
|
224
|
+
### Incremental Delivery
|
|
225
|
+
|
|
226
|
+
1. Complete Setup + Foundational → Foundation ready
|
|
227
|
+
2. Add User Story 1 → Test independently → Deploy/Demo (MVP!)
|
|
228
|
+
3. Add User Story 2 → Test independently → Deploy/Demo
|
|
229
|
+
4. Add User Story 3 → Test independently → Deploy/Demo
|
|
230
|
+
5. Add User Story 4 → Test independently → Deploy/Demo
|
|
231
|
+
6. Add User Story 5 → Test independently → Deploy/Demo
|
|
232
|
+
7. Each story adds value without breaking previous stories
|
|
233
|
+
|
|
234
|
+
### Parallel Team Strategy
|
|
235
|
+
|
|
236
|
+
With multiple developers:
|
|
237
|
+
|
|
238
|
+
1. Team completes Setup + Foundational together
|
|
239
|
+
2. Once Foundational is done:
|
|
240
|
+
- Developer A: User Stories 1 & 2
|
|
241
|
+
- Developer B: User Stories 3 & 4
|
|
242
|
+
- Developer C: User Story 5
|
|
243
|
+
3. Stories complete and integrate independently
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## Notes
|
|
248
|
+
|
|
249
|
+
- [P] tasks = different files, no dependencies
|
|
250
|
+
- [Story] label maps task to specific user story for traceability
|
|
251
|
+
- Each user story should be independently completable and testable
|
|
252
|
+
- Verify tests fail before implementing
|
|
253
|
+
- Commit after each task or logical group
|
|
254
|
+
- Stop at any checkpoint to validate story independently
|
|
255
|
+
- Avoid: vague tasks, same file conflicts, cross-story dependencies that break independence
|
|
@@ -52,52 +52,28 @@ function _readTemplate ( tpl ) {
|
|
|
52
52
|
|
|
53
53
|
if ( typeof chop === 'string' ) hasError = chop
|
|
54
54
|
else {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
// Check helpers - sanity check
|
|
81
|
-
placeholders.forEach ( holder => {
|
|
82
|
-
if ( !holder.action ) return
|
|
83
|
-
holder.action.every ( act => {
|
|
84
|
-
if ( act === '#' ) return true
|
|
85
|
-
if ( act === '^^' ) return true
|
|
86
|
-
if ( act.startsWith('^') && act !== '^^' ) return true
|
|
87
|
-
if ( act.startsWith ( '?' )) act = act.replace ( '?', '' )
|
|
88
|
-
if ( act.startsWith ( '+' )) act = act.replace ( '+', '' )
|
|
89
|
-
if ( act.startsWith ( '[]' )) act = act.replace ( '[]', '' )
|
|
90
|
-
if ( act.startsWith ( '>' )) act = act.replace ( '>', '' )
|
|
91
|
-
if ( act === '' ) return true
|
|
92
|
-
if ( helpers[act] ) return true
|
|
93
|
-
else {
|
|
94
|
-
hasError = `Error: Missing helper: ${act}`
|
|
95
|
-
return false
|
|
96
|
-
}
|
|
97
|
-
}) // every action
|
|
98
|
-
}) // forEach placeholders
|
|
99
|
-
|
|
100
|
-
|
|
55
|
+
chop.forEach ( (item,i) => {
|
|
56
|
+
const
|
|
57
|
+
// Placeholder contains: Opening tag(TG_PRX), dataName, delimiter(:), list of operations, placeholder's name, closing tag(TG_SFX)
|
|
58
|
+
finding = RegExp ( TG_PRX + '\\s*(.*?)\\s*(?::\\s*(.*?)\\s*)?(?::\\s*(.*?)\\s*)?' + TG_SFX, 'g' )
|
|
59
|
+
, isPlaceholder = item.includes( TG_PRX )
|
|
60
|
+
;
|
|
61
|
+
|
|
62
|
+
if ( isPlaceholder ) {
|
|
63
|
+
const x = finding.exec ( item )
|
|
64
|
+
if ( !x ) return
|
|
65
|
+
let holder = {
|
|
66
|
+
index: i
|
|
67
|
+
, data : readData ( x[1] )
|
|
68
|
+
, action : x[2] ? x[2].split(',').map ( x => x.trim()) : null
|
|
69
|
+
, name : x[3] ? x[3].trim() : null
|
|
70
|
+
}
|
|
71
|
+
placeholders.push ( holder )
|
|
72
|
+
snippets[placeholders.length-1] = holder
|
|
73
|
+
if ( holder.name ) snippets[holder.name] = holder
|
|
74
|
+
} // if isPlaceholder
|
|
75
|
+
}) // forEach chop
|
|
76
|
+
} // else error
|
|
101
77
|
|
|
102
78
|
return {
|
|
103
79
|
hasError
|
|
@@ -40,14 +40,7 @@ function _setupActions ( actions, dataDeepLevel=10 ) {
|
|
|
40
40
|
if ( actLevel > dataDeepLevel ) return false
|
|
41
41
|
return true
|
|
42
42
|
}
|
|
43
|
-
|
|
44
|
-
actSetup[actLevel].push ({
|
|
45
|
-
type: 'route'
|
|
46
|
-
, name: act.replace ( '?', '' )
|
|
47
|
-
, level: actLevel
|
|
48
|
-
})
|
|
49
|
-
return true
|
|
50
|
-
}
|
|
43
|
+
|
|
51
44
|
if ( act.startsWith ('^') && act !== '^^' ) {
|
|
52
45
|
actSetup[actLevel].push ({
|
|
53
46
|
type: 'save'
|