1
0
mirror of https://github.com/suk-ws/ph-Bookshelf.git synced 2025-01-19 15:25:03 +08:00

add support for md front matter & open page unlisted

- support page config define in front matter
  - support `title`, which can set HTML title.
    - if `title` is not set, then HTML title will try find page title defined in book.xml
	- if `title` is set but <h1> title not set, it will generated a <h1> title using the value of `title`
  - support `configurations` which can set page level configs here.
- now can open page that has .md file but not defined in book.xml (must in a book defined)
- old.title.gen is not supported yet.
This commit is contained in:
A.C.Sukazyo Eyre 2023-03-25 20:11:10 +08:00
parent 0f0e024a31
commit f79060f32f
Signed by: Eyre_S
GPG Key ID: C17CE40291207874
20 changed files with 207 additions and 413 deletions

View File

@ -8,7 +8,6 @@
<xs:complexType name="phb-config-level-site"> <xs:complexType name="phb-config-level-site">
<xs:all> <xs:all>
<xs:element minOccurs="0" name="old.title.gen" type="xs:boolean" />
<xs:element minOccurs="0" name="highlightjs" type="xs:boolean" /> <xs:element minOccurs="0" name="highlightjs" type="xs:boolean" />
<xs:element minOccurs="0" name="highlightjs.languages" type="xs:string" /> <xs:element minOccurs="0" name="highlightjs.languages" type="xs:string" />
<xs:element minOccurs="0" name="highlightjs.theme" type="xs:string" /> <xs:element minOccurs="0" name="highlightjs.theme" type="xs:string" />
@ -24,7 +23,6 @@
</xs:complexType> </xs:complexType>
<xs:attributeGroup name="phb-config-level-page"> <xs:attributeGroup name="phb-config-level-page">
<xs:attribute name="old.title.gen" type="xs:boolean" />
<xs:attribute name="highlightjs" type="xs:boolean" /> <xs:attribute name="highlightjs" type="xs:boolean" />
<xs:attribute name="highlightjs.languages" type="xs:string" /> <xs:attribute name="highlightjs.languages" type="xs:string" />
<xs:attribute name="highlightjs.theme" type="xs:string" /> <xs:attribute name="highlightjs.theme" type="xs:string" />

View File

@ -17,14 +17,12 @@
} }
}, },
"require": { "require": {
"php": ">=8.1", "php": ">=8.2",
"ext-xml": "*", "ext-xml": "*",
"ext-dom": "*", "ext-dom": "*",
"ext-mbstring": "*", "ext-mbstring": "*",
"ext-fileinfo": "*", "ext-fileinfo": "*",
"league/commonmark": ">=2.3.8", "league/commonmark": ">=2.4",
"symfony/yaml": ">=4.0", "symfony/yaml": ">=4.0"
"gregwar/rst": "^1.0",
"xemlock/php-latex": "dev-master"
} }
} }

