167 lines
5.6 KiB
PHP
167 lines
5.6 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use App\Render\BladeRenderer;
|
|
use App\Render\MarkdownRenderer;
|
|
use App\Render\Renderer;
|
|
use App\SiteConfiguration;
|
|
use Illuminate\Contracts\Filesystem\Filesystem;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use League\CommonMark\Environment\Environment;
|
|
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
|
|
use League\CommonMark\Extension\FrontMatter\FrontMatterExtension;
|
|
use League\CommonMark\Extension\FrontMatter\Output\RenderedContentWithFrontMatter;
|
|
use League\CommonMark\MarkdownConverter;
|
|
|
|
use function Illuminate\Filesystem\join_paths;
|
|
|
|
// TODO: Load page's frontmatter and replace things like
|
|
// title and layout from it. Also set any default,
|
|
// values for things like layout from the config
|
|
// if they're not present on the page.
|
|
class Page
|
|
{
|
|
public string $filename;
|
|
public string $fileExtension;
|
|
public string $directory;
|
|
public string $title;
|
|
public string $slug;
|
|
public bool $isIndex;
|
|
public string $key;
|
|
protected Filesystem $sourceDisk;
|
|
public ?string $layout;
|
|
public ?string $collection = null;
|
|
public string $entityName; // The name of this page. Ex: projects/myproject = myproject
|
|
protected string $content;
|
|
|
|
public function __construct(public string $path)
|
|
{
|
|
$this->sourceDisk = Storage::disk('source');
|
|
|
|
$this->filename = basename($this->path);
|
|
$this->fileExtension = (str_ends_with($this->filename, '.blade.php')) ? 'blade.php' : pathinfo($this->filename, PATHINFO_EXTENSION);
|
|
$this->fileExtension = str($this->fileExtension)->trim('.')->toString();
|
|
$this->title = str($this->filename)->remove("." . $this->fileExtension)->title()->toString();
|
|
$this->slug = str($this->title)->slug();
|
|
$this->isIndex = str($this->filename)->remove("." . $this->fileExtension)->toString() == "index";
|
|
$this->directory = dirname($this->path);
|
|
$this->key = str($this->path)->remove("." . $this->fileExtension)->replace("/", ".")->lower()->toString();
|
|
$this->entityName = $this->isIndex ? basename($this->directory) : $this->slug;
|
|
|
|
$this->detectCollection();
|
|
$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
|
|
* as well as the config and overwrite
|
|
* or fill in any missing attributes.
|
|
*
|
|
* @return void
|
|
*/
|
|
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
|
|
if ($this->fileExtension == 'md') {
|
|
// Build the markdown parser
|
|
$mdEnvironment = new Environment();
|
|
$mdEnvironment->addExtension(new CommonMarkCoreExtension);
|
|
$mdEnvironment->addExtension(new FrontMatterExtension);
|
|
|
|
$parser = new MarkdownConverter($mdEnvironment);
|
|
$parsed = $parser->convert($this->content());
|
|
if ($parsed instanceof RenderedContentWithFrontMatter) {
|
|
$frontMatter = $parsed->getFrontMatter();
|
|
foreach ($frontMatter as $field => $value) {
|
|
$this->$field = $value;
|
|
}
|
|
}
|
|
}
|
|
|
|
// If layout is still empty just set it to main
|
|
if (empty($this->layout)) $this->layout = 'main';
|
|
}
|
|
|
|
public function renderer(): Renderer
|
|
{
|
|
return ($this->fileExtension == 'blade.php') ? new BladeRenderer : new MarkdownRenderer;
|
|
}
|
|
|
|
public function render(): string
|
|
{
|
|
return $this->renderer()->render($this);
|
|
}
|
|
|
|
public function outputPath(): string
|
|
{
|
|
|
|
$baseDirectory = $this->directory;
|
|
if ($this->isIndex) {
|
|
return join_paths($baseDirectory, "index.html");
|
|
}
|
|
|
|
return join_paths($baseDirectory, "{$this->slug}", "index.html");
|
|
}
|
|
|
|
public function content(): string
|
|
{
|
|
if (!empty($this->content)) {
|
|
return $this->content;
|
|
}
|
|
|
|
$content = Storage::disk('source')->get($this->path);
|
|
$this->content = $content;
|
|
return $content;
|
|
}
|
|
}
|