Projects islamic-network libraries qalam Files
Revision indexing in progress... (search in this revision will be accurate after indexed)
src Loading last commit info...
tests
.gitignore
README.md
composer.json
phpunit.xml
README.md

qalam — قلم

Content wrappers for the Islamic Network ilm CMS: the shared layer between Directus and the public Kipchak APIs (pray, events, people). Included as a Composer package by the APIs and the Islamic Network SDK.

Everything the API contracts promise that Directus doesn't do lives here:

ComponentJob
Markdown\RendererCMS Markdown → HTML (CommonMark; inline HTML allowed, unsafe links not)
Markdown\BracketSpansThe authoring convention […]{.translit} / […]{lang=ur} → spans
Html\LanguageNormalizerWraps untagged Arabic runs in <span lang="ar">; promotes all-Arabic blocks to <p lang="ar" dir="rtl">; honorific ligatures (ﷺ) flow inline
Text\ProseA prose field as served: {raw: <markdown>, html: <rendered+normalized>}
Directus\TranslationsPivots *_translations rows into {ar, ar-Latn, en, …} objects (BCP 47 keys, canonical order, empties omitted)
Text\DiacriticFolderSearch folding: tasbih matches Ṣalāt al-Tasbīḥ and تَسْبِيح
Content\TimesThe times-of-day contract enum → {key, label} pairs
Api\Pagination?page/?limit parsing + the meta block ({total, page, limit, pages})

The response envelope ({code, status, data}) is not here — Kipchak owns it.

Requirements

PHP 8.4+ (uses the new Dom\HTMLDocument API), ext-dom, ext-intl, ext-mbstring.

Tests are the contract

tests/fixtures/ holds copies of the locked API samples from ../api/. The pipeline tests assert that rendering each sample's raw produces its html byte-for-byte (modulo inter-tag whitespace) — if a convention changes, change the sample first and the tests say what code must follow.

composer install
composer test

Usage sketch

use IslamicNetwork\Qalam\Directus\Translations;
use IslamicNetwork\Qalam\Text\Prose;
use IslamicNetwork\Qalam\Content\Times;

$t = new Translations($directusRow['translations']);

$record = [
    'name'         => $t->text('name'),          // {ar, ar-Latn, en}
    'description'  => $t->prose('description'),  // {en: {raw, html}}
    'translations' => $t->text('translation'),   // {ar-Latn, en, ur, …}
    'times'        => Times::toApi($junction['times']),
];
Please wait...
Connection lost or session expired, reload to recover
Page is in error, reload to recover