237
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "992b2bf6550d780081ce38b8a3010d02", "content-hash": "070684f2b1149b2154d297b64b637ed3",
"packages": [ "packages": [
{ {
"name": "dflydev/dot-access-data", "name": "dflydev/dot-access-data",
@ -81,70 +81,18 @@
}, },
"time": "2022-10-27T11:44:00+00:00" "time": "2022-10-27T11:44:00+00:00"
}, },
{
"name": "gregwar/rst",
"version": "v1.0.6",
"target-dir": "Gregwar/RST",
"source": {
"type": "git",
"url": "https://github.com/Gregwar/RST.git",
"reference": "93c630ae18c47d8f7503230fa6ca39a79ad3c598"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Gregwar/RST/zipball/93c630ae18c47d8f7503230fa6ca39a79ad3c598",
"reference": "93c630ae18c47d8f7503230fa6ca39a79ad3c598",
"shasum": ""
},
"require": {
"php": ">=5.3.0",
"symfony/polyfill-mbstring": "^1.12"
},
"require-dev": {
"phpunit/phpunit": "^6.4"
},
"type": "library",
"autoload": {
"psr-0": {
"Gregwar\\RST": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Grégoire Passault",
"email": "g.passault@gmail.com",
"homepage": "http://www.gregwar.com/"
}
],
"description": "PHP library to parse reStructuredText documents",
"homepage": "https://github.com/Gregwar/RST",
"keywords": [
"markup",
"parser",
"rst"
],
"support": {
"issues": "https://github.com/Gregwar/RST/issues",
"source": "https://github.com/Gregwar/RST/tree/v1.0.6"
},
"time": "2020-04-09T08:09:05+00:00"
},
{ {
"name": "league/commonmark", "name": "league/commonmark",
"version": "2.3.8", "version": "2.4.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/thephpleague/commonmark.git", "url": "https://github.com/thephpleague/commonmark.git",
"reference": "c493585c130544c4e91d2e0e131e6d35cb0cbc47" "reference": "d44a24690f16b8c1808bf13b1bd54ae4c63ea048"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/c493585c130544c4e91d2e0e131e6d35cb0cbc47", "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/d44a24690f16b8c1808bf13b1bd54ae4c63ea048",
"reference": "c493585c130544c4e91d2e0e131e6d35cb0cbc47", "reference": "d44a24690f16b8c1808bf13b1bd54ae4c63ea048",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -180,7 +128,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-main": "2.4-dev" "dev-main": "2.5-dev"
} }
}, },
"autoload": { "autoload": {
@ -237,7 +185,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2022-12-10T16:02:17+00:00" "time": "2023-03-24T15:16:10+00:00"
}, },
{ {
"name": "league/config", "name": "league/config",
@ -385,16 +333,16 @@
}, },
{ {
"name": "nette/utils", "name": "nette/utils",
"version": "v4.0.0-RC3", "version": "v4.0.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/nette/utils.git", "url": "https://github.com/nette/utils.git",
"reference": "d5e843cbb941999f3a52ea410baeb2b07580233a" "reference": "cacdbf5a91a657ede665c541eda28941d4b09c1e"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/nette/utils/zipball/d5e843cbb941999f3a52ea410baeb2b07580233a", "url": "https://api.github.com/repos/nette/utils/zipball/cacdbf5a91a657ede665c541eda28941d4b09c1e",
"reference": "d5e843cbb941999f3a52ea410baeb2b07580233a", "reference": "cacdbf5a91a657ede665c541eda28941d4b09c1e",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -466,9 +414,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/nette/utils/issues", "issues": "https://github.com/nette/utils/issues",
"source": "https://github.com/nette/utils/tree/v4.0.0-RC3" "source": "https://github.com/nette/utils/tree/v4.0.0"
}, },
"time": "2023-01-19T21:45:44+00:00" "time": "2023-02-02T10:41:53+00:00"
}, },
{ {
"name": "psr/event-dispatcher", "name": "psr/event-dispatcher",
@ -522,16 +470,16 @@
}, },
{ {
"name": "symfony/deprecation-contracts", "name": "symfony/deprecation-contracts",
"version": "v3.2.0", "version": "v3.2.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git", "url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "1ee04c65529dea5d8744774d474e7cbd2f1206d3" "reference": "e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/1ee04c65529dea5d8744774d474e7cbd2f1206d3", "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e",
"reference": "1ee04c65529dea5d8744774d474e7cbd2f1206d3", "reference": "e2d1534420bd723d0ef5aec58a22c5fe60ce6f5e",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -569,7 +517,7 @@
"description": "A generic function and convention to trigger deprecation notices", "description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.2.0" "source": "https://github.com/symfony/deprecation-contracts/tree/v3.2.1"
}, },
"funding": [ "funding": [
{ {
@ -585,7 +533,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2022-11-25T10:21:52+00:00" "time": "2023-03-01T10:25:55+00:00"
}, },
{ {
"name": "symfony/polyfill-ctype", "name": "symfony/polyfill-ctype",
@ -669,89 +617,6 @@
], ],
"time": "2022-11-03T14:55:06+00:00" "time": "2022-11-03T14:55:06+00:00"
}, },
{
"name": "symfony/polyfill-mbstring",
"version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"provide": {
"ext-mbstring": "*"
},
"suggest": {
"ext-mbstring": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Mbstring\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for the Mbstring extension",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"mbstring",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-11-03T14:55:06+00:00"
},
{ {
"name": "symfony/polyfill-php80", "name": "symfony/polyfill-php80",
"version": "v1.27.0", "version": "v1.27.0",
@ -837,16 +702,16 @@
}, },
{ {
"name": "symfony/yaml", "name": "symfony/yaml",
"version": "v6.2.5", "version": "v6.2.7",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/yaml.git", "url": "https://github.com/symfony/yaml.git",
"reference": "2bbfbdacc8a15574f8440c4838ce0d7bb6c86b19" "reference": "e8e6a1d59e050525f27a1f530aa9703423cb7f57"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/2bbfbdacc8a15574f8440c4838ce0d7bb6c86b19", "url": "https://api.github.com/repos/symfony/yaml/zipball/e8e6a1d59e050525f27a1f530aa9703423cb7f57",
"reference": "2bbfbdacc8a15574f8440c4838ce0d7bb6c86b19", "reference": "e8e6a1d59e050525f27a1f530aa9703423cb7f57",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -891,7 +756,7 @@
"description": "Loads and dumps YAML files", "description": "Loads and dumps YAML files",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/yaml/tree/v6.2.5" "source": "https://github.com/symfony/yaml/tree/v6.2.7"
}, },
"funding": [ "funding": [
{ {
@ -907,65 +772,17 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-01-10T18:53:53+00:00" "time": "2023-02-16T09:57:23+00:00"
},
{
"name": "xemlock/php-latex",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/xemlock/php-latex.git",
"reference": "d60bf4c919426d4fa6978aa1f63208d64df5cc73"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/xemlock/php-latex/zipball/d60bf4c919426d4fa6978aa1f63208d64df5cc73",
"reference": "d60bf4c919426d4fa6978aa1f63208d64df5cc73",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-mbstring": "*",
"php": ">=5.3.0"
},
"require-dev": {
"phpunit/phpunit": ">=5.7"
},
"default-branch": true,
"type": "library",
"autoload": {
"psr-0": {
"PhpLatex_": "library"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "xemlock",
"email": "xemlock@gmail.com"
}
],
"description": "LaTeX parser and renderer",
"support": {
"issues": "https://github.com/xemlock/php-latex/issues",
"source": "https://github.com/xemlock/php-latex/tree/master"
},
"time": "2022-05-03T22:31:34+00:00"
} }
], ],
"packages-dev": [], "packages-dev": [],
"aliases": [], "aliases": [],
"minimum-stability": "alpha", "minimum-stability": "alpha",
"stability-flags": { "stability-flags": [],
"xemlock/php-latex": 20
},
"prefer-stable": false, "prefer-stable": false,
"prefer-lowest": false, "prefer-lowest": false,
"platform": { "platform": {
"php": ">=8.1", "php": ">=8.2",
"ext-xml": "*", "ext-xml": "*",
"ext-dom": "*", "ext-dom": "*",
"ext-mbstring": "*", "ext-mbstring": "*",

View File

@ -2,6 +2,6 @@
const APP_NAME = "ph-Bookshelf"; const APP_NAME = "ph-Bookshelf";
const VERSION = "0.5.0-alpha1"; const VERSION = "0.5.0-alpha2";
const CHANNEL = "suk-ws"; const CHANNEL = "suk-ws";
const BRANCH = "master"; const BRANCH = "config-v2.0";

View File

@ -6,8 +6,15 @@ require "./vendor/autoload.php";
use SukWs\Bookshelf\Data\PageMeta; use SukWs\Bookshelf\Data\PageMeta;
use SukWs\Bookshelf\Data\SiteConfig\RobotsPolicy; use SukWs\Bookshelf\Data\SiteConfig\RobotsPolicy;
use SukWs\Bookshelf\Data\SiteMeta; use SukWs\Bookshelf\Data\SiteMeta;
use SukWs\Bookshelf\Utils\Markdown\Markdown;
use SukWs\Bookshelf\Utils\PageParse; use SukWs\Bookshelf\Utils\PageParse;
use SukWs\Bookshelf\Utils\RequestNotExistException; use SukWs\Bookshelf\Web\Main;
//$parser = new Markdown();
//
//$data = $parser->parse(file_get_contents("./data/test_page.md"));
//
//exit($data->page_html);
try { try {
@ -35,41 +42,17 @@ try {
exit(SiteMeta::getConfigurationLevelShelf("site.robots")); exit(SiteMeta::getConfigurationLevelShelf("site.robots"));
} }
} } else if (PageMeta::init($uri)) {
try { require "./template/header.php";
// 寻找页面 require "./template/nav.php";
Main::main(PageMeta::$page_data);
require "./template/footer.php";
if (sizeof($uri) > 0 && $uri[0] != null) {
// 非主页面,判定当前定义的 book
if ($uri[0] == "%root") {
PageMeta::$book = SiteMeta::getBookshelf()->getRootBook();
} else { } else {
$tmp = SiteMeta::getBookshelf()->getBook($uri[0]);
if ($tmp == null)
throw new RequestNotExistException("Book required \"$uri[0]\" not found!");
PageMeta::$bookId = $uri[0];
PageMeta::$book = $tmp->getContentedNode();
}
// 判定当前页面
if (sizeof($uri) > 1 && $uri[1] != null) {
$tmp = PageMeta::$book->getPage($uri[1]);
if ($tmp == null) throw new RequestNotExistException("Page required \"$uri[1]\" not found on book \"$uri[0]\"!");
PageMeta::$page = $tmp;
} else {
PageMeta::$page = PageMeta::$book->getChildren()->getChildren()[0];
}
} else {
// 主页面
PageMeta::$bookId = "%root";
PageMeta::$book = SiteMeta::getBookshelf()->getRootBook();
PageMeta::$page = PageMeta::$book->getChildren()->getChildren()[0];
PageMeta::$isMainPage = true;
}
} catch (RequestNotExistException $e) {
// 页面寻找失败,寻找资源文件 // 页面寻找失败,寻找资源文件
@ -88,20 +71,12 @@ try {
) {} else if ( // 搜索root书中的书籍资源文件夹中的文件 ) {} else if ( // 搜索root书中的书籍资源文件夹中的文件
file_exists($resLoc = "./data/%root/%assets/$req") file_exists($resLoc = "./data/%root/%assets/$req")
) {} else { ) {} else {
throw $e; // 找不到资源文件 throw new Exception("cannot find file " . $req); // 找不到资源文件
} }
PageParse::outputBinaryFile($resLoc); PageParse::outputBinaryFile($resLoc);
} }
require "./template/header.php";
require "./template/nav.php";
require "./template/main.php";
require "./template/footer.php";
} catch (Exception $e) { } catch (Exception $e) {
echo "<h1>ERROR</h1><p>" . $e->getMessage() . "</p>"; echo "<h1>ERROR</h1><p>" . $e->getMessage() . "</p>";

28
src/Data/PageData.php Normal file
View File

@ -0,0 +1,28 @@
<?php
namespace SukWs\Bookshelf\Data;
readonly class PageData {
public string $page_html;
public ?string $title;
public bool $gen_title;
public array $configurations;
public function __construct (
string $page_html, array $configurations = array(),
string $title = null, bool $gen_title = false
) {
$this->page_html = $page_html;
$this->configurations = $configurations;
$this->title = $title;
$this->gen_title = $gen_title;
}
public function getConfiguration (string $key): ?string {
return @$this->configurations[$key];
}
}

View File

@ -2,19 +2,69 @@
namespace SukWs\Bookshelf\Data; namespace SukWs\Bookshelf\Data;
use Exception;
use SukWs\Bookshelf\Data\SiteConfig\ConfigName; use SukWs\Bookshelf\Data\SiteConfig\ConfigName;
use SukWs\Bookshelf\Element\BookContent\BookContented; use SukWs\Bookshelf\Element\BookContent\BookContented;
use SukWs\Bookshelf\Element\BookContent\Page; use SukWs\Bookshelf\Element\BookContent\Page;
use SukWs\Bookshelf\Utils\Markdown\Markdown;
use SukWs\Bookshelf\Utils\RequestNotExistException;
class PageMeta { class PageMeta {
public static string $bookId; public static string $bookId;
public static BookContented $book; public static BookContented $book;
public static Page $page; public static string $page_id;
public static PageData $page_data;
public static bool $isMainPage = false; public static bool $isMainPage = false;
/**
* @throws RequestNotExistException
* @throws Exception
*/
public static function init (array $uri): bool {
if (!isset($uri[0]) || $uri[0] == "%root" || $uri[0] == "/" || $uri[0] == "") {
self::$book = SiteMeta::getBookshelf()->getRootBook();
self::$bookId = "%root";
} else {
$tmp = SiteMeta::getBookshelf()->getBook($uri[0]);
if ($tmp == null)
throw new RequestNotExistException("Book required \"$uri[0]\" not found!");
self::$bookId = $uri[0];
self::$book = $tmp->getContentedNode();
}
if (isset($uri[1])) {
self::$page_id = $uri[1];
} else {
$tmp = self::$book->getChildren()->getChildren()[0];
if ($tmp instanceof Page) self::$page_id = $tmp->getId();
else throw new RequestNotExistException("No main page in required book \"$uri[0]\"");
self::$isMainPage = true;
}
if ($content = @file_get_contents(self::getPagePath("md"))) {
self::$page_data = (new Markdown())->parse($content);
} else {
return false;
}
return true;
}
public static function getHtmlTitle (): string {
return self::getPageTitle() . " - " . self::$book->getName();
}
public static function getPageTitle (): string { public static function getPageTitle (): string {
return self::$page->getName()." - ".self::$book->getName(); if (self::$page_data->title === null) {
$page_def = self::$book->getPage(self::$page_id);
if ($page_def === null) {
return "...";
}
return $page_def->getName();
}
return self::$page_data->title;
} }
public static function getDescription (): string { public static function getDescription (): string {
@ -30,17 +80,11 @@ class PageMeta {
public static function getConfigurationLevelPage (string $key): ?string { public static function getConfigurationLevelPage (string $key): ?string {
$value = self::getConfigurationLevelBook($key); $value = self::getConfigurationLevelBook($key);
$valueAttr = self::$page->getConfiguration($key); $valueAttr = self::$page_data->getConfiguration($key);
if ($valueAttr != null) $value = $valueAttr; if ($valueAttr != null) $value = $valueAttr;
return $value; return $value;
} }
public static function compatibilityOldTitlePolicy (): bool {
if (self::getConfigurationLevelPage(ConfigName::old_title_gen) == "true")
return true;
return false;
}
public static function highlightJsTheme (): string { public static function highlightJsTheme (): string {
$theme = trim(self::getConfigurationLevelPage(ConfigName::highlightjs_theme)); $theme = trim(self::getConfigurationLevelPage(ConfigName::highlightjs_theme));
if (empty($theme)) return "atom-one-dark"; if (empty($theme)) return "atom-one-dark";
@ -68,4 +112,8 @@ class PageMeta {
return $lang; return $lang;
} }
public static function getPagePath (?string $extension = null): string {
return "./data/" . self::$bookId . "/" . self::$page_id . ($extension == null ? "" : ".".$extension);
}
} }

View File

@ -20,6 +20,4 @@ class ConfigName {
public const ext_title_permalink_flash = "title.permalink.flash"; public const ext_title_permalink_flash = "title.permalink.flash";
public const ext_rolling_title = "web-title.rolling"; public const ext_rolling_title = "web-title.rolling";
public const old_title_gen = "old.title.gen";
} }

View File

@ -94,7 +94,7 @@ class Chapter {
<a class='no-style menu-item' href='javascript:'>%s</a> <a class='no-style menu-item' href='javascript:'>%s</a>
<div class='children'> <div class='children'>
EOL, EOL,
$this->getPage(PageMeta::$page->getId())==null?"":" active", $this->getPage(PageMeta::$page_id)==null?"":" active",
$this->name $this->name
); );
foreach ($this->children as $node) { foreach ($this->children as $node) {

View File

@ -14,8 +14,6 @@ class Page {
private Chapter $parent; private Chapter $parent;
private array $configurations = array();
public function __construct (string $id, string $name, Chapter $parent) { public function __construct (string $id, string $name, Chapter $parent) {
$this->id = $id; $this->id = $id;
$this->name = $name; $this->name = $name;
@ -50,10 +48,6 @@ class Page {
return $this->parent; return $this->parent;
} }
public function getConfiguration (string $key): ?string {
return @$this->configurations[$key];
}
public function getSummaryHtml (): string { public function getSummaryHtml (): string {
// $str = // $str =
// "<li id='page/$this->id' page-id='$this->id' class='page-contented chapter link-page " . // "<li id='page/$this->id' page-id='$this->id' class='page-contented chapter link-page " .
@ -80,8 +74,8 @@ class Page {
href='%s'>%s</a> href='%s'>%s</a>
EOF, EOF,
$this->id, $this->id, $this->id, $this->id,
PageMeta::$page->getId()==$this->id ? " current" : "", PageMeta::$page_id==$this->id ? " current" : "",
PageMeta::$page->getId()==$this->id ? "#top" : $this->encodeUrl(), PageMeta::$page_id==$this->id ? "#top" : $this->encodeUrl(),
$this->name $this->name
); );
} }
@ -93,16 +87,4 @@ class Page {
); );
} }
public function getContentFilename (string $type): string {
return sprintf("./data/%s/%s.%s", PageMeta::$bookId, $this->id, $type);
}
public function hasContent (string $type): string {
return file_exists($this->getContentFilename($type));
}
public function getContent (string $type): string {
return file_get_contents($this->getContentFilename($type));
}
} }

View File

@ -1,24 +0,0 @@
<?php
namespace SukWs\Bookshelf\Utils\LaTeX;
use PhpLatex_Parser;
use PhpLatex_Renderer_Html;
use SukWs\Bookshelf\Utils\PageContentType;
class LaTeX implements PageContentType {
public const type = array("tex");
/**
* @return string[]
*/
public function type (): array {
return self::type;
}
public function parse (string $raw): string {
return (new PhpLatex_Renderer_Html())->render((new PhpLatex_Parser())->parse($raw));
}
}

View File

@ -10,11 +10,13 @@ use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
use League\CommonMark\Extension\DescriptionList\DescriptionListExtension; use League\CommonMark\Extension\DescriptionList\DescriptionListExtension;
use League\CommonMark\Extension\Footnote\FootnoteExtension; use League\CommonMark\Extension\Footnote\FootnoteExtension;
use League\CommonMark\Extension\FrontMatter\FrontMatterExtension; use League\CommonMark\Extension\FrontMatter\FrontMatterExtension;
use League\CommonMark\Extension\FrontMatter\Output\RenderedContentWithFrontMatter;
use League\CommonMark\Extension\HeadingPermalink\HeadingPermalinkExtension; use League\CommonMark\Extension\HeadingPermalink\HeadingPermalinkExtension;
use League\CommonMark\Extension\Strikethrough\StrikethroughExtension; use League\CommonMark\Extension\Strikethrough\StrikethroughExtension;
use League\CommonMark\Extension\Table\TableExtension; use League\CommonMark\Extension\Table\TableExtension;
use League\CommonMark\Extension\TaskList\TaskListExtension; use League\CommonMark\Extension\TaskList\TaskListExtension;
use League\CommonMark\MarkdownConverter; use League\CommonMark\MarkdownConverter;
use SukWs\Bookshelf\Data\PageData;
use SukWs\Bookshelf\Utils\PageContentType; use SukWs\Bookshelf\Utils\PageContentType;
class Markdown implements PageContentType { class Markdown implements PageContentType {
@ -82,8 +84,35 @@ class Markdown implements PageContentType {
return $this->converter; return $this->converter;
} }
public function parse (string $raw): string { public function parse (string $raw): PageData {
return $this->getParser()->convert($raw);
$parsed = $this->getParser()->convert($raw);
$configurations = array();
$title = null;
$gen_title = false;
if ($parsed instanceof RenderedContentWithFrontMatter) {
$front_matter = $parsed->getFrontMatter();
if (isset($front_matter['title'])) {
$title = strval($front_matter['title']);
if (!str_starts_with($parsed->getContent(), '<h1>')) {
$gen_title = true;
}
}
if (isset($front_matter['configurations'])) {
$configurations = $front_matter['configurations'];
}
}
return new PageData(
$parsed->getContent(), $configurations,
$title, $gen_title
);
} }
} }

