spec-up-t 1.6.10 → 1.6.12

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.
Files changed (36) hide show
  1. package/package.json +1 -1
  2. package/src/install-from-boilerplate/boilerplate/.github/workflows/menu.yml +13 -13
  3. package/src/install-from-boilerplate/boilerplate/.github/workflows/render-and-deploy.yml +109 -0
  4. package/src/install-from-boilerplate/boilerplate/.github/workflows/set-gh-pages.yml +42 -40
  5. package/src/install-from-boilerplate/boilerplate/gitignore +3 -0
  6. package/src/install-from-boilerplate/boilerplate-templates/boilerplate-template-01/spec/spec-body.md +52 -0
  7. package/src/install-from-boilerplate/boilerplate-templates/boilerplate-template-01/spec/spec-coda.md +25 -0
  8. package/src/install-from-boilerplate/boilerplate-templates/boilerplate-template-01/spec/spec-head.md +33 -0
  9. package/src/install-from-boilerplate/boilerplate-templates/boilerplate-template-01/spec/terms-and-definitions-intro.md +5 -0
  10. package/src/install-from-boilerplate/boilerplate-templates/boilerplate-template-01/spec/terms-definitions/access-control.md +5 -0
  11. package/src/install-from-boilerplate/boilerplate-templates/boilerplate-template-01/spec/terms-definitions/decentralized-identifier.md +7 -0
  12. package/src/install-from-boilerplate/boilerplate-templates/boilerplate-template-01/spec/terms-definitions/trust-registry.md +7 -0
  13. package/src/install-from-boilerplate/boilerplate-templates/boilerplate-template-01/spec/terms-definitions/verifiable-credential.md +7 -0
  14. package/src/install-from-boilerplate/boilerplate-templates/boilerplate-template-01/specs.json +35 -0
  15. package/src/install-from-boilerplate/boilerplate-templates/boilerplate-template-02/spec/spec-part-1.md +17 -0
  16. package/src/install-from-boilerplate/boilerplate-templates/boilerplate-template-02/spec/spec-part-2.md +65 -0
  17. package/src/install-from-boilerplate/boilerplate-templates/boilerplate-template-02/spec/spec-part-3.md +17 -0
  18. package/src/install-from-boilerplate/boilerplate-templates/boilerplate-template-02/spec/terms-and-definitions-intro.md +5 -0
  19. package/src/install-from-boilerplate/boilerplate-templates/boilerplate-template-02/spec/terms-definitions/composability.md +5 -0
  20. package/src/install-from-boilerplate/boilerplate-templates/boilerplate-template-02/spec/terms-definitions/compost.md +3 -0
  21. package/src/install-from-boilerplate/boilerplate-templates/boilerplate-template-02/spec/terms-definitions/dormancy.md +5 -0
  22. package/src/install-from-boilerplate/boilerplate-templates/boilerplate-template-02/spec/terms-definitions/fertilizer.md +3 -0
  23. package/src/install-from-boilerplate/boilerplate-templates/boilerplate-template-02/spec/terms-definitions/greenhouse.md +5 -0
  24. package/src/install-from-boilerplate/boilerplate-templates/boilerplate-template-02/spec/terms-definitions/mulch.md +3 -0
  25. package/src/install-from-boilerplate/boilerplate-templates/boilerplate-template-02/spec/terms-definitions/pruning.md +3 -0
  26. package/src/install-from-boilerplate/boilerplate-templates/boilerplate-template-02/spec/terms-definitions/seedling.md +3 -0
  27. package/src/install-from-boilerplate/boilerplate-templates/boilerplate-template-02/spec/terms-definitions/soil.md +13 -0
  28. package/src/install-from-boilerplate/boilerplate-templates/boilerplate-template-02/spec/terms-definitions/watering.md +3 -0
  29. package/src/install-from-boilerplate/boilerplate-templates/boilerplate-template-02/specs.json +40 -0
  30. package/src/install-from-boilerplate/config-gitignore-entries.js +3 -1
  31. package/src/install-from-boilerplate/config-system-files.js +1 -0
  32. package/src/install-from-boilerplate/config-templates.js +39 -0
  33. package/src/install-from-boilerplate/copy-boilerplate.js +61 -8
  34. package/src/install-from-boilerplate/copy-system-files.js +6 -0
  35. package/src/install-from-boilerplate/install.js +11 -1
  36. package/src/install-from-boilerplate/select-template.js +51 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spec-up-t",
3
- "version": "1.6.10",
3
+ "version": "1.6.12",
4
4
  "description": "Technical specification drafting tool that generates rich specification documents from markdown. Forked from https://github.com/decentralized-identity/spec-up by Daniel Buchner (https://github.com/csuwildcat)",
5
5
  "main": "./index",
6
6
  "repository": {
@@ -33,7 +33,8 @@ jobs:
33
33
  build-and-deploy-spec:
34
34
  runs-on: ubuntu-latest
35
35
  permissions:
36
- contents: write # Needed for pushing changes and deploying to Pages
36
+ contents: write # Needed for pushing changes
37
+ actions: write # Needed to dispatch render-and-deploy.yml
37
38
  steps:
38
39
  - name: Checkout šŸ›Žļø
39
40
  uses: actions/checkout@v4
@@ -68,7 +69,14 @@ jobs:
68
69
  run: |
69
70
  case "${{ github.event.inputs.action_type }}" in
70
71
  render)
71
- npm run render
72
+ # Rendering is handled by render-and-deploy.yml.
73
+ # Dispatch that workflow to render and deploy to GitHub Pages.
74
+ curl -s -X POST \
75
+ -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
76
+ -H "Accept: application/vnd.github+json" \
77
+ "https://api.github.com/repos/${{ github.repository }}/actions/workflows/render-and-deploy.yml/dispatches" \
78
+ -d "{\"ref\":\"${{ github.ref_name }}\"}"
79
+ echo "render-and-deploy.yml dispatched"
72
80
  ;;
73
81
  topdf)
74
82
  npm run topdf
@@ -105,7 +113,8 @@ jobs:
105
113
  # Commit with appropriate message
106
114
  case "${{ github.event.inputs.action_type }}" in
107
115
  render)
108
- git commit -m "Render specification: Update files" || echo "No changes to commit"
116
+ # render-and-deploy.yml already handles the commit/deploy; nothing to commit here.
117
+ echo "Render dispatched to render-and-deploy.yml — no direct commit needed"
109
118
  ;;
