abstract/core
Composer 安装命令:
composer require abstract/core
包简介
Spec-first, language-agnostic tree processor with a PHP v0 implementation.
README 文档
README
Abstract is a spec-first, language-agnostic tree processor. It turns structured source formats into a canonical Abstract Tree, resolves safe runtime nodes, maps that tree into a target model, and emits output such as HTML, JSX, JSON, schemas, workflows, or future custom targets.
This repository is the PHP v0 implementation. The concepts, fixtures, and docs are intentionally portable so a future JavaScript/TypeScript implementation can follow the same behavior.
Status
Abstract Core v0 currently supports:
- JSON tag-key syntax
- canonical
element,runtime,value, andfragmentnodes - primitive type inference
- explicit typed nodes such as
:string,:int,:float,:bool,:null,:array, and:object @props and#children- shorthand object and array children
:propsand:attributesparent prop modifiers- data-based
:expr,:if,:else, and:each - inline
:importand:include - DOMDocument-backed HTML and XML markup parsing
- YAML, TOML, and Pkl parsing through the shared tag-key normalizer
- compact, tagged, and canonical JSON tree export
- strict and loose runtime modes
- HTML, XML, YAML, TOML, Pkl, and JSX-like output pipelines
- target-aware custom render targets and mapper overrides
- shared JSON fixtures and PHPUnit coverage
- benchmark scripts for JSON core flows and large HTML roundtrips
Unsafe code execution is not enabled. :php, :js, :ts, and :code are recognized as payload directives, but the default strict runtime rejects them instead of executing or rendering them.
Installation
composer install
Quick Example
<?php require 'vendor/autoload.php'; use Abstract\AbstractCore; $core = new AbstractCore(); $tree = $core->parseJson('{ "div": { "@": { "class": "card" }, "#": [ { "h1": "Title" }, { "p": "Body" } ] } }'); echo $core->renderHtml($tree); // <div class="card"><h1>Title</h1><p>Body</p></div>
JSON Tag-Key Syntax
The user syntax is tag-key based:
{
"div": "hello"
}
This normalizes to an element named div with one typed string child.
Canonical props and children:
{
"div": {
"@": {
"class": "card",
"id": "main"
},
"#": [
{
"span": "Hello"
}
]
}
}
Shorthand child objects are supported:
{
"div": {
"h1": "Title",
"p": "Body"
}
}
Repeated JSON object keys are impossible, so repeated elements must use arrays:
{
"ul": [
{ "li": "One" },
{ "li": "Two" }
]
}
Runtime Nodes
Keys beginning with : are runtime nodes. They are used during processing and are never rendered as literal output tags.
{
"div": [
{ ":attributes": { "class": "card" } },
{ "span": "Hello" }
]
}
This renders as:
<div class="card"><span>Hello</span></div>
Runtime logic is data-based:
{
":if": {
"@": {
"test": {
":expr": { "var": "user.isLoggedIn" }
}
},
"#": [
{ "Dashboard": [] }
],
":else": [
{ "Login": [] }
]
}
}
Imports
Imports resolve relative to the current source file and are cached by path, mtime, and content hash.
{
":import": {
"@": {
"src": "./components/Card.abstract.json",
"props": {
"title": "Welcome"
}
},
"#": [
{ "p": "This becomes slot content." }
]
}
}
For v0, slot children are appended to the imported root element or fragment. A richer component/slot system can be added later.
HTML Markup Parsing
HTML can be parsed through the same canonical tree model:
use Abstract\AbstractCore; use Abstract\Emitter\JsonEmitter; use Abstract\Parser\Markup\MarkupParseOptions; $core = new AbstractCore(); $tree = $core->parseHtmlFile('benchmarks/big-html.html', new MarkupParseOptions(includeMeta: false)); $compactJson = $core->treeJson($tree, pretty: false, mode: JsonEmitter::MODE_COMPACT); $html = $core->renderHtml($core->parseJson($compactJson));
The parser uses native DOMDocument/libxml for v0 performance. Correctness is structural: output is not beautified and is not expected to be byte-identical to the source, but parsed nodes, attributes, text, comments, raw script/style content, and doctype data are preserved through the benchmark comparator.
JSON export modes:
canonical: full internalkind/name/props/childrentreecompact: storage-oriented tag-key JSON with fewer model stringstagged: explicit Abstract tags for API/debug use
Text-only markup is treated as content, not as an implicit DOM paragraph:
$tree = $core->parseHtml('Hello Test'); echo $core->treeJson($tree, pretty: false, mode: JsonEmitter::MODE_COMPACT); // "Hello Test" echo $core->renderHtml($tree); // Hello Test
XML, YAML, TOML, And Pkl
All data/config formats decode into native values and then use the same tag-key normalizer as JSON.
$tree = $core->parseYamlFile('page.abstract.yaml'); echo $core->renderHtml($tree); echo $core->renderYaml($tree);
Available parser methods:
parseXml,parseXmlFileparseYaml,parseYamlFileparseToml,parseTomlFileparsePkl,parsePklFile
Available render methods:
renderXmlrenderYamlrenderTomlrenderPkl
YAML supports scalar, list, and map roots. TOML and Pkl rendering require object/map roots because their module/document syntax is property-oriented. Pkl parsing uses the local pkl CLI with eval --format=json --no-project --root-dir; it is an explicit parser path for trusted local config modules, not implicit code execution.
Custom Render Targets
AbstractCore is a facade over parsers, runtime resolution, render targets, and tree serializers. renderHtml(), renderJsx(), and renderXml() use registered render targets internally, and render($target, ...) can call a target by name.
Custom mapping is target-aware. A JSX override does not affect HTML, and an HTML override does not affect JSX.
Custom JSX mapping:
use Abstract\AbstractCore; use Abstract\Emitter\JsxEmitter; use Abstract\Mapper\ReactComponent; use Abstract\Mapper\ReactMapper; use Abstract\Render\RenderTarget; $core = AbstractCore::default() ->withRenderTarget('jsx', RenderTarget::make( ReactMapper::make() ->component('input', ReactComponent::imported( source: '@headlessui/react', export: 'Input', as: 'HeadlessInput', )), new JsxEmitter(), )); echo $core->renderJsx($tree);
Output:
import { Input as HeadlessInput } from "@headlessui/react"; <HeadlessInput name="email" />
Custom HTML mapping:
use Abstract\AbstractCore; use Abstract\Emitter\HtmlEmitter; use Abstract\Mapper\HtmlElementMapping; use Abstract\Mapper\HtmlMapper; use Abstract\Render\RenderTarget; $core = AbstractCore::default() ->withRenderTarget('html', RenderTarget::make( HtmlMapper::make() ->element('input', HtmlElementMapping::tag('x-input')), new HtmlEmitter(), )); echo $core->renderHtml($tree);
Output:
<x-input name="email"></x-input>
Config-driven customization is also available for simple JSX components and HTML tag replacement:
$core = AbstractCore::fromConfig([ 'targets' => [ 'jsx' => [ 'components' => [ 'input' => [ 'source' => '@headlessui/react', 'export' => 'Input', 'as' => 'HeadlessInput', ], ], ], 'html' => [ 'elements' => [ 'input' => ['tag' => 'x-input'], ], ], ], ]);
YAML, TOML, Pkl, and treeJson() currently serialize resolved Abstract Tree data directly. They remain configurable through their render methods and may gain dedicated mappers later.
Tests
./vendor/bin/phpunit --configuration phpunit.xml
Current verified result:
OK (53 tests, 87 assertions)
Benchmarks
php benchmarks/core-benchmark.php php benchmarks/markup-benchmark.php
Benchmark results are recorded in PERFORMANCE.md.
Examples
Runnable examples live in examples/. They include JSON-to-HTML, React/JSX mapping, runtime logic, imports, text-only markup, XML/YAML/TOML/Pkl scenarios, custom render targets, a small HTML roundtrip, and a large examples/big-html.html roundtrip that writes compact JSON and HTML output under examples/output/.
Documentation
- SPEC.md defines the portable Abstract syntax and processing rules.
- ARCHITECTURE.md explains the PHP v0 implementation.
- DEVELOPMENT.md explains how to change the codebase safely.
- REPORT.md records the repo rescue and design decisions.
- PERFORMANCE.md records benchmark method and results.
abstract/core 适用场景与选型建议
abstract/core 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 15 次下载、GitHub Stars 达 0, 最近一次更新时间为 2023 年 05 月 11 日, 在 PHP 生态内属于活跃度较高的组件。
我们在过去多个企业项目中使用过 abstract/core 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。
基于 abstract/core 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。
线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。
承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。
统计信息
- 总下载量: 15
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 11
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: proprietary
- 更新时间: 2023-05-11