From 0113d5eee03c10e46ffa98669e43331a33f36b07 Mon Sep 17 00:00:00 2001 From: OKAN TIKTAS <346542017+OKAN-SOFTWARE@users.noreply.github.com> Date: Fri, 6 Nov 2026 13:54:58 -0500 Subject: [PATCH 1/3] docs: refresh v0.5 guides and add a static browser demo --- .github/workflows/ci.yml | 3 ++ .gitignore | 3 ++ CHANGELOG.md | 2 ++ README.md | 33 +++++++++++++----- docs/RELEASING.md | 67 +++++++++++++++++-------------------- docs/USER-GUIDE.md | 53 +++++++++++++++++++++++++++++ docs/WEB-DEMO.md | 45 +++++++++++++++++++++++++ scripts/build-web-demo.mjs | 43 ++++++++++++++++++++++++ src/test/js/demo.test.cjs | 45 +++++++++++++++++++++++++ web-demo/engine.js | 68 ++++++++++++++++++++++++++++++++++++++ 10 files changed, 317 insertions(+), 45 deletions(-) create mode 100644 docs/USER-GUIDE.md create mode 100644 docs/WEB-DEMO.md create mode 100644 scripts/build-web-demo.mjs create mode 100644 src/test/js/demo.test.cjs create mode 100644 web-demo/engine.js diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3107ce6..d7243e0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,3 +23,6 @@ jobs: - name: Test browser export safety run: node --test src/test/js/*.test.cjs + + - name: Build static browser demo + run: node scripts/build-web-demo.mjs diff --git a/.gitignore b/.gitignore index 38c5662..845489f 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,6 @@ Thumbs.db .env .env.* !.env.example + +# Generated browser demo (built from tracked sources) +/demo-dist/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c288c4..329563d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ All notable Doc2FAQ changes are recorded here. Version numbers follow semantic v ## [0.5.0] — Unreleased ### Added +- Browser-only website demo built from the shared frontend, with simplified text drafting, explicit PDF/Word limitations, homepage navigation, and text exports. +- Source & Review user guide and current documentation for development builds, schema compatibility, and v0.5.0 release preparation. - Read-only source viewer highlighting the selected FAQ's exact original passages, with a stacked layout on narrow screens. - Per-FAQ Needs review / Approved status, persisted in saved projects and optional browser autosave. - Combined question/answer search and review-status filters, visible result counts, and Clear filters. diff --git a/README.md b/README.md index 326eec0..b44ce1d 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,9 @@ Doc2FAQ is a Java 21 / Spring Boot document-to-FAQ workbench. Paste text or uplo Created by **Okan Tiktas** · [OKAN-SOFTWARE](https://github.com/OKAN-SOFTWARE). -> **Current version: v0.4.0 — Review, Save & Export.** Download the ready-to-run JAR or Windows ZIP from [GitHub Releases](https://github.com/OKAN-SOFTWARE/Doc2FAQ/releases/tag/v0.4.0). +> **Latest published download: v0.4.0 — Review, Save & Export.** Download the ready-to-run JAR or Windows ZIP from [GitHub Releases](https://github.com/OKAN-SOFTWARE/Doc2FAQ/releases/tag/v0.4.0). -## In development: v0.5.0 — Source & Review +## Current source: v0.5.0-SNAPSHOT — Source & Review - **Source beside answer:** select **View source beside answer** on an FAQ to highlight all of its original passages in a read-only document viewer beside the review editor on desktop (stacked on smaller screens). References still use extracted-text lines, not PDF page numbers. Manual FAQs have no automatic reference. - **Review status:** FAQs start as **Needs review**. Mark a complete answer **Approved** after checking it. Editing its question or answer, or merging FAQs, returns it to **Needs review**. Moving an item preserves approval; Undo restores the status from before a removal or merge. @@ -50,6 +50,12 @@ The document placeholder now uses neutral Q&A prompts, and Generate Mode's sampl **Privacy and accuracy:** The current Generate Mode is **deterministic and rule-based, not a generative AI model**. No API key, paid AI service, or external model is required. Its questions are suggestions; answers come from excerpts in your source document. Similar-question flags are suggestions and can include questions you want to keep. It cannot reliably interpret every layout or guarantee an accurate summary. Always review before publishing. +## Try it in your browser + +[Open the interactive browser demo](https://okantiktas.com/projects/doc2faq/) · [Source & Review user guide](docs/USER-GUIDE.md) · [Demo capabilities and deployment](docs/WEB-DEMO.md) + +The demo processes pasted text and TXT/Markdown in your browser, using simplified rules. Try both drafting modes, source highlighting, editing, approval status, duplicate review, search/filters, saved projects, and Markdown/JSON/HTML exports. PDF/Word imports and exports require the downloadable Java app; the demo does not run a public Java backend. The development demo may include features newer than the latest release download. + For detailed changes, see [CHANGELOG.md](CHANGELOG.md). For the release checklist, see [docs/RELEASING.md](docs/RELEASING.md). ## Requirements @@ -196,9 +202,12 @@ The preview heading and footer display the full project version from `pom.xml`. 1. Paste your document's text or choose a `.txt`, `.md`, `.pdf`, or `.docx` file. 2. Select **Extract Mode** if your text already contains FAQ questions; select **Generate Mode** for a normal document with section headings. 3. Click **Extract FAQ draft** or **Generate FAQ draft**, depending on the mode. -4. Expand **Show source** and review each question and answer. Reorder, remove, or add entries. Review similar questions and use Undo after a removal or merge. -5. Set the document title printed on your FAQ and use **Save work** to keep the source and your edits. Use **Open saved work** to continue later. Optionally enable browser autosave. -6. Choose **Markdown**, **JSON**, **HTML**, **PDF**, or **Word**, optionally include references, and inspect **Preview export**. Use **Copy** for text formats or **Download** for any format. Blank questions or answers must be completed before export. +4. Select **View source beside answer** to highlight original passages beside the editor on desktop (above it on mobile). You can also expand **Show source** for individual excerpts. Typing preserves the source viewer's scroll position; selecting a source explicitly reveals its highlighted passage. +5. Edit and verify each FAQ, then change its status from **Needs review** to **Approved**. Blank entries cannot be approved. Editing either field or merging resets approval; moving an FAQ preserves it. +6. Combine the question/answer search with the **All statuses**, **Needs review**, or **Approved** filter. Read the visible and review counts; use **Clear filters** to restore the list. Filters do not restrict saved projects, previews, or exports. +7. Reorder, remove, or add FAQs. Review similar questions, choose Keep both or merge, and use Undo immediately after a removal/merge if needed. Review status changes clear that undo history too. +8. Set the document title and use **Save work** to keep source, edits, order, references, duplicate decisions, and review status. **Open saved work** resumes a project. Optional autosave is off by default. New schema-2 project files require v0.5 or later; schema-1 files open with Needs review defaults. +9. Choose **Markdown**, **JSON**, **HTML**, **PDF**, or **Word**, optionally include references, and inspect **Preview export**. Use **Copy** for text formats or **Download** for any format. All FAQs are included, even if filtered out. Any blank question or answer blocks export; approval is a review aid and is not required to export. Example document for **Generate Mode**: @@ -230,7 +239,8 @@ Generate Mode preserves explicit FAQ pairs and suggests questions for additional | PDF | Text extraction using Apache PDFBox | 5 MB upload, 50 pages, 50,000 extracted characters | | DOCX | Text extraction using Apache POI | 5 MB upload, 50,000 extracted characters | | FAQ drafts | Local rules based on source text | Maximum 30 suggested/extracted pairs | -| Project files | Validated JSON, read in the browser | 4 MB, 30 FAQs, 50,000 source characters | +| Project files | Validated JSON, read in the browser; schema 1 reads, schema 2 saves | 4 MB, 30 FAQs, 50,000 source characters | +| Review status | Browser workspace and project saves | Needs review / Approved; complete FAQs only for approval | | Exports | Text formats in browser; PDF/DOCX on the server | Title 200 characters; question 500; answer 50,000; combined FAQ text 300,000 | The server checks file signatures, not just extensions. Empty, corrupted, password-protected, and unsupported documents are rejected with clear errors. **Scanned/image-only PDFs require OCR**, which this version does not provide. Complex tables and multi-column layouts can lead to imperfect text order; inspect the extracted text before drafting. @@ -246,6 +256,8 @@ The server checks file signatures, not just extensions. Empty, corrupted, passwo | POST | `/api/faqs/export/pdf` | Validated FAQ JSON to downloadable PDF | | POST | `/api/faqs/export/docx` | Validated FAQ JSON to downloadable Word document | +**Review state is client-side:** approval status, search, and filters are not API parameters. Project JSON preserves approval status; finished FAQ JSON exports contain content and optional references, rather than the full workspace. + Both FAQ endpoints take JSON input: ```json @@ -294,9 +306,10 @@ Export references are supplied by the caller. They identify passages for human r ```bash mvn -B -ntp clean verify node --test src/test/js/*.test.cjs +node scripts/build-web-demo.mjs ``` -GitHub Actions automatically runs the Java and JavaScript checks on pushes and pull requests. Tests cover both modes, exact source references, preservation of distinct passages, stale responses, document import errors, project round trips and invalid files, merge behavior, API validation, Unicode exports, PDF pagination, and export safety. The frontend tests require Node.js and have no npm dependencies. +GitHub Actions automatically runs the Java and JavaScript checks on pushes and pull requests. Tests cover both modes, exact source references, preservation of distinct passages, stale responses, document import errors, project round trips and invalid files, merge behavior, API validation, Unicode exports, PDF pagination, and export safety. They also cover approval restore/reset, legacy project migration, combined filters, source-viewer scroll preservation, and browser-demo drafting rules. The frontend tests require Node.js and have no npm dependencies. ## Troubleshooting @@ -306,6 +319,10 @@ GitHub Actions automatically runs the Java and JavaScript checks on pushes and p | `'mvn' is not recognized` | Run the temporary PATH command above, reopen CMD after permanent PATH setup, or use the full `mvn.cmd` path | | Maven selects the wrong Java version | Check `mvn -version` and set `JAVA_HOME` to your JDK 21 installation | | `No complete Q&A pairs found` | Switch from **Extract Mode** to **Generate Mode**, or format existing pairs as Markdown question headings | +| No FAQs visible after filtering | Use **Clear filters**; the draft and its export still include every FAQ | +| Approval changes after editing | Expected: edited or merged content returns to Needs review | +| Saved project will not open in v0.4 | Schema-2 projects need v0.5 or later; keep the original schema-1 file when using older releases | +| PDF/Word unavailable on the website demo | Use the local Java app; the browser demo supports text formats only | | Scanned PDF fails | The file is image-only; run OCR outside Doc2FAQ first | | Port 8080 already in use | Stop the other program or start Doc2FAQ with port 9090 | | Maven downloads fail | Check internet access, proxy configuration, corporate restrictions, and the Maven Central repository | @@ -322,4 +339,4 @@ MIT · Copyright © 2026 **Okan Tiktas**. ## Later releases -Optional AI generation with explicit opt-in and token/cost limits, OCR, and account/subscription workflows are outside the v0.4.0 scope. See [docs/RELEASING.md](docs/RELEASING.md) for the validation and release process. +Optional AI generation with explicit opt-in and token/cost limits, OCR, and account/subscription workflows are outside the current v0.5.0 scope. See [docs/RELEASING.md](docs/RELEASING.md) for the validation and release process. diff --git a/docs/RELEASING.md b/docs/RELEASING.md index 4fdaf82..e50eaa5 100644 --- a/docs/RELEASING.md +++ b/docs/RELEASING.md @@ -1,46 +1,37 @@ # Doc2FAQ release checklist -The release version is **v0.4.0**. The release commit uses `0.4.0` in `pom.xml`; earlier development builds used `0.4.0-SNAPSHOT`. Merging source changes alone does not publish a GitHub Release or update an already downloaded JAR. +**Current source:** `0.5.0-SNAPSHOT`. **Latest published download:** v0.4.0. The next planned release is **v0.5.0 — Source & Review**. Merging source changes does not publish a release or update an installed JAR. Keep existing tags and assets unchanged. -## v0.5.0 development checks - -The next development version is `0.5.0-SNAPSHOT`; use `target/doc2faq-0.5.0-SNAPSHOT.jar` when testing a source build. The v0.4.0 publishing instructions below describe the existing release; update the release version and notes before publishing v0.5.0. - -Before preparing v0.5.0: - -1. Select an FAQ's source viewer and check every highlighted passage, including multiple references after merge. Try a manual FAQ and a document containing HTML-like text. Check desktop side-by-side and mobile stacked layouts. -2. Approve a complete FAQ; edit its question or answer and confirm it needs review again. Confirm blank FAQs cannot be approved. Remove/Undo and reorder approved FAQs. -3. Combine search and status filters, edit a matching FAQ, check counts, and clear filters. Add an FAQ while filtering and confirm it is visible. -4. Save/reopen and autosave/reload approvals; import a schema-1 project and confirm Needs review defaults. Reject malformed review states without replacing the workspace. -5. With filters active, preview and export all five formats. Confirm all FAQs remain included in draft order; a hidden blank entry must still prevent export. -6. Run the Java and JavaScript checks below and smoke-test the packaged JAR. - -## Validate the release build +## Validate the development build Use JDK 21, Maven 3.6.3+, and Node.js: ```cmd mvn -B -ntp clean verify node --test src/test/js/*.test.cjs -java -jar target/doc2faq-0.4.0.jar +node scripts/build-web-demo.mjs +java -jar target/doc2faq-0.5.0-SNAPSHOT.jar ``` -Open `http://localhost:8080` (or use `--server.port=8081` if occupied). Check the packaged JAR with these steps: +Open `http://localhost:8080` (or use `--server.port=8081` if occupied). Test the packaged JAR, not only a static frontend preview: -1. Extract explicit Markdown and Q:/A: questions. Expand Show source; verify exact excerpts and text-line ranges. -2. Generate from multiple sections, including repeated topics with different details. Confirm distinct passages remain. Use Keep both, merge, and Undo; confirm both references survive a merge. -3. Edit a question/answer; confirm its edited label. Remove an item and Undo. Reorder items and use search. -4. Set a document title, use Save work, refresh, and reopen it. Confirm source, order, edited values, references, and review choices. Save and reopen an incomplete FAQ too. An invalid project must leave the workspace intact. -5. Enable autosave, edit, wait for Saved in this browser, and reload. Confirm restore. Clear saved data and reload; confirm it is gone. Test with browser storage unavailable and use Save work as the fallback. -6. Preview exports and download Markdown, JSON, HTML, PDF, and DOCX with edited content. Upload `TEst Data.pdf` and confirm the suggested filename is `testdata-Doc2FAQ.pdf`; rename it and check the actual download. Clear document, reload, and confirm the previous PDF and draft stay cleared. Check centered titles, Lato PDF fonts, no FAQ-count subtitle, and optional references; HTML must display document markup as text. -7. Open PDF and Word downloads with short and long answers, Unicode text, long unbroken tokens, and page breaks. Check margins, heading placement, footer page numbers, and the final answer. Unsupported PDF glyphs must produce an error with the DOCX option. -8. Change source/mode or open a project while a draft/file request is pending. The old response must not replace current work. Check desktop and narrow-screen controls and keyboard focus. Move the pointer to check the background; enable reduced motion and confirm it stays still. +1. Import TXT, Markdown, PDF, and DOCX. Extract explicit questions and generate from ordinary sections; inspect exact excerpts and text-line ranges. Scanned PDFs must explain the OCR limitation. +2. Select an FAQ's source viewer and check all highlights, including multiple references after merge. Try a manual FAQ and HTML-like source text. Check desktop side-by-side and mobile stacked layouts. Typing in questions/answers must preserve page and source scroll positions. +3. Approve complete FAQs, then edit each field or merge and confirm Needs review. Blank entries cannot be approved. Move an approved FAQ and confirm approval remains. Remove/Undo restores status and references. +4. Combine question/answer search and review filters. Check visible/approved/pending counts, live edits, Clear filters, and adding a blank FAQ while filtered. Filters must not restrict saving or exporting. +5. Use Keep both, merge, and Undo on similar questions. Preserve distinct passages and all references; newer edits or review decisions must clear stale undo history. +6. Save/reopen a complete and incomplete project. Verify source, filename, title, mode, order, edits, original excerpts, duplicate choices, and review status. Schema-1 files upgrade; new saves use schema 2. Invalid states and mismatched references leave the workspace intact. +7. Enable autosave, edit, wait for Saved in this browser, and reload. Clear saved data leaves the workspace open; Clear document removes source, draft, names, pending results, and its saved copy. Test blocked browser storage and use Save work as fallback. +8. With filters active, preview/download Markdown, JSON, HTML, PDF, and Word. Every FAQ remains included in draft order; a hidden incomplete entry blocks export. Verify edited values and optional references. Finished FAQ JSON is not a full project save. +9. Import `TEst Data.pdf`, check the suggested `testdata-Doc2FAQ.pdf`, rename it, and verify the download. Check centered titles, PDF Lato fonts, page numbers, long answers/tokens, Unicode, and page breaks. Unsupported PDF glyphs must suggest Word. HTML must escape document markup. +10. Change source/mode, clear the document, or open another project during pending imports/drafting/exports. Old results must not replace or download current work. Check keyboard focus, mobile widths, and reduced motion. +11. Follow [WEB-DEMO.md](WEB-DEMO.md) for the separate static browser demo; verify its feature disclosure and website links. The demo cannot substitute for packaged-JAR testing. -## Prepare the release commit +## Prepare v0.5.0 -1. Review and merge the development PR after CI and the checks above pass. -2. Change the project version from `0.4.0-SNAPSHOT` to `0.4.0`, mark the changelog section released, and update README run commands. Review that release-preparation change. -3. Update a clean local checkout to the merged release commit: +1. Review and merge development changes after CI and packaged-JAR checks pass. +2. Change `pom.xml` from `0.5.0-SNAPSHOT` to `0.5.0`; date the changelog section and update README source/run commands and download links. Keep historical v0.4.0 notes accurate. Review this release-preparation change. +3. Update a clean checkout to the merged release commit, then build again: ```cmd git switch main @@ -49,17 +40,19 @@ Open `http://localhost:8080` (or use `--server.port=8081` if occupied). Check th git rev-parse HEAD mvn -B -ntp clean verify node --test src/test/js/*.test.cjs - java -jar target/doc2faq-0.4.0.jar + node scripts/build-web-demo.mjs + java -jar target/doc2faq-0.5.0.jar ``` -4. Confirm the working tree is clean and record the exact commit SHA. Repeat the packaged-JAR smoke check. Confirm no existing v0.4.0 tag or Release exists. +4. Confirm a clean working tree and record the exact SHA. Repeat the packaged-JAR smoke check. Confirm that v0.5.0 does not already exist as a tag or release. -## Publish when ready +## Publish tested artifacts 1. Open [Draft a new release](https://github.com/OKAN-SOFTWARE/Doc2FAQ/releases/new). -2. Create tag `v0.4.0` at the exact recorded commit; title: **Doc2FAQ v0.4.0 — Review, Save & Export**. -3. Copy the 0.4.0 changelog section into the notes. Attach the tested `target/doc2faq-0.4.0.jar`, never `.jar.original` or a renamed older JAR. Also attach `Doc2FAQ-0.4.0-Windows.zip` containing that same JAR, `Start-Doc2FAQ.cmd`, and a quick-start README, plus `SHA256SUMS.txt` for both downloads. Confirm the launcher references `doc2faq-0.4.0.jar` and neither the ZIP nor its instructions reference the snapshot build. -4. Review the tag, commit, notes, and asset before publishing. Keep existing release artifacts unchanged. -5. Download the published JAR and ZIP to a separate folder, verify their hashes against `SHA256SUMS.txt`, and confirm that the JAR inside the ZIP matches the standalone JAR. Run it with Java 21 and verify the version, health, project restore, source review, and PDF/Word downloads. +2. Tag the exact tested commit `v0.5.0`; title **Doc2FAQ v0.5.0 — Source & Review**. +3. Copy the v0.5.0 changelog notes. Attach the tested `target/doc2faq-0.5.0.jar`, never `.jar.original` or a renamed old JAR. +4. Also attach `Doc2FAQ-0.5.0-Windows.zip` with that exact JAR, `Start-Doc2FAQ.cmd`, and a quick-start README. The launcher must reference `doc2faq-0.5.0.jar`. Include `SHA256SUMS.txt` for both downloads; remove snapshot and older-version instructions from the new bundle. +5. Review tag, commit, notes, and assets before publishing. Download the published assets separately, verify hashes and that the ZIP's JAR matches the standalone JAR, then run with Java 21. Confirm version, health, saved review status, source viewer, and PDF/Word exports. +6. Rebuild/synchronize the website demo when its shared frontend changes. Verify the actual live route and update the portfolio link if needed. -Accounts, billing, OCR, optional external AI, and public-server hardening remain separate work. This build is intended for local use. +Accounts, billing, OCR, external AI, and public-server hardening remain separate work. The Java build is intended for local use; the static browser demo runs its simplified drafting on visitors' devices. diff --git a/docs/USER-GUIDE.md b/docs/USER-GUIDE.md new file mode 100644 index 0000000..c47e8b7 --- /dev/null +++ b/docs/USER-GUIDE.md @@ -0,0 +1,53 @@ +# Doc2FAQ — Source & Review guide + +This guide describes the `0.5.0-SNAPSHOT` source build. The latest published v0.4.0 download does not include the new source viewer or approval filters. See the [README](../README.md) for installation and [browser-demo comparison](WEB-DEMO.md) for the website's supported features. + +## Create a draft + +1. Start the Java app and open the localhost URL printed by the app (8080 by default). +2. Paste text or import TXT, Markdown, PDF, or DOCX. Inspect extracted text; scanned PDFs require external OCR. +3. Choose Extract Mode for explicit Markdown question headings or Q:/A: pairs. Choose Generate Mode for ordinary sections. Neither mode calls AI. +4. Create the draft. Maximums are 50,000 source characters and 30 FAQ entries. Drafts require human review. + +Changing source text or mode clears the current draft. Save work before replacing a document or generating another draft if you need the old edits. + +## Compare an answer with its source + +Select **View source beside answer** on an FAQ. The read-only viewer highlights every matching original passage, including multiple references retained after merging. On desktop it sits beside the editor; on narrow screens it stacks above it. References use extracted-text line numbers, not original PDF pages. **Show source** expands a specific excerpt within the FAQ card. + +Editing a question or answer preserves the source viewer's content and scroll position. Explicitly opening a source selection scrolls to its first highlight. Selecting another FAQ updates the highlighted passages. Manually added FAQs have no automatic source reference; the viewer says so. An edited badge means the current text differs from its original draft; approving does not remove that history. + +## Track review + +| Action | Review status | +| --- | --- | +| Create/extract/generate or add an FAQ | Needs review | +| Approve a complete question and answer | Approved | +| Edit either field or merge FAQs | Needs review | +| Move an FAQ up/down | Preserved | +| Undo a removal or merge | Restores the previous snapshot, including status | +| Open a schema-1 project | Needs review unless a recognized status was explicitly present | + +Approval is a manual review decision. It does not automatically verify accuracy or prevent export of other complete FAQs. + +## Search and organize + +Search matches questions and answers without case sensitivity. Combine it with All statuses, Needs review, or Approved. Counts show the visible number and the whole draft's approved/pending totals. Clear filters restores the list. Adding an FAQ clears filters so the new blank entry is visible. + +Editing a matching FAQ can make it disappear from the filtered list; the edit remains in the draft. Search and filters never remove data, restrict exports, or limit saved projects. + +Similar-question warnings use word overlap. Keep both retains distinct passages; Merge into this FAQ combines answers and source references. Review the merged result. Undo removal / merge restores the previous snapshot until another edit, addition, reorder, review choice, or approval-status change clears that history. + +## Save and reopen + +**Save work** downloads versioned project JSON, including source text, title, filename, mode, FAQ order, original values, references, duplicate decisions, and review status. Incomplete entries may be saved. **Open saved work** validates the file before replacing the workspace; invalid files leave current work intact. + +The source build reads schemas 1 and 2, and saves schema 2. Older v0.4 apps reject schema-2 files. Keep an original project copy if you also use an older release. The limit remains 4 MB. + +Optional browser autosave is off by default. Enabling it stores source and drafts on that browser origin. Clear saved data removes the stored copy while leaving the open workspace intact. Clear document removes source, drafts, pending results, and the saved copy. Download a project when browser storage is unavailable. + +## Export + +Set the document title and download filename, choose a format, optionally include source references, and preview the result. All FAQs are exported in draft order, regardless of search or status filters. Every entry must have a nonblank question and answer; approval is optional. + +Markdown, JSON, and standalone HTML can be copied or downloaded. PDF and Word downloads use the local Java server and apply their own pagination. Unsupported PDF glyphs produce an error suggesting Word. Finished FAQ JSON is an export, not a saved project: use Save work to preserve review state and resume editing later. diff --git a/docs/WEB-DEMO.md b/docs/WEB-DEMO.md new file mode 100644 index 0000000..dfaaaa9 --- /dev/null +++ b/docs/WEB-DEMO.md @@ -0,0 +1,45 @@ +# Browser demo and website deployment + +The public-facing route is `https://okantiktas.com/projects/doc2faq/`. The portfolio's existing singular convention, `/project/doc2faq/`, redirects to it. The homepage's Doc2FAQ card links to the interactive demo. + +## What visitors can try + +| Capability | Browser demo | Java app from current source | +| --- | --- | --- | +| Paste text, import TXT/Markdown | Yes; all drafting runs in the browser | Yes; drafts processed by local Java server | +| Extract explicit Q&A | Simplified JavaScript rules | Java extraction service | +| Suggest questions from sections | Simplified Markdown-heading rules | Java generation service, with broader heuristics | +| Source viewer, editing, reorder, duplicate review | Shared frontend | Yes | +| Approval status, search, filters | Shared frontend | Yes | +| Saved projects and optional browser autosave | Yes; schemas 1/2 read, schema 2 saved | Yes | +| Markdown/JSON/HTML export | Browser downloads | Browser downloads | +| PDF/DOCX import and export | Use the downloadable app | Yes | +| OCR, external AI, accounts/billing | No | Not implemented | + +The demo demonstrates the review workflow; it is not a hosted Java backend and does not claim identical generation results. Its development features may be newer than the latest published JAR. No pasted text is sent to an FAQ server. Optional autosave and downloaded project files contain source text; clear saved data on shared devices. Normal website hosting still serves the page and assets. + +## Build and keep it synchronized + +Run from the repository root with Node.js: + +```sh +node --test src/test/js/*.test.cjs +node scripts/build-web-demo.mjs +``` + +The builder creates ignored `demo-dist/` from the actual app frontend, shared project validator, stylesheet, and background. It replaces backend requests with the browser-only adapter in `web-demo/engine.js`, limits uploads to TXT/Markdown, removes binary export choices, uses relative asset paths, fills the source-build version, and adds demo disclosure and homepage/source/download links. It does not modify the Java application's served UI. + +Copy the complete contents of `demo-dist/` into `projects/doc2faq/` in the private `OKAN-SOFTWARE/okantiktas.com` repository. Preserve relative filenames. Update the Doc2FAQ homepage card to the demo route. Keep `/project/doc2faq/index.html` as a redirect with a visible fallback link. Do not replace the rest of the portfolio or its activity scripts. + +The portfolio is hosted through its existing GitHub-main → Hostinger deployment. Pushing source and observing a live deployment are separate steps: verify the actual custom-domain route after deployment before reporting it live. Do not deploy the full Java app to static hosting or change DNS to add this subdirectory. + +## Verify before publishing + +- Both demo routes resolve; homepage, source, and download links work. +- Examples and pasted TXT/Markdown work in both modes; text source references match exactly. +- Source highlights remain stable while typing, including on mobile. +- Approvals persist after save/open and optional autosave/reload; edits/merges reset approval. +- Search and status filters combine; downloads and previews retain all FAQs. +- Invalid/oversized files are rejected and PDF/Word requests explain how to use the local app. +- No document content becomes executable HTML; no FAQ requests go to a server. +- Check desktop, narrow-screen controls, keyboard navigation, and reduced-motion behavior. diff --git a/scripts/build-web-demo.mjs b/scripts/build-web-demo.mjs new file mode 100644 index 0000000..6335c8e --- /dev/null +++ b/scripts/build-web-demo.mjs @@ -0,0 +1,43 @@ +import {readFile, writeFile, mkdir, copyFile} from 'node:fs/promises'; +import {fileURLToPath} from 'node:url'; +import path from 'node:path'; +const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); +const output = path.join(root, 'demo-dist'); +const source = path.join(root, 'src/main/resources/static'); +await mkdir(output, {recursive: true}); +const pom = await readFile(path.join(root, 'pom.xml'), 'utf8'); +const version = pom.match(/doc2faq<\/artifactId>\s*([^<]+)<\/version>/)[1]; +let html = await readFile(path.join(source, 'index.html'), 'utf8'); +html = html.replaceAll('@project.version@', version) + .replace('content="Doc2FAQ extracts existing Q&A or builds source-grounded FAQ suggestions from TXT, Markdown, PDF, and DOCX. Review, edit, and export."', 'content="Try Doc2FAQ in your browser: draft FAQs from text, inspect sources, edit, approve, and export."') + .replaceAll('href="/styles.css"', 'href="./styles.css"') + .replaceAll('src="/project.js"', 'src="./project.js"') + .replace('src="/app.js"', 'src="./app.js"') + .replace('src="/background.js"', 'src="./background.js"') + .replace('\n ', 'extract'); + assert.equal(result.items[0].answer, ''); +}); diff --git a/web-demo/engine.js b/web-demo/engine.js new file mode 100644 index 0000000..2b4a48a --- /dev/null +++ b/web-demo/engine.js @@ -0,0 +1,68 @@ +/* Browser-only demonstration rules. The Java services remain the full application's engine. */ +(function (root) { + 'use strict'; + const splitLines = text => text.split(/\r\n|[\n\r\v\f\u0085\u2028\u2029]/); + function draft(content, mode) { + if (typeof content !== 'string' || !content.trim()) throw new Error('Add document text first.'); + if (content.length > 50000) throw new Error('Document text exceeds 50,000 characters.'); + const lines = splitLines(content), items = [], seen = new Set(); + function add(question, start, end, answerLines) { + const answer = answerLines.join(' ').trim(); + question = question.slice(0, 500); + const key = question.toLowerCase() + '\n' + answer.toLowerCase(); + if (!answer || !question || seen.has(key) || items.length >= 30) return; + seen.add(key); + items.push({question, answer, source: {section: question, startLine: start + 1, endLine: end + 1, + excerpt: lines.slice(start, end + 1).join('\n')}}); + } + let question = null, start = 0, end = 0, answer = []; + for (let i = 0; i < lines.length; i++) { + const line = lines[i].trim(); + const prefix = /^(?:#{1,6}\s+|(?:Q|Question):\s*)/i.exec(line); + if (prefix && line.endsWith('?') && line.slice(prefix[0].length).trim().length > 1) { + add(question || '', start, end, answer); + question = line.slice(prefix[0].length).trim(); start = end = i; answer = []; + } else if (line.startsWith('#')) { + add(question || '', start, end, answer); question = null; answer = []; + } else if (question && line) { + const value = line.replace(/^(?:A|Answer):\s*/i, '').trim(); + if (value) { answer.push(value); end = i; } + } + } + add(question || '', start, end, answer); + if (mode === 'generate') { + const explicit = [...items]; + const headings = lines.map((line, i) => ({line: line.trim(), i})).filter(x => /^#{1,6}\s+/.test(x.line)); + for (let j = 0; j < headings.length; j++) { + const heading = headings[j], last = (headings[j + 1]?.i ?? lines.length) - 1; + const label = heading.line.replace(/^#{1,6}\s+/, '').trim(); + if (heading.line.startsWith('# ') || /\?$/.test(label) || /^faq\b/i.test(label) || + explicit.some(item => heading.i + 1 >= item.source.startLine && heading.i + 1 <= item.source.endLine)) continue; + let finish = last; + while (finish > heading.i && !lines[finish].trim()) finish--; + const body = lines.slice(heading.i + 1, finish + 1).map(line => line.trim()).filter(Boolean); + const phrasing = {services: 'What services are included?', support: 'Where can I get support?', + 'team responsibilities': 'What are the team responsibilities?', 'knowledge sharing': 'How is knowledge shared?', + 'technical skills': 'Which skills and technologies are listed?'}; + add(phrasing[label.toLowerCase()] || 'What should I know about ' + label + '?', heading.i, finish, body); + } + if (!headings.length && !items.length) { + let first = lines.findIndex(line => line.trim()), last = lines.length - 1; + while (last > first && !lines[last].trim()) last--; + add('What does this document explain?', first, last, lines.slice(first, last + 1).map(line => line.trim()).filter(Boolean)); + } + } + return {items, count: items.length, notice: 'Browser demo: simplified text rules; review every answer.'}; + } + const api = {draft, async request(url, options) { + if (!['/api/faqs/preview', '/api/faqs/generate'].includes(url)) { + return {ok: false, json: async () => ({message: 'PDF and Word processing are available in the downloadable Java app.'})}; + } + try { + const data = draft(JSON.parse(options.body).content, url.endsWith('/generate') ? 'generate' : 'extract'); + return {ok: true, json: async () => data}; + } catch (error) { return {ok: false, json: async () => ({message: error.message})}; } + }}; + if (typeof module !== 'undefined' && module.exports) module.exports = api; + else root.Doc2FaqDemo = api; +})(globalThis); From 128b6770fec3fdf625c947a418fd7827046e3aa1 Mon Sep 17 00:00:00 2001 From: OKAN TIKTAS <346542017+OKAN-SOFTWARE@users.noreply.github.com> Date: Fri, 6 Nov 2026 13:58:52 -0500 Subject: [PATCH 2/3] fix: use own-property lookup for browser demo heading phrases --- src/test/js/demo.test.cjs | 10 ++++++++++ web-demo/engine.js | 4 +++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/test/js/demo.test.cjs b/src/test/js/demo.test.cjs index 088377d..19d0785 100644 --- a/src/test/js/demo.test.cjs +++ b/src/test/js/demo.test.cjs @@ -43,3 +43,13 @@ test('HTML-like document text remains source text in the demo result', () => { const result = draft('Q: What?\nA: ', 'extract'); assert.equal(result.items[0].answer, ''); }); + +test('unrecognized headings use string fallback even when named like Object properties', () => { + const text = '## Constructor\nFirst detail.\n## __proto__\nSecond detail.\n## toString\nThird detail.\n## Services\nOnboarding.'; + const result = draft(text, 'generate'); + assert.equal(result.count, 4); + assert.equal(result.items[0].question, 'What should I know about Constructor?'); + assert.equal(result.items[1].question, 'What should I know about __proto__?'); + assert.equal(result.items[2].question, 'What should I know about toString?'); + assert.equal(result.items[3].question, 'What services are included?'); +}); diff --git a/web-demo/engine.js b/web-demo/engine.js index 2b4a48a..a053769 100644 --- a/web-demo/engine.js +++ b/web-demo/engine.js @@ -44,7 +44,9 @@ const phrasing = {services: 'What services are included?', support: 'Where can I get support?', 'team responsibilities': 'What are the team responsibilities?', 'knowledge sharing': 'How is knowledge shared?', 'technical skills': 'Which skills and technologies are listed?'}; - add(phrasing[label.toLowerCase()] || 'What should I know about ' + label + '?', heading.i, finish, body); + const suggestion = Object.hasOwn(phrasing, label.toLowerCase()) + ? phrasing[label.toLowerCase()] : 'What should I know about ' + label + '?'; + add(suggestion, heading.i, finish, body); } if (!headings.length && !items.length) { let first = lines.findIndex(line => line.trim()), last = lines.length - 1; From da37008c836824b985d7d05764451db6ffc6930d Mon Sep 17 00:00:00 2001 From: OKAN TIKTAS <346542017+OKAN-SOFTWARE@users.noreply.github.com> Date: Fri, 6 Nov 2026 13:59:44 -0500 Subject: [PATCH 3/3] fix: version browser demo assets by content hash --- docs/WEB-DEMO.md | 2 +- scripts/build-web-demo.mjs | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/WEB-DEMO.md b/docs/WEB-DEMO.md index dfaaaa9..a697fc4 100644 --- a/docs/WEB-DEMO.md +++ b/docs/WEB-DEMO.md @@ -27,7 +27,7 @@ node --test src/test/js/*.test.cjs node scripts/build-web-demo.mjs ``` -The builder creates ignored `demo-dist/` from the actual app frontend, shared project validator, stylesheet, and background. It replaces backend requests with the browser-only adapter in `web-demo/engine.js`, limits uploads to TXT/Markdown, removes binary export choices, uses relative asset paths, fills the source-build version, and adds demo disclosure and homepage/source/download links. It does not modify the Java application's served UI. +The builder creates ignored `demo-dist/` from the actual app frontend, shared project validator, stylesheet, and background. It replaces backend requests with the browser-only adapter in `web-demo/engine.js`, limits uploads to TXT/Markdown, removes binary export choices, uses relative asset paths with content-hash cache versions, fills the source-build version, and adds demo disclosure and homepage/source/download links. It does not modify the Java application's served UI. Copy the complete contents of `demo-dist/` into `projects/doc2faq/` in the private `OKAN-SOFTWARE/okantiktas.com` repository. Preserve relative filenames. Update the Doc2FAQ homepage card to the demo route. Keep `/project/doc2faq/index.html` as a redirect with a visible fallback link. Do not replace the rest of the portfolio or its activity scripts. diff --git a/scripts/build-web-demo.mjs b/scripts/build-web-demo.mjs index 6335c8e..b117457 100644 --- a/scripts/build-web-demo.mjs +++ b/scripts/build-web-demo.mjs @@ -1,6 +1,7 @@ import {readFile, writeFile, mkdir, copyFile} from 'node:fs/promises'; import {fileURLToPath} from 'node:url'; import path from 'node:path'; +import {createHash} from 'node:crypto'; const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); const output = path.join(root, 'demo-dist'); const source = path.join(root, 'src/main/resources/static'); @@ -40,4 +41,9 @@ await writeFile(path.join(output, 'app.js'), app); for (const file of ['project.js', 'background.js', 'styles.css']) await copyFile(path.join(source, file), path.join(output, file)); await copyFile(path.join(root, 'web-demo/engine.js'), path.join(output, 'engine.js')); await writeFile(path.join(output, 'styles.css'), (await readFile(path.join(output, 'styles.css'), 'utf8')) + '\n.demo-links{display:flex;gap:12px;flex-wrap:wrap;margin:0 0 18px}.demo-links .button-primary{flex:0 1 auto}.demo-disclosure{color:var(--muted);font-size:13px;line-height:1.7;margin-bottom:30px}.demo-disclosure a{color:var(--mint)}\n'); +for (const file of ['app.js', 'engine.js', 'project.js', 'background.js', 'styles.css']) { + const digest = createHash('sha256').update(await readFile(path.join(output, file))).digest('hex').slice(0, 12); + html = html.replaceAll('./' + file + '"', './' + file + '?v=' + digest + '"'); +} +await writeFile(path.join(output, 'index.html'), html); console.log('Built browser demo at ' + output);