View File

@ -2,6 +2,8 @@
namespace SukWs\Bookshelf\Utils; namespace SukWs\Bookshelf\Utils;
use SukWs\Bookshelf\Data\PageData;
interface PageContentType { interface PageContentType {
/** /**
@ -9,6 +11,6 @@ interface PageContentType {
*/ */
public function type (): array; public function type (): array;
public function parse (string $raw): string; public function parse (string $raw): PageData;
} }

View File

@ -1,23 +0,0 @@
<?php
namespace SukWs\Bookshelf\Utils\ReST;
use Gregwar\RST\Parser;
use SukWs\Bookshelf\Utils\PageContentType;
class ReST implements PageContentType {
public const type = array("rst", "rest");
/**
* @return string[]
*/
public function type (): array {
return self::type;
}
public function parse (string $raw): string {
return (new Parser())->parse($raw);
}
}

34
src/Web/Main.php Normal file
View File

@ -0,0 +1,34 @@
<?php
namespace SukWs\Bookshelf\Web;
use SukWs\Bookshelf\Data\PageData;
class Main {
public static function main (PageData $page): void {
?>
<main id="main">
<div id="top"></div>
<div id="main-heading">
<div id="page-tools">
<button id="sidebar-show"></button>
</div>
</div>
<article id="article">
<?php self::article($page); ?>
</article>
</main>
<?php
}
public static function article (PageData $page): void {
if ($page->gen_title) {
?><h1><?= htmlentities($page->title) ?></h1><?php
}
echo $page->page_html;
}
}