110
119
  topdf)
111
120
  git commit -m "Export to PDF" || echo "No changes to commit"
@@ -128,16 +137,7 @@ jobs:
128
137
  esac
129
138
 
130
139
  # Push changes
131
- git push https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git HEAD:main
132
-
133
- - name: Commit output files
134
- if: success()
135
- run: |
136
- git config --global user.email "actions@github.com"
137
- git config --global user.name "GitHub Actions"
138
- git add "$OUTPUT_PATH"
139
- git commit -m "Update output files in $OUTPUT_PATH" || echo "No changes to commit in output directory"
140
- git push https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git HEAD:main
140
+ git push https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git HEAD:${{ github.ref_name }}
141
141
 
142
142
  - name: Clean up
143
143
  if: always()
@@ -0,0 +1,109 @@
1
+ name: Render and Deploy to GitHub Pages
2
+
3
+ # Triggered automatically on every push to main or master, or manually via
4
+ # the Actions tab (or when dispatched by menu.yml for a render action).
5
+ # Renders the specification and pushes the output to the gh-pages branch.
6
+ # docs/ is NEVER committed to main/master.
7
+
8
+ on:
9
+ push:
10
+ branches:
11
+ - main
12
+ - master
13
+ # Do not trigger on workflow file changes (.github/). Each workflow file
14
+ # is uploaded as a separate commit during repo creation, which would cause
15
+ # multiple competing runs in the same concurrency group. Real spec content
16
+ # changes (spec/, specs.json, package.json, etc.) still trigger a render.
17
+ # The initial render after repo creation is handled by an explicit dispatch.
18
+ # The trigger matrix is now:
19
+ #
20
+ # Event --> Triggers render?
21
+ #
22
+ # Push spec content (spec, specs.json, etc.) --> āœ… yes
23
+ # Push `.github/workflows/*.yml` (repo creation) --> āŒ no
24
+ # `workflow_dispatch` (GitHubUi "render" button, or menu.yml) --> āœ… yes
25
+ # PR into main/master --> āŒ not triggered (no `pull_request:` event)
26
+
27
+ paths-ignore:
28
+ - '.github/**'
29
+ workflow_dispatch:
30
+
31
+ # Only allow one deployment at a time; do not cancel in-progress runs so that
32
+ # a completed deploy is never replaced by a stale one.
33
+ # NOTE: do NOT use 'pages' as the group name — that conflicts with GitHub's own
34
+ # internal Pages deployment concurrency group and causes spurious cancellations.
35
+ concurrency:
36
+ group: render-and-deploy-${{ github.ref }}
37
+ cancel-in-progress: false
38
+
39
+ jobs:
40
+ # ── Build & Deploy ────────────────────────────────────────────────────────────
41
+ build-and-deploy:
42
+ runs-on: ubuntu-latest
43
+ # GitHub automatically generates a GITHUB_TOKEN for each workflow run.
44
+ # This ephemeral token is scoped only to the current repository and expires
45
+ # after the run completes. The 'permissions' block declares what this token
46
+ # is allowed to do — GitHub denies operations outside these scopes.
47
+ permissions:
48
+ contents: write # Required by peaceiris/actions-gh-pages to push to gh-pages
49
+ pages: write # Required to configure GitHub Pages source via API
50
+ steps:
51
+ - name: Checkout šŸ›Žļø
52
+ uses: actions/checkout@v4
53
+
54
+ - name: Set up Node.js
55
+ uses: actions/setup-node@v4
56
+ with:
57
+ node-version: '20'
58
+
59
+ - name: Install dependencies šŸ”§
60
+ run: npm install
61
+
62
+ # Collect external references — this also renders the specification and
63
+ # writes output to the path defined in specs.json (output_path, typically ./docs/).
64
+ - name: Collect external references and render
65
+ run: npm run collectExternalReferences
66
+
67
+ # Push the rendered ./docs output to the gh-pages branch.
68
+ # peaceiris/actions-gh-pages creates the branch on first run when it
69
+ # does not yet exist — no manual branch setup is required.
70
+ # Uses GITHUB_TOKEN (automatically injected by GitHub) with 'contents: write'
71
+ # permission to push to this repository.
72
+ - name: Deploy to GitHub Pages šŸš€
73
+ uses: peaceiris/actions-gh-pages@v3
74
+ with:
75
+ github_token: ${{ secrets.GITHUB_TOKEN }}
76
+ publish_dir: ./docs
77
+ publish_branch: gh-pages
78
+
79
+ # Configure GitHub Pages to serve from the gh-pages branch (root /).
80
+ # This uses the GitHub REST API with GITHUB_TOKEN (permission: 'pages: write').
81
+ # It is idempotent — safe to run on every render (201=create, 409/422=exists, update).
82
+ # GITHUB_TOKEN is ephemeral (created per-run, expires at run end), scoped only to
83
+ # this repository, and never logged. GitHub accepts it because the token is issued
84
+ # by GitHub itself and this workflow declares 'pages: write' permission.
85
+ # continue-on-error: the API call may return a conflict on the very first run while
86
+ # GitHub is still processing the new gh-pages branch — this is non-fatal.
87
+ - name: Configure GitHub Pages source
88
+ continue-on-error: true
89
+ run: |
90
+ TOKEN="${{ secrets.GITHUB_TOKEN }}"
91
+ REPO="${{ github.repository }}"
92
+
93
+ HTTP_CODE=$(curl -s -o response.json -w "%{http_code}" \
94
+ -X POST \
95
+ -H "Authorization: token $TOKEN" \
96
+ -H "Accept: application/vnd.github+json" \
97
+ "https://api.github.com/repos/$REPO/pages" \
98
+ -d '{"source":{"branch":"gh-pages","path":"/"}}')
99
+
100
+ # 201 = created; 409/422 = already exists, update instead
101
+ if [ "$HTTP_CODE" -eq 409 ] || [ "$HTTP_CODE" -eq 422 ]; then
102
+ curl -s -o /dev/null \
103
+ -X PUT \
104
+ -H "Authorization: token $TOKEN" \
105
+ -H "Accept: application/vnd.github+json" \
106
+ "https://api.github.com/repos/$REPO/pages" \
107
+ -d '{"source":{"branch":"gh-pages","path":"/"}}'
108
+ fi
109
+ echo "GitHub Pages source set to gh-pages branch"
@@ -1,5 +1,10 @@
1
1
  name: Set GitHub Pages and Homepage
