16 changed files with 87 additions and 376 deletions
@ -1,58 +0,0 @@
@@ -1,58 +0,0 @@
|
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
namespace App\Util; |
||||
|
||||
use App\Enum\KindsEnum; |
||||
|
||||
/** |
||||
* NIP-51 kind 30004 (curation set) for the home strip: ordered `a` tags for kind **30023** only. |
||||
* Other address kinds and `e` tags are ignored. |
||||
*/ |
||||
final class CurationSet30004Home |
||||
{ |
||||
/** |
||||
* @param iterable<int, mixed> $tags Event tag rows (Nostr JSON shape) |
||||
* |
||||
* @return array{title: string, items: list<array{type: 'article', pk: string, slug: string}>} |
||||
*/ |
||||
public static function parseTitleAndOrderedRefs(iterable $tags): array |
||||
{ |
||||
$title = ''; |
||||
$items = []; |
||||
foreach ($tags as $tag) { |
||||
if (!\is_array($tag) || $tag === []) { |
||||
continue; |
||||
} |
||||
$name = isset($tag[0]) ? strtolower((string) $tag[0]) : ''; |
||||
$v = isset($tag[1]) ? (string) $tag[1] : ''; |
||||
if ($v === '') { |
||||
continue; |
||||
} |
||||
if ($name === 'title' && $title === '') { |
||||
$title = trim($v); |
||||
continue; |
||||
} |
||||
if ($name !== 'a') { |
||||
continue; |
||||
} |
||||
$parts = explode(':', $v, 3); |
||||
if (\count($parts) < 3) { |
||||
continue; |
||||
} |
||||
$kind = (int) $parts[0]; |
||||
if ($kind !== KindsEnum::LONGFORM->value) { |
||||
continue; |
||||
} |
||||
$pk = strtolower(trim($parts[1])); |
||||
$slug = trim($parts[2]); |
||||
if (64 !== \strlen($pk) || !ctype_xdigit($pk) || $slug === '') { |
||||
continue; |
||||
} |
||||
$items[] = ['type' => 'article', 'pk' => $pk, 'slug' => $slug]; |
||||
} |
||||
|
||||
return ['title' => $title, 'items' => $items]; |
||||
} |
||||
} |
||||
@ -1,19 +1,18 @@
@@ -1,19 +1,18 @@
|
||||
{# |
||||
NIP-51 30004 home strip: section title from list `title` tag; each item reads like a static landing |
||||
section — illustration (max 400px, natural aspect), headline, then full article body (Markdown + |
||||
highlights as on /p/…/d/…). Body is not wrapped in a single <a> (markdown may contain links). |
||||
Home: magazine root kind 30040 — long-form `a` tags in index order (top to bottom). Section title from |
||||
root `title` tag. Same layout as before: illustration, headline, full article body (Markdown + highlights). |
||||
#} |
||||
{% if tiles is not empty %} |
||||
<section |
||||
class="home-curation-landmark" |
||||
{% if section_title|default('') != '' %} |
||||
aria-labelledby="home-curation-landmark-heading" |
||||
aria-labelledby="home-magazine-strip-heading" |
||||
{% else %} |
||||
aria-label="{{ (website_name ~ ' — curated articles')|e('html_attr') }}" |
||||
aria-label="{{ (website_name ~ ' — featured articles')|e('html_attr') }}" |
||||
{% endif %} |
||||
> |
||||
{% if section_title|default('') != '' %} |
||||
<h2 id="home-curation-landmark-heading" class="home-curation-landmark__title">{{ section_title|e }}</h2> |
||||
<h2 id="home-magazine-strip-heading" class="home-curation-landmark__title">{{ section_title|e }}</h2> |
||||
{% endif %} |
||||
<div class="home-curation-landmark__articles"> |
||||
{% for tile in tiles %} |
||||
@ -1,44 +0,0 @@
@@ -1,44 +0,0 @@
|
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
namespace App\Tests\Util; |
||||
|
||||
use App\Util\CurationSet30004Home; |
||||
use PHPUnit\Framework\TestCase; |
||||
|
||||
final class CurationSet30004HomeTest extends TestCase |
||||
{ |
||||
public function testParsesTitleAndOrdered30023RefsOnly(): void |
||||
{ |
||||
$eid = 'd78ba0d5dce22bfff9db0a9e996c9ef27e2c91051de0c4e1da340e0326b4941e'; |
||||
$tags = [ |
||||
['d', 'jvdy9i4'], |
||||
['title', 'Yaks'], |
||||
['image', 'https://example.com/y.jpg'], |
||||
['a', '30023:26dc95542e18b8b7aec2f14610f55c335abebec76f3db9e58c254661d0593a0c:slug-one'], |
||||
['e', $eid], |
||||
['a', '30024:26dc95542e18b8b7aec2f14610f55c335abebec76f3db9e58c254661d0593a0c:draft-only'], |
||||
['a', '30023:26dc95542e18b8b7aec2f14610f55c335abebec76f3db9e58c254661d0593a0c:slug-two'], |
||||
]; |
||||
$out = CurationSet30004Home::parseTitleAndOrderedRefs($tags); |
||||
self::assertSame('Yaks', $out['title']); |
||||
self::assertSame([ |
||||
['type' => 'article', 'pk' => '26dc95542e18b8b7aec2f14610f55c335abebec76f3db9e58c254661d0593a0c', 'slug' => 'slug-one'], |
||||
['type' => 'article', 'pk' => '26dc95542e18b8b7aec2f14610f55c335abebec76f3db9e58c254661d0593a0c', 'slug' => 'slug-two'], |
||||
], $out['items']); |
||||
} |
||||
|
||||
public function testSkipsNon30023ATags(): void |
||||
{ |
||||
$tags = [ |
||||
['a', '30040:26dc95542e18b8b7aec2f14610f55c335abebec76f3db9e58c254661d0593a0c:mag'], |
||||
['a', '30023:26dc95542e18b8b7aec2f14610f55c335abebec76f3db9e58c254661d0593a0c:ok'], |
||||
]; |
||||
$out = CurationSet30004Home::parseTitleAndOrderedRefs($tags); |
||||
self::assertSame('', $out['title']); |
||||
self::assertCount(1, $out['items']); |
||||
self::assertSame('article', $out['items'][0]['type']); |
||||
self::assertSame('ok', $out['items'][0]['slug']); |
||||
} |
||||
} |
||||
Loading…
Reference in new issue