Collection detection you already know

This commit is contained in:
Javier Feliz 2025-08-20 00:56:22 -04:00
parent 06d22835c7
commit 8d3ec7a983
7 changed files with 114 additions and 12 deletions

View File

@ -2,6 +2,9 @@
namespace App\Commands; namespace App\Commands;
use App\Build\SiteParser;
use App\Models\ContentCollection;
use App\SiteConfiguration;
use Illuminate\Console\Scheduling\Schedule; use Illuminate\Console\Scheduling\Schedule;
use LaravelZero\Framework\Commands\Command; use LaravelZero\Framework\Commands\Command;
use Symfony\Component\Yaml\Yaml; use Symfony\Component\Yaml\Yaml;
@ -25,5 +28,15 @@ class ParseConfigCommand extends Command
/** /**
* Execute the console command. * Execute the console command.
*/ */
public function handle() {} public function handle()
{
// $col = new ContentCollection("projects");
// dd(SiteConfiguration::collections());
foreach ((new SiteParser)->getPages() as $p) {
$this->info($p->key);
$this->warn("- " . $p->entityName);
$this->warn("- " . $p->collection);
$this->warn("- " . $p->layout);
}
}
} }

View File

@ -2,10 +2,35 @@
namespace App\Models; namespace App\Models;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Storage;
class ContentCollection class ContentCollection
{ {
public function __construct( public Collection $pages;
protected string $name,
protected string $layout public function __construct(public string $name)
) {} {
$directories = Storage::disk('source')->directories($name);
$files = Storage::disk('source')->files($name);
$pages = collect();
foreach ($files as $f) {
$p = new Page($f);
$p->collection = $name;
$pages->push($p);
}
// Go through directories and check for index.md
foreach ($directories as $dir) {
if (Storage::disk('source')->exists("$dir/index.md")) {
$p = new Page("$dir/index.md");
$p->collection = $name;
$pages->push($p);
}
}
$this->pages = $pages;
}
} }

View File

@ -5,6 +5,7 @@ namespace App\Models;
use App\Render\BladeRenderer; use App\Render\BladeRenderer;
use App\Render\MarkdownRenderer; use App\Render\MarkdownRenderer;
use App\Render\Renderer; use App\Render\Renderer;
use App\SiteConfiguration;
use Illuminate\Contracts\Filesystem\Filesystem; use Illuminate\Contracts\Filesystem\Filesystem;
use Illuminate\Support\Facades\Storage; use Illuminate\Support\Facades\Storage;
use League\CommonMark\Environment\Environment; use League\CommonMark\Environment\Environment;
@ -30,6 +31,8 @@ class Page
public string $key; public string $key;
protected Filesystem $sourceDisk; protected Filesystem $sourceDisk;
public ?string $layout; public ?string $layout;
public ?string $collection = null;
public string $entityName; // The name of this page. Ex: projects/myproject = myproject
protected string $content; protected string $content;
public function __construct(public string $path) public function __construct(public string $path)
@ -44,10 +47,45 @@ class Page
$this->isIndex = str($this->filename)->remove("." . $this->fileExtension)->toString() == "index"; $this->isIndex = str($this->filename)->remove("." . $this->fileExtension)->toString() == "index";
$this->directory = dirname($this->path); $this->directory = dirname($this->path);
$this->key = str($this->path)->remove("." . $this->fileExtension)->replace("/", ".")->lower()->toString(); $this->key = str($this->path)->remove("." . $this->fileExtension)->replace("/", ".")->lower()->toString();
$this->entityName = $this->isIndex ? basename($this->directory) : $this->slug;
$this->detectCollection();
$this->fillAdditionalData(); $this->fillAdditionalData();
} }
// TODO: Do something with the [params]
// from the collection name if present.
// Maybe store it in a $collectionParams
// array on the page or something.
public function detectCollection()
{
$key_parts = explode('.', $this->key);
$collections = SiteConfiguration::collections();
foreach ($collections as $c) {
$parts = explode('.', $c);
// If we have key: projects.something
// and collection projects.[project_name].docs
// then it's not it
if (count($parts) > $key_parts) {
continue;
}
// Get a subset of max length key parts
$key_compare = array_slice($key_parts, 0, count($parts));
$match = true;
foreach ($key_compare as $i => $v) {
// TODO: Use regex here to search for [] instead of just [
if ($v !== $parts[$i] && !str($parts[$i])->contains("[")) {
$match = false;
break;
}
}
if ($match) $this->collection = $c;
}
}
/** /**
* Grab data from the file's front matter * Grab data from the file's front matter
* as well as the config and overwrite * as well as the config and overwrite
@ -57,6 +95,22 @@ class Page
*/ */
public function fillAdditionalData() public function fillAdditionalData()
{ {
// If we have a collection, get the settings from it
if (!empty($this->collection)) {
$config = SiteConfiguration::getConfig()['collections'][$this->collection];
// if ($this->collection == "projects") {
// dd($config);
// }
$fillIfEmpty = ['layout'];
foreach ($fillIfEmpty as $field) {
if (empty($this->$field) && !empty($config[$field])) {
$this->$field = $config[$field];
}
}
}
// Grab front matter data if any // Grab front matter data if any
if ($this->fileExtension == 'md') { if ($this->fileExtension == 'md') {
// Build the markdown parser // Build the markdown parser
@ -73,6 +127,9 @@ class Page
} }
} }
} }
// If layout is still empty just set it to main
if (empty($this->layout)) $this->layout = 'main';
} }
public function renderer(): Renderer public function renderer(): Renderer