2
2
 
3
+ # One-time setup workflow: run this AFTER the first successful
4
+ # render-and-deploy run, which creates the gh-pages branch.
5
+ # It configures GitHub Pages to serve from the gh-pages branch (root /)
6
+ # and sets the repository homepage URL.
7
+
3
8
  on:
4
9
  workflow_dispatch:
5
10
 
@@ -7,93 +12,90 @@ jobs:
7
12
  configure-pages-and-homepage:
8
13
  runs-on: ubuntu-latest
9
14
  permissions:
10
- contents: read # To check branches
11
- pages: write # To configure Pages settings
15
+ contents: read
12
16
  steps:
13
- - name: Check if gh-pages branch exists
14
- id: check-branch
15
- run: |
16
- RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" \
17
- -H "Authorization: token ${{ secrets.MY_PAT }}" \
18
- -H "Accept: application/vnd.github+json" \
19
- https://api.github.com/repos/${{ github.repository }}/branches/gh-pages)
20
- if [ "$RESPONSE" -eq 200 ]; then
21
- echo "gh-pages branch exists"
22
- echo "BRANCH_EXISTS=true" >> $GITHUB_ENV
23
- elif [ "$RESPONSE" -eq 404 ]; then
24
- echo "Error: gh-pages branch does not exist in ${{ github.repository }}"
25
- exit 1
26
- else
27
- echo "Unexpected response code: $RESPONSE"
28
- exit 1
29
- fi
30
-
31
- - name: Set GitHub Pages to gh-pages
32
- if: env.BRANCH_EXISTS == 'true'
17
+ # Configure Pages to serve from the gh-pages branch (root /).
18
+ # POST creates the resource; a 409 means it already exists, so we PUT
19
+ # to update the source to the gh-pages branch.
20
+ - name: Enable GitHub Pages (gh-pages branch source)
33
21
  env:
34
22
  PAT: ${{ secrets.MY_PAT }}
35
23
  run: |
36
- RESPONSE=$(curl -s -L \
24
+ HTTP_CODE=$(curl -s -L \
37
25
  -X POST \
38
26
  -H "Authorization: token $PAT" \
39
27
  -H "Accept: application/vnd.github+json" \
40
28
  https://api.github.com/repos/${{ github.repository }}/pages \
41
29
  -d '{"source":{"branch":"gh-pages","path":"/"}}' \
42
- -w "%{http_code}" -o response.json)
43
- if [ "$RESPONSE" -eq 201 ] || [ "$RESPONSE" -eq 200 ]; then
44
- echo "GitHub Pages set to gh-pages branch for ${{ github.repository }}"
30
+ -w "%{http_code}" -o response.json | tail -n1)
31
+
32
+ if [ "$HTTP_CODE" -eq 201 ] || [ "$HTTP_CODE" -eq 200 ]; then
33
+ echo "GitHub Pages enabled with gh-pages branch as source"
34
+ elif [ "$HTTP_CODE" -eq 409 ]; then
35
+ echo "Pages already exists — updating source to gh-pages branch..."
36
+ HTTP_CODE2=$(curl -s -L \
37
+ -X PUT \
38
+ -H "Authorization: token $PAT" \
39
+ -H "Accept: application/vnd.github+json" \
40
+ https://api.github.com/repos/${{ github.repository }}/pages \
41
+ -d '{"source":{"branch":"gh-pages","path":"/"}}' \
42
+ -w "%{http_code}" -o response2.json | tail -n1)
43
+ if [ "$HTTP_CODE2" -eq 200 ] || [ "$HTTP_CODE2" -eq 204 ]; then
44
+ echo "GitHub Pages source updated to gh-pages branch"
45
+ else
46
+ echo "Failed to update Pages: $HTTP_CODE2"
47
+ cat response2.json
48
+ exit 1
49
+ fi
45
50
  else
46
- echo "Failed to set GitHub Pages: $RESPONSE"
51
+ echo "Failed to configure Pages: $HTTP_CODE"
47
52
  cat response.json
48
53
  exit 1
49
54
  fi
50
55
 
56
+ # Set the repository homepage field to the expected GitHub Pages URL so
57
+ # it appears prominently on the repository landing page.
51
58
  - name: Set repository homepage to GitHub Pages URL
52
- if: env.BRANCH_EXISTS == 'true'
53
59
  env:
54
60
  PAT: ${{ secrets.MY_PAT }}
55
61
  run: |
56
- # Construct the expected GitHub Pages URL
57
62
  REPO_NAME=$(echo "${{ github.repository }}" | cut -d'/' -f2)
58
63
  OWNER=$(echo "${{ github.repository }}" | cut -d'/' -f1)
59
64
  PAGES_URL="https://${OWNER}.github.io/${REPO_NAME}"
60
65
 
61
- # Set the homepage via API
62
- RESPONSE=$(curl -s -L \
66
+ HTTP_CODE=$(curl -s -L \
63
67
  -X PATCH \
64
68
  -H "Authorization: token $PAT" \
65
69
  -H "Accept: application/vnd.github+json" \
66
70
  https://api.github.com/repos/${{ github.repository }} \
67
71
  -d "{\"homepage\":\"${PAGES_URL}\"}" \
68
- -w "%{http_code}" -o response.json)
72
+ -w "%{http_code}" -o response.json | tail -n1)
69
73
 
70
- if [ "$RESPONSE" -eq 200 ]; then
71
- echo "Repository homepage set to $PAGES_URL for ${{ github.repository }}"
74
+ if [ "$HTTP_CODE" -eq 200 ]; then
75
+ echo "Repository homepage set to $PAGES_URL"
72
76
  else
73
- echo "Failed to set homepage: $RESPONSE"
77
+ echo "Failed to set homepage: $HTTP_CODE"
74
78
  cat response.json
75
79
  exit 1
76
80
  fi
77
81
 
82
+ # Verify the homepage was written correctly.
78
83
  - name: Verify homepage matches GitHub Pages URL
79
- if: env.BRANCH_EXISTS == 'true'
80
84
  env:
81
85
  PAT: ${{ secrets.MY_PAT }}
82
86
  run: |
