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 + +

+ New Feature Release +

+ +**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 - Next + Now + Next Later

-### Now (v0.5.2 - v0.5.4) +### Now (v0.5.3 - v0.5.5) -- ![v0.5.2](https://img.shields.io/badge/v0.5.2-22C55E?style=flat-square) 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) - ![v0.5.3](https://img.shields.io/badge/v0.5.3-22C55E?style=flat-square) 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) - ![v0.5.4](https://img.shields.io/badge/v0.5.4-22C55E?style=flat-square) 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) +- ![v0.5.5](https://img.shields.io/badge/v0.5.5-22C55E?style=flat-square) 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) -- ![v0.5.5](https://img.shields.io/badge/v0.5.5-F59E0B?style=flat-square) 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) - ![v0.5.6](https://img.shields.io/badge/v0.5.6-F59E0B?style=flat-square) Safe Mode startup. Tracking: [#27](https://github.com/h3pdesign/Neon-Vision-Editor/issues/27) - ![v0.5.7](https://img.shields.io/badge/v0.5.7-F59E0B?style=flat-square) incremental loading for huge files. Tracking: [#28](https://github.com/h3pdesign/Neon-Vision-Editor/issues/28) +- ![v0.5.8](https://img.shields.io/badge/v0.5.8-F59E0B?style=flat-square) 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'Now' + ) + next_badge = ( + f'Next' + ) + + readme = re.sub( + r'(?m)^ Now$', + f" {now_badge}", + readme, + ) + readme = re.sub( + r'(?m)^ Next$', + 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)^ New Feature Release$', + f' New Feature Release', + 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)