rougin / staticka
又一款基于PHP的静态站点生成器。
Requires
- php: >=5.3.0
- erusev/parsedown: ~1.6
- symfony/yaml: ~2.8|~3.0|~4.0|~5.0|~6.0|~7.0
Requires (Dev)
- phpunit/phpunit: ~4.2|~5.7|~6.0|~7.0|~8.0|~9.0
- sanmai/phpunit-legacy-adapter: ~6.1|~8.0
This package is auto-updated.
Last update: 2024-09-25 07:18:03 UTC
README
这是一款基于PHP的静态站点生成器。它可以将Markdown内容和PHP文件转换为静态HTML。它受到了流行的静态站点生成器如Hugo和Jekyll的启发。
安装
通过Composer安装Staticka
$ composer require rougin/staticka
基本用法
从字符串生成简单的HTML
Staticka
可以将简单的Markdown内容从字符串转换为HTML
// index.php use Rougin\Staticka\Page; use Rougin\Staticka\Parser; // Creates a new page with the specified body --------- $page = new Page; $page->setName('Hello world!'); $page->setBody("# {NAME}\nThis is a sample template."); // ---------------------------------------------------- // Converts the page into an HTML --- $parser = new Parser; echo $parser->parsePage($page); // ----------------------------------
$ php index.php <h1>Hello world!</h1> <p>This is a sample template.</p>
注意
这里的{NAME}
只是一个占位符,用于将name
值从Page
类插入到主体中。
使用.md
文件
Staticka
还支持通过将指定.md
文件的路径添加到Page
类来转换基于Markdown的文件(.md
文件)
<!-- app/pages/hello-world.md --> # Hello World! This is a sample **Markdown** file!
// index.php // ... // Specify the path of the Markdown file ----- $file = __DIR__ . '/app/pages/hello-world.md'; $page = new Page($file); // ------------------------------------------- // ...
$ php index.php <h1>Hello World!</h1> <p>This is a sample <strong>Markdown</strong> file!</p>
添加Front Matter,额外数据
Staticka
支持Front Matter,可以在特定内容中添加预定义变量。默认情况下,还会生成特殊的变量,如path
、link
和name
,但可以在内容内部覆盖这些变量。
<!-- app/pages/hello-world.md --> --- link: hello-world --- # Hello World! The link is **{LINK}**.
$ php index.php <h1>Hello World!</h1> <p>The link is <strong>hello-world</strong>.</p>
构建HTML页面
可以使用Site
类将多个Page
实例转换为具有相应目录名称的.html
文件
// index.pp // ... use Rougin\Staticka\Site; // ... // Builds the site with its pages ------------ $site = new Site($parser); $file = __DIR__ . '/app/pages/hello-world.md'; $site->addPage(new Page((string) $file)); $site->build(__DIR__ . '/app/web'); // -------------------------------------------
$ php index.php
<!-- app/web/hello-world/index.html --> <h1>Hello World!</h1> <p>The link is <strong>hello-world</strong>.</p>
Site
类还可以清空指定目录或复制具有其文件的目录。如果输出目录需要CSS和JS文件,则此功能很有用。
app/
├─ web/
│ ├─ index.html
styles/
├─ index.css
// ... // Empty the "output" directory --- $output = __DIR__ . '/app/web'; $site->emptyDir($output); // -------------------------------- // Copy the "styles" directory to "output" --- $styles = __DIR__ . '/styles'; $site->copyDir($styles, $output); // ------------------------------------------- // ...
在指定场景中,可以在同一个Site
类中添加适用于所有生成页面的数据。
// ... $data = array('ga_code' => '12345678'); $data['website'] = 'https://roug.in'; $site->setData($data); // ...
警告
如果在Site
类中添加包含Page
类保留属性名称(例如,link
、plate
等)的数据,将覆盖页面中定义的数据。
添加模板引擎
仅从Markdown文件构建HTML页面只会返回内容本身。通过添加第三方模板引擎,可以更容易地添加部分(例如,布局)或为每个页面提供额外的样式。要添加模板引擎,必须在Parser
类内部使用Render
类
<!-- app/pages/hello-world.md --> --- name: Hello world! link: hello-world plate: main.php --- # This is a hello world! The link is **{LINK}**. And this is to get started...
注意
plate
属性指定了解析页面时使用的布局文件。在这个例子中,main.php
是用于hello-world.md
文件的布局。
<!-- app/plates/main.php --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title><?php echo $name; ?></title> </head> <body> <?php echo $html; ?> </body> </html>
注意
$html
变量是从解析的页面返回内容的预定义变量。预定义变量也基于页面的属性及其使用$page->getData()
方法的数据。
// index.php // ... use Rougin\Staticka\Parser; use Rougin\Staticka\Render; // ... // Sets the Render and Parser ---------- $paths = array(__DIR__ . '/app/plates'); $render = new Render($paths); $parser = new Parser($render); // ------------------------------------- // Render may be added to Parser after --- $parser->setRender($render); // --------------------------------------- // ...
注意
要找到前面示例中指定的main.php
文件,必须在Render
类中包含要搜索的路径。
$ php index.php
<!-- app/web/hello-world/index.html --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Hello world!</title> </head> <body> <h1>This is a hello world!</h1> <p>The link is <strong>hello-world</strong>. And this is to get started...</p></body> </html>
要为Staticka
实现自定义模板引擎,必须实现该引擎到RenderInterface
namespace Rougin\Staticka\Render; interface RenderInterface { /** * Renders a file from a specified template. * * @param string $name * @param array<string, mixed> $data * * @return string * @throws \InvalidArgumentException */ public function render($name, $data = array()); }
设置布局
在Staticka
中,一个Layout
类允许页面使用过滤器和辅助工具。它也可以作为class-string
传递到.md
文件中
// index.php use Rougin\Staticka\Layout; // ... $pages = __DIR__ . '/app/pages'; // Define the layout with the name "main.php" --- $layout = new Layout; $layout->setName('main.php'); // ---------------------------------------------- // ... // Set the layout into the page ------------- $page = new Page($pages . '/hello-world.md'); $site->addPage($page->setLayout($layout)); // ------------------------------------------
注意
使用这种方法,不需要从指定的.md
文件中指定plate
属性。
还可以在Front Matter详细信息中指定扩展了Layout
的类
namespace App\Layouts; use Rougin\Staticka\Layout; class HomeLayout extends Layout { /** * Specifies the plate to be used as the layout. * * @var string */ protected $name = 'home.php'; }
注意
必须指定指定的plate
的目录,在Render
实例中(例如,app/plates
)。
<!-- app/pages/hello-world.md --> --- name: Hello world! link: hello-world plate: App\Layouts\HomeLayout --- # This is a hello world! The link is **{LINK}**. And this is to get started...
扩展和定制
使用过滤器修改
Filter
允许在解析后修改页面
// index.php use Rougin\Staticka\Filter\HtmlMinifier; // ... // Set the layout class for "main.php" --- $layout = new Layout; $layout->setName('main.php'); // --------------------------------------- // Minifies the HTML after parsing the page --- $layout->addFilter(new HtmlMinifier) // -------------------------------------------- // ...
$ php index.php
<!-- app/web/hello-world/index.html --> <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Hello world!</title></head><body><h1>This is a hello world!</h1><p>The link is <strong>hello-world</strong>. And this is to get started...</p></body></html>
要创建自定义过滤器,请使用FilterInterface
实现。
namespace Rougin\Staticka\Filter; interface FilterInterface { /** * Filters the specified code. * * @param string $code * * @return string */ public function filter($code); }
使用辅助器的方法
Helper
在模板文件中提供了额外的功能方法。
// index.php use Rougin\Staticka\Helper\LinkHelper; // ... // Set the layout class for "main.php" --- $layout = new Layout; $layout->setName('main.php'); // --------------------------------------- // Add a "$url" variable in templates --- $url = new LinkHelper('https://roug.in'); $layout->addHelper($url); // -------------------------------------- // ...
<!-- app/plates/main.php --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title><?php echo $name; ?></title> </head> <body> <?php echo $html; ?> <a href="<?php echo $url->set($link); ?>"><?php echo $name; ?></a> </body> </html>
$ php index.php
<!-- app/web/hello-world/index.html --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Hello world!</title> </head> <body> <h1>This is a hello world!</h1> <p>The link is <strong>hello-world</strong>. And this is to get started...</p> <a href="https://roug.in/hello-world">Hello world!</a> </body> </html>
要创建模板辅助器,请在HelperInterface
中实现相关代码。
namespace Rougin\Staticka\Helper; interface HelperInterface { /** * Returns the name of the helper. * * @return string */ public function name(); }
将过滤器添加到解析器
按照设计,FilterInterface
下的过滤器应在解析器完成解析后执行。然而,在某些情况下,页面内容必须在解析前经过过滤器处理。
namespace App\Filters; use Rougin\Staticka\Filter\FilterInterface; class WorldFilter implements FilterInterface { public function filter($code) { return str_replace('Hello', 'World', $code); } }
// index.php use App\Filters\WorldFilter; // ... // Replaces "Hello" string to "World" --- $parser->addFilter(new WorldFilter); // -------------------------------------- // ...
更新日志
有关最近变更的详细信息,请参阅更新日志。
测试
$ composer test
致谢
许可证
MIT许可证(MIT)。有关更多信息,请参阅许可证。