From 853fd400f372d82b8dfbf929d7b616485c19734e Mon Sep 17 00:00:00 2001
From: h3p
Date: Mon, 16 Mar 2026 12:16:59 +0100
Subject: [PATCH] docs: automate new feature spotlight and roadmap sync
---
Neon Vision Editor.xcodeproj/project.pbxproj | 4 +-
Neon Vision Editor/UI/PanelsAndHelpers.swift | 2 +-
README.md | 31 +++--
scripts/prepare_release_docs.py | 118 ++++++++++++++++++-
4 files changed, 138 insertions(+), 17 deletions(-)
diff --git a/Neon Vision Editor.xcodeproj/project.pbxproj b/Neon Vision Editor.xcodeproj/project.pbxproj
index 655eff0..7649555 100644
--- a/Neon Vision Editor.xcodeproj/project.pbxproj
+++ b/Neon Vision Editor.xcodeproj/project.pbxproj
@@ -361,7 +361,7 @@
CODE_SIGNING_ALLOWED = YES;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 527;
+ CURRENT_PROJECT_VERSION = 528;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = CS727NF72U;
ENABLE_APP_SANDBOX = YES;
@@ -444,7 +444,7 @@
CODE_SIGNING_ALLOWED = YES;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 527;
+ CURRENT_PROJECT_VERSION = 528;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = CS727NF72U;
ENABLE_APP_SANDBOX = YES;
diff --git a/Neon Vision Editor/UI/PanelsAndHelpers.swift b/Neon Vision Editor/UI/PanelsAndHelpers.swift
index 37f1924..e8150cc 100644
--- a/Neon Vision Editor/UI/PanelsAndHelpers.swift
+++ b/Neon Vision Editor/UI/PanelsAndHelpers.swift
@@ -364,7 +364,7 @@ struct WelcomeTourView: View {
"Stabilized first-open rendering from the project sidebar so file content and syntax highlighting appear on first click without requiring tab switches.",
"Hardened startup/session behavior so `Reopen Last Session` reliably wins over conflicting blank-document startup states.",
"Refined large-file activation and loading placeholders to avoid misclassifying smaller files as large-file sessions.",
- "Fixed a session-restore regression where previously open files could appear empty on first sidebar click until changing tabs."
+ "Added Share Shot (`Code Snapshot`) creation flow with toolbar + selection-context actions (`camera.viewfinder`) and a styled share/export composer."
],
iconName: "sparkles.rectangle.stack",
colors: [Color(red: 0.40, green: 0.28, blue: 0.90), Color(red: 0.96, green: 0.46, blue: 0.55)],
diff --git a/README.md b/README.md
index 29c0847..ff69cd0 100644
--- a/README.md
+++ b/README.md
@@ -96,7 +96,7 @@
Download Metrics ·
Project Docs ·
Features ·
- Share Shot ·
+ New Feature ·
Platform Matrix
Roadmap (Near Term) ·
Troubleshooting ·
@@ -312,7 +312,13 @@ Platform-specific availability is tracked in the [Platform Matrix](#platform-mat
- Built-in theme collection: Dracula, One Dark Pro, Nord, Tokyo Night, Gruvbox, and Neon Glow.
- Grouped settings, optional StoreKit support flow, and AI Activity Log diagnostics on macOS.
-## Share Shot (Code Snapshot) Highlight
+## NEW FEATURE Spotlight
+
+
+
+
+
+**Featured in v0.5.5:** Share Shot (`Code Snapshot`) creation flow with toolbar + selection-context actions (`camera.viewfinder`) and a styled share/export composer.
Create polished share images directly from your selected code.
@@ -323,7 +329,7 @@ Create polished share images directly from your selected code.
Styled export preview for social sharing, changelogs, and issue discussions.
-- Toolbar button: click the `camera.viewfinder` icon in the top toolbar (`Create Code Snapshot`).
+- Toolbar button: click **📷 `camera.viewfinder`** in the top toolbar (`Create Code Snapshot`).
- Selection menu: right-click selected text and choose `Create Code Snapshot`.
- Composer controls: choose appearance, background, frame style, line numbers, and padding.
- Export: use `Share` to generate a PNG snapshot and share/save it.
@@ -506,28 +512,27 @@ Most editor features are shared across macOS, iOS, and iPadOS.
## Roadmap (Near Term)
-
-
+
+
-### Now (v0.5.2 - v0.5.4)
+### Now (v0.5.3 - v0.5.5)
--  updater diagnostics, large-file mode parity, CSV/TSV table mode, performance presets.
- Tracking: [Milestone 0.5.2](https://github.com/h3pdesign/Neon-Vision-Editor/milestone/3) · [#24](https://github.com/h3pdesign/Neon-Vision-Editor/issues/24) · [#25](https://github.com/h3pdesign/Neon-Vision-Editor/issues/25) · [#26](https://github.com/h3pdesign/Neon-Vision-Editor/issues/26) · [#30](https://github.com/h3pdesign/Neon-Vision-Editor/issues/30)
-  indexed project search and Open Recent favorites.
Tracking: [Milestone 0.5.3](https://github.com/h3pdesign/Neon-Vision-Editor/milestone/4) · [#29](https://github.com/h3pdesign/Neon-Vision-Editor/issues/29) · [#31](https://github.com/h3pdesign/Neon-Vision-Editor/issues/31)
-  large-file open mode, deferred/plain-text sessions, and stability work for huge documents.
Tracking: [Milestone 0.5.4](https://github.com/h3pdesign/Neon-Vision-Editor/milestone/5)
+-  first-open/sidebar rendering stabilization, session-restore hardening, and Share Shot (`Code Snapshot`) workflow polish.
+ Tracking: [Milestone 0.5.5](https://github.com/h3pdesign/Neon-Vision-Editor/milestone/6) · [Release v0.5.5](https://github.com/h3pdesign/Neon-Vision-Editor/releases/tag/v0.5.5)
-### Next (v0.5.5 - v0.5.7)
+### Next (v0.5.6 - v0.5.8)
--  iOS file-handler QA matrix and UI tests.
- Tracking: [Milestone 0.5.5](https://github.com/h3pdesign/Neon-Vision-Editor/milestone/6) · [#23](https://github.com/h3pdesign/Neon-Vision-Editor/issues/23)
-  Safe Mode startup.
Tracking: [#27](https://github.com/h3pdesign/Neon-Vision-Editor/issues/27)
-  incremental loading for huge files.
Tracking: [#28](https://github.com/h3pdesign/Neon-Vision-Editor/issues/28)
+-  follow-up platform polish and release hardening.
### Later (v0.6.0)
@@ -633,12 +638,12 @@ Latest stable: **v0.5.5** (2026-03-16)
| Version | Date | Highlights | Fixes | Breaking changes | Migration |
|---|---|---|---|---|---|
-| [`v0.5.5`](https://github.com/h3pdesign/Neon-Vision-Editor/releases/tag/v0.5.5) | 2026-03-16 | Stabilized first-open rendering from the project sidebar so file content and syntax highlighting appear on first click without requiring tab switches; Hardened startup/session behavior so `Reopen Last Session` reliably wins over conflicting blank-document startup states; Refined large-file activation and loading placeholders to avoid misclassifying smaller files as large-file sessions; Added Share Shot (`Code Snapshot`) creation via toolbar/selection action (`camera.viewfinder`) with styled export composer | a session-restore regression where previously open files could appear empty on first sidebar click until changing tabs; highlight scheduling during document-state transitions (`switch`, `finish load`, external edits) on macOS, iOS, and iPadOS; startup-default conflicts by aligning defaults and runtime startup gating between `Reopen Last Session` and `Open with Blank Document` | None noted | None required |
+| [`v0.5.5`](https://github.com/h3pdesign/Neon-Vision-Editor/releases/tag/v0.5.5) | 2026-03-16 | Stabilized first-open rendering from the project sidebar so file content and syntax highlighting appear on first click without requiring tab switches; Hardened startup/session behavior so `Reopen Last Session` reliably wins over conflicting blank-document startup states; Refined large-file activation and loading placeholders to avoid misclassifying smaller files as large-file sessions; Share Shot (`Code Snapshot`) creation flow with toolbar + selection-context actions (`camera.viewfinder`) and a styled share/export composer | a session-restore regression where previously open files could appear empty on first sidebar click until changing tabs; highlight scheduling during document-state transitions (`switch`, `finish load`, external edits) on macOS, iOS, and iPadOS; startup-default conflicts by aligning defaults and runtime startup gating between `Reopen Last Session` and `Open with Blank Document` | None noted | None required |
| [`v0.5.4`](https://github.com/h3pdesign/Neon-Vision-Editor/releases/tag/v0.5.4) | 2026-03-13 | a dedicated large-file open mode with deferred first paint, chunked text installation, and an optional plain-text session mode for ultra-large documents | large-file responsiveness regressions across project-sidebar reopen, tab switching, line-number visibility, status metrics, and large-file editor rendering stability | None noted | None required |
| [`v0.5.3`](https://github.com/h3pdesign/Neon-Vision-Editor/releases/tag/v0.5.3) | 2026-03-10 | a new high-readability colorful light theme preset: `Prism Daylight` (also selectable while app appearance is set to dark); double-click-to-close behavior for tabs on macOS tab strips; custom theme vibrancy by applying the vivid neon syntax profile to `Custom`, so syntax colors remain bright and saturated | toolbar-symbol contrast edge cases in dark mode where gray/black variants could appear too similar | None noted | None required |
- Full release history: [`CHANGELOG.md`](CHANGELOG.md)
-- Compare recent changes: [v0.5.2...v0.5.4](https://github.com/h3pdesign/Neon-Vision-Editor/compare/v0.5.2...v0.5.4)
+- Compare recent changes: [v0.5.4...v0.5.5](https://github.com/h3pdesign/Neon-Vision-Editor/compare/v0.5.4...v0.5.5)
## Known Limitations
diff --git a/scripts/prepare_release_docs.py b/scripts/prepare_release_docs.py
index 46de692..fb1a801 100755
--- a/scripts/prepare_release_docs.py
+++ b/scripts/prepare_release_docs.py
@@ -237,7 +237,7 @@ def sorted_latest_tags(tags: list[str], limit: int, ensure_tag: str | None = Non
def build_readme_release_row(tag: str, date: str, section_body: str) -> str:
- highlights_items = extract_heading_bullets(section_body, "Highlights", limit=3)
+ highlights_items = extract_heading_bullets(section_body, "Highlights", limit=4)
if not highlights_items:
highlights_items = extract_heading_bullets(section_body, "Added", limit=2) + extract_heading_bullets(
section_body, "Improved", limit=1
@@ -328,6 +328,119 @@ def update_readme_whats_new_heading(readme: str, previous_tag: str | None, curre
)
+def parse_stable_semver(tag: str) -> tuple[int, int, int] | None:
+ match = re.fullmatch(r"v(\d+)\.(\d+)\.(\d+)", tag)
+ if not match:
+ return None
+ return int(match.group(1)), int(match.group(2)), int(match.group(3))
+
+
+def update_readme_roadmap_windows(readme: str, tag: str) -> str:
+ stable = parse_stable_semver(tag)
+ if stable is None:
+ return readme
+
+ major, minor, patch = stable
+ now_start = max(0, patch - 2)
+ now_end = patch
+ next_start = patch + 1
+ next_end = patch + 3
+
+ now_badge = (
+ f'
'
+ )
+ next_badge = (
+ f'
'
+ )
+
+ readme = re.sub(
+ r'(?m)^
$',
+ f" {now_badge}",
+ readme,
+ )
+ readme = re.sub(
+ r'(?m)^
$',
+ f" {next_badge}",
+ readme,
+ )
+ readme = re.sub(
+ r"(?m)^### Now \(v\d+\.\d+\.\d+ - v\d+\.\d+\.\d+\)$",
+ f"### Now (v{major}.{minor}.{now_start} - v{major}.{minor}.{now_end})",
+ readme,
+ )
+ readme = re.sub(
+ r"(?m)^### Next \(v\d+\.\d+\.\d+ - v\d+\.\d+\.\d+\)$",
+ f"### Next (v{major}.{minor}.{next_start} - v{major}.{minor}.{next_end})",
+ readme,
+ )
+ return readme
+
+
+def update_readme_compare_link(readme: str, prev_tag: str | None, current_tag: str) -> str:
+ if not prev_tag:
+ return readme
+ return re.sub(
+ r"(?m)^- Compare recent changes: \[v[^]]+\.\.\.v[^]]+\]\(https://github\.com/h3pdesign/Neon-Vision-Editor/compare/v[^)]+\)$",
+ (
+ f"- Compare recent changes: [{prev_tag}...{current_tag}]"
+ f"(https://github.com/h3pdesign/Neon-Vision-Editor/compare/{prev_tag}...{current_tag})"
+ ),
+ readme,
+ )
+
+
+def pick_feature_spotlight(section_body: str) -> str:
+ highlight_items = extract_heading_bullets(section_body, "Highlights", limit=8)
+ preferred_keywords = ("share shot", "code snapshot", "camera.viewfinder", "snapshot")
+ for item in highlight_items:
+ lowered = item.lower()
+ if any(keyword in lowered for keyword in preferred_keywords):
+ cleaned = clean_release_cell_item(item)
+ if cleaned:
+ return cleaned
+ for item in highlight_items:
+ cleaned = clean_release_cell_item(item)
+ if cleaned:
+ return cleaned
+
+ added_items = extract_heading_bullets(section_body, "Added", limit=8)
+ for item in added_items:
+ lowered = item.lower()
+ if any(keyword in lowered for keyword in preferred_keywords):
+ cleaned = clean_release_cell_item(item)
+ if cleaned:
+ return cleaned
+ for item in added_items:
+ cleaned = clean_release_cell_item(item)
+ if cleaned:
+ return cleaned
+
+ fallback = summarize_section(section_body, limit=1)
+ if fallback:
+ return clean_release_cell_item(fallback[0][2:].strip())
+ return "See CHANGELOG.md release highlights."
+
+
+def update_readme_feature_spotlight(readme: str, tag: str, section_body: str) -> str:
+ feature_text = pick_feature_spotlight(section_body).rstrip(".")
+ badge = f'https://img.shields.io/badge/NEW%20FEATURE-{tag}-F97316?style=for-the-badge'
+ featured_line = f"**Featured in {tag}:** {feature_text}."
+
+ readme = re.sub(
+ r'(?m)^
$',
+ f'
',
+ readme,
+ )
+ readme = re.sub(
+ r"(?m)^\*\*Featured in v[0-9]+\.[0-9]+\.[0-9]+(?:-[A-Za-z0-9.]+)?:\*\* .*$",
+ featured_line,
+ readme,
+ )
+ return readme
+
+
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description="Prepare README and CHANGELOG for a release tag.")
parser.add_argument("tag", help="Release tag, e.g. v0.4.6")
@@ -364,6 +477,9 @@ def main() -> int:
readme = update_readme_release_refs(original_readme, tag)
prev_tag = previous_release_tag(changelog, tag)
readme = update_readme_whats_new_heading(readme, prev_tag, tag)
+ readme = update_readme_roadmap_windows(readme, tag)
+ readme = update_readme_compare_link(readme, prev_tag, tag)
+ readme = update_readme_feature_spotlight(readme, tag, section)
readme = update_readme_latest_stable_line(readme, tag, changelog)
readme = rebuild_readme_changelog_table(readme, changelog, tag, limit=3)