View File

@ -6,6 +6,7 @@ use App\Models\Page;
use Illuminate\Support\Facades\Blade; use Illuminate\Support\Facades\Blade;
use League\CommonMark\Environment\Environment; use League\CommonMark\Environment\Environment;
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension; use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
use League\CommonMark\Extension\FrontMatter\FrontMatterExtension;
use League\CommonMark\Extension\GithubFlavoredMarkdownExtension; use League\CommonMark\Extension\GithubFlavoredMarkdownExtension;
use League\CommonMark\MarkdownConverter; use League\CommonMark\MarkdownConverter;
@ -18,13 +19,15 @@ class MarkdownRenderer implements Renderer
$mdEnvironment = new Environment(); $mdEnvironment = new Environment();
$mdEnvironment->addExtension(new CommonMarkCoreExtension); $mdEnvironment->addExtension(new CommonMarkCoreExtension);
$mdEnvironment->addExtension(new GithubFlavoredMarkdownExtension); $mdEnvironment->addExtension(new GithubFlavoredMarkdownExtension);
$mdEnvironment->addExtension(new FrontMatterExtension);
$parser = new MarkdownConverter($mdEnvironment); $parser = new MarkdownConverter($mdEnvironment);
$parsed = $parser->convert($p->content()); $parsed = $parser->convert($p->content());
$layout = $p->layout;
$tmpBlade = <<<HTML $tmpBlade = <<<HTML
<x-layouts.main> <x-layouts.{$layout}>
$parsed $parsed
</x-layouts.main> </x-layouts.{$layout}>
HTML; HTML;
$rendered = Blade::render($tmpBlade, []); $rendered = Blade::render($tmpBlade, []);

View File

@ -9,8 +9,9 @@ class SiteConfiguration
public static function getConfig(): array public static function getConfig(): array
{ {
$configPath = base_path('zap.yml'); $configPath = base_path('zap.yml');
$config = Yaml::parseFile($configPath); return Yaml::parseFile($configPath);
} }
public static function collections(): array public static function collections(): array
{ {
$config = self::getConfig(); $config = self::getConfig();

View File

@ -45,7 +45,8 @@ export default function hotReloadPlugin(options = {}) {
"./site/**/*.md", "./site/**/*.md",
"./site/**/*.html", "./site/**/*.html",
"./config/**/*.php", "./config/**/*.php",
"./app/**/*.php" "./app/**/*.php",
"./zap.yml"
], ],
// Files to ignore // Files to ignore

View File

@ -5,6 +5,8 @@ collections:
schema: schema:
- name: string - name: string
- banner: string - banner: string
collections: projects.[project_name].docs:
docs: layout: docs
layout: docs schema:
- title: string
- section: string