Commit Graph

4294 Commits

Author SHA1 Message Date
0a4d1f7b0f Merge pull request 'Editor: live code view beside the editor; unchanged drafts are not kept' (#60) from feature/editor-code-view into main
Reviewed-on: #60
2026-10-08 23:21:09 +00:00
Anas Rashid
ed2973dea8 Editor: کوڈ shows the Divan text beside the editor, live; unchanged drafts are not kept
- کوڈ in the toolbar: the Divan text next to the editor (stacked on phones), updated as you type; the سورس tab still edits it.
- A draft is only listed (my drafts, history, activity) once its text differs from the text it started from;
  saving it unchanged drops it (compared as Divan text, so layout-only differences don't count) and says so;
  submitting an unchanged returned draft is refused.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 01:20:05 +02:00
f8517aeb85 Merge pull request 'UI: poet cards (corner bookmark, one size, years on two lines); centred previous/next' (#59) from feature/poet-card-layout into main
Reviewed-on: #59
2026-10-08 23:13:33 +00:00
73cf7c5c4c Merge pull request 'Urdu content editor on Tiptap (structured editing, with the source view)' (#58) from feature/tiptap-editor into main
Reviewed-on: #58
2026-10-08 23:13:20 +00:00
Anas Rashid
ff814a7b76 Reading pages: previous/next buttons centred, پچھلا on the right and اگلا on the left
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 01:11:10 +02:00
Anas Rashid
ad82ad3957 Poet cards: years in Naskh so their lines stay compact (cards grew too tall in Brave with Nastaliq)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 01:09:50 +02:00
Anas Rashid
7ca1c68c52 Poet cards: one size for all (210px, two per row on phones); long names end in … with the full name on hover
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 01:07:33 +02:00
Anas Rashid
9e110d8241 Poet cards: keep the bookmark inside the side padding so it never covers the name (Safari's wider fallback font)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 01:05:30 +02:00
Anas Rashid
6451b615bd Poet cards: bookmark in the top-left corner (saved cards keep their size); Hijri and Gregorian years on separate lines, more padding
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 01:02:28 +02:00
Anas Rashid
f6d0742a97 Editor: keep the font's ligatures (Tiptap's CSS turns them off, which broke Nastaliq)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 00:58:12 +02:00
Anas Rashid
267c693c87 Urdu content editor on Tiptap (#28): structured editing of Divan text, with the source view
- web/src/lib/editor.ts (Tiptap 3 MIT core): verse units of misras (1 = مصرع, 2 = شعر, 3+ = بند, as in
  Divan text) with مطلع/حسن مطلع/مقطع labels, prose paragraphs, chapter headings and sub-headings, a
  dictionary-link mark, footnotes and variant readings; Enter adds a misra (or moves into the next
  empty one), Enter on an empty misra starts a new unit.
- Revision page: editor and source tabs over the same text, the work's data points as rows, a
  toolbar (couplet, paragraph, headings, labels, dictionary link, footnote, variant, undo/redo,
  Roman typing, Urdu keyboard). Saving always sends Divan text.
- Divan text: inline segments keep where links, footnotes and variants sit; toText writes a
  document back. All 11,087 works round-trip unchanged through toText and through the editor.
- The Urdu keyboard and Roman typing type into rich editors; the reader's word sidebar and
  selection menu stay out of editors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 00:53:17 +02:00
20df27bb26 Merge pull request 'Moderators' guide: how to write Divan text with all the tags' (#57) from feature/mod-guide into main
Reviewed-on: #57
2026-10-08 22:44:14 +00:00
271d826fc2 Merge pull request 'Publishing commits to divan-data git; public names only; 'last edited' on poems' (#56) from feature/git-publishing into main
Reviewed-on: #56
2026-10-08 22:44:06 +00:00
Anas Rashid
b605d2722b Moderators' guide (رہنمائی): writing Divan text with every tag, Urdu spelling, summaries and review
/mod/guide, open to all: the tag summary table; the work header; ghazal couplets (Hasrat Mohani);
stanzas (Hali's musaddas); prose chapters and sub-headings (Muhammad Husain Azad's Aab-e-Hayat);
matla/maqta labels; dictionary links, footnotes and variant readings; Urdu letters, punctuation,
digits, diacritics, ZWNJ compounds and spacing; edit summaries; the L2 -> L1 -> admin review.
Every example shows its source beside the site's own rendering (shared DivanPreview component,
also used on the revision page). Linked from the moderation tabs and the editor.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 00:42:21 +02:00
Anas Rashid
93825fe5d9 Publishing commits to divan-data git (#34); public names only; 'last edited' on poems
- api/src/git.ts: each published version is a commit in the divan-data checkout (queued, one at a
  time): the moderator as author by public name with a placeholder email, the summary and version
  in the message, Reviewed-by / Approved-by / Divan-Revision / Divan-Version trailers;
  DIVAN_GIT_PUSH=1 pushes. The commit id is kept with the revision.
- Privacy fix: published files and commits carry public names (profile name, else 'موڈریٹر <id>'),
  never email addresses (divan-data is public).
- Poem pages: 'دیوان کا ورژن …' with who edited, reviewed and published, the date, and a link to
  the commit diff (DIVAN_DATA_COMMIT_URL).
- deploy/sync.sh: pull --rebase so publishing commits are kept.
- Admins are super moderators (documented).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 00:37:39 +02:00
acb8235403 Merge pull request 'Search box icons: search button; keyboard icons inside the poet name box' (#55) from feature/search-box-icons into main
Reviewed-on: #55
2026-10-08 22:34:59 +00:00
5929201efa Merge pull request 'Moderation: versions of works and the L2 → L1 → admin pipeline' (#54) from feature/moderation-pipeline into main
Reviewed-on: #54
2026-10-08 22:34:50 +00:00
835df62aad Merge pull request 'Divan-owned content: works edited in Divan, plus the content management model' (#53) from feature/divan-owned-content into main
Reviewed-on: #53
2026-10-08 22:34:40 +00:00
Anas Rashid
bf7c00d51d Search boxes: search icon at the far left of the top box; poet name box has the keyboard icons inside, like the top box
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 00:33:52 +02:00
Anas Rashid
19af91c594 Moderation: versions of works and the L2 -> L1 -> admin pipeline (#31, #51)
- revisions (a work's Divan text, summary, status, author/reviewer/publisher, the text it started from)
  and revision_events (who did what, with comments): the review thread and the moderation log.
- API (api/src/moderation.ts): what a moderator may do on a work, queue, drafts (one open draft per
  person and work), save, submit, approve, return/reject (reason required), publish; history; log.
  Rules come from the IAM grants: L2 drafts, an L1 covering the work reviews, an admin publishes; L1
  drafts go to the admin, admin drafts publish directly. Publishing numbers the version, writes it
  to divan-data (owned.ts) and updates the site; a draft based on an older version is refused (409).
- Line diff (api/src/diff.ts) against the text a draft started from.
- Site: ترمیم کریں / تاریخچہ on works, /mod (queue, activity log), /mod/rev/<id> (editor with the Urdu
  keyboard and Roman typing, diff, preview, actions, timeline), /mod/work/<id> (versions).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 00:31:47 +02:00
Anas Rashid
8d82527765 Divan-owned content (#30): write works as Divan text + generated JSON for divan-data; headings; content management model
- api/src/owned.ts: fromPoem (a work as Divan text, the start of an edit) and writeOwned (the .dtx
  source and the generated .json into divan-data/divan/); a CLI for writing one by hand.
- Divan text: chapter headings and sub-headings with levels, as their own verse entries.
- All 11,087 works convert to Divan text and back unchanged (apart from repeated spaces, and raw
  '== … ==' markers in prose becoming headings).
- docs/content-model.md: the content management model (what is identified, versions and who did
  what (#51), tags and tag search (#52), storage).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 00:22:31 +02:00
a9626b4d9e Merge pull request 'Research: content model and moderation (no wiki engine embedded; Divan text format)' (#49) from research/content-model into main 2026-10-08 22:16:18 +00:00
Anas Rashid
89231985b9 Merge remote-tracking branch 'gitea/main' into research/content-model 2026-10-09 00:16:13 +02:00
098a0185e6 Merge pull request 'Bookmark icon and wording: محفوظ کریں / محفوظ شدہ' (#48) from feature/bookmark-icon into main 2026-10-08 22:16:03 +00:00
Anas Rashid
6d1668b8d3 Merge remote-tracking branch 'gitea/main' into research/content-model 2026-10-09 00:15:49 +02:00
Anas Rashid
04d845c3e4 Merge main (search results) into feature/bookmark-icon 2026-10-09 00:15:47 +02:00
2ceab3164f Merge pull request 'Search: poets and content separately, numbered pages, author filter with Urdu input' (#50) from feature/search-results into main
Reviewed-on: #50
2026-10-08 22:14:49 +00:00
Anas Rashid
453659f5d1 Search: poets/writers and books separate from content; numbered pages; filter by authors with Urdu input
- Results in groups: شعرا و ادبا (by name or pen name, with years, work counts and a 'search in their
  works' link), کتابیں اور ابواب (books/chapters by title), and کلام (content).
- Content pages: numbered pagination (first, last, two either side, gaps) and 'نتائج ۴۱–۶۰ از ۸۱۱۶'.
- Author filter: chips for the authors the results come from, with counts; tick one or several to
  narrow; a name box finds any other poet/writer, with the Urdu keyboard and Roman-to-Urdu typing.
  The keyboard and Roman typing now work on any input marked data-urdu, not only the search box.
- API: poet=1,2 (several), authors with counts, poets and books on page 1 (api/src/search.ts).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 00:14:26 +02:00
Anas Rashid
9338c3dde0 Bookmark buttons say 'محفوظ کریں', then 'محفوظ شدہ' with the accent colour
Owner request. Saved state: filled accent-coloured glyph, bold accent text and border, light accent
tint; the label follows the state on load and on click. The selection menu's phrase option and the
couplet bookmark's label use the same words.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 00:07:53 +02:00
Anas Rashid
21ccf030ad Research: content model and moderation (#38): no wiki engine embedded; Divan text format prototype
docs/content-model.md compares MediaWiki (+FlaggedRevs/Approved Revs, ProofreadPage, SMW, Wikibase),
Wiki.js, BookStack, Outline, Docmost, DokuWiki, wikiparser-node, Tiptap/ProseMirror/CodeMirror, TEI P5
and Ganjoor's correction model, and recommends: Divan text (a Wikisource-compatible markup subset)
as the published source in divan-data, one file per work; moderation workflow in PostgreSQL; Tiptap
editor with a source view; wikiparser-node for Wikisource sync; TEI export.

Prototype api/src/divantext.ts (parse, verse JSON, TEI) with tests on a real Ghalib ghazal and Sir
Syed chapter: identical verses to today's export, Wikisource markup reads as-is, TEI validates.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 00:06:06 +02:00
Anas Rashid
bf96002fa1 Bookmark icon: our own rounded design (soft corners and notch), like common app icon packs
Owner reference: a Flaticon bookmark pack (similar, not the same). Drawn here, so no third-party
licence or attribution; grey outline when not set, filled brand colour when set.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 00:04:58 +02:00
Anas Rashid
cd404710f0 Bookmark icon like Android apps: grey outline when not set, filled brand colour when set
Material Design 'bookmark' / 'bookmark_border' (Apache-2.0) drawn as a CSS mask so it follows the
theme; replaces the 🔖 emoji on bookmark buttons, couplet bookmarks, bookmarked phrases, contents
lists and cards, and the نشانات tab.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 00:03:02 +02:00
2b558ea494 Merge pull request 'Bookmarks (🔖) for poets, books/chapters and poems; word book on its own page' (#47) from feature/bookmarks-and-word-book into main
Reviewed-on: #47
2026-10-08 22:00:43 +00:00
Anas Rashid
98585962e2 Bookmarks with 🔖 for poets, books/chapters and poems; word book on its own page
Owner direction: the word collection is separate from bookmarks, and bookmarks use the bookmark
glyph, not hearts.
- 🔖 نشان buttons on poet, book/chapter (new) and poem pages; contents lists and cards show 🔖.
- /library (نشانات): bookmarked poets, books and chapters, poems, couplets, phrases.
- /words (ذخیرۂ الفاظ): the word book on its own page; tabs between the two; header links.
- Word button: 'ذخیرۂ الفاظ میں ڈالیں' (+), 'ذخیرۂ الفاظ میں ہے' (✓) once added.
- API: library kind 'category' (books and chapters) in toggle, state, marks and the list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 23:58:59 +02:00
4b3d228f49 Merge pull request 'Word book: + instead of a heart for words' (#46) from feature/word-book into main
Reviewed-on: #46
2026-10-08 21:58:16 +00:00
Anas Rashid
d4eaab769c Word book: + to add words (ذخیرۂ الفاظ), ✓ when added; hearts only for poets and works
Owner request: words are not favourites. The sidebar button reads '+ ذخیرۂ الفاظ میں' and turns
into '✓' once added; the selection menu has '+ لفظ'; the library section is ذخیرۂ الفاظ.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 23:52:41 +02:00
c05ad94b53 Merge pull request 'Personal library: saved poets, works, couplets and words' (#45) from feature/library into main
Reviewed-on: #45
2026-10-08 21:51:04 +00:00
Anas Rashid
55cc602815 Library: bookmarked phrases, and glyphs where the reader's marks are
- Select any part of a couplet or paragraph and press نشان (selection menu): the phrase is
  bookmarked and shown underlined with a small 🔖, also across the two misras; clicking it removes
  the bookmark (with a confirmation). Listed in the library as نشان زدہ عبارتیں.
- Contents lists show ♥ on favourite works and 🔖 on works holding bookmarks; book/section cards and
  poet cards (home) show 🔖 when they hold any. API: GET /api/library/marks; phrases in state and
  library; phrase kind validated against the couplet's text.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 23:48:42 +02:00
531d4e9f69 Merge pull request 'Profile: full name and bio' (#43) from feature/profile into main
Reviewed-on: #43
2026-10-08 21:45:19 +00:00
Anas Rashid
8f4a71530d Personal library and word collection (#24, #25)
- Save (♡) poets and works, bookmark (🔖) couplets and paragraphs, save words from the word sidebar
  or the selection menu (with the couplet they came from); notes on items.
- /library (میری لائبریری): the reader's name and bio, then favourite poets, works, bookmarked
  couplets and saved words, each with its full path (poet » book » section » work) and a link to
  the couplet (#cN anchors on poem pages); saved words open the word sidebar.
- API (api/src/library.ts), JSON + Bearer tokens so mobile apps (#44) can use it; deleting an
  account deletes its library. Signed-out readers are sent to sign-in.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 23:35:34 +02:00
Anas Rashid
be0238521f Profile: full name and bio (#42)
Readers write their full name and a short bio (Urdu or any text) on /account; the name heads the
account page and the header shows the first name. API: POST /api/auth/profile (trimmed, control
characters dropped, 100 and 1,000 characters).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 23:31:19 +02:00
264a42c996 Merge pull request 'Permissions (IAM): moderators and scoped grants' (#40) from feature/permissions into main
Reviewed-on: #40
2026-10-08 21:22:26 +00:00
Anas Rashid
d72c14f8bd Permissions (IAM): L2/L1 moderators and scoped grants (#29)
- Roles: reader, mod-l2, mod-l1, admin. Grants: scope (all, poet, book/section with everything in
  it, one work) x content (poets, books, works, dictionary) x actions (create, edit, delete,
  arrange); dictionary grants are site-wide. can() in api/src/permissions.ts is the one check.
- Admin API and pages: role dropdown on /admin; /admin/user/:id lists a moderator's grants, adds
  them (target by poet id or page link) and revokes them; demoting a moderator clears their grants;
  grant and revoke go to the audit log.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 23:13:06 +02:00
48b106857d Merge pull request 'Admin panel: users, password resets, roles, audit log' (#39) from feature/admin-panel into main
Reviewed-on: #39
2026-10-08 21:10:04 +00:00
Anas Rashid
acf7767495 Admin panel: users, password reset on request, disable, roles, delete, audit log (#27)
- API (api/src/admin.ts, admins only): user list and search; password reset generates a temporary
  password shown once and ends the user's sessions; disable/enable (ends sessions, blocks sign-in);
  roles reader/admin; delete; an admin cannot disable, demote or delete themself. Every action is
  written to audit_log (kept when users are deleted).
- First admin from the server: npm run make-admin -- <email> (after signing up).
- Site: /admin (users) and /admin/audit; 'ایڈمن' link in the header for admins.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 23:08:19 +02:00
6610ed0f71 Merge pull request 'Accounts: email and password' (#37) from feature/accounts into main
Reviewed-on: #37
2026-10-08 21:05:05 +00:00
Anas Rashid
aa264aa6c3 Merge main (selection menu) into feature/accounts 2026-10-08 22:58:08 +02:00
c177b45561 Merge pull request 'Text selection menu like Ganjoor's' (#26) from feature/selection-menu into main
Reviewed-on: #26
2026-10-08 20:57:38 +00:00
Anas Rashid
e12f6eeb2a Selection menu: remove the قرآن option (owner request)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 22:56:46 +02:00
Anas Rashid
e409adc668 Accounts: email and password sign-up, sign-in/out, change password, delete account (#18)
- API (api/src/auth.ts): scrypt password hashes; random session tokens stored only as SHA-256;
  30-day sliding sessions; rate limits on sign-in (per IP and per email) and sign-up; changing the
  password signs out other devices; deleting the account removes its data.
- Site: /signup, /signin (returns to the page the reader came from), /account; header link; plain
  forms, no JavaScript needed. Session in an HTTP-only, SameSite=Lax cookie (Secure over HTTPS).
- CSRF: Astro's origin check, with the site's hostnames listed (SITE_HOSTS) so its own form posts
  pass and other sites' are refused.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 22:53:51 +02:00