View File

@ -13,7 +13,7 @@
<script><?= SiteMeta::getCustomScriptContent("custom") ?></script> <script><?= SiteMeta::getCustomScriptContent("custom") ?></script>
<script> <script>
bookCurrentId = "<?= PageMeta::$bookId ?>"; bookCurrentId = "<?= PageMeta::$bookId ?>";
pageCurrentId = "<?= PageMeta::$page->getId() ?>"; pageCurrentId = "<?= PageMeta::$page_id ?>";
<?php if (!(PageMeta::getConfigurationLevelPage(ConfigName::highlightjs)=="false")) : <?php if (!(PageMeta::getConfigurationLevelPage(ConfigName::highlightjs)=="false")) :
?>hljs.highlightAll();<?php endif; ?> ?>hljs.highlightAll();<?php endif; ?>
<?php if (!(PageMeta::getConfigurationLevelPage(ConfigName::regex_highlight)=="false")) : <?php if (!(PageMeta::getConfigurationLevelPage(ConfigName::regex_highlight)=="false")) :

View File

@ -14,7 +14,7 @@
<meta name="generator" content="<?= SiteMeta::get_frontpage_generate_version() ?>"> <meta name="generator" content="<?= SiteMeta::get_frontpage_generate_version() ?>">
<!-- Page Meta --> <!-- Page Meta -->
<link rel="shortcut icon" href="<?= SiteMeta::getGlobalIcon() ?>"> <link rel="shortcut icon" href="<?= SiteMeta::getGlobalIcon() ?>">
<title><?= PageMeta::getPageTitle() ?></title> <title><?= PageMeta::getHtmlTitle() ?></title>
<meta name="description" content="<?= PageMeta::getDescription() ?>"> <meta name="description" content="<?= PageMeta::getDescription() ?>">
<!-- Assets(css) --><?php <!-- Assets(css) --><?php
foreach (SiteMeta::getStylesheetsList() as $item) { foreach (SiteMeta::getStylesheetsList() as $item) {

View File

@ -1,14 +0,0 @@
<main id="main">
<div id="top" ></div>
<div id="main-heading"><div id="page-tools">
<button id="sidebar-show"></button>
</div></div>
<article id="article">
<?php require "./template/raw-article.php" ?>
</article>
</main>

View File

@ -1,49 +0,0 @@
<?php
use SukWs\Bookshelf\Data\PageMeta;
use SukWs\Bookshelf\Utils\HTML\HTML;
use SukWs\Bookshelf\Utils\LaTeX\LaTeX;
use SukWs\Bookshelf\Utils\Markdown\Markdown;
use SukWs\Bookshelf\Utils\ReST\ReST;
// if the `compatibility.article.title.oldversion` is enabled
// that means the title should be auto-generated from book.xml
// but not written on page.md.
// this code will generate a title from book.xml if the start
// of the page.md is not `# Title` formatting page title.
if (PageMeta::compatibilityOldTitlePolicy() && PageMeta::$page->hasContent(Markdown::type[0])) {
$pageMarkdownContent = PageMeta::$page->getContent(Markdown::type[0]);
$length = strlen($pageMarkdownContent);
for ($i=0; $i<$length; $i++) {
if (empty(trim($pageMarkdownContent[$i]))) {
continue;
} else if ($pageMarkdownContent[$i] == '#' && $pageMarkdownContent[$i+1] != '#') {
break;
}
echo "<!-- compatibility old-title policy triggered -->\n";
echo "<h1 id='phb-page-".PageMeta::$page->getId()."'>".PageMeta::$page->getName()."</h1>\n";
break;
}
}
$parsers = array(
new HTML(),
new Markdown(),
new LaTeX(),
new ReST()
);
$htmlContent = null;
foreach ($parsers as $parser) {
$ok = false;
foreach ($parser->type() as $suffix) {
if (PageMeta::$page->hasContent($suffix)) {
$htmlContent = $parser->parse(PageMeta::$page->getContent($suffix));
$ok = true;
}
}
if ($ok) break;
}
echo $htmlContent;

View File

@ -1,5 +0,0 @@
<?php
use SukWs\Bookshelf\Data\PageMeta;
PageMeta::$page->getSummaryHtml();