83
- # Construct the expected GitHub Pages URL
84
87
  REPO_NAME=$(echo "${{ github.repository }}" | cut -d'/' -f2)
85
88
  OWNER=$(echo "${{ github.repository }}" | cut -d'/' -f1)
86
89
  EXPECTED_URL="https://${OWNER}.github.io/${REPO_NAME}"
87
90
 
88
- # Fetch the current homepage from the repo
89
91
  CURRENT_HOMEPAGE=$(curl -s -L \
90
92
  -H "Authorization: token $PAT" \
91
93
  -H "Accept: application/vnd.github+json" \
92
94
  https://api.github.com/repos/${{ github.repository }} | jq -r '.homepage')
93
95
 
94
96
  if [ "$CURRENT_HOMEPAGE" = "$EXPECTED_URL" ]; then
95
- echo "Verified: Homepage is set to GitHub Pages URL ($EXPECTED_URL)"
97
+ echo "Verified: homepage is $EXPECTED_URL"
96
98
  else
97
- echo "Error: Homepage ($CURRENT_HOMEPAGE) does not match expected GitHub Pages URL ($EXPECTED_URL)"
99
+ echo "Error: homepage ($CURRENT_HOMEPAGE) does not match $EXPECTED_URL"
98
100
  exit 1
99
101
  fi
@@ -10,6 +10,9 @@
10
10
  # `.git/info/exclude` file instead of modifying the shared .gitignore.
11
11
  # Entries in `.git/info/exclude` stay completely local.
12
12
 
13
+ # Generated by render-and-deploy.yml — do not commit build output
14
+ docs/
15
+
13
16
  # Dependencies
14
17
  node_modules/
15
18
 
@@ -0,0 +1,52 @@
1
+ ## Requirements
2
+
3
+ *This section contains the normative requirements of the specification. Replace the examples below with your actual requirements.*
4
+
5
+ ### General Requirements
6
+
7
+ The following requirements apply to all conforming implementations:
8
+
9
+ 1. Implementations MUST ...
10
+ 2. Implementations SHOULD ...
11
+ 3. Implementations MAY ...
12
+
13
+ ### Protocol Requirements
14
+
15
+ *Add detailed technical or protocol requirements here.*
16
+
17
+ ::: note Informative Note
18
+ Requirements marked with MUST are normative. Requirements marked with SHOULD are recommended but not mandatory. Requirements marked with MAY are optional.
19
+ :::
20
+
21
+ ::: todo Open Issue
22
+ Placeholder — replace with actual open items or remove this block before publication.
23
+ :::
24
+
25
+ ## Architecture Overview
26
+
27
+ *Provide an architectural description of the system or protocol defined by this specification. Diagrams and tables are encouraged.*
28
+
29
+ ### The ToIP Stack Context
30
+
31
+ This specification operates within the [ToIP Technology Architecture Specification](https://trustoverip.github.io/TechArch/) layered model. The ToIP stack comprises four layers:
32
+
33
+ | Layer | Name | Description |
34
+ |------:|:-----|:------------|
35
+ | 4 | Application Ecosystem | Trust applications and governance frameworks |
36
+ | 3 | Trust Task | Credential exchange and trust negotiation |
37
+ | 2 | Trust Spanning | Peer-to-peer messaging between agents |
38
+ | 1 | Trust Support | Verifiable data registries and DID infrastructure |
39
+
40
+ *Indicate which layer(s) this specification addresses.*
41
+
42
+ ## Security Considerations
43
+
44
+ *Describe relevant security properties, threat models, and mitigations.*
45
+
46
+ ::: warning Security Note
47
+ Implementers MUST carefully review the security considerations before deployment.
48
+ :::
49
+
50
+ ## Privacy Considerations
51
+
52
+ *Describe how privacy is preserved and any data-minimization requirements.*
@@ -0,0 +1,25 @@
1
+ ## Appendix
2
+
3
+ ### Revision History
4
+
5
+ | Version | Date | Changes |
6
+ |--------:|:-----|:--------|
7
+ | 0.1 | [Date] | Initial draft |
8
+
9
+ ### References
10
+
11
+ #### Normative References
12
+
13
+ - ToIP Technical Architecture Specification — [https://trustoverip.github.io/TechArch/](https://trustoverip.github.io/TechArch/)
14
+ - W3C Verifiable Credentials Data Model — [https://www.w3.org/TR/vc-data-model/](https://www.w3.org/TR/vc-data-model/)
15
+ - W3C Decentralized Identifiers (DIDs) — [https://www.w3.org/TR/did-core/](https://www.w3.org/TR/did-core/)
16
+
17
+ #### Informative References
18
+
19
+ - Trust over IP Foundation — [https://trustoverip.org/](https://trustoverip.org/)
20
+ - ToIP Technical Architecture — [https://trustoverip.org/our-work/technical-architecture/](https://trustoverip.org/our-work/technical-architecture/)
21
+ - Spec-Up-T Documentation — [https://trustoverip.github.io/spec-up-t-website/](https://trustoverip.github.io/spec-up-t-website/)
22
+
23
+ ### Acknowledgements
24
+
25
+ This specification was developed with contributions from members of the [Trust over IP Foundation](https://trustoverip.org/) and reviewed by the ToIP Steering Committee.
@@ -0,0 +1,33 @@
1
+ # [Your Specification Title]
2
+
3
+ ::: warning Warning Notice
4
+ This content is created with Artificial Intelligence, based on information about ToIP available online.
5
+ :::
6
+
7
+ ## Introduction
8
+
9
+ *This is a template for [Trust over IP (ToIP)](https://trustoverip.org/) specifications. Replace all placeholder text with your own content. See the [Spec-Up-T documentation](https://trustoverip.github.io/spec-up-t-website/) for authoring guidance.*
10
+
11
+ This specification is developed under the auspices of the [Trust over IP Foundation](https://trustoverip.org/) and follows the structure recommended by the ToIP Steering Committee.
12
+
13
+ ## Abstract
14
+
15
+ *Provide a brief abstract summarizing the purpose, scope, and intended audience of this specification. One to three paragraphs is typical.*
16
+
17
+ ## Scope
18
+
19
+ This document defines the normative requirements for ...
20
+
21
+ The following topics are **within scope**:
22
+
23
+ - ...
24
+
25
+ The following topics are **out of scope**:
26
+
27
+ - ...
28
+
29
+ ## Conformance
30
+
31
+ As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
32
+
33
+ The key words *MAY*, *MUST*, *MUST NOT*, *OPTIONAL*, *RECOMMENDED*, *REQUIRED*, *SHOULD*, and *SHOULD NOT* in this document are to be interpreted as described in [BCP 14](https://www.rfc-editor.org/info/bcp14) when, and only when, they appear in all capitals, as shown here.
@@ -0,0 +1,5 @@
1
+ [//]: # (This file, named "terms-and-definitions-intro.md" is mandatory and should not be deleted. However, you can safely delete this comment and replace it with text of your choice.)
2
+
3
+ ## Terms and definitions
4
+
5
+ This section defines key terms used throughout this specification. Terms marked with cross-references (xref) or term-references (tref) link to definitions in other ToIP specifications.
@@ -0,0 +1,5 @@
1
+ [[tref: toipglos, access-control]]
2
+
3
+ ~ *Note: This is a **tref** example — the definition of "access-control" is imported from the ToIP Glossary rather than defined locally. Use `tref` when you want to reuse the exact definition from another specification. Replace `toipglos` with the external spec key configured in your `specs.json`.*
4
+
5
+ ~ See also: [[ref: trust registry]], [[xref: toipglos, controller]].
@@ -0,0 +1,7 @@
1
+ [[def: decentralized identifier, decentralized identifiers, DID, DIDs]]
2
+
3
+ ~ A **decentralized identifier** (DID) is a globally unique, persistent identifier that does not require a centralized registration authority. A DID resolves to a DID document containing cryptographic material that allows the [[ref: controller]] to authenticate and prove control.
4
+
5
+ ~ *Note: This is an example term included for demonstration purposes. Replace this definition with precise, normative language appropriate to your specification.*
6
+
7
+ ~ See also: [[ref: verifiable credential]], [[xref: toipglos, controller]].
@@ -0,0 +1,7 @@
1
+ [[def: trust registry, trust registries]]
2
+
3
+ ~ A **trust registry** is an authoritative source that an ecosystem uses to determine whether a party (such as an [[ref: issuer]] or [[ref: verifier]]) is trusted within the constraints of a given [[ref: governance framework]]. It enables automated trust decisions without relying on out-of-band verification.
4
+
5
+ ~ *Note: This is an example term included for demonstration purposes. Replace this definition with precise, normative language appropriate to your specification.*
6
+
7
+ ~ See also: [[ref: governance framework]], [[xref: toipglos, issuer]].
@@ -0,0 +1,7 @@
1
+ [[def: verifiable credential, verifiable credentials, VC, VCs]]
2
+
3
+ ~ A **verifiable credential** (VC) is a tamper-evident digital credential whose authorship can be cryptographically verified. It contains claims made by an [[ref: issuer]] about a [[ref: holder]], and is presented to a [[ref: verifier]] as proof.
4
+
5
+ ~ *Note: This is an example term included for demonstration purposes. Replace this definition with precise, normative language appropriate to your specification.*
6
+
7
+ ~ See also: [[xref: toipglos, issuer]], [[xref: toipglos, holder]] for how these roles are defined in the ToIP Glossary.
@@ -0,0 +1,35 @@
1
+ {
2
+ "specs": [
3
+ {
4
+ "title": "[Your Specification Title]",
5
+ "description": "A Trust over IP Foundation specification. Replace this description with a summary of your specification.",
6
+ "author": "Trust over IP Foundation",
7
+ "spec_directory": "./spec",
8
+ "spec_terms_directory": "terms-definitions",
9
+ "output_path": "./docs",
10
+ "markdown_paths": [
11
+ "spec-head.md",
12
+ "terms-and-definitions-intro.md",
13
+ "spec-body.md",
14
+ "spec-coda.md"
15
+ ],
16
+ "logo": "https://raw.githubusercontent.com/trustoverip/spec-up-t/refs/heads/master/src/install-from-boilerplate/boilerplate/static/logo.svg",
17
+ "logo_link": "https://github.com/trustoverip/spec-up-t",
18
+ "favicon": "https://raw.githubusercontent.com/trustoverip/spec-up-t/refs/heads/master/src/install-from-boilerplate/boilerplate/static/favicon.ico",
19
+ "source": {
20
+ "host": "github",
21
+ "account": "trustoverip",
22
+ "repo": "your-spec-repo"
23
+ },
24
+ "external_specs": [
25
+ {
26
+ "external_spec": "toipglos",
27
+ "gh_page": "https://glossary.trustoverip.org/",
28
+ "url": "https://github.com/trustoverip/ctwg-main-glossary"
29
+ }
30
+ ],
31
+ "katex": false,
32
+ "anchor_symbol": "§"
33
+ }
34
+ ]
35
+ }
@@ -0,0 +1,17 @@
1
+ # Spec-Up-T Specification
2
+
3
+ ## Part 1: Introduction and Background
4
+
5
+ ### About This Specification
6
+
7
+ This is a default Spec-Up-T installation using the "Multi-Part" content template. Find information on the [Spec-Up-T documentation website](https://trustoverip.github.io/spec-up-t-website/).
8
+
9
+ This is a demo site for Spec-Up-T. The subject matter – gardening and related terms – is used purely as an example to demonstrate how the system works. You can replace these demo terms and definitions with your own content to suit your documentation needs.
10
+
11
+ ### Background
12
+
13
+ Provide background information and context for your specification here. Explain the problem space, motivation, and any relevant history that helps readers understand the purpose of this document.
14
+
15
+ ### Scope and Purpose
16
+
17
+ Define the boundaries of what this specification covers and what it does not. Clearly stating the scope helps readers understand the applicability of the specification.
@@ -0,0 +1,65 @@
1
+ ## Part 2: Technical Details
2
+
3
+ This section contains the core technical content of the specification. Add your detailed requirements, algorithms, data formats, and protocols here.
4
+
5
+ ### Blockquote
6
+
7
+ > To be, or not to be, that is the question:
8
+ Whether 'tis nobler in the mind to suffer
9
+ The slings and arrows of outrageous fortune,
10
+ Or to take arms against a sea of troubles
11
+ And by opposing end them. To die—to sleep,
12
+ No more;
13
+
14
+ ### Notices
15
+
16
+ ::: note Basic Note
17
+ Check this out.
18
+ :::
19
+
20
+ ::: warning Warning Notice
21
+ Houston, I think we have a problem
22
+ :::
23
+
24
+ ::: todo Really Important
25
+ Get this done!
26
+ :::
27
+
28
+ ::: example Code Example
29
+
30
+ ```json
31
+ // Some comment in JSON
32
+ {
33
+ "foo": "bar",
34
+ "baz": 2
35
+ }
36
+ ```
37
+
38
+ :::
39
+
40
+ ### Content from External Files
41
+
42
+ Use the following format to pull in content from other files in your project:
43
+
44
+ This text has been inserted here from another file: [[insert: assets/test.text]]
45
+
46
+ ::: example Code Example
47
+
48
+ ```json
49
+ [[insert: assets/test.json]]
50
+ ```
51
+
52
+ :::
53
+
54
+ ### Tables
55
+
56
+ | Stage | Direct Products | ATP Yields |
57
+ | -----------------: | --------------: | ---------: |
58
+ | Glycolysis | 2 ATP | |
59
+ | ^^ | 2 NADH | 3--5 ATP |
60
+ | Pyruvaye oxidation | 2 NADH | 5 ATP |
61
+ | Citric acid cycle | 2 ATP | |
62
+ | ^^ | 6 NADH | 15 ATP |
63
+ | ^^ | 2 FADH2 | 3 ATP |
64
+ | **30--32** ATP | | |
65
+ [Net ATP yields per hexose]
@@ -0,0 +1,17 @@
1
+ ## Part 3: Summary and Implementation Notes
2
+
3
+ ### Summary
4
+
5
+ Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?
6
+
7
+ ### Implementation Notes
8
+
9
+ Include implementation guidance, best practices, and notes for implementers here. This section helps bridge the gap between the specification and practical implementation.
10
+
11
+ ### Future Work
12
+
13
+ Describe planned extensions, improvements, or areas for further development here.
14
+
15
+ ### References
16
+
17
+ This section can contain references to other documents, standards, and resources used in this specification.
@@ -0,0 +1,5 @@
1
+ [//]: # (This file, named "terms-and-definitions-intro.md" is mandatory and should not be deleted. However, you can safely delete this comment and replace it with text of your choice.)
2
+
3
+ ## Terms and definitions
4
+
5
+ This is the terms and definitions section
@@ -0,0 +1,5 @@
1
+ [[tref: ExtRef1, greenhouse]]
2
+
3
+ ~ Note: This is a tref example. The term "greenhouse" is imported from the ExtRef1 external glossary (focused on greenhouse and irrigation concepts).
4
+
5
+ ~ See also: [[xref: ExtRef2, propagation]] for plant propagation from ExtRef2.
@@ -0,0 +1,3 @@
1
+ [[def: compost, composting, Compost]]
2
+
3
+ ~ Compost is a mixture of decayed organic matter used to fertilize soil. It is created through the process of composting, where materials like leaves, food scraps, and grass clippings break down over time. Compost improves soil structure and provides nutrients for plants. See also [[ref: Mulch]], [[ref: Soil]], [[ref: Fertilizer]], [[ref: Seedling]], [[ref: Watering]].
@@ -0,0 +1,5 @@
1
+ [[tref: ExtRef2, dormancy]]
2
+
3
+ ~ Note: This is a tref example. The term "dormancy" is imported from the ExtRef2 external glossary (focused on plant lifecycle and propagation concepts).
4
+
5
+ ~ See also: [[xref: ExtRef1, perennial]] for perennial plants from ExtRef1.
@@ -0,0 +1,3 @@
1
+ [[def: fertilizer, fertilizing, Fertilizer]]
2
+
3
+ ~ Fertilizer is a substance added to soil or plants to supply essential nutrients and promote growth. Fertilizers can be organic, like compost, or synthetic. Proper fertilizing ensures healthy plant development. See also [[ref: Compost]], [[ref: Mulch]], [[ref: Soil]], [[ref: Watering]], [[ref: Seedling]].
@@ -0,0 +1,5 @@
1
+ [[tref: ExtRef1, greenhouse]]
2
+
3
+ ~ Note: This is a tref example. The term "greenhouse" is imported from the ExtRef1 external glossary (focused on greenhouse and irrigation concepts).
4
+
5
+ ~ See also: [[xref: ExtRef2, propagation]] for plant propagation from ExtRef2.
@@ -0,0 +1,3 @@
1
+ [[def: mulch, mulching, Mulch]]
2
+
3
+ ~ Mulch is a layer of material, such as wood chips or straw, spread on the surface of soil to retain moisture, suppress weeds, and regulate temperature. Mulching helps improve plant health and soil quality. Related terms: [[ref: Compost]], [[ref: Soil]], [[ref: Fertilizer]].
@@ -0,0 +1,3 @@
1
+ [[def: pruning, Pruning]]
2
+
3
+ ~ Pruning is the practice of trimming plants by cutting away dead or overgrown branches or stems. Pruning encourages healthy growth and improves the shape of plants. See also [[ref: Seedling]], [[ref: Watering]].
@@ -0,0 +1,3 @@
1
+ [[def: seedling, seedlings, Seedling]]
2
+
3
+ ~ A seedling is a young plant that has recently sprouted from a seed. Seedlings are delicate and require proper soil, water, and light to grow into mature plants. See also [[ref: Soil]], [[ref: Compost]], [[ref: Watering]].
@@ -0,0 +1,13 @@
1
+ [[def: soil, soils, Soil]]
2
+
3
+ ~ Soil is the upper layer of earth in which plants grow. It consists of a mixture of organic matter, minerals, gases, liquids, and organisms that together support life. Healthy soil is essential for gardening and agriculture.
4
+
5
+ ~ Refs examples: [[ref: Compost]], [[ref: Mulch]], [[ref: Fertilizer]].
6
+
7
+ ~ Xref examples from external gardening glossaries:
8
+ ~ - From ExtRef1 (greenhouse focus): [[xref: ExtRef1, greenhouse]], [[xref: ExtRef1, irrigation]]
9
+ ~ - From ExtRef2 (lifecycle focus): [[xref: ExtRef2, dormancy]], [[xref: ExtRef2, propagation]]
10
+
11
+ ~ Note: The term "soil" exists in ExtRef1 and ExtRef2 with different definitions focused on their respective themes.
12
+
13
+ ~ Soil quality affects water retention, nutrient availability, and plant health. Amending soil with compost or mulch can improve its structure and fertility. Fertilizer may be added to supplement nutrients as needed.
@@ -0,0 +1,3 @@
1
+ [[def: watering, Watering]]
2
+
3
+ ~ Watering is the act of supplying water to plants to help them grow. Proper watering is essential for healthy roots and overall plant development. Overwatering or underwatering can harm plants. See also [[ref: Soil]], [[ref: Seedling]], [[ref: Mulch]].
@@ -0,0 +1,40 @@
1
+ {
2
+ "specs": [
3
+ {
4
+ "title": "Spec-Up-T Starterpack",
5
+ "description": "Create technical specifications in markdown. Based on the original Spec-Up, extended with Terminology tooling",
6
+ "author": "Trust over IP Foundation",
7
+ "spec_directory": "./spec",
8
+ "spec_terms_directory": "terms-definitions",
9
+ "output_path": "./docs",
10
+ "markdown_paths": [
11
+ "spec-part-1.md",
12
+ "terms-and-definitions-intro.md",
13
+ "spec-part-2.md",
14
+ "spec-part-3.md"
15
+ ],
16
+ "logo": "https://raw.githubusercontent.com/trustoverip/spec-up-t/refs/heads/master/src/install-from-boilerplate/boilerplate/static/logo.svg",
17
+ "logo_link": "https://github.com/trustoverip/spec-up-t",
18
+ "favicon": "https://raw.githubusercontent.com/trustoverip/spec-up-t/refs/heads/master/src/install-from-boilerplate/boilerplate/static/favicon.ico",
19
+ "source": {
20
+ "host": "github",
21
+ "account": "trustoverip",
22
+ "repo": "spec-up-t-starter-pack"
23
+ },
24
+ "external_specs": [
25
+ {
26
+ "external_spec": "ExtRef1",
27
+ "gh_page": "https://trustoverip.github.io/spec-up-t-demo-external-ref-1/",
28
+ "url": "https://github.com/trustoverip/spec-up-t-demo-external-ref-1"
29
+ },
30
+ {
31
+ "external_spec": "ExtRef2",
32
+ "gh_page": "https://trustoverip.github.io/spec-up-t-demo-external-ref-2/",
33
+ "url": "https://github.com/trustoverip/spec-up-t-demo-external-ref-2"
34
+ }
35
+ ],
36
+ "katex": false,
37
+ "anchor_symbol": "§"
38
+ }
39
+ ]
40
+ }
@@ -12,7 +12,9 @@ const gitIgnoreEntries = {
12
12
  '.env',
13
13
  'coverage',
14
14
  'build',
15
- '.history'
15
+ '.history',
16
+ // Generated by render-and-deploy.yml — do not commit build output
17
+ 'docs'
16
18
  ],
17
19
  };
18
20
 
@@ -3,6 +3,7 @@ const systemFiles = [
3
3
  '.env.example',
4
4
  'menu-wrapper.sh',
5
5
  '.github/workflows/menu.yml',
6
+ '.github/workflows/render-and-deploy.yml',
6
7
  '.github/workflows/set-gh-pages.yml',
7
8
  'assets/test.json',
8
9
  'assets/test.text',
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Configuration for available content templates.
3
+ *
4
+ * Each template provides a different structure for specification markdown files.
5
+ * The assets/ and static/ directories remain the same across all templates
6
+ * and are always sourced from the original boilerplate.
7
+ *
8
+ * - id: unique identifier used in env var SPEC_UP_T_TEMPLATE and GitHubUi
9
+ * - name: human-readable name shown during selection
10
+ * - description: brief explanation of the template structure
11
+ * - directory: folder name inside boilerplate-templates/, or null for default
12
+ */
13
+
14
+
15
+ /**
16
+ * IMPORTANT: When adding new templates, also update the template selection logic in the GitHubUi file `CreateSpecUpProject.vue`.
17
+ */
18
+ const templates = [
19
+ {
20
+ id: 'default',
21
+ name: 'Default (Starter Pack)',
22
+ description: 'Standard boilerplate with head, body, and example markup files',
23
+ directory: null
24
+ },
25
+ {
26
+ id: 'boilerplate-template-01',
27
+ name: 'Trust over IP Specification (Intro, Body, Coda)',
28
+ description: 'Structured with introduction, body, and concluding sections',
29
+ directory: 'boilerplate-template-01'
30
+ },
31
+ {
32
+ id: 'boilerplate-template-02',
33
+ name: 'Multi-Part Specification (Part 1, 2, 3)',
34
+ description: 'Organized in sequential parts for longer specifications',
35
+ directory: 'boilerplate-template-02'
36
+ }
37
+ ];
38
+
39
+ module.exports = { templates };
@@ -1,23 +1,76 @@
1
1
  const fs = require('fs-extra');
2
- const path = require('path');
2
+ const path = require('node:path');
3
3
  const Logger = require('../utils/logger');
4
4
 
5
- function copyBoilerplate() {
5
+ /**
6
+ * Copies the boilerplate files to the consuming project root.
7
+ * If a template is specified (non-default), the template's spec/ directory
8
+ * and specs.json overwrite those from the default boilerplate.
9
+ * The assets/ and static/ directories always come from the original boilerplate.
10
+ *
11
+ * @param {Object|null} template - Template object from config-templates.js, or null/undefined for default.
12
+ */
13
+ function copyBoilerplate(template) {
6
14
  const sourceDir = path.join(__dirname, './', 'boilerplate');
15
+ // // Use process.cwd() so the destination is always the consuming project root,
16
+ // // regardless of whether spec-up-t is installed from npm or via `npm link`.
17
+ // // I am not sure if this works in all cases. Needs testing.
18
+ // const projectRoot = process.cwd();
19
+
20
+ const projectRoot = path.join(__dirname, '../../../../');
21
+
22
+ // Step 1: Copy everything from the default boilerplate
7
23
  const items = fs.readdirSync(sourceDir);
8
- items.forEach(item => {
24
+ for (const item of items) {
9
25
  const srcPath = path.join(sourceDir, item);
10
- // Root of the project
11
- const destPath = path.join(__dirname, '../../../../', item);
26
+ const destPath = path.join(projectRoot, item);
12
27
  fs.cpSync(srcPath, destPath, { recursive: true });
13
- });
28
+ }
14
29
 
15
30
  // Rename the copied gitignore file to .gitignore
16
- const gitignorePath = path.join(__dirname, '../../../../', 'gitignore');
17
- const gitignoreDestPath = path.join(__dirname, '../../../../', '.gitignore');
31
+ const gitignorePath = path.join(projectRoot, 'gitignore');
32
+ const gitignoreDestPath = path.join(projectRoot, '.gitignore');
18
33
  fs.renameSync(gitignorePath, gitignoreDestPath);
19
34
 
20
35
  Logger.success('Copied spec-up-t-boilerplate to current directory');
36
+
37
+ // Step 2: If a non-default template was selected, overlay template-specific files
38
+ if (template?.directory) {
39
+ applyTemplate(template, projectRoot);
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Overlays template-specific spec/ and specs.json onto the project root,
45
+ * replacing the default boilerplate versions.
46
+ *
47
+ * @param {Object} template - Template object with a directory property.
48
+ * @param {string} projectRoot - Absolute path to the consuming project root.
49
+ */
50
+ function applyTemplate(template, projectRoot) {
51
+ const templateDir = path.join(__dirname, 'boilerplate-templates', template.directory);
52
+
53
+ if (!fs.existsSync(templateDir)) {
54
+ Logger.error(`Template directory not found: ${template.directory}`);
55
+ return;
56
+ }
57
+
58
+ // Replace spec/ directory with the template's version
59
+ const destSpecDir = path.join(projectRoot, 'spec');
60
+ const templateSpecDir = path.join(templateDir, 'spec');
61
+
62
+ if (fs.existsSync(templateSpecDir)) {
63
+ fs.rmSync(destSpecDir, { recursive: true, force: true });
64
+ fs.cpSync(templateSpecDir, destSpecDir, { recursive: true });
65
+ Logger.success(`Applied template spec/ from: ${template.name}`);
66
+ }
67
+
68
+ // Replace specs.json with the template's version
69
+ const templateSpecsJson = path.join(templateDir, 'specs.json');
70
+ if (fs.existsSync(templateSpecsJson)) {
71
+ fs.cpSync(templateSpecsJson, path.join(projectRoot, 'specs.json'));
72
+ Logger.success(`Applied template specs.json from: ${template.name}`);
73
+ }
21
74
  }
22
75
 
23
76
  module.exports = copyBoilerplate;
@@ -14,9 +14,15 @@ function copySystemFiles() {
14
14
  systemFiles.forEach(item => {
15
15
  const srcPath = path.join(sourceDir, item);
16
16
 
17
+ // // Use process.cwd() so the destination is always the consuming project root,
18
+ // // regardless of whether spec-up-t is installed from npm or via `npm link`.
19
+ // // I am not sure if this works in all cases. Needs testing.
20
+ // const destPath = path.join(process.cwd(), item);
21
+
17
22
  // Root of the project
18
23
  const destPath = path.join(__dirname, '../../../../', item);
19
24
 
25
+
20
26
  try {
21
27
  fs.cpSync(srcPath, destPath, { recursive: true });
22
28
  Logger.success(`Copied ${item} to ${destPath}`);
@@ -1,8 +1,18 @@
1
1
  const copyBoilerplate = require('./copy-boilerplate');
2
2
  const { configScriptsKeys } = require('./config-scripts-keys');
3
3
  const addScriptsKeys = require('./add-scripts-keys');
4
+ const { templates } = require('./config-templates');
4
5
 
5
- copyBoilerplate();
6
+ // Resolve template from SPEC_UP_T_TEMPLATE environment variable.
7
+ // If not set or set to 'default', uses the original boilerplate (backward compatible).
8
+ const envTemplateId = process.env.SPEC_UP_T_TEMPLATE;
9
+ let selectedTemplate = null;
10
+
11
+ if (envTemplateId && envTemplateId !== 'default') {
12
+ selectedTemplate = templates.find(t => t.id === envTemplateId) || null;
13
+ }
14
+
15
+ copyBoilerplate(selectedTemplate);
6
16
  addScriptsKeys(configScriptsKeys);
7
17
 
8
18
  require('./postinstall-message');
@@ -0,0 +1,51 @@
1
+ const readline = require('node:readline');
2
+ const { templates } = require('./config-templates');
3
+ const Logger = require('../utils/logger');
4
+
5
+ /**
6
+ * Prompts the user to select a content template interactively.
7
+ * If the SPEC_UP_T_TEMPLATE environment variable is set, uses that value
8
+ * without prompting (for non-interactive use, e.g., GitHubUi or CI).
9
+ *
10
+ * @returns {Promise<Object>} The selected template object from config-templates.js
11
+ */
12
+ function selectTemplate() {
13
+ // Check environment variable first (non-interactive use)
14
+ const envTemplate = process.env.SPEC_UP_T_TEMPLATE;
15
+ if (envTemplate) {
16
+ const found = templates.find(t => t.id === envTemplate);
17
+ if (found) {
18
+ Logger.info(`Using content template from environment: ${found.name}`);
19
+ return Promise.resolve(found);
20
+ }
21
+ Logger.warn(`Unknown template "${envTemplate}", falling back to default`);
22
+ return Promise.resolve(templates[0]);
23
+ }
24
+
25
+ return new Promise((resolve) => {
26
+ const rl = readline.createInterface({
27
+ input: process.stdin,
28
+ output: process.stdout
29
+ });
30
+
31
+ console.log('\nšŸ“„ Available content templates:\n');
32
+ for (const [i, t] of templates.entries()) {
33
+ console.log(` [${i}] ${t.name}`);
34
+ console.log(` ${t.description}\n`);
35
+ }
36
+
37
+ rl.question('Select a content template (number) [0]: ', (answer) => {
38
+ rl.close();
39
+ const index = Number.parseInt(answer, 10);
40
+ if (!Number.isNaN(index) && index >= 0 && index < templates.length) {
41
+ Logger.info(`Selected template: ${templates[index].name}`);
42
+ resolve(templates[index]);
43
+ } else {
44
+ Logger.info('Using default template');
45
+ resolve(templates[0]);
46
+ }
47
+ });
48
+ });
49
+ }
50
+
51
+ module.exports = { selectTemplate, templates };