Commit Graph

4234 Commits

Author SHA1 Message Date
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
Anas Rashid
c558960ddc Text selection menu like Ganjoor's (#23)
Selecting reading text shows a menu by the selection: معنی (word sidebar, single words),
تلاش (search Divan, phrases quoted), کاپی (text with poet, title and link), شیئر (link to the
page with the selection highlighted via ?hl=; native share sheet where available), قرآن
(tanzil.net), گوگل. Escape or clearing the selection closes it; no layout shift.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 22:36:52 +02:00
Anas Rashid
3201a1c478 Word dictionary in full: all senses with usage examples, every IPA with dialect labels, every recording, full etymologies, synonyms, derived and related words
Panel folds the extras (more meanings, examples, long etymologies, long word lists). 175 MB in PostgreSQL.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 22:27:37 +02:00
Anas Rashid
19b68425f6 Word sidebar: readings by vowels, vowel variants, similar words; Persian/Arabic explained in Urdu
- readings: one spelling, different short vowels (ملک: مَلَک، مَلِک، مِلک، مُلک), each with form,
  transliteration, IPA, audio and meanings
- always: same consonants with other long vowels (consonant-skeleton regex)
- not found: inflection stems (آنکھوں -> آنکھ, جاتے -> جانا), prefix regex, trigram similarity
- Persian/Arabic words with no Urdu entry: Urdu translations via English first, then English, then
  their own language; filler glosses (especially, usually…) dropped
- punctuation, dashes and spaces dropped from selected words and lookup keys; clean titles

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 22:07:10 +02:00
Anas Rashid
7fcc0ee7fa Word dictionary: full Wiktionary data for Urdu, Persian and Arabic in PostgreSQL, kept in sync
- en.wiktionary entries via kaikki.org (meanings, IPA, transliteration, audio, etymology, synonyms)
- ur./fa./ar.wiktionary dumps for meanings in each language (incl. more Urdu entry formats)
- English->Urdu pivot table from Urdu entries' glosses and ur.wiktionary's English entries
- dict-sync.ts: re-imports sources when upstream publishes new files, applies daily recent changes;
  run from deploy/sync.sh
- lookups now read the database (2-7 ms) instead of calling Wikimedia live

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 21:48:56 +02:00
Anas Rashid
ef618094d5 Word sidebar: select a word for its meanings and pronunciation from Wiktionary
Urdu, Persian and Arabic Wiktionaries in that order, each labelled; English meanings, IPA,
transliteration and audio from en.wiktionary; Urdu equivalents pivoted through English when Urdu
Wiktionary has no entry. Cached in PostgreSQL for 30 days. Left panel on wide screens, bottom
sheet on phones.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 21:38:10 +02:00
Anas Rashid
efb7aacde3 Search: highlighted matches, matching couplet or prose excerpt, exact phrase first; opened pages keep the highlight (?hl=)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 21:30:42 +02:00
Anas Rashid
9a2db49eab Radif per ghazal, matla/maqta labels, pen name set apart; contents grouped by radif letter
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 21:27:43 +02:00
Anas Rashid
4c7e0559a7 Search: separate Roman-to-Urdu toggle and on-screen keyboard toggle; keys hidden until asked
The header's flex rule overrode [hidden], so the keys showed on every page.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 21:17:14 +02:00
Anas Rashid
647b9fa369 Keyboard in the Gboard/Windows Urdu layout with a shift layer; physical keys by position
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 21:15:58 +02:00
Anas Rashid
3e0e3a625d Keyboard rows stacked and centred (not the header's flex row)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 21:14:40 +02:00