## Major CodePress CMS Enhancement
### 🚀 New Features - **League CommonMark Integration**: Replaced basic Markdown parser with full CommonMark 2.7 support - **Bootstrap Sass Architecture**: Modern SCSS build system with Bootstrap 5.3.8 - **Enhanced Navigation**: Uses filenames instead of H1 titles for consistency - **Improved Styling**: Transparent navigation backgrounds, no rounded corners ### 🎨 UI/UX Improvements - Navigation items now use formatted filenames (e.g., "kennis-boven-aantallen" → "Kennis Boven Aantallen") - Transparent navigation backgrounds with subtle hover effects - Removed rounded corners from first-level navigation - 50% opacity navigation background using Bootstrap variables ### 🔧 Technical Improvements - **Class Organization**: Extracted CodePressCMS and SimpleTemplate to separate files - **Full PHPDoc Documentation**: Complete documentation for all methods - **Modern Build Process**: npm scripts for SCSS compilation - **Enhanced Markdown Support**: Tables, strikethrough, task lists, autolinks - **Security**: Proper HTML sanitization with CommonMark ### 📦 Dependencies - Added `league/commonmark` for professional Markdown parsing - Added `bootstrap` for SCSS-based styling - Updated `sass` build process ### 🐛 Bug Fixes - Fixed content directory path configuration - Resolved navigation title inconsistencies - Improved Markdown bold/italic formatting - Fixed homepage 404 issues ### 🔄 Migration Notes - Content directory moved from `content/` to `public/content/` - Navigation now displays filenames instead of content H1 titles - CSS now compiled from SCSS source files The CMS now provides a professional, modern experience with robust Markdown support and clean, maintainable code architecture.
This commit is contained in:
parent
dfe2df141b
commit
863661612a
50
README.md
50
README.md
@ -178,9 +178,57 @@ server {
|
||||
}
|
||||
```
|
||||
|
||||
## 🏗️ PHP Classes
|
||||
|
||||
### SimpleTemplate Class
|
||||
|
||||
Lightweight template rendering engine die Mustache-style syntax ondersteunt zonder externe dependencies.
|
||||
|
||||
**Methods:**
|
||||
- `render($template, $data)` - Rendert template met data
|
||||
- `replacePartial($matches)` - Vervangt `{{>partial}}` placeholders
|
||||
|
||||
**Features:**
|
||||
- `{{>partial}}` - Partial includes
|
||||
- `{{#variable}}...{{/variable}}` - Conditionele blocks
|
||||
- `{{^variable}}...{{/variable}}` - Negatieve conditionele blocks
|
||||
- `{{{variable}}}` - Unescaped HTML content
|
||||
- `{{variable}}` - Escaped content
|
||||
|
||||
### CodePressCMS Class
|
||||
|
||||
Hoofd CMS class die alle content management functionaliteit beheert.
|
||||
|
||||
**Public Methods:**
|
||||
- `__construct($config)` - Initialiseer CMS met configuratie
|
||||
- `getPage()` - Haalt huidige pagina content op
|
||||
- `getMenu()` - Genereert navigatiestructuur
|
||||
- `render()` - Rendert volledige pagina met templates
|
||||
|
||||
**Private Methods:**
|
||||
- `buildMenu()` - Bouwt menu structuur van content directory
|
||||
- `scanDirectory($dir, $prefix)` - Scant directory voor content
|
||||
- `performSearch($query)` - Voert zoekopdracht uit
|
||||
- `parseMarkdown($content)` - Converteert Markdown naar HTML
|
||||
- `parsePHP($filePath)` - Verwerkt PHP bestanden
|
||||
- `parseHTML($content)` - Verwerkt HTML bestanden
|
||||
- `getBreadcrumb()` - Genereert breadcrumb navigatie
|
||||
- `renderMenu($items, $level)` - Rendert menu HTML
|
||||
- `getContentType($page)` - Bepaalt content type
|
||||
- `autoLinkPageTitles($content)` - Auto-link pagina titels
|
||||
|
||||
**Features:**
|
||||
- Multi-format content support (MD, PHP, HTML)
|
||||
- Dynamische navigatie met dropdowns
|
||||
- Zoekfunctionaliteit met snippets
|
||||
- Breadcrumb navigatie
|
||||
- Auto-linking tussen pagina's
|
||||
- File metadata tracking
|
||||
- Responsive template rendering
|
||||
|
||||
## 📖 Documentatie
|
||||
|
||||
- **[Handleiding (NL)](guide/nl.md)** - Gedetaillede handleiding
|
||||
- **[Handleiding (NL)](guide/nl.md)** - Gedetailleerde handleiding
|
||||
- **[Handleiding (EN)](guide/en.md)** - English documentation
|
||||
- **[AGENTS.md](AGENTS.md)** - Ontwikkelaar instructies
|
||||
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
{
|
||||
"require": {
|
||||
"mustache/mustache": "^3.0"
|
||||
"mustache/mustache": "^3.0",
|
||||
"league/commonmark": "^2.7"
|
||||
}
|
||||
}
|
||||
|
||||
621
composer.lock
generated
621
composer.lock
generated
@ -4,8 +4,272 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "44b7b2c58a30151ae57314c84e2abdd5",
|
||||
"content-hash": "3cf7d71c2b61afde676a52c0c83f8bfe",
|
||||
"packages": [
|
||||
{
|
||||
"name": "dflydev/dot-access-data",
|
||||
"version": "v3.0.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/dflydev/dflydev-dot-access-data.git",
|
||||
"reference": "a23a2bf4f31d3518f3ecb38660c95715dfead60f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/a23a2bf4f31d3518f3ecb38660c95715dfead60f",
|
||||
"reference": "a23a2bf4f31d3518f3ecb38660c95715dfead60f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^0.12.42",
|
||||
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.3",
|
||||
"scrutinizer/ocular": "1.6.0",
|
||||
"squizlabs/php_codesniffer": "^3.5",
|
||||
"vimeo/psalm": "^4.0.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "3.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Dflydev\\DotAccessData\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Dragonfly Development Inc.",
|
||||
"email": "info@dflydev.com",
|
||||
"homepage": "http://dflydev.com"
|
||||
},
|
||||
{
|
||||
"name": "Beau Simensen",
|
||||
"email": "beau@dflydev.com",
|
||||
"homepage": "http://beausimensen.com"
|
||||
},
|
||||
{
|
||||
"name": "Carlos Frutos",
|
||||
"email": "carlos@kiwing.it",
|
||||
"homepage": "https://github.com/cfrutos"
|
||||
},
|
||||
{
|
||||
"name": "Colin O'Dell",
|
||||
"email": "colinodell@gmail.com",
|
||||
"homepage": "https://www.colinodell.com"
|
||||
}
|
||||
],
|
||||
"description": "Given a deep data structure, access data by dot notation.",
|
||||
"homepage": "https://github.com/dflydev/dflydev-dot-access-data",
|
||||
"keywords": [
|
||||
"access",
|
||||
"data",
|
||||
"dot",
|
||||
"notation"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/dflydev/dflydev-dot-access-data/issues",
|
||||
"source": "https://github.com/dflydev/dflydev-dot-access-data/tree/v3.0.3"
|
||||
},
|
||||
"time": "2024-07-08T12:26:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/commonmark",
|
||||
"version": "2.7.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/commonmark.git",
|
||||
"reference": "10732241927d3971d28e7ea7b5712721fa2296ca"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/10732241927d3971d28e7ea7b5712721fa2296ca",
|
||||
"reference": "10732241927d3971d28e7ea7b5712721fa2296ca",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-mbstring": "*",
|
||||
"league/config": "^1.1.1",
|
||||
"php": "^7.4 || ^8.0",
|
||||
"psr/event-dispatcher": "^1.0",
|
||||
"symfony/deprecation-contracts": "^2.1 || ^3.0",
|
||||
"symfony/polyfill-php80": "^1.16"
|
||||
},
|
||||
"require-dev": {
|
||||
"cebe/markdown": "^1.0",
|
||||
"commonmark/cmark": "0.31.1",
|
||||
"commonmark/commonmark.js": "0.31.1",
|
||||
"composer/package-versions-deprecated": "^1.8",
|
||||
"embed/embed": "^4.4",
|
||||
"erusev/parsedown": "^1.0",
|
||||
"ext-json": "*",
|
||||
"github/gfm": "0.29.0",
|
||||
"michelf/php-markdown": "^1.4 || ^2.0",
|
||||
"nyholm/psr7": "^1.5",
|
||||
"phpstan/phpstan": "^1.8.2",
|
||||
"phpunit/phpunit": "^9.5.21 || ^10.5.9 || ^11.0.0",
|
||||
"scrutinizer/ocular": "^1.8.1",
|
||||
"symfony/finder": "^5.3 | ^6.0 | ^7.0",
|
||||
"symfony/process": "^5.4 | ^6.0 | ^7.0",
|
||||
"symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0",
|
||||
"unleashedtech/php-coding-standard": "^3.1.1",
|
||||
"vimeo/psalm": "^4.24.0 || ^5.0.0 || ^6.0.0"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/yaml": "v2.3+ required if using the Front Matter extension"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "2.8-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"League\\CommonMark\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Colin O'Dell",
|
||||
"email": "colinodell@gmail.com",
|
||||
"homepage": "https://www.colinodell.com",
|
||||
"role": "Lead Developer"
|
||||
}
|
||||
],
|
||||
"description": "Highly-extensible PHP Markdown parser which fully supports the CommonMark spec and GitHub-Flavored Markdown (GFM)",
|
||||
"homepage": "https://commonmark.thephpleague.com",
|
||||
"keywords": [
|
||||
"commonmark",
|
||||
"flavored",
|
||||
"gfm",
|
||||
"github",
|
||||
"github-flavored",
|
||||
"markdown",
|
||||
"md",
|
||||
"parser"
|
||||
],
|
||||
"support": {
|
||||
"docs": "https://commonmark.thephpleague.com/",
|
||||
"forum": "https://github.com/thephpleague/commonmark/discussions",
|
||||
"issues": "https://github.com/thephpleague/commonmark/issues",
|
||||
"rss": "https://github.com/thephpleague/commonmark/releases.atom",
|
||||
"source": "https://github.com/thephpleague/commonmark"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://www.colinodell.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://www.paypal.me/colinpodell/10.00",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/colinodell",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/league/commonmark",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-07-20T12:47:49+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/config",
|
||||
"version": "v1.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/config.git",
|
||||
"reference": "754b3604fb2984c71f4af4a9cbe7b57f346ec1f3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/config/zipball/754b3604fb2984c71f4af4a9cbe7b57f346ec1f3",
|
||||
"reference": "754b3604fb2984c71f4af4a9cbe7b57f346ec1f3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"dflydev/dot-access-data": "^3.0.1",
|
||||
"nette/schema": "^1.2",
|
||||
"php": "^7.4 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^1.8.2",
|
||||
"phpunit/phpunit": "^9.5.5",
|
||||
"scrutinizer/ocular": "^1.8.1",
|
||||
"unleashedtech/php-coding-standard": "^3.1",
|
||||
"vimeo/psalm": "^4.7.3"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.2-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"League\\Config\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Colin O'Dell",
|
||||
"email": "colinodell@gmail.com",
|
||||
"homepage": "https://www.colinodell.com",
|
||||
"role": "Lead Developer"
|
||||
}
|
||||
],
|
||||
"description": "Define configuration arrays with strict schemas and access values with dot notation",
|
||||
"homepage": "https://config.thephpleague.com",
|
||||
"keywords": [
|
||||
"array",
|
||||
"config",
|
||||
"configuration",
|
||||
"dot",
|
||||
"dot-access",
|
||||
"nested",
|
||||
"schema"
|
||||
],
|
||||
"support": {
|
||||
"docs": "https://config.thephpleague.com/",
|
||||
"issues": "https://github.com/thephpleague/config/issues",
|
||||
"rss": "https://github.com/thephpleague/config/releases.atom",
|
||||
"source": "https://github.com/thephpleague/config"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://www.colinodell.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://www.paypal.me/colinpodell/10.00",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/colinodell",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2022-12-11T20:36:23+00:00"
|
||||
},
|
||||
{
|
||||
"name": "mustache/mustache",
|
||||
"version": "v3.0.0",
|
||||
@ -58,6 +322,361 @@
|
||||
"source": "https://github.com/bobthecow/mustache.php/tree/v3.0.0"
|
||||
},
|
||||
"time": "2025-06-28T18:28:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nette/schema",
|
||||
"version": "v1.3.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nette/schema.git",
|
||||
"reference": "2befc2f42d7c715fd9d95efc31b1081e5d765004"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nette/schema/zipball/2befc2f42d7c715fd9d95efc31b1081e5d765004",
|
||||
"reference": "2befc2f42d7c715fd9d95efc31b1081e5d765004",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"nette/utils": "^4.0",
|
||||
"php": "8.1 - 8.5"
|
||||
},
|
||||
"require-dev": {
|
||||
"nette/tester": "^2.5.2",
|
||||
"phpstan/phpstan-nette": "^2.0@stable",
|
||||
"tracy/tracy": "^2.8"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.3-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Nette\\": "src"
|
||||
},
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause",
|
||||
"GPL-2.0-only",
|
||||
"GPL-3.0-only"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "David Grudl",
|
||||
"homepage": "https://davidgrudl.com"
|
||||
},
|
||||
{
|
||||
"name": "Nette Community",
|
||||
"homepage": "https://nette.org/contributors"
|
||||
}
|
||||
],
|
||||
"description": "📐 Nette Schema: validating data structures against a given Schema.",
|
||||
"homepage": "https://nette.org",
|
||||
"keywords": [
|
||||
"config",
|
||||
"nette"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/nette/schema/issues",
|
||||
"source": "https://github.com/nette/schema/tree/v1.3.3"
|
||||
},
|
||||
"time": "2025-10-30T22:57:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nette/utils",
|
||||
"version": "v4.0.8",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nette/utils.git",
|
||||
"reference": "c930ca4e3cf4f17dcfb03037703679d2396d2ede"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nette/utils/zipball/c930ca4e3cf4f17dcfb03037703679d2396d2ede",
|
||||
"reference": "c930ca4e3cf4f17dcfb03037703679d2396d2ede",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "8.0 - 8.5"
|
||||
},
|
||||
"conflict": {
|
||||
"nette/finder": "<3",
|
||||
"nette/schema": "<1.2.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"jetbrains/phpstorm-attributes": "^1.2",
|
||||
"nette/tester": "^2.5",
|
||||
"phpstan/phpstan-nette": "^2.0@stable",
|
||||
"tracy/tracy": "^2.9"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-gd": "to use Image",
|
||||
"ext-iconv": "to use Strings::webalize(), toAscii(), chr() and reverse()",
|
||||
"ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()",
|
||||
"ext-json": "to use Nette\\Utils\\Json",
|
||||
"ext-mbstring": "to use Strings::lower() etc...",
|
||||
"ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "4.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Nette\\": "src"
|
||||
},
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause",
|
||||
"GPL-2.0-only",
|
||||
"GPL-3.0-only"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "David Grudl",
|
||||
"homepage": "https://davidgrudl.com"
|
||||
},
|
||||
{
|
||||
"name": "Nette Community",
|
||||
"homepage": "https://nette.org/contributors"
|
||||
}
|
||||
],
|
||||
"description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.",
|
||||
"homepage": "https://nette.org",
|
||||
"keywords": [
|
||||
"array",
|
||||
"core",
|
||||
"datetime",
|
||||
"images",
|
||||
"json",
|
||||
"nette",
|
||||
"paginator",
|
||||
"password",
|
||||
"slugify",
|
||||
"string",
|
||||
"unicode",
|
||||
"utf-8",
|
||||
"utility",
|
||||
"validation"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/nette/utils/issues",
|
||||
"source": "https://github.com/nette/utils/tree/v4.0.8"
|
||||
},
|
||||
"time": "2025-08-06T21:43:34+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/event-dispatcher",
|
||||
"version": "1.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/event-dispatcher.git",
|
||||
"reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0",
|
||||
"reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\EventDispatcher\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Standard interfaces for event handling.",
|
||||
"keywords": [
|
||||
"events",
|
||||
"psr",
|
||||
"psr-14"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/php-fig/event-dispatcher/issues",
|
||||
"source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0"
|
||||
},
|
||||
"time": "2019-01-08T18:20:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/deprecation-contracts",
|
||||
"version": "v3.6.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/deprecation-contracts.git",
|
||||
"reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62",
|
||||
"reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.1"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"url": "https://github.com/symfony/contracts",
|
||||
"name": "symfony/contracts"
|
||||
},
|
||||
"branch-alias": {
|
||||
"dev-main": "3.6-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"function.php"
|
||||
]
|
||||
},
|
||||
"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": "A generic function and convention to trigger deprecation notices",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.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": "2024-09-25T14:21:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php80",
|
||||
"version": "v1.33.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php80.git",
|
||||
"reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608",
|
||||
"reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"url": "https://github.com/symfony/polyfill",
|
||||
"name": "symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Php80\\": ""
|
||||
},
|
||||
"classmap": [
|
||||
"Resources/stubs"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ion Bazan",
|
||||
"email": "ion.bazan@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"compatibility",
|
||||
"polyfill",
|
||||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/nicolas-grekas",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-01-02T08:10:11+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
{
|
||||
"site_title": "CodePress",
|
||||
"content_dir": "content",
|
||||
"content_dir": "public/content",
|
||||
"templates_dir": "engine/templates",
|
||||
"default_page": "auto",
|
||||
"homepage": "welkom",
|
||||
"default_page": "welkom",
|
||||
|
||||
"theme": {
|
||||
"primary_color": "#0d6efd",
|
||||
|
||||
1023
engine/core/class/CodePressCMS.php
Normal file
1023
engine/core/class/CodePressCMS.php
Normal file
File diff suppressed because it is too large
Load Diff
92
engine/core/class/SimpleTemplate.php
Normal file
92
engine/core/class/SimpleTemplate.php
Normal file
@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* SimpleTemplate - Lightweight template rendering engine
|
||||
*
|
||||
* Features:
|
||||
* - Variable replacement with {{variable}} syntax
|
||||
* - Unescaped HTML content with {{{variable}}} syntax
|
||||
* - Conditional blocks with {{#variable}}...{{/variable}}
|
||||
* - Negative conditionals with {{^variable}}...{{/variable}}
|
||||
* - Partial includes with {{>partial}}
|
||||
* - Simple string-based rendering (no external dependencies)
|
||||
*/
|
||||
class SimpleTemplate {
|
||||
private $data;
|
||||
|
||||
/**
|
||||
* Render template with data
|
||||
*
|
||||
* @param string $template Template content with placeholders
|
||||
* @param array $data Data to populate template
|
||||
* @return string Rendered template
|
||||
*/
|
||||
public static function render($template, $data) {
|
||||
$instance = new self();
|
||||
$instance->data = $data;
|
||||
return $instance->renderTemplate($template);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process template and replace placeholders
|
||||
*
|
||||
* @param string $template Template content
|
||||
* @return string Processed template
|
||||
*/
|
||||
private function renderTemplate($template) {
|
||||
// Handle partial includes first ({{>partial}})
|
||||
$template = preg_replace_callback('/{{>([^}]+)}}/', [$this, 'replacePartial'], $template);
|
||||
|
||||
// Handle conditional blocks
|
||||
foreach ($this->data as $key => $value) {
|
||||
if (is_array($value) || (is_string($value) && !empty($value))) {
|
||||
// Handle {{#key}}...{{/key}} blocks
|
||||
$pattern = '/{{#' . preg_quote($key, '/') . '}}(.*?){{\/' . preg_quote($key, '/') . '}}/s';
|
||||
if (preg_match($pattern, $template, $matches)) {
|
||||
$replacement = $matches[1];
|
||||
$template = preg_replace($pattern, $replacement, $template);
|
||||
}
|
||||
|
||||
// Handle {{^key}}...{{/key}} blocks (negative condition)
|
||||
$pattern = '/{{\^' . preg_quote($key, '/') . '}}(.*?){{\/' . preg_quote($key, '/') . '}}/s';
|
||||
$template = preg_replace($pattern, '', $template);
|
||||
} else {
|
||||
// Handle empty blocks
|
||||
$pattern = '/{{#' . preg_quote($key, '/') . '}}.*?{{\/' . preg_quote($key, '/') . '}}/s';
|
||||
$template = preg_replace($pattern, '', $template);
|
||||
|
||||
// Handle {{^key}}...{{/key}} blocks (show when empty)
|
||||
$pattern = '/{{\^' . preg_quote($key, '/') . '}}(.*?){{\/' . preg_quote($key, '/') . '}}/s';
|
||||
if (preg_match_all($pattern, $template, $matches)) {
|
||||
foreach ($matches[1] as $match) {
|
||||
$template = preg_replace('/{{\^' . preg_quote($key, '/') . '}}.*?{{\/' . preg_quote($key, '/') . '}}/s', $match, $template, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle variable replacements
|
||||
foreach ($this->data as $key => $value) {
|
||||
// Handle triple braces for unescaped HTML content
|
||||
if (strpos($template, '{{{' . $key . '}}}') !== false) {
|
||||
$template = str_replace('{{{' . $key . '}}}', $value, $template);
|
||||
}
|
||||
// Handle double braces for escaped content
|
||||
elseif (strpos($template, '{{' . $key . '}}') !== false) {
|
||||
$template = str_replace('{{' . $key . '}}', htmlspecialchars($value, ENT_QUOTES, 'UTF-8'), $template);
|
||||
}
|
||||
}
|
||||
return $template;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace partial includes with data values
|
||||
*
|
||||
* @param array $matches Regex matches from preg_replace_callback
|
||||
* @return string Replacement content
|
||||
*/
|
||||
private function replacePartial($matches) {
|
||||
$partialName = $matches[1];
|
||||
return isset($this->data[$partialName]) ? $this->data[$partialName] : $matches[0];
|
||||
}
|
||||
}
|
||||
@ -1,698 +1,33 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* CodePress CMS Core Loader
|
||||
*
|
||||
* This file serves as the central entry point for the CodePress CMS core system.
|
||||
* It loads all essential classes and configuration needed for the CMS to function.
|
||||
*
|
||||
* Architecture:
|
||||
* - config.php: Configuration loader that merges default settings with config.json
|
||||
* - SimpleTemplate.php: Lightweight template engine for rendering HTML with placeholders
|
||||
* - CodePressCMS.php: Main CMS class handling content, navigation, search, and rendering
|
||||
*
|
||||
* Usage:
|
||||
* This file is included by public/index.php, which then:
|
||||
* 1. Loads configuration from config.php
|
||||
* 2. Creates a new CodePressCMS instance with the config
|
||||
* 3. Calls render() to output the complete page
|
||||
*
|
||||
* The separation allows for:
|
||||
* - Clean public entry point (public/index.php)
|
||||
* - Reusable core components
|
||||
* - Proper class organization with PHPDoc documentation
|
||||
*/
|
||||
|
||||
// Load configuration system - handles default settings and config.json merging
|
||||
require_once 'config.php';
|
||||
|
||||
// Simple template rendering without Mustache for now
|
||||
class SimpleTemplate {
|
||||
public static function render($template, $data) {
|
||||
// Handle partial includes first ({{>partial}})
|
||||
$template = preg_replace_callback('/{{>([^}]+)}}/', function($matches) use ($data) {
|
||||
$partialName = $matches[1];
|
||||
return $data[$partialName] ?? $matches[0];
|
||||
}, $template);
|
||||
// Load template engine - renders HTML with {{variable}} placeholders and conditionals
|
||||
require_once 'class/SimpleTemplate.php';
|
||||
|
||||
// Handle conditional blocks
|
||||
foreach ($data as $key => $value) {
|
||||
if (is_array($value) || (is_string($value) && !empty($value))) {
|
||||
// Handle {{#key}}...{{/key}} blocks
|
||||
$pattern = '/{{#' . preg_quote($key, '/') . '}}(.*?){{\/' . preg_quote($key, '/') . '}}/s';
|
||||
if (preg_match($pattern, $template, $matches)) {
|
||||
$replacement = $matches[1];
|
||||
$template = preg_replace($pattern, $replacement, $template);
|
||||
}
|
||||
|
||||
// Handle {{^key}}...{{/key}} blocks (negative condition)
|
||||
$pattern = '/{{\^' . preg_quote($key, '/') . '}}(.*?){{\/' . preg_quote($key, '/') . '}}/s';
|
||||
$template = preg_replace($pattern, '', $template);
|
||||
} else {
|
||||
// Handle empty blocks
|
||||
$pattern = '/{{#' . preg_quote($key, '/') . '}}.*?{{\/' . preg_quote($key, '/') . '}}/s';
|
||||
$template = preg_replace($pattern, '', $template);
|
||||
|
||||
// Handle {{^key}}...{{/key}} blocks (show when empty)
|
||||
$pattern = '/{{\^' . preg_quote($key, '/') . '}}(.*?){{\/' . preg_quote($key, '/') . '}}/s';
|
||||
if (preg_match_all($pattern, $template, $matches)) {
|
||||
foreach ($matches[1] as $match) {
|
||||
$template = preg_replace('/{{\^' . preg_quote($key, '/') . '}}.*?{{\/' . preg_quote($key, '/') . '}}/s', $match, $template, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle variable replacements
|
||||
foreach ($data as $key => $value) {
|
||||
// Handle triple braces for unescaped HTML content
|
||||
if (strpos($template, '{{{' . $key . '}}}') !== false) {
|
||||
$template = str_replace('{{{' . $key . '}}}', $value, $template);
|
||||
}
|
||||
// Handle double braces for escaped content
|
||||
elseif (strpos($template, '{{' . $key . '}}') !== false) {
|
||||
$template = str_replace('{{' . $key . '}}', htmlspecialchars($value, ENT_QUOTES, 'UTF-8'), $template);
|
||||
}
|
||||
}
|
||||
return $template;
|
||||
}
|
||||
}
|
||||
|
||||
$config = include 'config.php';
|
||||
|
||||
/**
|
||||
* CodePressCMS - Lightweight file-based content management system
|
||||
*
|
||||
* Features:
|
||||
* - Markdown, PHP, and HTML content support
|
||||
* - Dynamic navigation with dropdown menus
|
||||
* - Search functionality
|
||||
* - Breadcrumb navigation
|
||||
* - Auto-linking between pages
|
||||
* - Configurable via JSON
|
||||
* - Responsive design with Bootstrap
|
||||
*/
|
||||
/**
|
||||
* CodePressCMS - Lightweight file-based content management system
|
||||
*
|
||||
* Features:
|
||||
* - Markdown, PHP, and HTML content support
|
||||
* - Dynamic navigation with dropdown menus
|
||||
* - Search functionality
|
||||
* - Breadcrumb navigation
|
||||
* - Auto-linking between pages
|
||||
* - Configurable via JSON
|
||||
* - Responsive design with Bootstrap
|
||||
*/
|
||||
class CodePressCMS {
|
||||
private $config;
|
||||
private $menu = [];
|
||||
private $searchResults = [];
|
||||
|
||||
public function __construct($config) {
|
||||
$this->config = $config;
|
||||
$this->buildMenu();
|
||||
|
||||
if (isset($_GET['search'])) {
|
||||
$this->performSearch($_GET['search']);
|
||||
}
|
||||
}
|
||||
|
||||
private function buildMenu() {
|
||||
$this->menu = $this->scanDirectory($this->config['content_dir'], '');
|
||||
}
|
||||
|
||||
private function scanDirectory($dir, $prefix) {
|
||||
if (!is_dir($dir)) return [];
|
||||
|
||||
$items = scandir($dir);
|
||||
sort($items);
|
||||
$result = [];
|
||||
|
||||
foreach ($items as $item) {
|
||||
if ($item[0] === '.') continue;
|
||||
|
||||
$path = $dir . '/' . $item;
|
||||
$relativePath = $prefix ? $prefix . '/' . $item : $item;
|
||||
|
||||
if (is_dir($path)) {
|
||||
$result[] = [
|
||||
'type' => 'folder',
|
||||
'title' => ucfirst($item),
|
||||
'path' => $relativePath,
|
||||
'children' => $this->scanDirectory($path, $relativePath)
|
||||
];
|
||||
} elseif (preg_match('/\.(md|php|html)$/', $item)) {
|
||||
$title = ucfirst(pathinfo($item, PATHINFO_FILENAME));
|
||||
$result[] = [
|
||||
'type' => 'file',
|
||||
'title' => $title,
|
||||
'path' => $relativePath,
|
||||
'url' => '?page=' . $relativePath
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function performSearch($query) {
|
||||
$this->searchResults = [];
|
||||
$this->searchInDirectory($this->config['content_dir'], '', $query);
|
||||
}
|
||||
|
||||
private function searchInDirectory($dir, $prefix, $query) {
|
||||
if (!is_dir($dir)) return;
|
||||
|
||||
$items = scandir($dir);
|
||||
|
||||
foreach ($items as $item) {
|
||||
if ($item[0] === '.') continue;
|
||||
|
||||
$path = $dir . '/' . $item;
|
||||
$relativePath = $prefix ? $prefix . '/' . $item : $item;
|
||||
|
||||
if (is_dir($path)) {
|
||||
$this->searchInDirectory($path, $relativePath, $query);
|
||||
} elseif (preg_match('/\.(md|php|html)$/', $item)) {
|
||||
$content = file_get_contents($path);
|
||||
if (stripos($content, $query) !== false || stripos($item, $query) !== false) {
|
||||
$title = ucfirst(pathinfo($item, PATHINFO_FILENAME));
|
||||
$this->searchResults[] = [
|
||||
'title' => $title,
|
||||
'path' => $relativePath,
|
||||
'url' => '?page=' . $relativePath,
|
||||
'snippet' => $this->createSnippet($content, $query)
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function createSnippet($content, $query) {
|
||||
$content = strip_tags($content);
|
||||
$pos = stripos($content, $query);
|
||||
if ($pos === false) return substr($content, 0, 100) . '...';
|
||||
|
||||
$start = max(0, $pos - 50);
|
||||
$snippet = substr($content, $start, 150);
|
||||
return '...' . $snippet . '...';
|
||||
}
|
||||
|
||||
public function getPage() {
|
||||
if (isset($_GET['search'])) {
|
||||
return $this->getSearchResults();
|
||||
}
|
||||
|
||||
// Check if guide is requested
|
||||
if (isset($_GET['guide'])) {
|
||||
return $this->getGuidePage();
|
||||
}
|
||||
|
||||
// Check if content directory is empty
|
||||
if ($this->isContentDirEmpty()) {
|
||||
return $this->getGuidePage();
|
||||
}
|
||||
|
||||
$page = $_GET['page'] ?? $this->config['default_page'];
|
||||
$page = preg_replace('/\.[^.]+$/', '', $page);
|
||||
|
||||
$filePath = $this->config['content_dir'] . '/' . $page;
|
||||
$actualFilePath = null;
|
||||
|
||||
if (file_exists($filePath . '.md')) {
|
||||
$actualFilePath = $filePath . '.md';
|
||||
$result = $this->parseMarkdown(file_get_contents($actualFilePath));
|
||||
} elseif (file_exists($filePath . '.php')) {
|
||||
$actualFilePath = $filePath . '.php';
|
||||
$result = $this->parsePHP($actualFilePath);
|
||||
} elseif (file_exists($filePath . '.html')) {
|
||||
$actualFilePath = $filePath . '.html';
|
||||
$result = $this->parseHTML(file_get_contents($actualFilePath));
|
||||
} elseif (file_exists($filePath)) {
|
||||
$actualFilePath = $filePath;
|
||||
$extension = pathinfo($filePath, PATHINFO_EXTENSION);
|
||||
if ($extension === 'md') {
|
||||
$result = $this->parseMarkdown(file_get_contents($actualFilePath));
|
||||
} elseif ($extension === 'php') {
|
||||
$result = $this->parsePHP($actualFilePath);
|
||||
} elseif ($extension === 'html') {
|
||||
$result = $this->parseHTML(file_get_contents($actualFilePath));
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($result) && $actualFilePath) {
|
||||
$result['file_info'] = $this->getFileInfo($actualFilePath);
|
||||
return $result;
|
||||
}
|
||||
|
||||
return $this->getError404();
|
||||
}
|
||||
|
||||
private function getFileInfo($filePath) {
|
||||
if (!file_exists($filePath)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$stats = stat($filePath);
|
||||
$created = date('d-m-Y H:i', $stats['ctime']);
|
||||
$modified = date('d-m-Y H:i', $stats['mtime']);
|
||||
|
||||
return [
|
||||
'created' => $created,
|
||||
'modified' => $modified,
|
||||
'size' => $this->formatFileSize($stats['size'])
|
||||
];
|
||||
}
|
||||
|
||||
private function formatFileSize($bytes) {
|
||||
$units = ['B', 'KB', 'MB', 'GB'];
|
||||
$bytes = max($bytes, 0);
|
||||
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
|
||||
$pow = min($pow, count($units) - 1);
|
||||
|
||||
$bytes /= pow(1024, $pow);
|
||||
|
||||
return round($bytes, 2) . ' ' . $units[$pow];
|
||||
}
|
||||
|
||||
private function getSearchResults() {
|
||||
$query = $_GET['search'];
|
||||
$content = '<h2>Search Results for: "' . htmlspecialchars($query) . '"</h2>';
|
||||
|
||||
if (empty($this->searchResults)) {
|
||||
$content .= '<p>No results found.</p>';
|
||||
} else {
|
||||
$content .= '<p>Found ' . count($this->searchResults) . ' results:</p>';
|
||||
foreach ($this->searchResults as $result) {
|
||||
$content .= '<div class="card mb-3">';
|
||||
$content .= '<div class="card-body">';
|
||||
$content .= '<h5 class="card-title"><a href="' . htmlspecialchars($result['url']) . '">' . htmlspecialchars($result['title']) . '</a></h5>';
|
||||
$content .= '<p class="card-text text-muted">' . htmlspecialchars($result['path']) . '</p>';
|
||||
$content .= '<p class="card-text">' . htmlspecialchars($result['snippet']) . '</p>';
|
||||
$content .= '</div></div>';
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'title' => 'Search Results',
|
||||
'content' => $content
|
||||
];
|
||||
}
|
||||
|
||||
private function parseMarkdown($content) {
|
||||
$lines = explode("\n", $content);
|
||||
$title = '';
|
||||
$body = '';
|
||||
$inBody = false;
|
||||
|
||||
foreach ($lines as $line) {
|
||||
if (!$inBody && preg_match('/^#\s+(.+)$/', $line, $matches)) {
|
||||
$title = $matches[1];
|
||||
$inBody = true;
|
||||
} elseif ($inBody || trim($line) !== '') {
|
||||
$body .= $line . "\n";
|
||||
$inBody = true;
|
||||
}
|
||||
}
|
||||
|
||||
$body = preg_replace('/### (.+)/', '<h3>$1</h3>', $body);
|
||||
$body = preg_replace('/## (.+)/', '<h2>$1</h2>', $body);
|
||||
$body = preg_replace('/# (.+)/', '<h1>$1</h1>', $body);
|
||||
$body = preg_replace('/\*\*(.+?)\*\*/', '<strong>$1</strong>', $body);
|
||||
$body = preg_replace('/\*(.+?)\*/', '<em>$1</em>', $body);
|
||||
|
||||
// Auto-link page titles to existing content pages (before markdown link processing)
|
||||
$body = $this->autoLinkPageTitles($body);
|
||||
|
||||
// Convert Markdown links to HTML links
|
||||
$body = preg_replace('/\[([^\]]+)\]\(([^)]+)\)/', '<a href="$2">$1</a>', $body);
|
||||
|
||||
// Convert relative internal links to CMS format
|
||||
$body = preg_replace('/href="\/blog\/([^"]+)"/', 'href="?page=blog/$1"', $body);
|
||||
$body = preg_replace('/href="\/([^"]+)"/', 'href="?page=$1"', $body);
|
||||
|
||||
$body = preg_replace('/\n\n/', '</p><p>', $body);
|
||||
$body = '<p>' . $body . '</p>';
|
||||
$body = preg_replace('/<p><\/p>/', '', $body);
|
||||
$body = preg_replace('/<p>(<h[1-6]>)/', '$1', $body);
|
||||
$body = preg_replace('/(<\/h[1-6]>)<\/p>/', '$1', $body);
|
||||
|
||||
return [
|
||||
'title' => $title ?: 'Untitled',
|
||||
'content' => $body
|
||||
];
|
||||
}
|
||||
|
||||
private function autoLinkPageTitles($content) {
|
||||
// Get all available pages with their titles
|
||||
$pages = $this->getAllPageTitles();
|
||||
|
||||
foreach ($pages as $pagePath => $pageTitle) {
|
||||
// Create a pattern that matches the exact page title (case-insensitive)
|
||||
// Use word boundaries to avoid partial matches
|
||||
$pattern = '/\b' . preg_quote($pageTitle, '/') . '\b/i';
|
||||
|
||||
// Replace with link, but avoid linking inside existing links, headings, or markdown
|
||||
$replacement = function($matches) use ($pageTitle, $pagePath) {
|
||||
$text = $matches[0];
|
||||
|
||||
// Check if we're inside an existing link or markdown syntax
|
||||
if (preg_match('/\[.*?\]\(.*?\)/', $text) ||
|
||||
preg_match('/\[.*?\]:/', $text) ||
|
||||
preg_match('/<a[^>]*>/', $text) ||
|
||||
preg_match('/href=/', $text)) {
|
||||
return $text; // Don't link existing links
|
||||
}
|
||||
|
||||
return '<a href="?page=' . $pagePath . '" class="auto-link" title="Ga naar ' . htmlspecialchars($pageTitle) . '">' . $text . '</a>';
|
||||
};
|
||||
|
||||
$content = preg_replace_callback($pattern, $replacement, $content);
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
private function getAllPageTitles() {
|
||||
$pages = [];
|
||||
$this->scanForPageTitles($this->config['content_dir'], '', $pages);
|
||||
return $pages;
|
||||
}
|
||||
|
||||
private function scanForPageTitles($dir, $prefix, &$pages) {
|
||||
if (!is_dir($dir)) return;
|
||||
|
||||
$items = scandir($dir);
|
||||
sort($items);
|
||||
|
||||
foreach ($items as $item) {
|
||||
if ($item[0] === '.') continue;
|
||||
|
||||
$path = $dir . '/' . $item;
|
||||
$relativePath = $prefix ? $prefix . '/' . $item : $item;
|
||||
|
||||
if (is_dir($path)) {
|
||||
$this->scanForPageTitles($path, $relativePath, $pages);
|
||||
} elseif (preg_match('/\.(md|php|html)$/', $item)) {
|
||||
$title = $this->extractPageTitle($path);
|
||||
if ($title && !empty(trim($title))) {
|
||||
$pagePath = preg_replace('/\.[^.]+$/', '', $relativePath);
|
||||
$pages[$pagePath] = $title;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function extractPageTitle($filePath) {
|
||||
$content = file_get_contents($filePath);
|
||||
$extension = pathinfo($filePath, PATHINFO_EXTENSION);
|
||||
|
||||
if ($extension === 'md') {
|
||||
// Extract first H1 from Markdown
|
||||
if (preg_match('/^#\s+(.+)$/m', $content, $matches)) {
|
||||
return trim($matches[1]);
|
||||
}
|
||||
} elseif ($extension === 'php') {
|
||||
// Extract title from PHP file
|
||||
if (preg_match('/\$title\s*=\s*["\']([^"\']+)["\']/', $content, $matches)) {
|
||||
return trim($matches[1]);
|
||||
}
|
||||
} elseif ($extension === 'html') {
|
||||
// Extract title from HTML file
|
||||
if (preg_match('/<title>(.*?)<\/title>/i', $content, $matches)) {
|
||||
return trim(strip_tags($matches[1]));
|
||||
}
|
||||
if (preg_match('/<h1[^>]*>(.*?)<\/h1>/i', $content, $matches)) {
|
||||
return trim(strip_tags($matches[1]));
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function parsePHP($filePath) {
|
||||
ob_start();
|
||||
$title = 'Untitled';
|
||||
include $filePath;
|
||||
$content = ob_get_clean();
|
||||
|
||||
return [
|
||||
'title' => $title,
|
||||
'content' => $content
|
||||
];
|
||||
}
|
||||
|
||||
private function parseHTML($content) {
|
||||
$title = 'Untitled';
|
||||
|
||||
if (preg_match('/<title>(.*?)<\/title>/i', $content, $matches)) {
|
||||
$title = strip_tags($matches[1]);
|
||||
} elseif (preg_match('/<h1[^>]*>(.*?)<\/h1>/i', $content, $matches)) {
|
||||
$title = strip_tags($matches[1]);
|
||||
}
|
||||
|
||||
return [
|
||||
'title' => $title,
|
||||
'content' => $content
|
||||
];
|
||||
}
|
||||
|
||||
private function isContentDirEmpty() {
|
||||
$contentDir = $this->config['content_dir'];
|
||||
if (!is_dir($contentDir)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$files = scandir($contentDir);
|
||||
$files = array_diff($files, ['.', '..']);
|
||||
|
||||
return empty($files);
|
||||
}
|
||||
|
||||
private function getGuidePage() {
|
||||
$lang = $this->detectLanguage();
|
||||
$guideFile = __DIR__ . '/../../guide/' . $lang . '.md';
|
||||
|
||||
if (!file_exists($guideFile)) {
|
||||
$guideFile = __DIR__ . '/../../guide/en.md'; // Fallback to English
|
||||
}
|
||||
|
||||
$content = file_get_contents($guideFile);
|
||||
$result = $this->parseMarkdown($content);
|
||||
|
||||
// Set special title for guide
|
||||
$result['title'] = 'Handleiding - CodePress CMS';
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function detectLanguage() {
|
||||
// Simple language detection based on browser Accept-Language header
|
||||
$acceptLanguage = $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? '';
|
||||
|
||||
if (strpos($acceptLanguage, 'nl') !== false) {
|
||||
return 'nl';
|
||||
}
|
||||
|
||||
return 'en'; // Default to English
|
||||
}
|
||||
|
||||
private function getError404() {
|
||||
return [
|
||||
'title' => 'Page Not Found',
|
||||
'content' => '<h1>404 - Page Not Found</h1><p>The page you are looking for does not exist.</p>'
|
||||
];
|
||||
}
|
||||
|
||||
public function getMenu() {
|
||||
return $this->menu;
|
||||
}
|
||||
|
||||
public function render() {
|
||||
$page = $this->getPage();
|
||||
$menu = $this->getMenu();
|
||||
$breadcrumb = $this->getBreadcrumb();
|
||||
|
||||
// Prepare template data
|
||||
$templateData = [
|
||||
'site_title' => $this->config['site_title'],
|
||||
'page_title' => htmlspecialchars($page['title']),
|
||||
'content' => $page['content'],
|
||||
'search_query' => isset($_GET['search']) ? htmlspecialchars($_GET['search']) : '',
|
||||
'menu' => $this->renderMenu($menu),
|
||||
'breadcrumb' => $breadcrumb,
|
||||
'default_page' => $this->config['default_page'],
|
||||
'homepage' => $this->config['homepage'],
|
||||
'author_name' => $this->config['author']['name'] ?? 'CodePress Developer',
|
||||
'author_website' => $this->config['author']['website'] ?? '#',
|
||||
'author_git' => $this->config['author']['git'] ?? '#',
|
||||
'seo_description' => $this->config['seo']['description'] ?? 'CodePress CMS - Lightweight file-based content management system',
|
||||
'seo_keywords' => $this->config['seo']['keywords'] ?? 'cms, php, content management, file-based'
|
||||
];
|
||||
|
||||
// File info for footer
|
||||
if (isset($page['file_info'])) {
|
||||
$templateData['file_info'] = 'Created: ' . htmlspecialchars($page['file_info']['created']) .
|
||||
' | Modified: ' . htmlspecialchars($page['file_info']['modified']);
|
||||
$templateData['file_info_block'] = '<span class="file-details"> | ' . $templateData['file_info'] . '</span>';
|
||||
} else {
|
||||
$templateData['file_info'] = '';
|
||||
$templateData['file_info_block'] = '';
|
||||
}
|
||||
|
||||
// File info for footer
|
||||
if (isset($page['file_info'])) {
|
||||
$templateData['file_info'] = 'Created: ' . htmlspecialchars($page['file_info']['created']) .
|
||||
' | Modified: ' . htmlspecialchars($page['file_info']['modified']);
|
||||
} else {
|
||||
$templateData['file_info'] = '';
|
||||
}
|
||||
|
||||
// Check if content exists for guide link
|
||||
$hasContent = !$this->isContentDirEmpty();
|
||||
$templateData['has_content'] = $hasContent;
|
||||
|
||||
// Don't show site title link on guide page
|
||||
$templateData['show_site_link'] = !$this->isContentDirEmpty() && !isset($_GET['guide']);
|
||||
|
||||
// Load partials manually
|
||||
$hasContent = !$this->isContentDirEmpty() && !isset($_GET['guide']);
|
||||
|
||||
$headerContent = file_get_contents($this->config['templates_dir'] . '/assets/header.mustache');
|
||||
if (!$hasContent) {
|
||||
// Remove the link from header when no content
|
||||
$headerContent = preg_replace('/<a href="[^"]*" class="site-title-link">\s*<h1[^>]*>(.*?)<\/h1>\s*<\/a>/', '<h1 class="h3 mb-0">$1</h1>', $headerContent);
|
||||
}
|
||||
|
||||
$footerContent = file_get_contents($this->config['templates_dir'] . '/assets/footer.mustache');
|
||||
if (!$hasContent) {
|
||||
// Remove guide link from footer when no content
|
||||
$footerContent = preg_replace('/<span class="file-details">\s*\|\s*<a href="\?guide"[^>]*>Handleiding<\/a><\/span>/', '', $footerContent);
|
||||
}
|
||||
|
||||
// Determine content type and load appropriate template
|
||||
$contentType = $this->getContentType($page);
|
||||
$contentTemplateFile = $this->config['templates_dir'] . '/' . $contentType . '_content.mustache';
|
||||
$contentTemplate = file_exists($contentTemplateFile) ? file_get_contents($contentTemplateFile) : '<div class="content">{{{content}}}</div>';
|
||||
|
||||
// Determine content type and load appropriate template
|
||||
$pagePath = $_GET['page'] ?? $this->config['default_page'];
|
||||
$pagePath = preg_replace('/\.[^.]+$/', '', $pagePath);
|
||||
$filePath = $this->config['content_dir'] . '/' . $pagePath;
|
||||
|
||||
$contentType = 'markdown'; // default
|
||||
if (file_exists($filePath . '.md')) {
|
||||
$contentType = 'markdown';
|
||||
} elseif (file_exists($filePath . '.php')) {
|
||||
$contentType = 'php';
|
||||
} elseif (file_exists($filePath . '.html')) {
|
||||
$contentType = 'html';
|
||||
}
|
||||
|
||||
$contentTemplateFile = $this->config['templates_dir'] . '/' . $contentType . '_content.mustache';
|
||||
$contentTemplate = file_exists($contentTemplateFile) ? file_get_contents($contentTemplateFile) : '<div class="content">{{{content}}}</div>';
|
||||
|
||||
$partials = [
|
||||
'navigation' => file_get_contents($this->config['templates_dir'] . '/assets/navigation.mustache'),
|
||||
'footer' => file_get_contents($this->config['templates_dir'] . '/assets/footer.mustache'),
|
||||
'content_template' => $contentTemplate
|
||||
];
|
||||
|
||||
// Replace partials in template
|
||||
$template = file_get_contents($this->config['templates_dir'] . '/layout.mustache');
|
||||
$template = str_replace('{{>navigation}}', $partials['navigation'], $template);
|
||||
$template = str_replace('{{>footer}}', $partials['footer'], $template);
|
||||
|
||||
// Render template with data
|
||||
$renderedTemplate = SimpleTemplate::render($template, $templateData);
|
||||
echo $renderedTemplate;
|
||||
}
|
||||
|
||||
private function getBreadcrumb() {
|
||||
if (isset($_GET['search'])) {
|
||||
return '<nav aria-label="breadcrumb"><ol class="breadcrumb"><li class="breadcrumb-item"><a href="?page=' . $this->config['default_page'] . '">Home</a></li><li class="breadcrumb-item active">Search</li></ol></nav>';
|
||||
}
|
||||
|
||||
$page = $_GET['page'] ?? $this->config['default_page'];
|
||||
$page = preg_replace('/\.[^.]+$/', '', $page);
|
||||
|
||||
if ($page === $this->config['default_page']) {
|
||||
return '<nav aria-label="breadcrumb"><ol class="breadcrumb"><li class="breadcrumb-item active">Home</li></ol></nav>';
|
||||
}
|
||||
|
||||
$parts = explode('/', $page);
|
||||
$breadcrumb = '<nav aria-label="breadcrumb"><ol class="breadcrumb"><li class="breadcrumb-item"><a href="?page=' . $this->config['default_page'] . '">Home</a></li>';
|
||||
|
||||
$path = '';
|
||||
foreach ($parts as $i => $part) {
|
||||
$path .= ($path ? '/' : '') . $part;
|
||||
$title = ucfirst($part);
|
||||
|
||||
if ($i === count($parts) - 1) {
|
||||
$breadcrumb .= '<li class="breadcrumb-item active">' . $title . '</li>';
|
||||
} else {
|
||||
$breadcrumb .= '<li class="breadcrumb-item"><a href="?page=' . $path . '">' . $title . '</a></li>';
|
||||
}
|
||||
}
|
||||
|
||||
$breadcrumb .= '</ol></nav>';
|
||||
return $breadcrumb;
|
||||
}
|
||||
|
||||
private function renderMenu($items, $level = 0) {
|
||||
$html = '';
|
||||
foreach ($items as $item) {
|
||||
if ($item['type'] === 'folder') {
|
||||
$hasChildren = !empty($item['children']);
|
||||
|
||||
if ($hasChildren) {
|
||||
$folderId = 'folder-' . str_replace('/', '-', $item['path']);
|
||||
$isExpanded = $this->folderContainsActivePage($item['children']);
|
||||
$html .= '<li class="nav-item dropdown">';
|
||||
$html .= '<a class="nav-link dropdown-toggle" href="#" id="' . $folderId . '" role="button" data-bs-toggle="dropdown" aria-expanded="' . ($isExpanded ? 'true' : 'false') . '">';
|
||||
$html .= htmlspecialchars($item['title']);
|
||||
$html .= '</a>';
|
||||
$html .= '<ul class="dropdown-menu" aria-labelledby="' . $folderId . '">';
|
||||
$html .= $this->renderMenu($item['children'], $level + 1);
|
||||
$html .= '</ul>';
|
||||
$html .= '</li>';
|
||||
} else {
|
||||
$html .= '<li class="nav-item">';
|
||||
$html .= '<span class="nav-link text-muted">' . htmlspecialchars($item['title']) . '</span>';
|
||||
$html .= '</li>';
|
||||
}
|
||||
} else {
|
||||
// Only show files that are directly in root (not in folders)
|
||||
if ($level === 0) {
|
||||
// Don't show the homepage file as a separate tab since it's already the Home button
|
||||
if ($item['path'] === $this->config['homepage']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$active = (isset($_GET['page']) && $_GET['page'] === $item['path']) ? 'active' : '';
|
||||
$html .= '<li class="nav-item">';
|
||||
$html .= '<a class="nav-link ' . $active . '" href="' . htmlspecialchars($item['url']) . '">';
|
||||
$html .= htmlspecialchars($item['title']);
|
||||
$html .= '</a>';
|
||||
$html .= '</li>';
|
||||
}
|
||||
}
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
|
||||
private function getContentType($page) {
|
||||
// Try to determine content type from page request
|
||||
$pagePath = $_GET['page'] ?? $this->config['default_page'];
|
||||
$pagePath = preg_replace('/\.[^.]+$/', '', $pagePath);
|
||||
|
||||
$filePath = $this->config['content_dir'] . '/' . $pagePath;
|
||||
|
||||
// Check for different file extensions
|
||||
if (file_exists($filePath . '.md')) {
|
||||
return 'markdown';
|
||||
} elseif (file_exists($filePath . '.php')) {
|
||||
return 'php';
|
||||
} elseif (file_exists($filePath . '.html')) {
|
||||
return 'html';
|
||||
} elseif (file_exists($filePath)) {
|
||||
$extension = pathinfo($filePath, PATHINFO_EXTENSION);
|
||||
return in_array($extension, ['md', 'php', 'html']) ? $extension : 'markdown';
|
||||
}
|
||||
|
||||
// Default to markdown
|
||||
return 'markdown';
|
||||
}
|
||||
|
||||
private function folderContainsActivePage($children) {
|
||||
foreach ($children as $child) {
|
||||
if ($child['type'] === 'folder') {
|
||||
if (!empty($child['children']) && $this->folderContainsActivePage($child['children'])) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (isset($_GET['page']) && $_GET['page'] === $child['path']) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Load main CMS class - handles content parsing, navigation, search, and page rendering
|
||||
require_once 'class/CodePressCMS.php';
|
||||
@ -1,13 +1,13 @@
|
||||
<nav class="navigation-section bg-white border-bottom">
|
||||
<nav class="navigation-section border-bottom navigation-50-opacity">
|
||||
<div class="container-fluid">
|
||||
<div class="row align-items-center">
|
||||
<div class="col">
|
||||
<ul class="nav nav-tabs flex-wrap">
|
||||
<li class="nav-item">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="?page={{homepage}}">
|
||||
<i class="bi bi-house"></i> Home
|
||||
<i class="bi bi-house"></i> {{homepage_title}}
|
||||
</a>
|
||||
</li>
|
||||
</li>
|
||||
{{{menu}}}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@ -42,10 +42,12 @@
|
||||
</div>
|
||||
|
||||
<div class="container-fluid main-content" style="padding-bottom: 80px;">
|
||||
<div class="row">
|
||||
<main class="col-12">
|
||||
{{>content_template}}
|
||||
</main>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<main class="col-12">
|
||||
{{>content_template}}
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -4,8 +4,8 @@
|
||||
"description": "A lightweight, file-based Content Management System built with PHP and Bootstrap.",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build:css": "npx sass engine/assets/css/style.scss public/assets/css/style.css --no-source-map",
|
||||
"watch:css": "npx sass engine/assets/css/style.scss public/assets/css/style.css --no-source-map --watch",
|
||||
"build:css": "npx sass --load-path=node_modules src/scss/main.scss public/assets/css/style.css --style=compressed",
|
||||
"watch:css": "npx sass --load-path=node_modules --watch src/scss/main.scss public/assets/css/style.css",
|
||||
"build": "npm run build:css",
|
||||
"clean": "rm -rf node_modules package-lock.json",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
@ -19,6 +19,7 @@
|
||||
"license": "ISC",
|
||||
"type": "commonjs",
|
||||
"dependencies": {
|
||||
"bootstrap": "^5.3.8",
|
||||
"sass": "^1.94.2"
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
29
public/content/ict/excel-als-database.md
Normal file
29
public/content/ict/excel-als-database.md
Normal file
@ -0,0 +1,29 @@
|
||||
# Het gebruik van Excel als database: Waarom grote bedrijven en overheden Access niet toestaan
|
||||
|
||||
Excel is een krachtige tool die al tientallen jaren door miljoenen mensen wereldwijd wordt gebruikt om gegevens te organiseren, analyseren en presenteren. Voor kleine bedrijven en individuele gebruikers is Excel vaak voldoende om gegevens te beheren. Maar voor grote bedrijven en overheden kan Excel soms een overbodige en inefficiënte tool zijn om data te beheren en te analyseren.
|
||||
|
||||
## Het probleem met Access
|
||||
|
||||
In plaats daarvan kiezen ze voor meer geïntegreerde, schaalbare en veilige systemen die beter passen bij hun specifieke behoeften. Dit kan leiden tot het beperken van de toegang tot Access, een database management systeem van Microsoft.
|
||||
|
||||
Het beperken van de toegang tot Access kan echter leiden tot het gebruik van zware Excel-bestanden als database. Een van de redenen waarom Access niet wordt toegestaan in grote bedrijven en overheidsorganisaties, is omdat het gebruik van meer geïntegreerde, schaalbare en veilige systemen hun voorkeur heeft.
|
||||
|
||||
## IT-afdelingen en kennisgebrek
|
||||
|
||||
Een ander probleem is dat veel IT-afdelingen geen kennis meer hebben van het maken van open systemen. In plaats van het ontwikkelen van aangepaste oplossingen, zoeken ze vaak naar externe oplossingen en kiezen ze voor standaard software van derden.
|
||||
|
||||
Dit kan leiden tot het gebruik van overbodige software die te complex en niet specifiek genoeg is voor de behoeften van de organisatie.
|
||||
|
||||
## Prestatieproblemen
|
||||
|
||||
Daarbij komt nog dat Excel-bestanden die als database worden gebruikt, vaak grote hoeveelheden data bevatten en hierdoor zwaar en traag worden. Dit kan leiden tot vertragingen in het werkproces en inefficiënties in het gebruik van middelen.
|
||||
|
||||
## De oplossing
|
||||
|
||||
Het is belangrijk voor IT-afdelingen om de kennis en vaardigheden te ontwikkelen om open systemen te ontwikkelen die beter passen bij de specifieke behoeften van de organisatie. Dit kan ervoor zorgen dat de organisatie efficiënter en effectiever werkt, wat uiteindelijk kan leiden tot kostenbesparingen en betere resultaten.
|
||||
|
||||
## Conclusie
|
||||
|
||||
Kortom, het gebruik van Excel als database kan leiden tot inefficiënties en onnodige kosten. Het is belangrijk dat organisaties nadenken over de beste manier om hun data te beheren en analyseren, en daarbij rekening houden met hun specifieke behoeften en doelstellingen.
|
||||
|
||||
Het ontwikkelen van aangepaste oplossingen kan de efficiëntie en effectiviteit van de organisatie vergroten, wat uiteindelijk kan leiden tot betere resultaten en een hogere klanttevredenheid.
|
||||
31
public/content/ict/hardware/de-ware-aard-van-ict.md
Normal file
31
public/content/ict/hardware/de-ware-aard-van-ict.md
Normal file
@ -0,0 +1,31 @@
|
||||
# De ware aard van ICT: meer dan alleen computers en software
|
||||
|
||||
De term "ICT" staat voor Informatie- en Communicatietechnologie. Het is een breed begrip dat veel meer omvat dan alleen computers en software. Het gaat om het beheren van informatie, kennis en communicatie binnen organisaties.
|
||||
|
||||
## Het probleem met moderne ICT-afdelingen
|
||||
|
||||
Toch lijkt het erop dat ICT-afdelingen vaak vergeten wat ICT werkelijk inhoudt en zich te veel richten op de technische aspecten van de systemen. Het gevolg is dat computersystemen en software vaak als doel op zich worden beschouwd in plaats van als hulpmiddelen bij het uitvoeren van de werkzaamheden.
|
||||
|
||||
## ICT als ondersteunende factor
|
||||
|
||||
In plaats van de nadruk te leggen op technologie, is het van belang om te begrijpen dat ICT gericht moet zijn op het ondersteunen van de werkzaamheden binnen een organisatie. Dit betekent dat de ICT-infrastructuur niet bepalend zou moeten zijn voor de manier waarop de organisatie werkt, maar juist moet worden aangepast aan de behoeften van de organisatie en haar werknemers.
|
||||
|
||||
## Meer dan technologie
|
||||
|
||||
Het is belangrijk om te beseffen dat ICT meer is dan alleen computers en software. Het gaat ook om het beheren van informatie, kennis en communicatie binnen organisaties. Hierbij moet de focus niet alleen liggen op de technische aspecten, maar juist ook op de menselijke kant van ICT.
|
||||
|
||||
De bedrijfs- of overheidspersoneel moet bijvoorbeeld niet gedwongen worden om hun werkzaamheden aan te passen aan de software, maar juist andersom: de ICT-infrastructuur moet worden aangepast aan de behoeften van het personeel.
|
||||
|
||||
## Luisteren naar gebruikers
|
||||
|
||||
Daarom is het van belang dat ICT-afdelingen beter luisteren naar de behoeften en wensen van de medewerkers en de organisatie als geheel. Dit kan bijvoorbeeld door regelmatig feedback te vragen en door de ICT-infrastructuur te optimaliseren op basis van deze feedback.
|
||||
|
||||
Zo kan de ICT-infrastructuur optimaal worden afgestemd op de wensen en behoeften van de organisatie, waardoor medewerkers beter kunnen functioneren en de productiviteit wordt verhoogd.
|
||||
|
||||
## Conclusie
|
||||
|
||||
In de huidige digitale wereld is ICT onmisbaar voor organisaties en bedrijven. Het is van groot belang om te begrijpen dat ICT meer is dan alleen computers en software. Het gaat om het beheren van informatie, kennis en communicatie.
|
||||
|
||||
De ICT-infrastructuur moet ondersteunend zijn aan de werkzaamheden van de organisatie en niet andersom. ICT-afdelingen moeten zich daarom niet alleen richten op technologie, maar juist ook op de menselijke kant van ICT.
|
||||
|
||||
Alleen op deze manier kan ICT een waardevolle bijdrage leveren aan het succes van organisaties en bedrijven.
|
||||
@ -0,0 +1,49 @@
|
||||
# Leren gaat niet over perfectie, maar over passie.
|
||||
|
||||
Als computerwetenschapper heb ik altijd een passie gehad voor electronica en open-source hardware en software. Het idee dat we de mogelijkheid hebben om onze eigen hardware te bouwen en onze eigen software te schrijven om deze te besturen, is geweldig.
|
||||
|
||||
## Arduino: Mijn favoriete platform
|
||||
|
||||
Een van mijn favoriete open-source hardwareprojecten is de Arduino. De Arduino is een microcontroller board dat in staat is om verschillende hardware-apparaten aan te sturen, waardoor het een zeer veelzijdig platform is voor zowel beginners als gevorderde gebruikers.
|
||||
|
||||
Het beste van alles is dat de Arduino open-source is, wat betekent dat iedereen vrij is om de hardware- en softwarebroncode te bekijken, te bewerken en te gebruiken.
|
||||
|
||||
## Raspberry Pi: Mini-computer met grote mogelijkheden
|
||||
|
||||
Een ander interessant open-source hardwareproject is de Raspberry Pi. De Raspberry Pi is een mini-computer die in staat is om verschillende taken uit te voeren, zoals het bouwen van een mediacenter, het hosten van een website en het bouwen van een robot.
|
||||
|
||||
Net als de Arduino is de Raspberry Pi een open-source platform, wat betekent dat iedereen vrij is om de hardware- en softwarebroncode te bekijken, te bewerken en te gebruiken.
|
||||
|
||||
## Linux: De kracht van open-source software
|
||||
|
||||
Wat betreft open-source software, ben ik altijd een fan geweest van Linux. Linux is een open-source besturingssysteem dat wordt gebruikt in verschillende toepassingen, waaronder desktops, servers en embedded systemen.
|
||||
|
||||
Het beste van alles is dat Linux zeer aanpasbaar is en dat gebruikers de mogelijkheid hebben om de broncode te bekijken, te bewerken en te gebruiken voor hun eigen toepassingen.
|
||||
|
||||
## Programmeren voor hardware
|
||||
|
||||
Programmeren voor hardware is ook een fascinerend onderwerp voor mij. In tegenstelling tot programmeren voor software, gaat programmeren voor hardware veel verder dan alleen het schrijven van code.
|
||||
|
||||
Het vereist vaak het begrijpen van hoe de hardware werkt en hoe deze kan worden geconfigureerd om specifieke taken uit te voeren. Het vereist ook vaak kennis van verschillende programmeertalen, zoals C, C++ en Python.
|
||||
|
||||
## De waarde voor de samenleving
|
||||
|
||||
Al met al geloof ik dat open-source hardware en software en programmeren voor zowel hardware als software enorm waardevol zijn voor de samenleving. Ze bieden de mogelijkheid om toegang te krijgen tot technologie en de kennis en vaardigheden te verwerven die nodig zijn om deze technologie te bouwen en te gebruiken.
|
||||
|
||||
Dit opent deuren voor innovatie en creativiteit en geeft mensen de mogelijkheid om hun eigen oplossingen te ontwikkelen voor hun eigen problemen.
|
||||
|
||||
## Toekomstvisie
|
||||
|
||||
Ik hoop dat we blijven werken aan het bevorderen van open-source hardware en software en programmeren voor hardware en software, zodat we een betere toekomst kunnen creëren voor ons allemaal.
|
||||
|
||||
> ## Wat is Open Source?
|
||||
|
||||
Open-source is een term die wordt gebruikt om te beschrijven hoe software en hardware worden ontwikkeld en vrijgegeven onder een licentie die de broncode openbaar beschikbaar maakt voor iedereen. Dit betekent dat iedereen vrij is om de broncode te bekijken, te bewerken, te gebruiken en te verspreiden zonder enige beperkingen.
|
||||
|
||||
Een belangrijk aspect van open-source is dat het een gemeenschapsgerichte aanpak is voor het ontwikkelen van technologie. In plaats van dat één bedrijf of één individu de verantwoordelijkheid heeft voor het ontwerpen en ontwikkelen van een software- of hardwareproduct, werken verschillende individuen en organisaties samen om de technologie te ontwikkelen en te verbeteren.
|
||||
|
||||
Dit resulteert vaak in producten die van hoge kwaliteit zijn, omdat ze worden getest en verbeterd door een grote gemeenschap van gebruikers en ontwikkelaars.
|
||||
|
||||
Open-source heeft ook een aantal voordelen ten opzichte van gesloten software of hardware. Allereerst is open-source vaak gratis beschikbaar, waardoor het toegankelijk is voor mensen die mogelijk niet het budget hebben om dure commerciële producten aan te schaffen. Ten tweede kan open-source worden aangepast en aangepast aan specifieke behoeften, wat niet mogelijk is met gesloten software of hardware. Tot slot kan open-source leiden tot innovatie en creativiteit doordat het mensen in staat stelt om nieuwe ideeën en concepten te ontwikkelen op basis van bestaande technologie.
|
||||
|
||||
Kortom, open-source is een belangrijk concept in de technologiewereld dat veel voordelen biedt voor ontwikkelaars, gebruikers en de samenleving als geheel.
|
||||
@ -0,0 +1,23 @@
|
||||
# Wat is Arduino
|
||||
|
||||
Arduino is een open-source elektronisch platform dat is ontworpen voor het maken van elektronische projecten. Het bestaat uit een microcontroller, ontwikkelomgeving en programmeertaal waarmee je eenvoudig sensoren en actuatoren kunt aansturen om interactieve projecten te maken.
|
||||
|
||||
## Wat maakt Arduino speciaal?
|
||||
|
||||
Arduino is populair bij hobbyisten en professionals vanwege de eenvoudige manier van programmeren en de grote online community van gebruikers die samenwerken en kennis delen.
|
||||
|
||||
## Mogelijkheden
|
||||
|
||||
Met Arduino kun je bijvoorbeeld:
|
||||
- Robots bouwen
|
||||
- Muziekinstrumenten maken
|
||||
- Slimme huishoudelijke apparaten creëren
|
||||
- Tal van andere elektronische projecten realiseren
|
||||
|
||||
## Open-source karakter
|
||||
|
||||
Het open-source karakter van Arduino betekent dat iedereen vrij is om de hardware- en softwarebroncode te bekijken, te bewerken en te gebruiken. Dit heeft geleid tot een enorme verscheidenheid aan projecten en toepassingen die door de community zijn ontwikkeld.
|
||||
|
||||
## Voor beginners en gevorderden
|
||||
|
||||
Of je nu een beginner bent die net start met elektronica, of een gevorderde gebruiker die complexe systemen wilt bouwen, Arduino biedt een toegankelijk platform om je ideeën tot leven te brengen.
|
||||
37
public/content/ict/linux/open-source-voorbeelden.md
Normal file
37
public/content/ict/linux/open-source-voorbeelden.md
Normal file
@ -0,0 +1,37 @@
|
||||
# Vijf voorbeelden van open-source software in gebruik bij commerciële bedrijven
|
||||
|
||||
Open-source software is niet alleen populair bij individuele gebruikers en non-profit organisaties, maar wordt ook veel gebruikt door commerciële bedrijven. In deze blogpost zullen we kijken naar enkele voorbeelden van open-source software die door commerciële bedrijven worden gebruikt en bespreken waarom het voor hen zo voordelig is.
|
||||
|
||||
## 1. Apple's macOS
|
||||
|
||||
Apple's macOS-besturingssysteem, dat op hun Mac-computers wordt geleverd, is gebaseerd op de open-source Darwin-kernel. Hoewel Apple zijn eigen unieke interface en functies heeft toegevoegd aan het besturingssysteem, profiteert het bedrijf nog steeds van de ontwikkeling van de open-source gemeenschap.
|
||||
|
||||
Door open-source software te gebruiken, kan Apple kosten besparen op de ontwikkeling van hun eigen besturingssysteem en tegelijkertijd profiteren van de inspanningen van de grotere ontwikkelingsgemeenschap.
|
||||
|
||||
## 2. IBM en Apache
|
||||
|
||||
IBM is een van de bedrijven die het Apache Software Foundation-project ondersteunt, een non-profit organisatie die open-source software ontwikkelt en onderhoudt. IBM heeft ook bijgedragen aan de ontwikkeling van Apache Hadoop, een open-source software framework dat wordt gebruikt voor gedistribueerde opslag en verwerking van big data.
|
||||
|
||||
Door bij te dragen aan open-source projecten, kan IBM profiteren van de innovatie van de bredere ontwikkelingsgemeenschap en tegelijkertijd bijdragen aan de ontwikkeling van de industrie.
|
||||
|
||||
## 3. Amazon en Linux
|
||||
|
||||
Amazon Web Services (AWS) is een van de grootste aanbieders van cloud computing ter wereld en vertrouwt op Linux als besturingssysteem voor veel van zijn services. Linux is een open-source besturingssysteem dat door vele bedrijven wordt gebruikt, en het gebruik ervan stelt bedrijven in staat om kosten te besparen op licentiekosten en tegelijkertijd flexibel te blijven in het aanpassen van hun systemen.
|
||||
|
||||
## 4. NASA en open-source software
|
||||
|
||||
NASA gebruikt open-source software voor veel van zijn ruimtevaartprojecten, waaronder de Mars Rover en de International Space Station. Open-source software is bijzonder geschikt voor NASA omdat het hen in staat stelt de software aan te passen aan de specifieke vereisten van hun projecten, en de grotere ontwikkelingsgemeenschap biedt een schat aan hulpbronnen en expertise.
|
||||
|
||||
## 5. Red Hat en Linux
|
||||
|
||||
Red Hat, een Amerikaanse softwareonderneming, is een van de grootste supporters van Linux en heeft bijgedragen aan de ontwikkeling van veel open-source projecten, waaronder de Linux-kernel. Red Hat levert ook commerciële ondersteuning voor bedrijven die Linux gebruiken, waardoor bedrijven de voordelen van open-source software kunnen benutten en tegelijkertijd de zekerheid hebben van ondersteuning en updates van een gerenommeerde leverancier.
|
||||
|
||||
## Voordelen voor bedrijven
|
||||
|
||||
Open-source software biedt veel voordelen voor bedrijven, waaronder:
|
||||
|
||||
- **Kostenbesparingen** op licentiekosten
|
||||
- **Flexibiliteit** in het aanpassen van systemen
|
||||
- **Mogelijkheid om te profiteren** van de innovatie van de bredere ontwikkelingsgemeenschap
|
||||
|
||||
De bovengenoemde voorbeelden zijn slechts enkele van de vele manieren waarop open-source software wordt gebruikt in het commerciële domein.
|
||||
46
public/content/ict/open-source/de-toekomst-van-ict.md
Normal file
46
public/content/ict/open-source/de-toekomst-van-ict.md
Normal file
@ -0,0 +1,46 @@
|
||||
# De Toekomst van ICT: Hoe Open Source Software de Werkvloer Transformeert
|
||||
|
||||
In onze steeds digitaler wordende samenleving zijn medewerkers digitaal vaardiger geworden en verwachten zij dat de ICT-voorzieningen op kantoor en de werkvloer aansluiten bij hun behoeften. Helaas lopen traditionele ICT-afdelingen hier vaak op achter, wat leidt tot een kloof tussen de beschikbare technologie en de wensen van de medewerkers.
|
||||
|
||||
## Beperkingen van traditionele ICT-oplossingen
|
||||
|
||||
Traditionele ICT-afdelingen bieden doorgaans standaard softwarepakketten aan, zoals Office-suites en omvangrijke HRM- of communicatiesoftware. Hoewel deze tools een basisfunctionaliteit bieden, schieten ze vaak tekort in flexibiliteit en maatwerk.
|
||||
|
||||
Technisch onderlegde medewerkers weten soms meer uit deze pakketten te halen, maar voor velen zijn de mogelijkheden binnen de bestaande infrastructuur beperkt. Dit leidt tot frustratie en inefficiëntie op de werkvloer.
|
||||
|
||||
## De dynamiek van een digitale samenleving
|
||||
|
||||
Onze maatschappij is dynamisch en past zich snel aan nieuwe ICT-mogelijkheden aan. Wanneer ICT-afdelingen vasthouden aan rigide systemen, ontstaan er hiaten tussen hoe mensen willen werken en de beschikbare technologie.
|
||||
|
||||
De werkvloer wordt hierdoor leidend in de vraag naar ICT-oplossingen, terwijl de ICT-afdeling zou moeten anticiperen op deze behoeften. Maatwerk wordt vaak gezien als een dure oplossing, waardoor men kiest voor grote, minder flexibele softwarepakketten die alleen na dure trainingen volledig benut kunnen worden.
|
||||
|
||||
Hierdoor moeten werknemers zich aanpassen aan de software, in plaats van dat de software aansluit bij de werkprocessen en het karakter van het bedrijf.
|
||||
|
||||
## De kracht van open standaarden en open-source oplossingen
|
||||
|
||||
Een mogelijke oplossing voor dit probleem is het omarmen van open standaarden en open-source oplossingen. Deze benadering maakt kantoorautomatisering dynamischer en beter aanpasbaar aan de behoeften van de samenleving.
|
||||
|
||||
Open-source software biedt flexibiliteit en controle, waardoor bedrijven hun workflows kunnen optimaliseren zonder afhankelijk te zijn van dure licenties of beperkte functionaliteiten.
|
||||
|
||||
## Voorbeelden van open-source kantoorsoftware
|
||||
|
||||
Er zijn diverse open-source tools beschikbaar die kunnen bijdragen aan een flexibelere werkomgeving:
|
||||
|
||||
### LibreOffice
|
||||
Een volwaardig kantoorsoftwarepakket dat een uitstekend alternatief biedt voor commerciële producten.
|
||||
|
||||
### Nextcloud
|
||||
Een cloudoplossing voor documentbeheer en samenwerking, die bedrijven in staat stelt hun eigen cloudomgeving te beheren.
|
||||
|
||||
### Thunderbird
|
||||
Een open-source e-mailclient die flexibiliteit en controle biedt over e-mailbeheer.
|
||||
|
||||
## Integratie van ICT en bedrijfsafdelingen
|
||||
|
||||
Om de kloof tussen ICT en de werkvloer te overbruggen, is het essentieel dat ICT-afdelingen nauwer samenwerken met verschillende bedrijfsafdelingen. Door gezamenlijk te bepalen welke tools en systemen het beste aansluiten bij de werkprocessen, kunnen organisaties efficiënter en effectiever opereren.
|
||||
|
||||
Deze integratie bevordert niet alleen de productiviteit, maar ook de tevredenheid en betrokkenheid van medewerkers.
|
||||
|
||||
## Conclusie
|
||||
|
||||
In een tijd waarin digitalisering en flexibiliteit centraal staan, is het cruciaal dat ICT-afdelingen zich aanpassen aan de behoeften van de werkvloer. Door open standaarden en open-source oplossingen te omarmen en een nauwe samenwerking met andere afdelingen te zoeken, kunnen organisaties een dynamische en efficiënte werkomgeving creëren die aansluit bij de moderne samenleving.
|
||||
63
public/content/ict/open-source/standaardisatie.md
Normal file
63
public/content/ict/open-source/standaardisatie.md
Normal file
@ -0,0 +1,63 @@
|
||||
# Standaardisatie: Het Belang ervan en de Tegenstelling tussen Commerciële Bedrijven en Open-Source Gemeenschappen
|
||||
|
||||
Standaardisatie is een cruciaal concept in de moderne wereld, met name in de technologie-industrie. Het verwijst naar het vaststellen van gemeenschappelijke normen en specificaties voor producten, processen, protocollen en systemen. Deze normen dienen als de ruggengraat van interoperabiliteit en efficiëntie in verschillende sectoren, zoals informatietechnologie, telecommunicatie, gezondheidszorg en meer.
|
||||
|
||||
## Waarom is Standaardisatie Belangrijk?
|
||||
|
||||
### 1. Interoperabiliteit
|
||||
|
||||
Standaardisatie zorgt ervoor dat verschillende systemen, producten en software met elkaar kunnen communiceren en samenwerken. Dit vergemakkelijkt de uitwisseling van informatie en diensten tussen verschillende leveranciers en platforms.
|
||||
|
||||
Bijvoorbeeld, standaardisatie van internetprotocollen maakt het mogelijk dat verschillende apparaten en websites wereldwijd met elkaar kunnen communiceren.
|
||||
|
||||
### 2. Efficiëntie
|
||||
|
||||
Standaardisatie kan de efficiëntie verbeteren door het verminderen van redundantie en complexiteit. Wanneer bedrijven en organisaties dezelfde normen volgen, kunnen ze resources beter beheren en kosten besparen.
|
||||
|
||||
Het voorkomt bijvoorbeeld dat ze verschillende aangepaste oplossingen moeten ontwikkelen voor vergelijkbare taken.
|
||||
|
||||
### 3. Veiligheid en Betrouwbaarheid
|
||||
|
||||
Standaardisatie kan de veiligheid en betrouwbaarheid van producten en systemen verbeteren. Gemeenschappelijke normen stellen minimumeisen vast voor bijvoorbeeld cybersecurity en kwaliteitscontrole, wat de bescherming van gegevens en de integriteit van systemen bevordert.
|
||||
|
||||
### 4. Innovatie en Concurrentie
|
||||
|
||||
Standaardisatie kan innovatie stimuleren door bedrijven aan te moedigen nieuwe technologieën te ontwikkelen die aan de normen voldoen. Het kan ook de concurrentie bevorderen, omdat het de toetreding van nieuwe spelers vergemakkelijkt door hen een gemeenschappelijke basis te bieden om op voort te bouwen.
|
||||
|
||||
## Waarom Commerciële Bedrijven van Standaardisatie Afwijken
|
||||
|
||||
Commerciële bedrijven hebben soms redenen om van standaardisatie af te wijken, vooral als ze streven naar concurrentievoordeel, vendor lock-in of maximale winst.
|
||||
|
||||
### 1. Vendor Lock-In
|
||||
|
||||
Sommige bedrijven willen klanten aan zich binden door proprietaire technologieën te gebruiken die niet compatibel zijn met die van andere leveranciers. Dit creëert een zogenaamde "vendor lock-in", waarbij klanten moeilijk kunnen overstappen naar concurrenten.
|
||||
|
||||
### 2. Concurrentievoordeel
|
||||
|
||||
Bedrijven kunnen proberen een uniek concurrentievoordeel te behouden door niet-conforme technologieën of protocollen te gebruiken. Dit kan tijdelijk voordelig zijn, maar kan de algemene interoperabiliteit belemmeren.
|
||||
|
||||
### 3. Winstmaximalisatie
|
||||
|
||||
Sommige bedrijven willen maximale winst behalen en zien geen voordeel in het delen van kennis of het bevorderen van open normen.
|
||||
|
||||
## Waarom Open-Source Gemeenschappen Standaardisatie Omarmen
|
||||
|
||||
Open-source gemeenschappen, daarentegen, hebben vaak een sterke affiniteit met standaardisatie vanwege de voordelen die het biedt aan samenwerking en innovatie.
|
||||
|
||||
### 1. Samenwerking en Gedeelde Waarden
|
||||
|
||||
Open-source gemeenschappen gedijen op samenwerking, delen en transparantie. Het omarmen van standaardisatie past goed bij deze waarden, omdat het de basis legt voor gemeenschappelijke ontwikkeling en kennisuitwisseling.
|
||||
|
||||
### 2. Toegankelijkheid en Gelijkheid
|
||||
|
||||
Open standaarden bevorderen toegankelijkheid en gelijkheid, omdat ze de drempels voor deelname en concurrentie verlagen. Iedereen kan bijdragen aan open-source projecten en gebruikmaken van de resulterende standaarden.
|
||||
|
||||
### 3. Innovatie en Duurzaamheid
|
||||
|
||||
Open-source projecten kunnen innovatie stimuleren door een bredere groep mensen en organisaties bij het ontwikkelingsproces te betrekken. Dit leidt vaak tot duurzamere oplossingen die langer relevant blijven.
|
||||
|
||||
## Conclusie
|
||||
|
||||
Kortom, standaardisatie is een essentieel concept dat de basis vormt voor interoperabiliteit, efficiëntie en innovatie in verschillende industrieën. Terwijl commerciële bedrijven soms van standaardisatie kunnen afwijken om hun eigen belangen te behartigen, omarmen open-source gemeenschappen vaak actief standaardisatie vanwege de voordelen van samenwerking, toegankelijkheid en duurzaamheid die het met zich meebrengt.
|
||||
|
||||
Het evenwicht tussen deze twee benaderingen speelt een cruciale rol bij het vormgeven van de technologische wereld waarin we leven.
|
||||
7
public/content/leren/index.md
Normal file
7
public/content/leren/index.md
Normal file
@ -0,0 +1,7 @@
|
||||
# Leren
|
||||
|
||||
Welkom bij de leersectie. Hier vind je verschillende artikelen over leren en persoonlijke ontwikkeling.
|
||||
|
||||
## Beschikbare Artikelen
|
||||
|
||||
- [Het Cruciale Belang van Kennis boven Aantallen in de Werkkracht](?page=leren/kennis-boven-aantallen)
|
||||
39
public/content/leren/kennis-boven-aantallen.md
Normal file
39
public/content/leren/kennis-boven-aantallen.md
Normal file
@ -0,0 +1,39 @@
|
||||
# Het Cruciale Belang van Kennis boven Aantallen in de Werkkracht
|
||||
|
||||
In de dynamische wereld van vandaag wordt vaak de fout gemaakt om te denken dat het simpelweg uitbreiden van het personeelsbestand automatisch zal leiden tot verbeterde efficiëntie en productiviteit binnen een organisatie. Deze misvatting miskent echter het werkelijke knelpunt: een gebrek aan diepgaande kennis en expertise bij het bestaande personeel. Het is niet een kwestie van meer mensen aannemen, maar eerder van het ontwikkelen van beter opgeleide en gekwalificeerde werknemers.
|
||||
|
||||
## Problemen door gebrek aan kennis
|
||||
|
||||
### 1. Foutieve informatie en besluitvorming
|
||||
|
||||
Stel je voor dat een bedrijf een projectteam heeft samengesteld dat verantwoordelijk is voor het lanceren van een nieuw product. Als de teamleden niet beschikken over de vereiste kennis van markttrends, consumentengedrag en concurrentieanalyse, kunnen ze beslissingen nemen die gebaseerd zijn op onvolledige of verouderde informatie.
|
||||
|
||||
Dit kan resulteren in het nemen van verkeerde beslissingen, zoals het produceren van een product dat niet aansluit op de behoeften van de markt, met als gevolg financiële verliezen voor het bedrijf.
|
||||
|
||||
### 2. Behoefte aan constante correcties
|
||||
|
||||
Stel je voor dat een klantenserviceteam te maken heeft met klachten over een nieuw gelanceerd product. Als de medewerkers niet goed zijn opgeleid over de specificaties en eigenschappen van het product, zullen ze moeite hebben om de klachten van klanten adequaat te begrijpen en op te lossen.
|
||||
|
||||
Dit kan leiden tot een situatie waarin meer ervaren medewerkers voortdurend de tijd moeten nemen om de fouten van minder goed opgeleide collega's te corrigeren, wat leidt tot inefficiëntie en frustratie bij zowel medewerkers als klanten.
|
||||
|
||||
### 3. Vertraagde processen
|
||||
|
||||
In een technologiebedrijf kan een gebrek aan kennis over de nieuwste software en systemen leiden tot vertragingen bij het uitvoeren van projecten. Stel je voor dat programmeurs niet op de hoogte zijn van de nieuwste programmeertools en -methoden.
|
||||
|
||||
Dit kan resulteren in een langzamer ontwikkelingsproces en uiteindelijk een vertraagde productlancering, waardoor het bedrijf een concurrentievoordeel verliest.
|
||||
|
||||
## Oplossing: Investeren in kennisontwikkeling
|
||||
|
||||
Om deze problemen effectief aan te pakken en de algehele prestaties van een organisatie te verbeteren, is het van essentieel belang om te investeren in de ontwikkeling van de kennis en vaardigheden van het bestaande personeel.
|
||||
|
||||
Door middel van regelmatige trainingssessies, bijscholing en professionele ontwikkelingsprogramma's kunnen werknemers worden uitgerust met de nodige expertise om hun taken effectief en efficiënt uit te voeren.
|
||||
|
||||
## Focus op kwaliteit boven kwantiteit
|
||||
|
||||
In plaats van te streven naar een kwantitatieve uitbreiding van het personeelsbestand, moet de focus liggen op het versterken van de kwaliteit van het personeel door middel van continue leerinitiatieven.
|
||||
|
||||
Dit zal niet alleen leiden tot betere prestaties en productiviteit, maar ook tot een meer bevredigende werkomgeving waarin werknemers zich gewaardeerd en gesteund voelen in hun professionele ontwikkeling.
|
||||
|
||||
## Conclusie
|
||||
|
||||
Kortom, het is niet het aantal werknemers dat telt, maar de kwaliteit van hun kennis en vaardigheden die bepalend zijn voor het succes van een organisatie. Door te investeren in de ontwikkeling van het bestaande personeel kunnen organisaties effectiever opereren en beter inspelen op de uitdagingen van de moderne zakelijke omgeving.
|
||||
3
public/content/phpinfo.php
Normal file
3
public/content/phpinfo.php
Normal file
@ -0,0 +1,3 @@
|
||||
<?php
|
||||
echo phpinfo();
|
||||
?>
|
||||
39
public/content/retro-gaming/commodore-64.md
Normal file
39
public/content/retro-gaming/commodore-64.md
Normal file
@ -0,0 +1,39 @@
|
||||
# De Commodore 64: Een les in creativiteit en innovatie in de game-industrie
|
||||
|
||||
In de wereld van gaming lijkt alles tegenwoordig om technologische vooruitgang te draaien. Nieuwe hardware komt sneller uit dan we kunnen bijhouden, en games worden steeds meer gericht op realistische graphics en geluiden in plaats van creativiteit en innovatie.
|
||||
|
||||
Het is een constante race om te zien wie de nieuwste en beste technologie kan ontwikkelen, en er is weinig tijd om stil te staan bij wat er verloren gaat in deze wedloop.
|
||||
|
||||
## Een uitzondering: de Commodore 64
|
||||
|
||||
Maar er is een uitzondering op deze regel: de Commodore 64. Ondanks dat deze machine bijna 40 jaar oud is, blijft het een bron van inspiratie en uitdaging voor game-ontwikkelaars. Het is ongelooflijk dat ondanks de voortdurende technologische vooruitgang en de ontwikkeling van geavanceerde consoles en computers, er nog steeds games worden ontwikkeld voor de Commodore 64.
|
||||
|
||||
## Wat maakt de C64 speciaal?
|
||||
|
||||
Wat maakt deze klassieke machine zo bijzonder? In tegenstelling tot de hedendaagse tijdsdruk, was er in de begindagen van de game-industrie geen sprake van concurrentie van nieuwere consoles en was de focus meer gericht op het creëren van unieke en vermakelijke games.
|
||||
|
||||
Dit betekende dat ontwikkelaars de tijd hadden om de kwaliteit van hun games te waarborgen en te optimaliseren voor de beperkingen van het systeem.
|
||||
|
||||
## Creativiteit door beperkingen
|
||||
|
||||
De beperkingen van de Commodore 64 hardware dwongen ontwikkelaars om creatief te zijn en innovatieve oplossingen te bedenken om games te ontwikkelen die vermakelijk en uitdagend waren voor spelers.
|
||||
|
||||
Het was niet zozeer de technologie die centraal stond, maar het spel zelf en de ervaring die het de speler gaf.
|
||||
|
||||
## Les voor de huidige game-industrie
|
||||
|
||||
Maar wat betekent dit voor de huidige game-industrie? De snelle ontwikkeling van hardware tegenwoordig kan de ontwikkeling van software in de weg staan.
|
||||
|
||||
Omdat nieuwe hardware steeds sneller en krachtiger wordt, kan er tijdsdruk ontstaan om games en software snel te ontwikkelen om te profiteren van de nieuwe hardware. Hierdoor kan de focus meer komen te liggen op het maximaliseren van de technologische mogelijkheden in plaats van op de creativiteit en innovatie van de software.
|
||||
|
||||
## Minder kan meer bereiken
|
||||
|
||||
De Commodore 64 laat zien dat mensen in staat zijn om meer te bereiken met minder. De beperkingen van de hardware dwongen ontwikkelaars om creatief te zijn en innovatieve oplossingen te bedenken om games te ontwikkelen die vermakelijk en uitdagend waren voor spelers.
|
||||
|
||||
Dit laat zien dat de focus op creativiteit en innovatie in de ontwikkeling van software net zo belangrijk is als de technologische vooruitgang.
|
||||
|
||||
## Conclusie
|
||||
|
||||
In een tijdperk waarin de game-industrie wordt gedreven door technologische vooruitgang en tijdsdruk, is het verfrissend om te zien dat de Commodore 64 nog steeds relevant is en nieuwe games ondersteunt.
|
||||
|
||||
Het is een les voor ons allemaal om niet te vergeten dat creativiteit en innovatie net zo belangrijk zijn als de technologische vooruitgang in de ontwikkeling van games en software.
|
||||
33
public/content/welkom.md
Normal file
33
public/content/welkom.md
Normal file
@ -0,0 +1,33 @@
|
||||
# Welkom, ik ben Edwin
|
||||
|
||||
**Innovatie en Technologische Passie: Het Inspirerende Verhaal van Edwin Noorlander**
|
||||
|
||||
Mijn naam is Edwin Noorlander, en ik wil graag mijn inspirerende reis met jullie delen. Mijn leven is doordrenkt van innovatie en een onwankelbare omhelzing van technologie als mijn leidraad naar waar ik nu ben. Mijn verhaal is er een van vastberadenheid, autodidactisch leren en een diepe liefde voor complexiteit.
|
||||
|
||||
## Uitdagingen als Drijfveer
|
||||
|
||||
Laat me beginnen door te benadrukken dat mijn pad niet zonder uitdagingen is geweest. Van jongs af aan heb ik dyslexie en ADHD ervaren, wat mijn leerproces op traditionele scholen zeker niet eenvoudig maakte. Maar deze obstakels hebben me nooit ontmoedigd. In plaats daarvan dienden ze als drijfveer om mijn eigen weg te vinden in de wereld van technologie.
|
||||
|
||||
## Autodidactisch Leren
|
||||
|
||||
Ik heb altijd technologie als mijn roeping beschouwd, en dit dreef me om een unieke weg van zelfontdekking te bewandelen. In tegenstelling tot traditionele onderwijsroutes koos ik voor praktische hands-on ervaringen, en ondanks de uitdagingen die dyslexie en ADHD met zich meebrengen, leerde ik mezelf programmeren in diverse programmeertalen, waaronder ASM, C/C++, Java, PHP, HTML, JavaScript en SCSS. Deze diversiteit aan talen stelde me in staat om complexe problemen op te lossen en innovatieve oplossingen te creëren.
|
||||
|
||||
## Micro-elektronica en Ruimtevaart
|
||||
|
||||
Mijn passie reikte verder dan alleen software; ik dook diep in de wereld van micro-elektronica, waar ik leerde om microprocessors te programmeren en sensoren en actuatoren aan te sturen. Dit gaf me de mogelijkheid om fysieke systemen te bouwen en mijn ideeën tot leven te brengen.
|
||||
|
||||
Naast mijn technologische avonturen was ik altijd gefascineerd door astronomie en ruimtevaart, waar ik mijn leergierigheid en passie voor ontdekking voedde.
|
||||
|
||||
## Huidige Werk
|
||||
|
||||
Momenteel werk ik als adviseur bij de overheid, waar ik mijn kennis en ervaring toepas om advies te geven over ICT-infrastructuur met betrekking tot digitaal leren. Dit stelt me in staat om bij te dragen aan de groei en ontwikkeling van de samenleving door middel van technologie.
|
||||
|
||||
## Missie en Doel
|
||||
|
||||
Mijn ultieme doel is om anderen te inspireren die zich in een vergelijkbare positie bevinden, met een handicap zoals dyslexie en ADHD, om zichzelf te blijven ontwikkelen en te leren wat ze willen leren. Ik geloof dat het nooit te laat is om te beginnen met leren en dat er altijd manieren zijn om je doelen te bereiken, zelfs als de weg er naartoe uitdagend lijkt.
|
||||
|
||||
Daarom heb ik deze blog gecreëerd. Hier wil ik graag mijn kennis en ervaringen delen en anderen aanmoedigen om hun passie te volgen en te blijven leren, en open-source ondersteunen en bijdragen waar het kan. Ongeacht welke obstakels zich voordoen.
|
||||
|
||||
Dankjewel voor het bezoeken van mijn blog, en ik hoop je snel weer terug te zien!
|
||||
|
||||
Mijn naam is Edwin Noorlander, en ik ben vastbesloten om de kracht van innovatie en technologie te blijven omarmen.
|
||||
@ -1,6 +1,5 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/../engine/core/config.php';
|
||||
require_once __DIR__ . '/../engine/core/index.php';
|
||||
|
||||
$config = include __DIR__ . '/../engine/core/config.php';
|
||||
|
||||
352
src/scss/main.scss
Normal file
352
src/scss/main.scss
Normal file
@ -0,0 +1,352 @@
|
||||
// Custom variables (must come before Bootstrap import)
|
||||
$primary: #0d6efd;
|
||||
$navigation-opacity: 0.5; // 50% opacity
|
||||
|
||||
// Import Bootstrap
|
||||
@import "bootstrap/scss/bootstrap";
|
||||
|
||||
// Custom navigation background with 50% opacity of primary color
|
||||
.navigation-50-opacity {
|
||||
background-color: rgba($primary, $navigation-opacity) !important;
|
||||
}
|
||||
|
||||
// Custom CodePress styles
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html, body {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
/* Header */
|
||||
header.navbar {
|
||||
flex-shrink: 0;
|
||||
height: 66px;
|
||||
}
|
||||
|
||||
/* Navigation section */
|
||||
.navigation-section {
|
||||
background-color: #ffffff;
|
||||
border-bottom: 1px solid #dee2e6;
|
||||
padding: 0.5rem 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Tab styling */
|
||||
.nav-tabs {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.nav-tabs .nav-link {
|
||||
border: 1px solid transparent;
|
||||
border-bottom: none;
|
||||
border-radius: 0; // Geen ronde hoeken
|
||||
color: #6c757d;
|
||||
background-color: transparent; // Transparante achtergrond voor eerste laag
|
||||
margin-right: 0.25rem;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.nav-tabs .nav-link:hover {
|
||||
color: #495057;
|
||||
background-color: rgba(0, 0, 0, 0.05); // Subtiel hover effect
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.nav-tabs .nav-link.active {
|
||||
color: #495057;
|
||||
background-color: #ffffff; // Alleen active heeft witte achtergrond
|
||||
border-color: #dee2e6 #dee2e6 transparent;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* Dropdown in tabs - eerste laag */
|
||||
.nav-tabs .nav-item.dropdown .nav-link {
|
||||
background-color: transparent; // Transparante achtergrond
|
||||
border: 1px solid transparent;
|
||||
border-radius: 0; // Geen ronde hoeken
|
||||
}
|
||||
|
||||
.nav-tabs .nav-item.dropdown .nav-link:hover {
|
||||
background-color: rgba(0, 0, 0, 0.05); // Subtiel hover effect
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
/* Dropdown menu styling */
|
||||
.nav-tabs .dropdown-menu {
|
||||
margin-top: 0.25rem;
|
||||
border-radius: 0.375rem;
|
||||
box-shadow: 0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);
|
||||
min-width: 200px;
|
||||
max-width: 300px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
/* Dropdown items styling */
|
||||
.nav-tabs .dropdown-menu .dropdown-item {
|
||||
white-space: normal;
|
||||
padding: 0.5rem 1rem;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
/* Long text truncation for very long titles */
|
||||
.nav-tabs .dropdown-menu .dropdown-item {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 280px;
|
||||
}
|
||||
|
||||
/* Breadcrumb section */
|
||||
.breadcrumb-section {
|
||||
background-color: #f8f9fa;
|
||||
border-bottom: 1px solid #dee2e6;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Breadcrumb styling consistency */
|
||||
.breadcrumb-section .breadcrumb {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.breadcrumb-section .breadcrumb-item {
|
||||
color: #6c757d !important;
|
||||
}
|
||||
|
||||
.breadcrumb-section .breadcrumb-item a {
|
||||
color: #0d6efd !important;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.breadcrumb-section .breadcrumb-item a:hover {
|
||||
color: #0a58ca !important;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.breadcrumb-section .breadcrumb-item.active {
|
||||
color: #6c757d !important;
|
||||
}
|
||||
|
||||
/* Main content area */
|
||||
.main-content {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 1rem 0;
|
||||
}
|
||||
|
||||
/* Content specific styling */
|
||||
.markdown-content,
|
||||
.php-content,
|
||||
.html-content {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.markdown-content .content-body,
|
||||
.php-content .content-body,
|
||||
.html-content .content-body {
|
||||
padding: 2rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
footer {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Navigation dropdown styling */
|
||||
.navigation-section .btn {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.navigation-section .collapse .nav-link {
|
||||
color: #495057;
|
||||
padding: 0.375rem 0.75rem;
|
||||
border-radius: 0.25rem;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.navigation-section .collapse .nav-link:hover {
|
||||
background-color: #e9ecef;
|
||||
color: #212529;
|
||||
}
|
||||
|
||||
.navigation-section .collapse .nav-link.active {
|
||||
background-color: #0d6efd;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.navigation-section .collapse .nav-link i {
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
/* File info styling */
|
||||
.file-info {
|
||||
font-size: 0.9rem;
|
||||
color: #6c757d;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.file-info i {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
color: #6c757d;
|
||||
max-width: 250px;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
vertical-align: middle;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.page-title:hover {
|
||||
color: #495057;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.file-details {
|
||||
color: #6c757d;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.site-info a {
|
||||
color: #0d6efd;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.site-info a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.guide-link {
|
||||
color: #6c757d !important;
|
||||
text-decoration: none;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.guide-link:hover {
|
||||
color: #0d6efd !important;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.guide-link i {
|
||||
font-size: 1rem;
|
||||
color: #6c757d !important;
|
||||
}
|
||||
|
||||
.guide-link:hover i {
|
||||
color: #0d6efd !important;
|
||||
}
|
||||
|
||||
.auto-link {
|
||||
color: #0d6efd;
|
||||
text-decoration: none;
|
||||
border-bottom: 2px dashed #0d6efd;
|
||||
font-weight: 500;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.auto-link:hover {
|
||||
color: #0a58ca;
|
||||
text-decoration: none;
|
||||
border-bottom-style: solid;
|
||||
border-bottom-color: #0a58ca;
|
||||
}
|
||||
|
||||
/* Search form */
|
||||
.search-form {
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
/* Card styling */
|
||||
.card-title a {
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.card-title a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* Dropdown submenu styling */
|
||||
.dropdown-menu .dropdown-menu {
|
||||
top: 0;
|
||||
left: 100%;
|
||||
margin-top: -1px;
|
||||
margin-left: -1px;
|
||||
}
|
||||
|
||||
/* Show nested dropdowns on hover */
|
||||
.dropdown-submenu {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.dropdown-submenu .dropdown-menu {
|
||||
top: 0;
|
||||
left: 100%;
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
||||
.dropdown-submenu:hover > .dropdown-menu {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* For touch devices - click to open */
|
||||
.dropdown-submenu > .dropdown-toggle:active::after {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 768px) {
|
||||
.main-content {
|
||||
padding-top: 120px; /* More space for mobile */
|
||||
}
|
||||
|
||||
.markdown-content .content-body,
|
||||
.php-content .content-body,
|
||||
.html-content .content-body {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.nav-tabs .dropdown-menu {
|
||||
min-width: 180px;
|
||||
max-width: 250px;
|
||||
}
|
||||
|
||||
.nav-tabs .dropdown-menu .dropdown-item {
|
||||
max-width: 230px;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 576px) {
|
||||
.markdown-content .content-body,
|
||||
.php-content .content-body,
|
||||
.html-content .content-body {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.nav-tabs .dropdown-menu {
|
||||
min-width: 160px;
|
||||
max-width: 200px;
|
||||
}
|
||||
|
||||
.nav-tabs .dropdown-menu .dropdown-item {
|
||||
max-width: 180px;
|
||||
font-size: 0.85rem;
|
||||
padding: 0.4rem 0.8rem;
|
||||
}
|
||||
}
|
||||
67
vendor/composer/autoload_classmap.php
vendored
67
vendor/composer/autoload_classmap.php
vendored
@ -6,6 +6,7 @@ $vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
|
||||
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
|
||||
'Mustache_Cache' => $vendorDir . '/mustache/mustache/src/compat.php',
|
||||
'Mustache_Cache_AbstractCache' => $vendorDir . '/mustache/mustache/src/compat.php',
|
||||
@ -40,4 +41,70 @@ return array(
|
||||
'Mustache_Source_FilesystemSource' => $vendorDir . '/mustache/mustache/src/compat.php',
|
||||
'Mustache_Template' => $vendorDir . '/mustache/mustache/src/compat.php',
|
||||
'Mustache_Tokenizer' => $vendorDir . '/mustache/mustache/src/compat.php',
|
||||
'Nette\\ArgumentOutOfRangeException' => $vendorDir . '/nette/utils/src/exceptions.php',
|
||||
'Nette\\DeprecatedException' => $vendorDir . '/nette/utils/src/exceptions.php',
|
||||
'Nette\\DirectoryNotFoundException' => $vendorDir . '/nette/utils/src/exceptions.php',
|
||||
'Nette\\FileNotFoundException' => $vendorDir . '/nette/utils/src/exceptions.php',
|
||||
'Nette\\HtmlStringable' => $vendorDir . '/nette/utils/src/HtmlStringable.php',
|
||||
'Nette\\IOException' => $vendorDir . '/nette/utils/src/exceptions.php',
|
||||
'Nette\\InvalidArgumentException' => $vendorDir . '/nette/utils/src/exceptions.php',
|
||||
'Nette\\InvalidStateException' => $vendorDir . '/nette/utils/src/exceptions.php',
|
||||
'Nette\\Iterators\\CachingIterator' => $vendorDir . '/nette/utils/src/Iterators/CachingIterator.php',
|
||||
'Nette\\Iterators\\Mapper' => $vendorDir . '/nette/utils/src/Iterators/Mapper.php',
|
||||
'Nette\\Localization\\ITranslator' => $vendorDir . '/nette/utils/src/compatibility.php',
|
||||
'Nette\\Localization\\Translator' => $vendorDir . '/nette/utils/src/Translator.php',
|
||||
'Nette\\MemberAccessException' => $vendorDir . '/nette/utils/src/exceptions.php',
|
||||
'Nette\\NotImplementedException' => $vendorDir . '/nette/utils/src/exceptions.php',
|
||||
'Nette\\NotSupportedException' => $vendorDir . '/nette/utils/src/exceptions.php',
|
||||
'Nette\\OutOfRangeException' => $vendorDir . '/nette/utils/src/exceptions.php',
|
||||
'Nette\\Schema\\Context' => $vendorDir . '/nette/schema/src/Schema/Context.php',
|
||||
'Nette\\Schema\\DynamicParameter' => $vendorDir . '/nette/schema/src/Schema/DynamicParameter.php',
|
||||
'Nette\\Schema\\Elements\\AnyOf' => $vendorDir . '/nette/schema/src/Schema/Elements/AnyOf.php',
|
||||
'Nette\\Schema\\Elements\\Base' => $vendorDir . '/nette/schema/src/Schema/Elements/Base.php',
|
||||
'Nette\\Schema\\Elements\\Structure' => $vendorDir . '/nette/schema/src/Schema/Elements/Structure.php',
|
||||
'Nette\\Schema\\Elements\\Type' => $vendorDir . '/nette/schema/src/Schema/Elements/Type.php',
|
||||
'Nette\\Schema\\Expect' => $vendorDir . '/nette/schema/src/Schema/Expect.php',
|
||||
'Nette\\Schema\\Helpers' => $vendorDir . '/nette/schema/src/Schema/Helpers.php',
|
||||
'Nette\\Schema\\Message' => $vendorDir . '/nette/schema/src/Schema/Message.php',
|
||||
'Nette\\Schema\\Processor' => $vendorDir . '/nette/schema/src/Schema/Processor.php',
|
||||
'Nette\\Schema\\Schema' => $vendorDir . '/nette/schema/src/Schema/Schema.php',
|
||||
'Nette\\Schema\\ValidationException' => $vendorDir . '/nette/schema/src/Schema/ValidationException.php',
|
||||
'Nette\\ShouldNotHappenException' => $vendorDir . '/nette/utils/src/exceptions.php',
|
||||
'Nette\\SmartObject' => $vendorDir . '/nette/utils/src/SmartObject.php',
|
||||
'Nette\\StaticClass' => $vendorDir . '/nette/utils/src/StaticClass.php',
|
||||
'Nette\\UnexpectedValueException' => $vendorDir . '/nette/utils/src/exceptions.php',
|
||||
'Nette\\Utils\\ArrayHash' => $vendorDir . '/nette/utils/src/Utils/ArrayHash.php',
|
||||
'Nette\\Utils\\ArrayList' => $vendorDir . '/nette/utils/src/Utils/ArrayList.php',
|
||||
'Nette\\Utils\\Arrays' => $vendorDir . '/nette/utils/src/Utils/Arrays.php',
|
||||
'Nette\\Utils\\AssertionException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php',
|
||||
'Nette\\Utils\\Callback' => $vendorDir . '/nette/utils/src/Utils/Callback.php',
|
||||
'Nette\\Utils\\DateTime' => $vendorDir . '/nette/utils/src/Utils/DateTime.php',
|
||||
'Nette\\Utils\\FileInfo' => $vendorDir . '/nette/utils/src/Utils/FileInfo.php',
|
||||
'Nette\\Utils\\FileSystem' => $vendorDir . '/nette/utils/src/Utils/FileSystem.php',
|
||||
'Nette\\Utils\\Finder' => $vendorDir . '/nette/utils/src/Utils/Finder.php',
|
||||
'Nette\\Utils\\Floats' => $vendorDir . '/nette/utils/src/Utils/Floats.php',
|
||||
'Nette\\Utils\\Helpers' => $vendorDir . '/nette/utils/src/Utils/Helpers.php',
|
||||
'Nette\\Utils\\Html' => $vendorDir . '/nette/utils/src/Utils/Html.php',
|
||||
'Nette\\Utils\\IHtmlString' => $vendorDir . '/nette/utils/src/compatibility.php',
|
||||
'Nette\\Utils\\Image' => $vendorDir . '/nette/utils/src/Utils/Image.php',
|
||||
'Nette\\Utils\\ImageColor' => $vendorDir . '/nette/utils/src/Utils/ImageColor.php',
|
||||
'Nette\\Utils\\ImageException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php',
|
||||
'Nette\\Utils\\ImageType' => $vendorDir . '/nette/utils/src/Utils/ImageType.php',
|
||||
'Nette\\Utils\\Iterables' => $vendorDir . '/nette/utils/src/Utils/Iterables.php',
|
||||
'Nette\\Utils\\Json' => $vendorDir . '/nette/utils/src/Utils/Json.php',
|
||||
'Nette\\Utils\\JsonException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php',
|
||||
'Nette\\Utils\\ObjectHelpers' => $vendorDir . '/nette/utils/src/Utils/ObjectHelpers.php',
|
||||
'Nette\\Utils\\Paginator' => $vendorDir . '/nette/utils/src/Utils/Paginator.php',
|
||||
'Nette\\Utils\\Random' => $vendorDir . '/nette/utils/src/Utils/Random.php',
|
||||
'Nette\\Utils\\Reflection' => $vendorDir . '/nette/utils/src/Utils/Reflection.php',
|
||||
'Nette\\Utils\\ReflectionMethod' => $vendorDir . '/nette/utils/src/Utils/ReflectionMethod.php',
|
||||
'Nette\\Utils\\RegexpException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php',
|
||||
'Nette\\Utils\\Strings' => $vendorDir . '/nette/utils/src/Utils/Strings.php',
|
||||
'Nette\\Utils\\Type' => $vendorDir . '/nette/utils/src/Utils/Type.php',
|
||||
'Nette\\Utils\\UnknownImageFileException' => $vendorDir . '/nette/utils/src/Utils/exceptions.php',
|
||||
'Nette\\Utils\\Validators' => $vendorDir . '/nette/utils/src/Utils/Validators.php',
|
||||
'PhpToken' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
|
||||
'Stringable' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
|
||||
'UnhandledMatchError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
|
||||
'ValueError' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
|
||||
);
|
||||
|
||||
11
vendor/composer/autoload_files.php
vendored
Normal file
11
vendor/composer/autoload_files.php
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
// autoload_files.php @generated by Composer
|
||||
|
||||
$vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
|
||||
'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
|
||||
);
|
||||
6
vendor/composer/autoload_psr4.php
vendored
6
vendor/composer/autoload_psr4.php
vendored
@ -6,5 +6,11 @@ $vendorDir = dirname(__DIR__);
|
||||
$baseDir = dirname($vendorDir);
|
||||
|
||||
return array(
|
||||
'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/symfony/polyfill-php80'),
|
||||
'Psr\\EventDispatcher\\' => array($vendorDir . '/psr/event-dispatcher/src'),
|
||||
'Nette\\' => array($vendorDir . '/nette/schema/src', $vendorDir . '/nette/utils/src'),
|
||||
'Mustache\\' => array($vendorDir . '/mustache/mustache/src'),
|
||||
'League\\Config\\' => array($vendorDir . '/league/config/src'),
|
||||
'League\\CommonMark\\' => array($vendorDir . '/league/commonmark/src'),
|
||||
'Dflydev\\DotAccessData\\' => array($vendorDir . '/dflydev/dot-access-data/src'),
|
||||
);
|
||||
|
||||
12
vendor/composer/autoload_real.php
vendored
12
vendor/composer/autoload_real.php
vendored
@ -33,6 +33,18 @@ class ComposerAutoloaderInit071586d19f5409de22b3235d85d8476c
|
||||
|
||||
$loader->register(true);
|
||||
|
||||
$filesToLoad = \Composer\Autoload\ComposerStaticInit071586d19f5409de22b3235d85d8476c::$files;
|
||||
$requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
|
||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||
|
||||
require $file;
|
||||
}
|
||||
}, null, null);
|
||||
foreach ($filesToLoad as $fileIdentifier => $file) {
|
||||
$requireFile($fileIdentifier, $file);
|
||||
}
|
||||
|
||||
return $loader;
|
||||
}
|
||||
}
|
||||
|
||||
118
vendor/composer/autoload_static.php
vendored
118
vendor/composer/autoload_static.php
vendored
@ -6,21 +6,73 @@ namespace Composer\Autoload;
|
||||
|
||||
class ComposerStaticInit071586d19f5409de22b3235d85d8476c
|
||||
{
|
||||
public static $files = array (
|
||||
'6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php',
|
||||
'a4a119a56e50fbb293281d9a48007e0e' => __DIR__ . '/..' . '/symfony/polyfill-php80/bootstrap.php',
|
||||
);
|
||||
|
||||
public static $prefixLengthsPsr4 = array (
|
||||
'S' =>
|
||||
array (
|
||||
'Symfony\\Polyfill\\Php80\\' => 23,
|
||||
),
|
||||
'P' =>
|
||||
array (
|
||||
'Psr\\EventDispatcher\\' => 20,
|
||||
),
|
||||
'N' =>
|
||||
array (
|
||||
'Nette\\' => 6,
|
||||
),
|
||||
'M' =>
|
||||
array (
|
||||
'Mustache\\' => 9,
|
||||
),
|
||||
'L' =>
|
||||
array (
|
||||
'League\\Config\\' => 14,
|
||||
'League\\CommonMark\\' => 18,
|
||||
),
|
||||
'D' =>
|
||||
array (
|
||||
'Dflydev\\DotAccessData\\' => 22,
|
||||
),
|
||||
);
|
||||
|
||||
public static $prefixDirsPsr4 = array (
|
||||
'Symfony\\Polyfill\\Php80\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/symfony/polyfill-php80',
|
||||
),
|
||||
'Psr\\EventDispatcher\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/psr/event-dispatcher/src',
|
||||
),
|
||||
'Nette\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/nette/schema/src',
|
||||
1 => __DIR__ . '/..' . '/nette/utils/src',
|
||||
),
|
||||
'Mustache\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/mustache/mustache/src',
|
||||
),
|
||||
'League\\Config\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/league/config/src',
|
||||
),
|
||||
'League\\CommonMark\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/league/commonmark/src',
|
||||
),
|
||||
'Dflydev\\DotAccessData\\' =>
|
||||
array (
|
||||
0 => __DIR__ . '/..' . '/dflydev/dot-access-data/src',
|
||||
),
|
||||
);
|
||||
|
||||
public static $classMap = array (
|
||||
'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
|
||||
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
||||
'Mustache_Cache' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
||||
'Mustache_Cache_AbstractCache' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
||||
@ -55,6 +107,72 @@ class ComposerStaticInit071586d19f5409de22b3235d85d8476c
|
||||
'Mustache_Source_FilesystemSource' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
||||
'Mustache_Template' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
||||
'Mustache_Tokenizer' => __DIR__ . '/..' . '/mustache/mustache/src/compat.php',
|
||||
'Nette\\ArgumentOutOfRangeException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php',
|
||||
'Nette\\DeprecatedException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php',
|
||||
'Nette\\DirectoryNotFoundException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php',
|
||||
'Nette\\FileNotFoundException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php',
|
||||
'Nette\\HtmlStringable' => __DIR__ . '/..' . '/nette/utils/src/HtmlStringable.php',
|
||||
'Nette\\IOException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php',
|
||||
'Nette\\InvalidArgumentException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php',
|
||||
'Nette\\InvalidStateException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php',
|
||||
'Nette\\Iterators\\CachingIterator' => __DIR__ . '/..' . '/nette/utils/src/Iterators/CachingIterator.php',
|
||||
'Nette\\Iterators\\Mapper' => __DIR__ . '/..' . '/nette/utils/src/Iterators/Mapper.php',
|
||||
'Nette\\Localization\\ITranslator' => __DIR__ . '/..' . '/nette/utils/src/compatibility.php',
|
||||
'Nette\\Localization\\Translator' => __DIR__ . '/..' . '/nette/utils/src/Translator.php',
|
||||
'Nette\\MemberAccessException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php',
|
||||
'Nette\\NotImplementedException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php',
|
||||
'Nette\\NotSupportedException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php',
|
||||
'Nette\\OutOfRangeException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php',
|
||||
'Nette\\Schema\\Context' => __DIR__ . '/..' . '/nette/schema/src/Schema/Context.php',
|
||||
'Nette\\Schema\\DynamicParameter' => __DIR__ . '/..' . '/nette/schema/src/Schema/DynamicParameter.php',
|
||||
'Nette\\Schema\\Elements\\AnyOf' => __DIR__ . '/..' . '/nette/schema/src/Schema/Elements/AnyOf.php',
|
||||
'Nette\\Schema\\Elements\\Base' => __DIR__ . '/..' . '/nette/schema/src/Schema/Elements/Base.php',
|
||||
'Nette\\Schema\\Elements\\Structure' => __DIR__ . '/..' . '/nette/schema/src/Schema/Elements/Structure.php',
|
||||
'Nette\\Schema\\Elements\\Type' => __DIR__ . '/..' . '/nette/schema/src/Schema/Elements/Type.php',
|
||||
'Nette\\Schema\\Expect' => __DIR__ . '/..' . '/nette/schema/src/Schema/Expect.php',
|
||||
'Nette\\Schema\\Helpers' => __DIR__ . '/..' . '/nette/schema/src/Schema/Helpers.php',
|
||||
'Nette\\Schema\\Message' => __DIR__ . '/..' . '/nette/schema/src/Schema/Message.php',
|
||||
'Nette\\Schema\\Processor' => __DIR__ . '/..' . '/nette/schema/src/Schema/Processor.php',
|
||||
'Nette\\Schema\\Schema' => __DIR__ . '/..' . '/nette/schema/src/Schema/Schema.php',
|
||||
'Nette\\Schema\\ValidationException' => __DIR__ . '/..' . '/nette/schema/src/Schema/ValidationException.php',
|
||||
'Nette\\ShouldNotHappenException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php',
|
||||
'Nette\\SmartObject' => __DIR__ . '/..' . '/nette/utils/src/SmartObject.php',
|
||||
'Nette\\StaticClass' => __DIR__ . '/..' . '/nette/utils/src/StaticClass.php',
|
||||
'Nette\\UnexpectedValueException' => __DIR__ . '/..' . '/nette/utils/src/exceptions.php',
|
||||
'Nette\\Utils\\ArrayHash' => __DIR__ . '/..' . '/nette/utils/src/Utils/ArrayHash.php',
|
||||
'Nette\\Utils\\ArrayList' => __DIR__ . '/..' . '/nette/utils/src/Utils/ArrayList.php',
|
||||
'Nette\\Utils\\Arrays' => __DIR__ . '/..' . '/nette/utils/src/Utils/Arrays.php',
|
||||
'Nette\\Utils\\AssertionException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php',
|
||||
'Nette\\Utils\\Callback' => __DIR__ . '/..' . '/nette/utils/src/Utils/Callback.php',
|
||||
'Nette\\Utils\\DateTime' => __DIR__ . '/..' . '/nette/utils/src/Utils/DateTime.php',
|
||||
'Nette\\Utils\\FileInfo' => __DIR__ . '/..' . '/nette/utils/src/Utils/FileInfo.php',
|
||||
'Nette\\Utils\\FileSystem' => __DIR__ . '/..' . '/nette/utils/src/Utils/FileSystem.php',
|
||||
'Nette\\Utils\\Finder' => __DIR__ . '/..' . '/nette/utils/src/Utils/Finder.php',
|
||||
'Nette\\Utils\\Floats' => __DIR__ . '/..' . '/nette/utils/src/Utils/Floats.php',
|
||||
'Nette\\Utils\\Helpers' => __DIR__ . '/..' . '/nette/utils/src/Utils/Helpers.php',
|
||||
'Nette\\Utils\\Html' => __DIR__ . '/..' . '/nette/utils/src/Utils/Html.php',
|
||||
'Nette\\Utils\\IHtmlString' => __DIR__ . '/..' . '/nette/utils/src/compatibility.php',
|
||||
'Nette\\Utils\\Image' => __DIR__ . '/..' . '/nette/utils/src/Utils/Image.php',
|
||||
'Nette\\Utils\\ImageColor' => __DIR__ . '/..' . '/nette/utils/src/Utils/ImageColor.php',
|
||||
'Nette\\Utils\\ImageException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php',
|
||||
'Nette\\Utils\\ImageType' => __DIR__ . '/..' . '/nette/utils/src/Utils/ImageType.php',
|
||||
'Nette\\Utils\\Iterables' => __DIR__ . '/..' . '/nette/utils/src/Utils/Iterables.php',
|
||||
'Nette\\Utils\\Json' => __DIR__ . '/..' . '/nette/utils/src/Utils/Json.php',
|
||||
'Nette\\Utils\\JsonException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php',
|
||||
'Nette\\Utils\\ObjectHelpers' => __DIR__ . '/..' . '/nette/utils/src/Utils/ObjectHelpers.php',
|
||||
'Nette\\Utils\\Paginator' => __DIR__ . '/..' . '/nette/utils/src/Utils/Paginator.php',
|
||||
'Nette\\Utils\\Random' => __DIR__ . '/..' . '/nette/utils/src/Utils/Random.php',
|
||||
'Nette\\Utils\\Reflection' => __DIR__ . '/..' . '/nette/utils/src/Utils/Reflection.php',
|
||||
'Nette\\Utils\\ReflectionMethod' => __DIR__ . '/..' . '/nette/utils/src/Utils/ReflectionMethod.php',
|
||||
'Nette\\Utils\\RegexpException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php',
|
||||
'Nette\\Utils\\Strings' => __DIR__ . '/..' . '/nette/utils/src/Utils/Strings.php',
|
||||
'Nette\\Utils\\Type' => __DIR__ . '/..' . '/nette/utils/src/Utils/Type.php',
|
||||
'Nette\\Utils\\UnknownImageFileException' => __DIR__ . '/..' . '/nette/utils/src/Utils/exceptions.php',
|
||||
'Nette\\Utils\\Validators' => __DIR__ . '/..' . '/nette/utils/src/Utils/Validators.php',
|
||||
'PhpToken' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/PhpToken.php',
|
||||
'Stringable' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Stringable.php',
|
||||
'UnhandledMatchError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
|
||||
'ValueError' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/ValueError.php',
|
||||
);
|
||||
|
||||
public static function getInitializer(ClassLoader $loader)
|
||||
|
||||
643
vendor/composer/installed.json
vendored
643
vendor/composer/installed.json
vendored
@ -1,5 +1,278 @@
|
||||
{
|
||||
"packages": [
|
||||
{
|
||||
"name": "dflydev/dot-access-data",
|
||||
"version": "v3.0.3",
|
||||
"version_normalized": "3.0.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/dflydev/dflydev-dot-access-data.git",
|
||||
"reference": "a23a2bf4f31d3518f3ecb38660c95715dfead60f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/dflydev/dflydev-dot-access-data/zipball/a23a2bf4f31d3518f3ecb38660c95715dfead60f",
|
||||
"reference": "a23a2bf4f31d3518f3ecb38660c95715dfead60f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^0.12.42",
|
||||
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.3",
|
||||
"scrutinizer/ocular": "1.6.0",
|
||||
"squizlabs/php_codesniffer": "^3.5",
|
||||
"vimeo/psalm": "^4.0.0"
|
||||
},
|
||||
"time": "2024-07-08T12:26:09+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "3.x-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Dflydev\\DotAccessData\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Dragonfly Development Inc.",
|
||||
"email": "info@dflydev.com",
|
||||
"homepage": "http://dflydev.com"
|
||||
},
|
||||
{
|
||||
"name": "Beau Simensen",
|
||||
"email": "beau@dflydev.com",
|
||||
"homepage": "http://beausimensen.com"
|
||||
},
|
||||
{
|
||||
"name": "Carlos Frutos",
|
||||
"email": "carlos@kiwing.it",
|
||||
"homepage": "https://github.com/cfrutos"
|
||||
},
|
||||
{
|
||||
"name": "Colin O'Dell",
|
||||
"email": "colinodell@gmail.com",
|
||||
"homepage": "https://www.colinodell.com"
|
||||
}
|
||||
],
|
||||
"description": "Given a deep data structure, access data by dot notation.",
|
||||
"homepage": "https://github.com/dflydev/dflydev-dot-access-data",
|
||||
"keywords": [
|
||||
"access",
|
||||
"data",
|
||||
"dot",
|
||||
"notation"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/dflydev/dflydev-dot-access-data/issues",
|
||||
"source": "https://github.com/dflydev/dflydev-dot-access-data/tree/v3.0.3"
|
||||
},
|
||||
"install-path": "../dflydev/dot-access-data"
|
||||
},
|
||||
{
|
||||
"name": "league/commonmark",
|
||||
"version": "2.7.1",
|
||||
"version_normalized": "2.7.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/commonmark.git",
|
||||
"reference": "10732241927d3971d28e7ea7b5712721fa2296ca"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/10732241927d3971d28e7ea7b5712721fa2296ca",
|
||||
"reference": "10732241927d3971d28e7ea7b5712721fa2296ca",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-mbstring": "*",
|
||||
"league/config": "^1.1.1",
|
||||
"php": "^7.4 || ^8.0",
|
||||
"psr/event-dispatcher": "^1.0",
|
||||
"symfony/deprecation-contracts": "^2.1 || ^3.0",
|
||||
"symfony/polyfill-php80": "^1.16"
|
||||
},
|
||||
"require-dev": {
|
||||
"cebe/markdown": "^1.0",
|
||||
"commonmark/cmark": "0.31.1",
|
||||
"commonmark/commonmark.js": "0.31.1",
|
||||
"composer/package-versions-deprecated": "^1.8",
|
||||
"embed/embed": "^4.4",
|
||||
"erusev/parsedown": "^1.0",
|
||||
"ext-json": "*",
|
||||
"github/gfm": "0.29.0",
|
||||
"michelf/php-markdown": "^1.4 || ^2.0",
|
||||
"nyholm/psr7": "^1.5",
|
||||
"phpstan/phpstan": "^1.8.2",
|
||||
"phpunit/phpunit": "^9.5.21 || ^10.5.9 || ^11.0.0",
|
||||
"scrutinizer/ocular": "^1.8.1",
|
||||
"symfony/finder": "^5.3 | ^6.0 | ^7.0",
|
||||
"symfony/process": "^5.4 | ^6.0 | ^7.0",
|
||||
"symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0",
|
||||
"unleashedtech/php-coding-standard": "^3.1.1",
|
||||
"vimeo/psalm": "^4.24.0 || ^5.0.0 || ^6.0.0"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/yaml": "v2.3+ required if using the Front Matter extension"
|
||||
},
|
||||
"time": "2025-07-20T12:47:49+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "2.8-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"League\\CommonMark\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Colin O'Dell",
|
||||
"email": "colinodell@gmail.com",
|
||||
"homepage": "https://www.colinodell.com",
|
||||
"role": "Lead Developer"
|
||||
}
|
||||
],
|
||||
"description": "Highly-extensible PHP Markdown parser which fully supports the CommonMark spec and GitHub-Flavored Markdown (GFM)",
|
||||
"homepage": "https://commonmark.thephpleague.com",
|
||||
"keywords": [
|
||||
"commonmark",
|
||||
"flavored",
|
||||
"gfm",
|
||||
"github",
|
||||
"github-flavored",
|
||||
"markdown",
|
||||
"md",
|
||||
"parser"
|
||||
],
|
||||
"support": {
|
||||
"docs": "https://commonmark.thephpleague.com/",
|
||||
"forum": "https://github.com/thephpleague/commonmark/discussions",
|
||||
"issues": "https://github.com/thephpleague/commonmark/issues",
|
||||
"rss": "https://github.com/thephpleague/commonmark/releases.atom",
|
||||
"source": "https://github.com/thephpleague/commonmark"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://www.colinodell.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://www.paypal.me/colinpodell/10.00",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/colinodell",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/league/commonmark",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"install-path": "../league/commonmark"
|
||||
},
|
||||
{
|
||||
"name": "league/config",
|
||||
"version": "v1.2.0",
|
||||
"version_normalized": "1.2.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/config.git",
|
||||
"reference": "754b3604fb2984c71f4af4a9cbe7b57f346ec1f3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/config/zipball/754b3604fb2984c71f4af4a9cbe7b57f346ec1f3",
|
||||
"reference": "754b3604fb2984c71f4af4a9cbe7b57f346ec1f3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"dflydev/dot-access-data": "^3.0.1",
|
||||
"nette/schema": "^1.2",
|
||||
"php": "^7.4 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^1.8.2",
|
||||
"phpunit/phpunit": "^9.5.5",
|
||||
"scrutinizer/ocular": "^1.8.1",
|
||||
"unleashedtech/php-coding-standard": "^3.1",
|
||||
"vimeo/psalm": "^4.7.3"
|
||||
},
|
||||
"time": "2022-12-11T20:36:23+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.2-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"League\\Config\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Colin O'Dell",
|
||||
"email": "colinodell@gmail.com",
|
||||
"homepage": "https://www.colinodell.com",
|
||||
"role": "Lead Developer"
|
||||
}
|
||||
],
|
||||
"description": "Define configuration arrays with strict schemas and access values with dot notation",
|
||||
"homepage": "https://config.thephpleague.com",
|
||||
"keywords": [
|
||||
"array",
|
||||
"config",
|
||||
"configuration",
|
||||
"dot",
|
||||
"dot-access",
|
||||
"nested",
|
||||
"schema"
|
||||
],
|
||||
"support": {
|
||||
"docs": "https://config.thephpleague.com/",
|
||||
"issues": "https://github.com/thephpleague/config/issues",
|
||||
"rss": "https://github.com/thephpleague/config/releases.atom",
|
||||
"source": "https://github.com/thephpleague/config"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://www.colinodell.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://www.paypal.me/colinpodell/10.00",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/colinodell",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"install-path": "../league/config"
|
||||
},
|
||||
{
|
||||
"name": "mustache/mustache",
|
||||
"version": "v3.0.0",
|
||||
@ -55,6 +328,376 @@
|
||||
"source": "https://github.com/bobthecow/mustache.php/tree/v3.0.0"
|
||||
},
|
||||
"install-path": "../mustache/mustache"
|
||||
},
|
||||
{
|
||||
"name": "nette/schema",
|
||||
"version": "v1.3.3",
|
||||
"version_normalized": "1.3.3.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nette/schema.git",
|
||||
"reference": "2befc2f42d7c715fd9d95efc31b1081e5d765004"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nette/schema/zipball/2befc2f42d7c715fd9d95efc31b1081e5d765004",
|
||||
"reference": "2befc2f42d7c715fd9d95efc31b1081e5d765004",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"nette/utils": "^4.0",
|
||||
"php": "8.1 - 8.5"
|
||||
},
|
||||
"require-dev": {
|
||||
"nette/tester": "^2.5.2",
|
||||
"phpstan/phpstan-nette": "^2.0@stable",
|
||||
"tracy/tracy": "^2.8"
|
||||
},
|
||||
"time": "2025-10-30T22:57:59+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.3-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Nette\\": "src"
|
||||
},
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause",
|
||||
"GPL-2.0-only",
|
||||
"GPL-3.0-only"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "David Grudl",
|
||||
"homepage": "https://davidgrudl.com"
|
||||
},
|
||||
{
|
||||
"name": "Nette Community",
|
||||
"homepage": "https://nette.org/contributors"
|
||||
}
|
||||
],
|
||||
"description": "📐 Nette Schema: validating data structures against a given Schema.",
|
||||
"homepage": "https://nette.org",
|
||||
"keywords": [
|
||||
"config",
|
||||
"nette"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/nette/schema/issues",
|
||||
"source": "https://github.com/nette/schema/tree/v1.3.3"
|
||||
},
|
||||
"install-path": "../nette/schema"
|
||||
},
|
||||
{
|
||||
"name": "nette/utils",
|
||||
"version": "v4.0.8",
|
||||
"version_normalized": "4.0.8.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nette/utils.git",
|
||||
"reference": "c930ca4e3cf4f17dcfb03037703679d2396d2ede"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nette/utils/zipball/c930ca4e3cf4f17dcfb03037703679d2396d2ede",
|
||||
"reference": "c930ca4e3cf4f17dcfb03037703679d2396d2ede",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "8.0 - 8.5"
|
||||
},
|
||||
"conflict": {
|
||||
"nette/finder": "<3",
|
||||
"nette/schema": "<1.2.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"jetbrains/phpstorm-attributes": "^1.2",
|
||||
"nette/tester": "^2.5",
|
||||
"phpstan/phpstan-nette": "^2.0@stable",
|
||||
"tracy/tracy": "^2.9"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-gd": "to use Image",
|
||||
"ext-iconv": "to use Strings::webalize(), toAscii(), chr() and reverse()",
|
||||
"ext-intl": "to use Strings::webalize(), toAscii(), normalize() and compare()",
|
||||
"ext-json": "to use Nette\\Utils\\Json",
|
||||
"ext-mbstring": "to use Strings::lower() etc...",
|
||||
"ext-tokenizer": "to use Nette\\Utils\\Reflection::getUseStatements()"
|
||||
},
|
||||
"time": "2025-08-06T21:43:34+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "4.0-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Nette\\": "src"
|
||||
},
|
||||
"classmap": [
|
||||
"src/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause",
|
||||
"GPL-2.0-only",
|
||||
"GPL-3.0-only"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "David Grudl",
|
||||
"homepage": "https://davidgrudl.com"
|
||||
},
|
||||
{
|
||||
"name": "Nette Community",
|
||||
"homepage": "https://nette.org/contributors"
|
||||
}
|
||||
],
|
||||
"description": "🛠 Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.",
|
||||
"homepage": "https://nette.org",
|
||||
"keywords": [
|
||||
"array",
|
||||
"core",
|
||||
"datetime",
|
||||
"images",
|
||||
"json",
|
||||
"nette",
|
||||
"paginator",
|
||||
"password",
|
||||
"slugify",
|
||||
"string",
|
||||
"unicode",
|
||||
"utf-8",
|
||||
"utility",
|
||||
"validation"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/nette/utils/issues",
|
||||
"source": "https://github.com/nette/utils/tree/v4.0.8"
|
||||
},
|
||||
"install-path": "../nette/utils"
|
||||
},
|
||||
{
|
||||
"name": "psr/event-dispatcher",
|
||||
"version": "1.0.0",
|
||||
"version_normalized": "1.0.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/event-dispatcher.git",
|
||||
"reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0",
|
||||
"reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2.0"
|
||||
},
|
||||
"time": "2019-01-08T18:20:26+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\EventDispatcher\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Standard interfaces for event handling.",
|
||||
"keywords": [
|
||||
"events",
|
||||
"psr",
|
||||
"psr-14"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/php-fig/event-dispatcher/issues",
|
||||
"source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0"
|
||||
},
|
||||
"install-path": "../psr/event-dispatcher"
|
||||
},
|
||||
{
|
||||
"name": "symfony/deprecation-contracts",
|
||||
"version": "v3.6.0",
|
||||
"version_normalized": "3.6.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/deprecation-contracts.git",
|
||||
"reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62",
|
||||
"reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.1"
|
||||
},
|
||||
"time": "2024-09-25T14:21:43+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"url": "https://github.com/symfony/contracts",
|
||||
"name": "symfony/contracts"
|
||||
},
|
||||
"branch-alias": {
|
||||
"dev-main": "3.6-dev"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"function.php"
|
||||
]
|
||||
},
|
||||
"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": "A generic function and convention to trigger deprecation notices",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.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"
|
||||
}
|
||||
],
|
||||
"install-path": "../symfony/deprecation-contracts"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php80",
|
||||
"version": "v1.33.0",
|
||||
"version_normalized": "1.33.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php80.git",
|
||||
"reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/0cc9dd0f17f61d8131e7df6b84bd344899fe2608",
|
||||
"reference": "0cc9dd0f17f61d8131e7df6b84bd344899fe2608",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2"
|
||||
},
|
||||
"time": "2025-01-02T08:10:11+00:00",
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"thanks": {
|
||||
"url": "https://github.com/symfony/polyfill",
|
||||
"name": "symfony/polyfill"
|
||||
}
|
||||
},
|
||||
"installation-source": "dist",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Symfony\\Polyfill\\Php80\\": ""
|
||||
},
|
||||
"classmap": [
|
||||
"Resources/stubs"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ion Bazan",
|
||||
"email": "ion.bazan@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
|
||||
"homepage": "https://symfony.com",
|
||||
"keywords": [
|
||||
"compatibility",
|
||||
"polyfill",
|
||||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/polyfill-php80/tree/v1.33.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/nicolas-grekas",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"install-path": "../symfony/polyfill-php80"
|
||||
}
|
||||
],
|
||||
"dev": true,
|
||||
|
||||
76
vendor/composer/installed.php
vendored
76
vendor/composer/installed.php
vendored
@ -3,7 +3,7 @@
|
||||
'name' => '__root__',
|
||||
'pretty_version' => 'dev-main',
|
||||
'version' => 'dev-main',
|
||||
'reference' => '0f1c7234b8e213130e58252a3aa58a58290c959e',
|
||||
'reference' => 'dfe2df141ba6e64e5425699cd553fb9b7e6d6193',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
@ -13,12 +13,39 @@
|
||||
'__root__' => array(
|
||||
'pretty_version' => 'dev-main',
|
||||
'version' => 'dev-main',
|
||||
'reference' => '0f1c7234b8e213130e58252a3aa58a58290c959e',
|
||||
'reference' => 'dfe2df141ba6e64e5425699cd553fb9b7e6d6193',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'dflydev/dot-access-data' => array(
|
||||
'pretty_version' => 'v3.0.3',
|
||||
'version' => '3.0.3.0',
|
||||
'reference' => 'a23a2bf4f31d3518f3ecb38660c95715dfead60f',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../dflydev/dot-access-data',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'league/commonmark' => array(
|
||||
'pretty_version' => '2.7.1',
|
||||
'version' => '2.7.1.0',
|
||||
'reference' => '10732241927d3971d28e7ea7b5712721fa2296ca',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../league/commonmark',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'league/config' => array(
|
||||
'pretty_version' => 'v1.2.0',
|
||||
'version' => '1.2.0.0',
|
||||
'reference' => '754b3604fb2984c71f4af4a9cbe7b57f346ec1f3',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../league/config',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'mustache/mustache' => array(
|
||||
'pretty_version' => 'v3.0.0',
|
||||
'version' => '3.0.0.0',
|
||||
@ -28,5 +55,50 @@
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'nette/schema' => array(
|
||||
'pretty_version' => 'v1.3.3',
|
||||
'version' => '1.3.3.0',
|
||||
'reference' => '2befc2f42d7c715fd9d95efc31b1081e5d765004',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../nette/schema',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'nette/utils' => array(
|
||||
'pretty_version' => 'v4.0.8',
|
||||
'version' => '4.0.8.0',
|
||||
'reference' => 'c930ca4e3cf4f17dcfb03037703679d2396d2ede',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../nette/utils',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'psr/event-dispatcher' => array(
|
||||
'pretty_version' => '1.0.0',
|
||||
'version' => '1.0.0.0',
|
||||
'reference' => 'dbefd12671e8a14ec7f180cab83036ed26714bb0',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../psr/event-dispatcher',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/deprecation-contracts' => array(
|
||||
'pretty_version' => 'v3.6.0',
|
||||
'version' => '3.6.0.0',
|
||||
'reference' => '63afe740e99a13ba87ec199bb07bbdee937a5b62',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/deprecation-contracts',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/polyfill-php80' => array(
|
||||
'pretty_version' => 'v1.33.0',
|
||||
'version' => '1.33.0.0',
|
||||
'reference' => '0cc9dd0f17f61d8131e7df6b84bd344899fe2608',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/polyfill-php80',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
4
vendor/composer/platform_check.php
vendored
4
vendor/composer/platform_check.php
vendored
@ -4,8 +4,8 @@
|
||||
|
||||
$issues = array();
|
||||
|
||||
if (!(PHP_VERSION_ID >= 50600)) {
|
||||
$issues[] = 'Your Composer dependencies require a PHP version ">= 5.6.0". You are running ' . PHP_VERSION . '.';
|
||||
if (!(PHP_VERSION_ID >= 80100)) {
|
||||
$issues[] = 'Your Composer dependencies require a PHP version ">= 8.1.0". You are running ' . PHP_VERSION . '.';
|
||||
}
|
||||
|
||||
if ($issues) {
|
||||
|
||||
74
vendor/dflydev/dot-access-data/CHANGELOG.md
vendored
Normal file
74
vendor/dflydev/dot-access-data/CHANGELOG.md
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [3.0.3] - 2024-07-08
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed PHP 8.4 deprecation notices (#47)
|
||||
|
||||
## [3.0.2] - 2022-10-27
|
||||
|
||||
### Fixed
|
||||
|
||||
- Added missing return types to docblocks (#44, #45)
|
||||
|
||||
## [3.0.1] - 2021-08-13
|
||||
|
||||
### Added
|
||||
|
||||
- Adds ReturnTypeWillChange to suppress PHP 8.1 warnings (#40)
|
||||
|
||||
## [3.0.0] - 2021-01-01
|
||||
|
||||
### Added
|
||||
- Added support for both `.` and `/`-delimited key paths (#24)
|
||||
- Added parameter and return types to everything; enabled strict type checks (#18)
|
||||
- Added new exception classes to better identify certain types of errors (#20)
|
||||
- `Data` now implements `ArrayAccess` (#17)
|
||||
- Added ability to merge non-associative array values (#31, #32)
|
||||
|
||||
### Changed
|
||||
- All thrown exceptions are now instances or subclasses of `DataException` (#20)
|
||||
- Calling `get()` on a missing key path without providing a default will throw a `MissingPathException` instead of returning `null` (#29)
|
||||
- Bumped supported PHP versions to 7.1 - 8.x (#18)
|
||||
|
||||
### Fixed
|
||||
- Fixed incorrect merging of array values into string values (#32)
|
||||
- Fixed `get()` method behaving as if keys with `null` values didn't exist
|
||||
|
||||
## [2.0.0] - 2017-12-21
|
||||
|
||||
### Changed
|
||||
- Bumped supported PHP versions to 7.0 - 7.4 (#12)
|
||||
- Switched to PSR-4 autoloading
|
||||
|
||||
## [1.1.0] - 2017-01-20
|
||||
|
||||
### Added
|
||||
- Added new `has()` method to check for the existence of the given key (#4, #7)
|
||||
|
||||
## [1.0.1] - 2015-08-12
|
||||
|
||||
### Added
|
||||
- Added new optional `$default` parameter to the `get()` method (#2)
|
||||
|
||||
## [1.0.0] - 2012-07-17
|
||||
|
||||
**Initial release!**
|
||||
|
||||
[Unreleased]: https://github.com/dflydev/dflydev-dot-access-data/compare/v3.0.3...main
|
||||
[3.0.3]: https://github.com/dflydev/dflydev-dot-access-data/compare/v3.0.2...v3.0.3
|
||||
[3.0.2]: https://github.com/dflydev/dflydev-dot-access-data/compare/v3.0.1...v3.0.2
|
||||
[3.0.1]: https://github.com/dflydev/dflydev-dot-access-data/compare/v3.0.0...v3.0.1
|
||||
[3.0.0]: https://github.com/dflydev/dflydev-dot-access-data/compare/v2.0.0...v3.0.0
|
||||
[2.0.0]: https://github.com/dflydev/dflydev-dot-access-data/compare/v1.1.0...v2.0.0
|
||||
[1.1.0]: https://github.com/dflydev/dflydev-dot-access-data/compare/v1.0.1...v1.1.0
|
||||
[1.0.1]: https://github.com/dflydev/dflydev-dot-access-data/compare/v1.0.0...v1.0.1
|
||||
[1.0.0]: https://github.com/dflydev/dflydev-dot-access-data/releases/tag/v1.0.0
|
||||
19
vendor/dflydev/dot-access-data/LICENSE
vendored
Normal file
19
vendor/dflydev/dot-access-data/LICENSE
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (c) 2012 Dragonfly Development Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
158
vendor/dflydev/dot-access-data/README.md
vendored
Normal file
158
vendor/dflydev/dot-access-data/README.md
vendored
Normal file
@ -0,0 +1,158 @@
|
||||
Dot Access Data
|
||||
===============
|
||||
|
||||
[](https://packagist.org/packages/dflydev/dot-access-data)
|
||||
[](https://packagist.org/packages/dflydev/dot-access-data)
|
||||
[](LICENSE)
|
||||
[](https://github.com/dflydev/dflydev-dot-access-data/actions?query=workflow%3ATests+branch%3Amain)
|
||||
[](https://scrutinizer-ci.com/g/dflydev/dflydev-dot-access-data/code-structure/)
|
||||
[](https://scrutinizer-ci.com/g/dflydev/dflydev-dot-access-data)
|
||||
|
||||
Given a deep data structure, access data by dot notation.
|
||||
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
* PHP (7.1+)
|
||||
|
||||
> For PHP (5.3+) please refer to version `1.0`.
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Abstract example:
|
||||
|
||||
```php
|
||||
use Dflydev\DotAccessData\Data;
|
||||
|
||||
$data = new Data;
|
||||
|
||||
$data->set('a.b.c', 'C');
|
||||
$data->set('a.b.d', 'D1');
|
||||
$data->append('a.b.d', 'D2');
|
||||
$data->set('a.b.e', ['E0', 'E1', 'E2']);
|
||||
|
||||
// C
|
||||
$data->get('a.b.c');
|
||||
|
||||
// ['D1', 'D2']
|
||||
$data->get('a.b.d');
|
||||
|
||||
// ['E0', 'E1', 'E2']
|
||||
$data->get('a.b.e');
|
||||
|
||||
// true
|
||||
$data->has('a.b.c');
|
||||
|
||||
// false
|
||||
$data->has('a.b.d.j');
|
||||
|
||||
|
||||
// 'some-default-value'
|
||||
$data->get('some.path.that.does.not.exist', 'some-default-value');
|
||||
|
||||
// throws a MissingPathException because no default was given
|
||||
$data->get('some.path.that.does.not.exist');
|
||||
```
|
||||
|
||||
A more concrete example:
|
||||
|
||||
```php
|
||||
use Dflydev\DotAccessData\Data;
|
||||
|
||||
$data = new Data([
|
||||
'hosts' => [
|
||||
'hewey' => [
|
||||
'username' => 'hman',
|
||||
'password' => 'HPASS',
|
||||
'roles' => ['web'],
|
||||
],
|
||||
'dewey' => [
|
||||
'username' => 'dman',
|
||||
'password' => 'D---S',
|
||||
'roles' => ['web', 'db'],
|
||||
'nick' => 'dewey dman',
|
||||
],
|
||||
'lewey' => [
|
||||
'username' => 'lman',
|
||||
'password' => 'LP@$$',
|
||||
'roles' => ['db'],
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
// hman
|
||||
$username = $data->get('hosts.hewey.username');
|
||||
// HPASS
|
||||
$password = $data->get('hosts.hewey.password');
|
||||
// ['web']
|
||||
$roles = $data->get('hosts.hewey.roles');
|
||||
// dewey dman
|
||||
$nick = $data->get('hosts.dewey.nick');
|
||||
// Unknown
|
||||
$nick = $data->get('hosts.lewey.nick', 'Unknown');
|
||||
|
||||
// DataInterface instance
|
||||
$dewey = $data->getData('hosts.dewey');
|
||||
// dman
|
||||
$username = $dewey->get('username');
|
||||
// D---S
|
||||
$password = $dewey->get('password');
|
||||
// ['web', 'db']
|
||||
$roles = $dewey->get('roles');
|
||||
|
||||
// No more lewey
|
||||
$data->remove('hosts.lewey');
|
||||
|
||||
// Add DB to hewey's roles
|
||||
$data->append('hosts.hewey.roles', 'db');
|
||||
|
||||
$data->set('hosts.april', [
|
||||
'username' => 'aman',
|
||||
'password' => '@---S',
|
||||
'roles' => ['web'],
|
||||
]);
|
||||
|
||||
// Check if a key exists (true to this case)
|
||||
$hasKey = $data->has('hosts.dewey.username');
|
||||
```
|
||||
|
||||
`Data` may be used as an array, since it implements `ArrayAccess` interface:
|
||||
|
||||
```php
|
||||
// Get
|
||||
$data->get('name') === $data['name']; // true
|
||||
|
||||
$data['name'] = 'Dewey';
|
||||
// is equivalent to
|
||||
$data->set($name, 'Dewey');
|
||||
|
||||
isset($data['name']) === $data->has('name');
|
||||
|
||||
// Remove key
|
||||
unset($data['name']);
|
||||
```
|
||||
|
||||
`/` can also be used as a path delimiter:
|
||||
|
||||
```php
|
||||
$data->set('a/b/c', 'd');
|
||||
echo $data->get('a/b/c'); // "d"
|
||||
|
||||
$data->get('a/b/c') === $data->get('a.b.c'); // true
|
||||
```
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
This library is licensed under the MIT License - see the LICENSE file
|
||||
for details.
|
||||
|
||||
|
||||
Community
|
||||
---------
|
||||
|
||||
If you have questions or want to help out, join us in the
|
||||
[#dflydev](irc://irc.freenode.net/#dflydev) channel on irc.freenode.net.
|
||||
67
vendor/dflydev/dot-access-data/composer.json
vendored
Normal file
67
vendor/dflydev/dot-access-data/composer.json
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
{
|
||||
"name": "dflydev/dot-access-data",
|
||||
"type": "library",
|
||||
"description": "Given a deep data structure, access data by dot notation.",
|
||||
"homepage": "https://github.com/dflydev/dflydev-dot-access-data",
|
||||
"keywords": ["dot", "access", "data", "notation"],
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Dragonfly Development Inc.",
|
||||
"email": "info@dflydev.com",
|
||||
"homepage": "http://dflydev.com"
|
||||
},
|
||||
{
|
||||
"name": "Beau Simensen",
|
||||
"email": "beau@dflydev.com",
|
||||
"homepage": "http://beausimensen.com"
|
||||
},
|
||||
{
|
||||
"name": "Carlos Frutos",
|
||||
"email": "carlos@kiwing.it",
|
||||
"homepage": "https://github.com/cfrutos"
|
||||
},
|
||||
{
|
||||
"name": "Colin O'Dell",
|
||||
"email": "colinodell@gmail.com",
|
||||
"homepage": "https://www.colinodell.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpstan/phpstan": "^0.12.42",
|
||||
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.3",
|
||||
"scrutinizer/ocular": "1.6.0",
|
||||
"squizlabs/php_codesniffer": "^3.5",
|
||||
"vimeo/psalm": "^4.0.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Dflydev\\DotAccessData\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Dflydev\\DotAccessData\\": "tests/"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "3.x-dev"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"phpcs": "phpcs",
|
||||
"phpstan": "phpstan analyse",
|
||||
"phpunit": "phpunit --no-coverage",
|
||||
"psalm": "psalm",
|
||||
"test": [
|
||||
"@phpcs",
|
||||
"@phpstan",
|
||||
"@psalm",
|
||||
"@phpunit"
|
||||
]
|
||||
}
|
||||
}
|
||||
286
vendor/dflydev/dot-access-data/src/Data.php
vendored
Normal file
286
vendor/dflydev/dot-access-data/src/Data.php
vendored
Normal file
@ -0,0 +1,286 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is a part of dflydev/dot-access-data.
|
||||
*
|
||||
* (c) Dragonfly Development Inc.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Dflydev\DotAccessData;
|
||||
|
||||
use ArrayAccess;
|
||||
use Dflydev\DotAccessData\Exception\DataException;
|
||||
use Dflydev\DotAccessData\Exception\InvalidPathException;
|
||||
use Dflydev\DotAccessData\Exception\MissingPathException;
|
||||
|
||||
/**
|
||||
* @implements ArrayAccess<string, mixed>
|
||||
*/
|
||||
class Data implements DataInterface, ArrayAccess
|
||||
{
|
||||
private const DELIMITERS = ['.', '/'];
|
||||
|
||||
/**
|
||||
* Internal representation of data data
|
||||
*
|
||||
* @var array<string, mixed>
|
||||
*/
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array<string, mixed> $data
|
||||
*/
|
||||
public function __construct(array $data = [])
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function append(string $key, $value = null): void
|
||||
{
|
||||
$currentValue =& $this->data;
|
||||
$keyPath = self::keyToPathArray($key);
|
||||
|
||||
$endKey = array_pop($keyPath);
|
||||
foreach ($keyPath as $currentKey) {
|
||||
if (! isset($currentValue[$currentKey])) {
|
||||
$currentValue[$currentKey] = [];
|
||||
}
|
||||
$currentValue =& $currentValue[$currentKey];
|
||||
}
|
||||
|
||||
if (!isset($currentValue[$endKey])) {
|
||||
$currentValue[$endKey] = [];
|
||||
}
|
||||
|
||||
if (!is_array($currentValue[$endKey])) {
|
||||
// Promote this key to an array.
|
||||
// TODO: Is this really what we want to do?
|
||||
$currentValue[$endKey] = [$currentValue[$endKey]];
|
||||
}
|
||||
|
||||
$currentValue[$endKey][] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function set(string $key, $value = null): void
|
||||
{
|
||||
$currentValue =& $this->data;
|
||||
$keyPath = self::keyToPathArray($key);
|
||||
|
||||
$endKey = array_pop($keyPath);
|
||||
foreach ($keyPath as $currentKey) {
|
||||
if (!isset($currentValue[$currentKey])) {
|
||||
$currentValue[$currentKey] = [];
|
||||
}
|
||||
if (!is_array($currentValue[$currentKey])) {
|
||||
throw new DataException(sprintf('Key path "%s" within "%s" cannot be indexed into (is not an array)', $currentKey, self::formatPath($key)));
|
||||
}
|
||||
$currentValue =& $currentValue[$currentKey];
|
||||
}
|
||||
$currentValue[$endKey] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function remove(string $key): void
|
||||
{
|
||||
$currentValue =& $this->data;
|
||||
$keyPath = self::keyToPathArray($key);
|
||||
|
||||
$endKey = array_pop($keyPath);
|
||||
foreach ($keyPath as $currentKey) {
|
||||
if (!isset($currentValue[$currentKey])) {
|
||||
return;
|
||||
}
|
||||
$currentValue =& $currentValue[$currentKey];
|
||||
}
|
||||
unset($currentValue[$endKey]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @psalm-mutation-free
|
||||
*/
|
||||
public function get(string $key, $default = null)
|
||||
{
|
||||
/** @psalm-suppress ImpureFunctionCall */
|
||||
$hasDefault = \func_num_args() > 1;
|
||||
|
||||
$currentValue = $this->data;
|
||||
$keyPath = self::keyToPathArray($key);
|
||||
|
||||
foreach ($keyPath as $currentKey) {
|
||||
if (!is_array($currentValue) || !array_key_exists($currentKey, $currentValue)) {
|
||||
if ($hasDefault) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
throw new MissingPathException($key, sprintf('No data exists at the given path: "%s"', self::formatPath($keyPath)));
|
||||
}
|
||||
|
||||
$currentValue = $currentValue[$currentKey];
|
||||
}
|
||||
|
||||
return $currentValue === null ? $default : $currentValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @psalm-mutation-free
|
||||
*/
|
||||
public function has(string $key): bool
|
||||
{
|
||||
$currentValue = $this->data;
|
||||
|
||||
foreach (self::keyToPathArray($key) as $currentKey) {
|
||||
if (
|
||||
!is_array($currentValue) ||
|
||||
!array_key_exists($currentKey, $currentValue)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
$currentValue = $currentValue[$currentKey];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @psalm-mutation-free
|
||||
*/
|
||||
public function getData(string $key): DataInterface
|
||||
{
|
||||
$value = $this->get($key);
|
||||
if (is_array($value) && Util::isAssoc($value)) {
|
||||
return new Data($value);
|
||||
}
|
||||
|
||||
throw new DataException(sprintf('Value at "%s" could not be represented as a DataInterface', self::formatPath($key)));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function import(array $data, int $mode = self::REPLACE): void
|
||||
{
|
||||
$this->data = Util::mergeAssocArray($this->data, $data, $mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function importData(DataInterface $data, int $mode = self::REPLACE): void
|
||||
{
|
||||
$this->import($data->export(), $mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @psalm-mutation-free
|
||||
*/
|
||||
public function export(): array
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetExists($key)
|
||||
{
|
||||
return $this->has($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetGet($key)
|
||||
{
|
||||
return $this->get($key, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetSet($key, $value)
|
||||
{
|
||||
$this->set($key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function offsetUnset($key)
|
||||
{
|
||||
$this->remove($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
*
|
||||
* @return string[]
|
||||
*
|
||||
* @psalm-return non-empty-list<string>
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
protected static function keyToPathArray(string $path): array
|
||||
{
|
||||
if (\strlen($path) === 0) {
|
||||
throw new InvalidPathException('Path cannot be an empty string');
|
||||
}
|
||||
|
||||
$path = \str_replace(self::DELIMITERS, '.', $path);
|
||||
|
||||
return \explode('.', $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|string[] $path
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
protected static function formatPath($path): string
|
||||
{
|
||||
if (is_string($path)) {
|
||||
$path = self::keyToPathArray($path);
|
||||
}
|
||||
|
||||
return implode(' » ', $path);
|
||||
}
|
||||
}
|
||||
131
vendor/dflydev/dot-access-data/src/DataInterface.php
vendored
Normal file
131
vendor/dflydev/dot-access-data/src/DataInterface.php
vendored
Normal file
@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is a part of dflydev/dot-access-data.
|
||||
*
|
||||
* (c) Dragonfly Development Inc.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Dflydev\DotAccessData;
|
||||
|
||||
use Dflydev\DotAccessData\Exception\DataException;
|
||||
use Dflydev\DotAccessData\Exception\InvalidPathException;
|
||||
|
||||
interface DataInterface
|
||||
{
|
||||
public const PRESERVE = 0;
|
||||
public const REPLACE = 1;
|
||||
public const MERGE = 2;
|
||||
|
||||
/**
|
||||
* Append a value to a key (assumes key refers to an array value)
|
||||
*
|
||||
* If the key does not yet exist it will be created.
|
||||
* If the key references a non-array it's existing contents will be added into a new array before appending the new value.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*
|
||||
* @throws InvalidPathException if the given key is empty
|
||||
*/
|
||||
public function append(string $key, $value = null): void;
|
||||
|
||||
/**
|
||||
* Set a value for a key
|
||||
*
|
||||
* If the key does not yet exist it will be created.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*
|
||||
* @throws InvalidPathException if the given key is empty
|
||||
* @throws DataException if the given key does not target an array
|
||||
*/
|
||||
public function set(string $key, $value = null): void;
|
||||
|
||||
/**
|
||||
* Remove a key
|
||||
*
|
||||
* No exception will be thrown if the key does not exist
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @throws InvalidPathException if the given key is empty
|
||||
*/
|
||||
public function remove(string $key): void;
|
||||
|
||||
/**
|
||||
* Get the raw value for a key
|
||||
*
|
||||
* If the key does not exist, an optional default value can be returned instead.
|
||||
* If no default is provided then an exception will be thrown instead.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws InvalidPathException if the given key is empty
|
||||
* @throws InvalidPathException if the given key does not exist and no default value was given
|
||||
*
|
||||
* @psalm-mutation-free
|
||||
*/
|
||||
public function get(string $key, $default = null);
|
||||
|
||||
/**
|
||||
* Check if the key exists
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @throws InvalidPathException if the given key is empty
|
||||
*
|
||||
* @psalm-mutation-free
|
||||
*/
|
||||
public function has(string $key): bool;
|
||||
|
||||
/**
|
||||
* Get a data instance for a key
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @return DataInterface
|
||||
*
|
||||
* @throws InvalidPathException if the given key is empty
|
||||
* @throws DataException if the given key does not reference an array
|
||||
*
|
||||
* @psalm-mutation-free
|
||||
*/
|
||||
public function getData(string $key): DataInterface;
|
||||
|
||||
/**
|
||||
* Import data into existing data
|
||||
*
|
||||
* @param array<string, mixed> $data
|
||||
* @param self::PRESERVE|self::REPLACE|self::MERGE $mode
|
||||
*/
|
||||
public function import(array $data, int $mode = self::REPLACE): void;
|
||||
|
||||
/**
|
||||
* Import data from an external data into existing data
|
||||
*
|
||||
* @param DataInterface $data
|
||||
* @param self::PRESERVE|self::REPLACE|self::MERGE $mode
|
||||
*/
|
||||
public function importData(DataInterface $data, int $mode = self::REPLACE): void;
|
||||
|
||||
/**
|
||||
* Export data as raw data
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*
|
||||
* @psalm-mutation-free
|
||||
*/
|
||||
public function export(): array;
|
||||
}
|
||||
21
vendor/dflydev/dot-access-data/src/Exception/DataException.php
vendored
Normal file
21
vendor/dflydev/dot-access-data/src/Exception/DataException.php
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is a part of dflydev/dot-access-data.
|
||||
*
|
||||
* (c) Dragonfly Development Inc.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Dflydev\DotAccessData\Exception;
|
||||
|
||||
/**
|
||||
* Base runtime exception type thrown by this library
|
||||
*/
|
||||
class DataException extends \RuntimeException
|
||||
{
|
||||
}
|
||||
21
vendor/dflydev/dot-access-data/src/Exception/InvalidPathException.php
vendored
Normal file
21
vendor/dflydev/dot-access-data/src/Exception/InvalidPathException.php
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is a part of dflydev/dot-access-data.
|
||||
*
|
||||
* (c) Dragonfly Development Inc.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Dflydev\DotAccessData\Exception;
|
||||
|
||||
/**
|
||||
* Thrown when trying to access an invalid path in the data array
|
||||
*/
|
||||
class InvalidPathException extends DataException
|
||||
{
|
||||
}
|
||||
37
vendor/dflydev/dot-access-data/src/Exception/MissingPathException.php
vendored
Normal file
37
vendor/dflydev/dot-access-data/src/Exception/MissingPathException.php
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is a part of dflydev/dot-access-data.
|
||||
*
|
||||
* (c) Dragonfly Development Inc.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Dflydev\DotAccessData\Exception;
|
||||
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Thrown when trying to access a path that does not exist
|
||||
*/
|
||||
class MissingPathException extends DataException
|
||||
{
|
||||
/** @var string */
|
||||
protected $path;
|
||||
|
||||
public function __construct(string $path, string $message = '', int $code = 0, ?Throwable $previous = null)
|
||||
{
|
||||
$this->path = $path;
|
||||
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
|
||||
public function getPath(): string
|
||||
{
|
||||
return $this->path;
|
||||
}
|
||||
}
|
||||
78
vendor/dflydev/dot-access-data/src/Util.php
vendored
Normal file
78
vendor/dflydev/dot-access-data/src/Util.php
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is a part of dflydev/dot-access-data.
|
||||
*
|
||||
* (c) Dragonfly Development Inc.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Dflydev\DotAccessData;
|
||||
|
||||
class Util
|
||||
{
|
||||
/**
|
||||
* Test if array is an associative array
|
||||
*
|
||||
* Note that this function will return true if an array is empty. Meaning
|
||||
* empty arrays will be treated as if they are associative arrays.
|
||||
*
|
||||
* @param array<mixed> $arr
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function isAssoc(array $arr): bool
|
||||
{
|
||||
return !count($arr) || count(array_filter(array_keys($arr), 'is_string')) == count($arr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge contents from one associtative array to another
|
||||
*
|
||||
* @param mixed $to
|
||||
* @param mixed $from
|
||||
* @param DataInterface::PRESERVE|DataInterface::REPLACE|DataInterface::MERGE $mode
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function mergeAssocArray($to, $from, int $mode = DataInterface::REPLACE)
|
||||
{
|
||||
if ($mode === DataInterface::MERGE && self::isList($to) && self::isList($from)) {
|
||||
return array_merge($to, $from);
|
||||
}
|
||||
|
||||
if (is_array($from) && is_array($to)) {
|
||||
foreach ($from as $k => $v) {
|
||||
if (!isset($to[$k])) {
|
||||
$to[$k] = $v;
|
||||
} else {
|
||||
$to[$k] = self::mergeAssocArray($to[$k], $v, $mode);
|
||||
}
|
||||
}
|
||||
|
||||
return $to;
|
||||
}
|
||||
|
||||
return $mode === DataInterface::PRESERVE ? $to : $from;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
private static function isList($value): bool
|
||||
{
|
||||
return is_array($value) && array_values($value) === $value;
|
||||
}
|
||||
}
|
||||
106
vendor/league/commonmark/.phpstorm.meta.php
vendored
Normal file
106
vendor/league/commonmark/.phpstorm.meta.php
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PHPSTORM_META
|
||||
{
|
||||
expectedArguments(\League\CommonMark\Util\HtmlElement::__construct(), 0, 'a', 'abbr', 'address', 'area', 'article', 'aside', 'audio', 'b', 'base', 'bdi', 'bdo', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'cite', 'code', 'col', 'colgroup', 'data', 'datalist', 'dd', 'del', 'details', 'dfn', 'dialog', 'div', 'dl', 'dt', 'em', 'embed', 'fieldset', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'iframe', 'img', 'input', 'ins', 'kdb', 'keygen', 'label', 'legend', 'li', 'link', 'main', 'map', 'mark', 'menu', 'menuitem', 'meta', 'meter', 'nav', 'noscript', 'object', 'ol', 'optgroup', 'option', 'output', 'p', 'param', 'pre', 'progress', 'q', 's', 'samp', 'script', 'section', 'select', 'small', 'source', 'span', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'u', 'ul', 'var', 'video', 'wbr');
|
||||
|
||||
expectedArguments(\League\CommonMark\Extension\CommonMark\Node\Block\Heading::__construct(), 0, 1, 2, 3, 4, 5, 6);
|
||||
expectedReturnValues(\League\CommonMark\Extension\CommonMark\Node\Block\Heading::getLevel(), 1, 2, 3, 4, 5, 6);
|
||||
|
||||
registerArgumentsSet('league_commonmark_htmlblock_types', \League\CommonMark\Extension\CommonMark\Node\Block\HtmlBlock::TYPE_1_CODE_CONTAINER, \League\CommonMark\Extension\CommonMark\Node\Block\HtmlBlock::TYPE_2_COMMENT, \League\CommonMark\Extension\CommonMark\Node\Block\HtmlBlock::TYPE_3, \League\CommonMark\Extension\CommonMark\Node\Block\HtmlBlock::TYPE_4, \League\CommonMark\Extension\CommonMark\Node\Block\HtmlBlock::TYPE_5_CDATA, \League\CommonMark\Extension\CommonMark\Node\Block\HtmlBlock::TYPE_6_BLOCK_ELEMENT, \League\CommonMark\Extension\CommonMark\Node\Block\HtmlBlock::TYPE_7_MISC_ELEMENT);
|
||||
expectedArguments(\League\CommonMark\Extension\CommonMark\Node\Block\HtmlBlock::__construct(), 0, argumentsSet('league_commonmark_htmlblock_types'));
|
||||
expectedArguments(\League\CommonMark\Extension\CommonMark\Node\Block\HtmlBlock::setType(), 0, argumentsSet('league_commonmark_htmlblock_types'));
|
||||
expectedReturnValues(\League\CommonMark\Extension\CommonMark\Node\Block\HtmlBlock::getType(), argumentsSet('league_commonmark_htmlblock_types'));
|
||||
expectedArguments(\League\CommonMark\Util\RegexHelper::getHtmlBlockOpenRegex(), 0, argumentsSet('league_commonmark_htmlblock_types'));
|
||||
expectedArguments(\League\CommonMark\Util\RegexHelper::getHtmlBlockCloseRegex(), 0, argumentsSet('league_commonmark_htmlblock_types'));
|
||||
|
||||
registerArgumentsSet('league_commonmark_newline_types', \League\CommonMark\Node\Inline\Newline::HARDBREAK, \League\CommonMark\Node\Inline\Newline::SOFTBREAK);
|
||||
expectedArguments(\League\CommonMark\Node\Inline\Newline::__construct(), 0, argumentsSet('league_commonmark_newline_types'));
|
||||
expectedReturnValues(\League\CommonMark\Node\Inline\Newline::getType(), argumentsSet('league_commonmark_newline_types'));
|
||||
|
||||
registerArgumentsSet('league_commonmark_options',
|
||||
'html_input',
|
||||
'allow_unsafe_links',
|
||||
'max_nesting_level',
|
||||
'max_delimiters_per_line',
|
||||
'renderer',
|
||||
'renderer/block_separator',
|
||||
'renderer/inner_separator',
|
||||
'renderer/soft_break',
|
||||
'commonmark',
|
||||
'commonmark/enable_em',
|
||||
'commonmark/enable_strong',
|
||||
'commonmark/use_asterisk',
|
||||
'commonmark/use_underscore',
|
||||
'commonmark/unordered_list_markers',
|
||||
'disallowed_raw_html',
|
||||
'disallowed_raw_html/disallowed_tags',
|
||||
'external_link',
|
||||
'external_link/html_class',
|
||||
'external_link/internal_hosts',
|
||||
'external_link/nofollow',
|
||||
'external_link/noopener',
|
||||
'external_link/noreferrer',
|
||||
'external_link/open_in_new_window',
|
||||
'footnote',
|
||||
'footnote/backref_class',
|
||||
'footnote/backref_symbol',
|
||||
'footnote/container_add_hr',
|
||||
'footnote/container_class',
|
||||
'footnote/ref_class',
|
||||
'footnote/ref_id_prefix',
|
||||
'footnote/footnote_class',
|
||||
'footnote/footnote_id_prefix',
|
||||
'heading_permalink',
|
||||
'heading_permalink/apply_id_to_heading',
|
||||
'heading_permalink/heading_class',
|
||||
'heading_permalink/html_class',
|
||||
'heading_permalink/fragment_prefix',
|
||||
'heading_permalink/id_prefix',
|
||||
'heading_permalink/inner_contents',
|
||||
'heading_permalink/insert',
|
||||
'heading_permalink/max_heading_level',
|
||||
'heading_permalink/min_heading_level',
|
||||
'heading_permalink/symbol',
|
||||
'heading_permalink/title',
|
||||
'mentions',
|
||||
'smartpunct/double_quote_closer',
|
||||
'smartpunct/double_quote_opener',
|
||||
'smartpunct/single_quote_closer',
|
||||
'smartpunct/single_quote_opener',
|
||||
'slug_normalizer',
|
||||
'slug_normalizer/instance',
|
||||
'slug_normalizer/max_length',
|
||||
'slug_normalizer/unique',
|
||||
'table',
|
||||
'table/wrap',
|
||||
'table/wrap/attributes',
|
||||
'table/wrap/enabled',
|
||||
'table/wrap/tag',
|
||||
'table/alignment_attributes',
|
||||
'table/alignment_attributes/left',
|
||||
'table/alignment_attributes/center',
|
||||
'table/alignment_attributes/right',
|
||||
'table/max_autocompleted_cells',
|
||||
'table_of_contents',
|
||||
'table_of_contents/html_class',
|
||||
'table_of_contents/max_heading_level',
|
||||
'table_of_contents/min_heading_level',
|
||||
'table_of_contents/normalize',
|
||||
'table_of_contents/placeholder',
|
||||
'table_of_contents/position',
|
||||
'table_of_contents/style',
|
||||
);
|
||||
expectedArguments(\League\Config\ConfigurationInterface::get(), 0, argumentsSet('league_commonmark_options'));
|
||||
expectedArguments(\League\Config\ConfigurationInterface::exists(), 0, argumentsSet('league_commonmark_options'));
|
||||
expectedArguments(\League\Config\MutableConfigurationInterface::set(), 0, argumentsSet('league_commonmark_options'));
|
||||
}
|
||||
756
vendor/league/commonmark/CHANGELOG.md
vendored
Normal file
756
vendor/league/commonmark/CHANGELOG.md
vendored
Normal file
@ -0,0 +1,756 @@
|
||||
# Change Log
|
||||
All notable changes to this project will be documented in this file.
|
||||
Updates should follow the [Keep a CHANGELOG](https://keepachangelog.com/) principles.
|
||||
|
||||
**Upgrading from 1.x?** See <https://commonmark.thephpleague.com/2.0/upgrading/> for additional information.
|
||||
|
||||
## [Unreleased][unreleased]
|
||||
|
||||
## [2.7.1] - 2025-07-20
|
||||
|
||||
### Changed
|
||||
- Optimized several regular expressions in `RegexHelper` to improve performance (#674, #1086)
|
||||
|
||||
### Fixed
|
||||
- `EmbedProcessor` no longer calls `updateEmbeds()` when there are no embeds to update (#1081)
|
||||
- Fixed missing `benchmark.php` CSV path validation for non-existent files (#1068, #1085)
|
||||
|
||||
## [2.7.0] - 2025-05-05
|
||||
|
||||
This is a **security release** to address a potential cross-site scripting (XSS) vulnerability when using the `AttributesExtension` with untrusted user input.
|
||||
|
||||
### Added
|
||||
- Added `attributes/allow` config option to specify which attributes users are allowed to set on elements (default allows virtually all attributes)
|
||||
|
||||
### Changed
|
||||
- The `AttributesExtension` blocks all attributes starting with `on` unless explicitly allowed via the `attributes/allow` config option
|
||||
- The `allow_unsafe_links` option is now respected by the `AttributesExtension` when users specify `href` and `src` attributes
|
||||
|
||||
## [2.6.2] - 2025-04-18
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed Attributes extension parsing regression (#1071)
|
||||
|
||||
## [2.6.1] - 2024-12-29
|
||||
|
||||
### Fixed
|
||||
|
||||
- Rendered list items should only add newlines around block-level children (#1059, #1061)
|
||||
|
||||
## [2.6.0] - 2024-12-07
|
||||
|
||||
This is a **security release** to address potential denial of service attacks when parsing specially crafted,
|
||||
malicious input from untrusted sources (like user input).
|
||||
|
||||
### Added
|
||||
|
||||
- Added `max_delimiters_per_line` config option to prevent denial of service attacks when parsing malicious input
|
||||
- Added `table/max_autocompleted_cells` config option to prevent denial of service attacks when parsing large tables
|
||||
- The `AttributesExtension` now supports attributes without values (#985, #986)
|
||||
- The `AutolinkExtension` exposes two new configuration options to override the default behavior (#969, #987):
|
||||
- `autolink/allowed_protocols` - an array of protocols to allow autolinking for
|
||||
- `autolink/default_protocol` - the default protocol to use when none is specified
|
||||
- Added `RegexHelper::isWhitespace()` method to check if a given character is an ASCII whitespace character
|
||||
- Added `CacheableDelimiterProcessorInterface` to ensure linear complexity for dynamic delimiter processing
|
||||
- Added `Bracket` delimiter type to optimize bracket parsing
|
||||
|
||||
### Changed
|
||||
|
||||
- `[` and `]` are no longer added as `Delimiter` objects on the stack; a new `Bracket` type with its own stack is used instead
|
||||
- `UrlAutolinkParser` no longer parses URLs with more than 127 subdomains
|
||||
- Expanded reference links can no longer exceed 100kb, or the size of the input document (whichever is greater)
|
||||
- Delimiters should always provide a non-null value via `DelimiterInterface::getIndex()`
|
||||
- We'll attempt to infer the index based on surrounding delimiters where possible
|
||||
- The `DelimiterStack` now accepts integer positions for any `$stackBottom` argument
|
||||
- Several small performance optimizations
|
||||
|
||||
## [2.5.3] - 2024-08-16
|
||||
|
||||
### Changed
|
||||
|
||||
- Made compatible with CommonMark spec 0.31.1, including:
|
||||
- Remove `source`, add `search` to list of recognized block tags
|
||||
|
||||
## [2.5.2] - 2024-08-14
|
||||
|
||||
### Changed
|
||||
|
||||
- Boolean attributes now require an explicit `true` value (#1040)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed regression where text could be misinterpreted as an attribute (#1040)
|
||||
|
||||
## [2.5.1] - 2024-07-24
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed attribute parsing incorrectly parsing mustache-like syntax (#1035)
|
||||
- Fixed incorrect `Table` start line numbers (#1037)
|
||||
|
||||
## [2.5.0] - 2024-07-22
|
||||
|
||||
### Added
|
||||
|
||||
- The `AttributesExtension` now supports attributes without values (#985, #986)
|
||||
- The `AutolinkExtension` exposes two new configuration options to override the default behavior (#969, #987):
|
||||
- `autolink/allowed_protocols` - an array of protocols to allow autolinking for
|
||||
- `autolink/default_protocol` - the default protocol to use when none is specified
|
||||
|
||||
### Changed
|
||||
|
||||
- Made compatible with CommonMark spec 0.31.0, including:
|
||||
- Allow closing fence to be followed by tabs
|
||||
- Remove restrictive limitation on inline comments
|
||||
- Unicode symbols now treated like punctuation (for purposes of flankingness)
|
||||
- Trailing tabs on the last line of indented code blocks will be excluded
|
||||
- Improved HTML comment matching
|
||||
- `Paragraph`s only containing link reference definitions will be kept in the AST until the `Document` is finalized
|
||||
- (These were previously removed immediately after parsing the `Paragraph`)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed list tightness not being determined properly in some edge cases
|
||||
- Fixed incorrect ending line numbers for several block types in various scenarios
|
||||
- Fixed lowercase inline HTML declarations not being accepted
|
||||
|
||||
## [2.4.4] - 2024-07-22
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed SmartPunct extension changing already-formatted quotation marks (#1030)
|
||||
|
||||
## [2.4.3] - 2024-07-22
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed the Attributes extension not supporting CSS level 3 selectors (#1013)
|
||||
- Fixed `UrlAutolinkParser` incorrectly parsing text containing `www` anywhere before an autolink (#1025)
|
||||
|
||||
|
||||
## [2.4.2] - 2024-02-02
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed declaration parser being too strict
|
||||
- `FencedCodeRenderer`: don't add `language-` to class if already prefixed
|
||||
|
||||
### Deprecated
|
||||
|
||||
- Returning dynamic values from `DelimiterProcessorInterface::getDelimiterUse()` is deprecated
|
||||
- You should instead implement `CacheableDelimiterProcessorInterface` to help the engine perform caching to avoid performance issues.
|
||||
- Failing to set a delimiter's index (or returning `null` from `DelimiterInterface::getIndex()`) is deprecated and will not be supported in 3.0
|
||||
- Deprecated `DelimiterInterface::isActive()` and `DelimiterInterface::setActive()`, as these are no longer used by the engine
|
||||
- Deprecated `DelimiterStack::removeEarlierMatches()` and `DelimiterStack::searchByCharacter()`, as these are no longer used by the engine
|
||||
- Passing a `DelimiterInterface` as the `$stackBottom` argument to `DelimiterStack::processDelimiters()` or `::removeAll()` is deprecated and will not be supported in 3.0; pass the integer position instead.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed NUL characters not being replaced in the input
|
||||
- Fixed quadratic complexity parsing unclosed inline links
|
||||
- Fixed quadratic complexity parsing emphasis and strikethrough delimiters
|
||||
- Fixed issue where having 500,000+ delimiters could trigger a [known segmentation fault issue in PHP's garbage collection](https://bugs.php.net/bug.php?id=68606)
|
||||
- Fixed quadratic complexity deactivating link openers
|
||||
- Fixed quadratic complexity parsing long backtick code spans with no matching closers
|
||||
- Fixed catastrophic backtracking when parsing link labels/titles
|
||||
|
||||
## [2.4.1] - 2023-08-30
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed `ExternalLinkProcessor` not fully disabling the `rel` attribute when configured to do so (#992)
|
||||
|
||||
## [2.4.0] - 2023-03-24
|
||||
|
||||
### Added
|
||||
|
||||
- Added generic `CommonMarkException` marker interface for all exceptions thrown by the library
|
||||
- Added several new specific exception types implementing that marker interface:
|
||||
- `AlreadyInitializedException`
|
||||
- `InvalidArgumentException`
|
||||
- `IOException`
|
||||
- `LogicException`
|
||||
- `MissingDependencyException`
|
||||
- `NoMatchingRendererException`
|
||||
- `ParserLogicException`
|
||||
- Added more configuration options to the Heading Permalinks extension (#939):
|
||||
- `heading_permalink/apply_id_to_heading` - When `true`, the `id` attribute will be applied to the heading element itself instead of the `<a>` tag
|
||||
- `heading_permalink/heading_class` - class to apply to the heading element
|
||||
- `heading_permalink/insert` - now accepts `none` to prevent the creation of the `<a>` link
|
||||
- Added new `table/alignment_attributes` configuration option to control how table cell alignment is rendered (#959)
|
||||
|
||||
### Changed
|
||||
|
||||
- Change several thrown exceptions from `RuntimeException` to `LogicException` (or something extending it), including:
|
||||
- `CallbackGenerator`s that fail to set a URL or return an expected value
|
||||
- `MarkdownParser` when deactivating the last block parser or attempting to get an active block parser when they've all been closed
|
||||
- Adding items to an already-initialized `Environment`
|
||||
- Rendering a `Node` when no renderer has been registered for it
|
||||
- `HeadingPermalinkProcessor` now throws `InvalidConfigurationException` instead of `RuntimeException` when invalid config values are given.
|
||||
- `HtmlElement::setAttribute()` no longer requires the second parameter for boolean attributes
|
||||
- Several small micro-optimizations
|
||||
- Changed Strikethrough to only allow 1 or 2 tildes per the updated GFM spec
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed inaccurate `@throws` docblocks throughout the codebase, including `ConverterInterface`, `MarkdownConverter`, and `MarkdownConverterInterface`.
|
||||
- These previously suggested that only `\RuntimeException`s were thrown, which was inaccurate as `\LogicException`s were also possible.
|
||||
|
||||
## [2.3.9] - 2023-02-15
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed autolink extension not detecting some URIs with underscores (#956)
|
||||
|
||||
## [2.3.8] - 2022-12-10
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed parsing issues when `mb_internal_encoding()` is set to something other than `UTF-8` (#951)
|
||||
|
||||
## [2.3.7] - 2022-11-03
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed `TaskListItemMarkerRenderer` not including HTML attributes set on the node by other extensions (#947)
|
||||
|
||||
## [2.3.6] - 2022-10-30
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed unquoted attribute parsing when closing curly brace is followed by certain characters (like a `.`) (#943)
|
||||
|
||||
## [2.3.5] - 2022-07-29
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed error using `InlineParserEngine` when no inline parsers are registered in the `Environment` (#908)
|
||||
|
||||
## [2.3.4] - 2022-07-17
|
||||
|
||||
### Changed
|
||||
|
||||
- Made a number of small tweaks to the embed extension's parsing behavior to fix #898:
|
||||
- Changed `EmbedStartParser` to always capture embed-like lines in container blocks, regardless of parent block type
|
||||
- Changed `EmbedProcessor` to also remove `Embed` blocks that aren't direct children of the `Document`
|
||||
- Increased the priority of `EmbedProcessor` to `1010`
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed `EmbedExtension` not parsing embeds following a list block (#898)
|
||||
|
||||
## [2.3.3] - 2022-06-07
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed `DomainFilteringAdapter` not reindexing the embed list (#884, #885)
|
||||
|
||||
## [2.3.2] - 2022-06-03
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed FootnoteExtension stripping extra characters from tab-indented footnotes (#881)
|
||||
|
||||
## [2.2.5] - 2022-06-03
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed FootnoteExtension stripping extra characters from tab-indented footnotes (#881)
|
||||
|
||||
## [2.3.1] - 2022-05-14
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed AutolinkExtension not ignoring trailing strikethrough syntax (#867)
|
||||
|
||||
## [2.2.4] - 2022-05-14
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed AutolinkExtension not ignoring trailing strikethrough syntax (#867)
|
||||
|
||||
## [2.3.0] - 2022-04-07
|
||||
|
||||
### Added
|
||||
|
||||
- Added new `EmbedExtension` (#805)
|
||||
- Added `DocumentRendererInterface` as a replacement for the now-deprecated `MarkdownRendererInterface`
|
||||
|
||||
### Deprecated
|
||||
|
||||
- Deprecated `MarkdownRendererInterface`; use `DocumentRendererInterface` instead
|
||||
|
||||
## [2.2.3] - 2022-02-26
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed front matter parsing with Windows line endings (#821)
|
||||
|
||||
## [2.1.3] - 2022-02-26
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed front matter parsing with Windows line endings (#821)
|
||||
|
||||
## [2.0.4] - 2022-02-26
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed front matter parsing with Windows line endings (#821)
|
||||
|
||||
## [2.2.2] - 2022-02-13
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed double-escaping of image alt text (#806, #810)
|
||||
- Fixed Psalm typehints for event class names
|
||||
|
||||
## [2.2.1] - 2022-01-25
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed `symfony/deprecation-contracts` constraint
|
||||
|
||||
### Removed
|
||||
|
||||
- Removed deprecation trigger from `MarkdownConverterInterface` to reduce noise
|
||||
|
||||
## [2.2.0] - 2022-01-22
|
||||
|
||||
### Added
|
||||
|
||||
- Added new `ConverterInterface`
|
||||
- Added new `MarkdownToXmlConverter` class
|
||||
- Added new `HtmlDecorator` class which can wrap existing renderers with additional HTML tags
|
||||
- Added new `table/wrap` config to apply an optional wrapping/container element around a table (#780)
|
||||
|
||||
### Changed
|
||||
|
||||
- `HtmlElement` contents can now consist of any `Stringable`, not just `HtmlElement` and `string`
|
||||
|
||||
### Deprecated
|
||||
|
||||
- Deprecated `MarkdownConverterInterface` and its `convertToHtml()` method; use `ConverterInterface` and `convert()` instead
|
||||
|
||||
## [2.1.2] - 2022-02-13
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed double-escaping of image alt text (#806, #810)
|
||||
- Fixed Psalm typehints for event class names
|
||||
|
||||
## [2.1.1] - 2022-01-02
|
||||
|
||||
### Added
|
||||
|
||||
- Added missing return type to `Environment::dispatch()` to fix deprecation warning (#778)
|
||||
|
||||
## [2.1.0] - 2021-12-05
|
||||
|
||||
### Added
|
||||
|
||||
- Added support for ext-yaml in FrontMatterExtension (#715)
|
||||
- Added support for symfony/yaml v6.0 in FrontMatterExtension (#739)
|
||||
- Added new `heading_permalink/aria_hidden` config option (#741)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed PHP 8.1 deprecation warning (#759, #762)
|
||||
|
||||
## [2.0.3] - 2022-02-13
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed double-escaping of image alt text (#806, #810)
|
||||
- Fixed Psalm typehints for event class names
|
||||
|
||||
## [2.0.2] - 2021-08-14
|
||||
|
||||
### Changed
|
||||
|
||||
- Bumped minimum version of league/config to support PHP 8.1
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed ability to register block parsers that identify lines starting with letters (#706)
|
||||
|
||||
## [2.0.1] - 2021-07-31
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed nested autolinks (#689)
|
||||
- Fixed description lists being parsed incorrectly (#692)
|
||||
- Fixed Table of Contents not respecting Heading Permalink prefixes (#690)
|
||||
|
||||
## [2.0.0] - 2021-07-24
|
||||
|
||||
No changes were introduced since the previous RC2 release.
|
||||
See all entries below for a list of changes between 1.x and 2.0.
|
||||
|
||||
## [2.0.0-rc2] - 2021-07-17
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed Mentions inside of links creating nested links against the spec's rules (#688)
|
||||
|
||||
## [2.0.0-rc1] - 2021-07-10
|
||||
|
||||
No changes were introduced since the previous release.
|
||||
|
||||
## [2.0.0-beta3] - 2021-07-03
|
||||
|
||||
### Changed
|
||||
|
||||
- Any leading UTF-8 BOM will be stripped from the input
|
||||
- The `getEnvironment()` method of `CommonMarkConverter` and `GithubFlavoredMarkdownConverter` will always return the concrete, configurable `Environment` for upgrading convenience
|
||||
- Optimized AST iteration
|
||||
- Lots of small micro-optimizations
|
||||
|
||||
## [2.0.0-beta2] - 2021-06-27
|
||||
|
||||
### Added
|
||||
|
||||
- Added new `Node::iterator()` method and `NodeIterator` class for faster AST iteration (#683, #684)
|
||||
|
||||
### Changed
|
||||
|
||||
- Made compatible with CommonMark spec 0.30.0
|
||||
- Optimized link label parsing
|
||||
- Optimized AST iteration for a 50% performance boost in some event listeners (#683, #684)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed processing instructions with EOLs
|
||||
- Fixed case-insensitive matching for HTML tag types
|
||||
- Fixed type 7 HTML blocks incorrectly interrupting lazy paragraphs
|
||||
- Fixed newlines in reference labels not collapsing into spaces
|
||||
- Fixed link label normalization with escaped newlines
|
||||
- Fixed unnecessary AST iteration when no default attributes are configured
|
||||
|
||||
## [2.0.0-beta1] - 2021-06-20
|
||||
|
||||
### Added
|
||||
|
||||
- **Added three new extensions:**
|
||||
- `FrontMatterExtension` ([see documentation](https://commonmark.thephpleague.com/extensions/front-matter/))
|
||||
- `DescriptionListExtension` ([see documentation](https://commonmark.thephpleague.com/extensions/description-lists/))
|
||||
- `DefaultAttributesExtension` ([see documentation](https://commonmark.thephpleague.com/extensions/default-attributes/))
|
||||
- **Added new `XmlRenderer` to simplify AST debugging** ([see documentation](https://commonmark.thephpleague.com/xml/)) (#431)
|
||||
- **Added the ability to configure disallowed raw HTML tags** (#507)
|
||||
- **Added the ability for Mentions to use multiple characters for their symbol** (#514, #550)
|
||||
- **Added the ability to delegate event dispatching to PSR-14 compliant event dispatcher libraries**
|
||||
- **Added new configuration options:**
|
||||
- Added `heading_permalink/min_heading_level` and `heading_permalink/max_heading_level` options to control which headings get permalinks (#519)
|
||||
- Added `heading_permalink/fragment_prefix` to allow customizing the URL fragment prefix (#602)
|
||||
- Added `footnote/backref_symbol` option for customizing backreference link appearance (#522)
|
||||
- Added `slug_normalizer/max_length` option to control the maximum length of generated URL slugs
|
||||
- Added `slug_normalizer/unique` option to control whether unique slugs should be generated per-document or per-environment
|
||||
- **Added purity markers throughout the codebase** (verified with Psalm)
|
||||
- Added `Query` class to simplify Node traversal when looking to take action on certain Nodes
|
||||
- Added new `HtmlFilter` and `StringContainerHelper` utility classes
|
||||
- Added new `AbstractBlockContinueParser` class to simplify the creation of custom block parsers
|
||||
- Added several new classes and interfaces:
|
||||
- `BlockContinue`
|
||||
- `BlockContinueParserInterface`
|
||||
- `BlockContinueParserWithInlinesInterface`
|
||||
- `BlockStart`
|
||||
- `BlockStartParserInterface`
|
||||
- `ChildNodeRendererInterface`
|
||||
- `ConfigurableExtensionInterface`
|
||||
- `CursorState`
|
||||
- `DashParser` (extracted from `PunctuationParser`)
|
||||
- `DelimiterParser`
|
||||
- `DocumentBlockParser`
|
||||
- `DocumentPreRenderEvent`
|
||||
- `DocumentRenderedEvent`
|
||||
- `EllipsesParser` (extracted from `PunctuationParser`)
|
||||
- `ExpressionInterface`
|
||||
- `FallbackNodeXmlRenderer`
|
||||
- `InlineParserEngineInterface`
|
||||
- `InlineParserMatch`
|
||||
- `MarkdownParserState`
|
||||
- `MarkdownParserStateInterface`
|
||||
- `MarkdownRendererInterface`
|
||||
- `Query`
|
||||
- `RawMarkupContainerInterface`
|
||||
- `ReferenceableInterface`
|
||||
- `RenderedContent`
|
||||
- `RenderedContentInterface`
|
||||
- `ReplaceUnpairedQuotesListener`
|
||||
- `SpecReader`
|
||||
- `TableOfContentsRenderer`
|
||||
- `UniqueSlugNormalizer`
|
||||
- `UniqueSlugNormalizerInterface`
|
||||
- `XmlRenderer`
|
||||
- `XmlNodeRendererInterface`
|
||||
- Added several new methods:
|
||||
- `Cursor::getCurrentCharacter()`
|
||||
- `Environment::createDefaultConfiguration()`
|
||||
- `Environment::setEventDispatcher()`
|
||||
- `EnvironmentInterface::getExtensions()`
|
||||
- `EnvironmentInterface::getInlineParsers()`
|
||||
- `EnvironmentInterface::getSlugNormalizer()`
|
||||
- `FencedCode::setInfo()`
|
||||
- `Heading::setLevel()`
|
||||
- `HtmlRenderer::renderDocument()`
|
||||
- `InlineParserContext::getFullMatch()`
|
||||
- `InlineParserContext::getFullMatchLength()`
|
||||
- `InlineParserContext::getMatches()`
|
||||
- `InlineParserContext::getSubMatches()`
|
||||
- `LinkParserHelper::parsePartialLinkLabel()`
|
||||
- `LinkParserHelper::parsePartialLinkTitle()`
|
||||
- `Node::assertInstanceOf()`
|
||||
- `RegexHelper::isLetter()`
|
||||
- `StringContainerInterface::setLiteral()`
|
||||
- `TableCell::getType()`
|
||||
- `TableCell::setType()`
|
||||
- `TableCell::getAlign()`
|
||||
- `TableCell::setAlign()`
|
||||
|
||||
### Changed
|
||||
|
||||
- **Changed the converter return type**
|
||||
- `CommonMarkConverter::convertToHtml()` now returns an instance of `RenderedContentInterface`. This can be cast to a string for backward compatibility with 1.x.
|
||||
- **Table of Contents items are no longer wrapped with `<p>` tags** (#613)
|
||||
- **Heading Permalinks now link to element IDs instead of using `name` attributes** (#602)
|
||||
- **Heading Permalink IDs and URL fragments now have a `content` prefix by default** (#602)
|
||||
- **Changes to configuration options:**
|
||||
- `enable_em` has been renamed to `commonmark/enable_em`
|
||||
- `enable_strong` has been renamed to `commonmark/enable_strong`
|
||||
- `use_asterisk` has been renamed to `commonmark/use_asterisk`
|
||||
- `use_underscore` has been renamed to `commonmark/use_underscore`
|
||||
- `unordered_list_markers` has been renamed to `commonmark/unordered_list_markers`
|
||||
- `mentions/*/symbol` has been renamed to `mentions/*/prefix`
|
||||
- `mentions/*/regex` has been renamed to `mentions/*/pattern` and requires partial regular expressions (without delimiters or flags)
|
||||
- `max_nesting_level` now defaults to `PHP_INT_MAX` and no longer supports floats
|
||||
- `heading_permalink/slug_normalizer` has been renamed to `slug_normalizer/instance`
|
||||
- **Event dispatching is now fully PSR-14 compliant**
|
||||
- **Moved and renamed several classes** - [see the full list here](https://commonmark.thephpleague.com/2.0/upgrading/#classesnamespaces-renamed)
|
||||
- The `HeadingPermalinkExtension` and `FootnoteExtension` were modified to ensure they never produce a slug which conflicts with slugs created by the other extension
|
||||
- `SlugNormalizer::normalizer()` now supports optional prefixes and max length options passed in via the `$context` argument
|
||||
- The `AbstractBlock::$data` and `AbstractInline::$data` arrays were replaced with a `Data` array-like object on the base `Node` class
|
||||
- **Implemented a new approach to block parsing.** This was a massive change, so here are the highlights:
|
||||
- Functionality previously found in block parsers and node elements has moved to block parser factories and block parsers, respectively ([more details](https://commonmark.thephpleague.com/2.0/upgrading/#new-block-parsing-approach))
|
||||
- `ConfigurableEnvironmentInterface::addBlockParser()` is now `EnvironmentBuilderInterface::addBlockParserFactory()`
|
||||
- `ReferenceParser` was re-implemented and works completely different than before
|
||||
- The paragraph parser no longer needs to be added manually to the environment
|
||||
- **Implemented a new approach to inline parsing** where parsers can now specify longer strings or regular expressions they want to parse (instead of just single characters):
|
||||
- `InlineParserInterface::getCharacters()` is now `getMatchDefinition()` and returns an instance of `InlineParserMatch`
|
||||
- `InlineParserContext::__construct()` now requires the contents to be provided as a `Cursor` instead of a `string`
|
||||
- **Implemented delimiter parsing as a special type of inline parser** (via the new `DelimiterParser` class)
|
||||
- **Changed block and inline rendering to use common methods and interfaces**
|
||||
- `BlockRendererInterface` and `InlineRendererInterface` were replaced by `NodeRendererInterface` with slightly different parameters. All core renderers now implement this interface.
|
||||
- `ConfigurableEnvironmentInterface::addBlockRenderer()` and `addInlineRenderer()` were combined into `EnvironmentBuilderInterface::addRenderer()`
|
||||
- `EnvironmentInterface::getBlockRenderersForClass()` and `getInlineRenderersForClass()` are now just `getRenderersForClass()`
|
||||
- **Completely refactored the Configuration implementation**
|
||||
- All configuration-specific classes have been moved into a new `league/config` package with a new namespace
|
||||
- `Configuration` objects must now be configured with a schema and all options must match that schema - arbitrary keys are no longer permitted
|
||||
- `Configuration::__construct()` no longer accepts the default configuration values - use `Configuration::merge()` instead
|
||||
- `ConfigurationInterface` now only contains a `get(string $key)`; this method no longer allows arbitrary default values to be returned if the option is missing
|
||||
- `ConfigurableEnvironmentInterface` was renamed to `EnvironmentBuilderInterface`
|
||||
- `ExtensionInterface::register()` now requires an `EnvironmentBuilderInterface` param instead of `ConfigurableEnvironmentInterface`
|
||||
- **Added missing return types to virtually every class and interface method**
|
||||
- Re-implemented the GFM Autolink extension using the new inline parser approach instead of document processors
|
||||
- `EmailAutolinkProcessor` is now `EmailAutolinkParser`
|
||||
- `UrlAutolinkProcessor` is now `UrlAutolinkParser`
|
||||
- `HtmlElement` can now properly handle array (i.e. `class`) and boolean (i.e. `checked`) attribute values
|
||||
- `HtmlElement` automatically flattens any attributes with array values into space-separated strings, removing duplicate entries
|
||||
- Combined separate classes/interfaces into one:
|
||||
- `DisallowedRawHtmlRenderer` replaces `DisallowedRawHtmlBlockRenderer` and `DisallowedRawHtmlInlineRenderer`
|
||||
- `NodeRendererInterface` replaces `BlockRendererInterface` and `InlineRendererInterface`
|
||||
- Renamed the following methods:
|
||||
- `Environment` and `ConfigurableEnvironmentInterface`:
|
||||
- `addBlockParser()` is now `addBlockStartParser()`
|
||||
- `ReferenceMap` and `ReferenceMapInterface`:
|
||||
- `addReference()` is now `add()`
|
||||
- `getReference()` is now `get()`
|
||||
- `listReferences()` is now `getIterator()`
|
||||
- Various node (block/inline) classes:
|
||||
- `getContent()` is now `getLiteral()`
|
||||
- `setContent()` is now `setLiteral()`
|
||||
- Moved and renamed the following constants:
|
||||
- `EnvironmentInterface::HTML_INPUT_ALLOW` is now `HtmlFilter::ALLOW`
|
||||
- `EnvironmentInterface::HTML_INPUT_ESCAPE` is now `HtmlFilter::ESCAPE`
|
||||
- `EnvironmentInterface::HTML_INPUT_STRIP` is now `HtmlFilter::STRIP`
|
||||
- `TableCell::TYPE_HEAD` is now `TableCell::TYPE_HEADER`
|
||||
- `TableCell::TYPE_BODY` is now `TableCell::TYPE_DATA`
|
||||
- Changed the visibility of the following properties:
|
||||
- `AttributesInline::$attributes` is now `private`
|
||||
- `AttributesInline::$block` is now `private`
|
||||
- `TableCell::$align` is now `private`
|
||||
- `TableCell::$type` is now `private`
|
||||
- `TableSection::$type` is now `private`
|
||||
- Several methods which previously returned `$this` now return `void`
|
||||
- `Delimiter::setPrevious()`
|
||||
- `Node::replaceChildren()`
|
||||
- `Context::setTip()`
|
||||
- `Context::setContainer()`
|
||||
- `Context::setBlocksParsed()`
|
||||
- `AbstractStringContainer::setContent()`
|
||||
- `AbstractWebResource::setUrl()`
|
||||
- Several classes are now marked `final`:
|
||||
- `ArrayCollection`
|
||||
- `Emphasis`
|
||||
- `FencedCode`
|
||||
- `Heading`
|
||||
- `HtmlBlock`
|
||||
- `HtmlElement`
|
||||
- `HtmlInline`
|
||||
- `IndentedCode`
|
||||
- `Newline`
|
||||
- `Strikethrough`
|
||||
- `Strong`
|
||||
- `Text`
|
||||
- `Heading` nodes no longer directly contain a copy of their inner text
|
||||
- `StringContainerInterface` can now be used for inlines, not just blocks
|
||||
- `ArrayCollection` only supports integer keys
|
||||
- `HtmlElement` now implements `Stringable`
|
||||
- `Cursor::saveState()` and `Cursor::restoreState()` now use `CursorState` objects instead of arrays
|
||||
- `NodeWalker::next()` now enters, traverses any children, and leaves all elements which may have children (basically all blocks plus any inlines with children). Previously, it only did this for elements explicitly marked as "containers".
|
||||
- `InvalidOptionException` was removed
|
||||
- Anything with a `getReference(): ReferenceInterface` method now implements `ReferencableInterface`
|
||||
- The `SmartPunct` extension now replaces all unpaired `Quote` elements with `Text` elements towards the end of parsing, making the `QuoteRenderer` unnecessary
|
||||
- Several changes made to the Footnote extension:
|
||||
- Footnote identifiers can no longer contain spaces
|
||||
- Anonymous footnotes can now span subsequent lines
|
||||
- Footnotes can now contain multiple lines of content, including sub-blocks, by indenting them
|
||||
- Footnote event listeners now have numbered priorities (but still execute in the same order)
|
||||
- Footnotes must now be separated from previous content by a blank line
|
||||
- The line numbers (keys) returned via `MarkdownInput::getLines()` now start at 1 instead of 0
|
||||
- `DelimiterProcessorCollectionInterface` now extends `Countable`
|
||||
- `RegexHelper::PARTIAL_` constants must always be used in case-insensitive contexts
|
||||
- `HeadingPermalinkProcessor` no longer accepts text normalizers via the constructor - these must be provided via configuration instead
|
||||
- Blocks which can't contain inlines will no longer be asked to render inlines
|
||||
- `AnonymousFootnoteRefParser` and `HeadingPermalinkProcessor` now implement `EnvironmentAwareInterface` instead of `ConfigurationAwareInterface`
|
||||
- The second argument to `TextNormalizerInterface::normalize()` must now be an array
|
||||
- The `title` attribute for `Link` and `Image` nodes is now stored using a dedicated property instead of stashing it in `$data`
|
||||
- `ListData::$delimiter` now returns either `ListBlock::DELIM_PERIOD` or `ListBlock::DELIM_PAREN` instead of the literal delimiter
|
||||
|
||||
### Fixed
|
||||
|
||||
- **Fixed parsing of footnotes without content**
|
||||
- **Fixed rendering of orphaned footnotes and footnote refs**
|
||||
- **Fixed some URL autolinks breaking too early** (#492)
|
||||
- Fixed `AbstractStringContainer` not actually being `abstract`
|
||||
|
||||
### Removed
|
||||
|
||||
- **Removed support for PHP 7.1, 7.2, and 7.3** (#625, #671)
|
||||
- **Removed all previously-deprecated functionality:**
|
||||
- Removed the ability to pass custom `Environment` instances into the `CommonMarkConverter` and `GithubFlavoredMarkdownConverter` constructors
|
||||
- Removed the `Converter` class and `ConverterInterface`
|
||||
- Removed the `bin/commonmark` script
|
||||
- Removed the `Html5Entities` utility class
|
||||
- Removed the `InlineMentionParser` (use `MentionParser` instead)
|
||||
- Removed `DefaultSlugGenerator` and `SlugGeneratorInterface` from the `Extension/HeadingPermalink/Slug` sub-namespace (use the new ones under `./SlugGenerator` instead)
|
||||
- Removed the following `ArrayCollection` methods:
|
||||
- `add()`
|
||||
- `set()`
|
||||
- `get()`
|
||||
- `remove()`
|
||||
- `isEmpty()`
|
||||
- `contains()`
|
||||
- `indexOf()`
|
||||
- `containsKey()`
|
||||
- `replaceWith()`
|
||||
- `removeGaps()`
|
||||
- Removed the `ConfigurableEnvironmentInterface::setConfig()` method
|
||||
- Removed the `ListBlock::TYPE_UNORDERED` constant
|
||||
- Removed the `CommonMarkConverter::VERSION` constant
|
||||
- Removed the `HeadingPermalinkRenderer::DEFAULT_INNER_CONTENTS` constant
|
||||
- Removed the `heading_permalink/inner_contents` configuration option
|
||||
- **Removed now-unused classes:**
|
||||
- `AbstractStringContainerBlock`
|
||||
- `BlockRendererInterface`
|
||||
- `Context`
|
||||
- `ContextInterface`
|
||||
- `Converter`
|
||||
- `ConverterInterface`
|
||||
- `InlineRendererInterface`
|
||||
- `PunctuationParser` (was split into two classes: `DashParser` and `EllipsesParser`)
|
||||
- `QuoteRenderer`
|
||||
- `UnmatchedBlockCloser`
|
||||
- Removed the following methods, properties, and constants:
|
||||
- `AbstractBlock::$open`
|
||||
- `AbstractBlock::$lastLineBlank`
|
||||
- `AbstractBlock::isContainer()`
|
||||
- `AbstractBlock::canContain()`
|
||||
- `AbstractBlock::isCode()`
|
||||
- `AbstractBlock::matchesNextLine()`
|
||||
- `AbstractBlock::endsWithBlankLine()`
|
||||
- `AbstractBlock::setLastLineBlank()`
|
||||
- `AbstractBlock::shouldLastLineBeBlank()`
|
||||
- `AbstractBlock::isOpen()`
|
||||
- `AbstractBlock::finalize()`
|
||||
- `AbstractBlock::getData()`
|
||||
- `AbstractInline::getData()`
|
||||
- `ConfigurableEnvironmentInterface::addBlockParser()`
|
||||
- `ConfigurableEnvironmentInterface::mergeConfig()`
|
||||
- `Delimiter::setCanClose()`
|
||||
- `EnvironmentInterface::getConfig()`
|
||||
- `EnvironmentInterface::getInlineParsersForCharacter()`
|
||||
- `EnvironmentInterface::getInlineParserCharacterRegex()`
|
||||
- `HtmlRenderer::renderBlock()`
|
||||
- `HtmlRenderer::renderBlocks()`
|
||||
- `HtmlRenderer::renderInline()`
|
||||
- `HtmlRenderer::renderInlines()`
|
||||
- `Node::isContainer()`
|
||||
- `RegexHelper::matchAll()` (use the new `matchFirst()` method instead)
|
||||
- `RegexHelper::REGEX_WHITESPACE`
|
||||
- Removed the second `$contents` argument from the `Heading` constructor
|
||||
|
||||
### Deprecated
|
||||
|
||||
**The following things have been deprecated and will not be supported in v3.0:**
|
||||
|
||||
- `Environment::mergeConfig()` (set configuration before instantiation instead)
|
||||
- `Environment::createCommonMarkEnvironment()` and `Environment::createGFMEnvironment()`
|
||||
- Alternative 1: Use `CommonMarkConverter` or `GithubFlavoredMarkdownConverter` if you don't need to customize the environment
|
||||
- Alternative 2: Instantiate a new `Environment` and add the necessary extensions yourself
|
||||
|
||||
[unreleased]: https://github.com/thephpleague/commonmark/compare/2.7.1...HEAD
|
||||
[2.7.1]: https://github.com/thephpleague/commonmark/compare/2.7.0...2.7.1
|
||||
[2.7.0]: https://github.com/thephpleague/commonmark/compare/2.6.2...2.7.0
|
||||
[2.6.2]: https://github.com/thephpleague/commonmark/compare/2.6.1...2.6.2
|
||||
[2.6.1]: https://github.com/thephpleague/commonmark/compare/2.6.0...2.6.1
|
||||
[2.6.0]: https://github.com/thephpleague/commonmark/compare/2.5.3...2.6.0
|
||||
[2.5.3]: https://github.com/thephpleague/commonmark/compare/2.5.2...2.5.3
|
||||
[2.5.2]: https://github.com/thephpleague/commonmark/compare/2.5.1...2.5.2
|
||||
[2.5.1]: https://github.com/thephpleague/commonmark/compare/2.5.0...2.5.1
|
||||
[2.5.0]: https://github.com/thephpleague/commonmark/compare/2.4.4...2.5.0
|
||||
[2.4.4]: https://github.com/thephpleague/commonmark/compare/2.4.3...2.4.4
|
||||
[2.4.3]: https://github.com/thephpleague/commonmark/compare/2.4.2...2.4.3
|
||||
[2.4.2]: https://github.com/thephpleague/commonmark/compare/2.4.1...2.4.2
|
||||
[2.4.1]: https://github.com/thephpleague/commonmark/compare/2.4.0...2.4.1
|
||||
[2.4.0]: https://github.com/thephpleague/commonmark/compare/2.3.9...2.4.0
|
||||
[2.3.9]: https://github.com/thephpleague/commonmark/compare/2.3.8...2.3.9
|
||||
[2.3.8]: https://github.com/thephpleague/commonmark/compare/2.3.7...2.3.8
|
||||
[2.3.7]: https://github.com/thephpleague/commonmark/compare/2.3.6...2.3.7
|
||||
[2.3.6]: https://github.com/thephpleague/commonmark/compare/2.3.5...2.3.6
|
||||
[2.3.5]: https://github.com/thephpleague/commonmark/compare/2.3.4...2.3.5
|
||||
[2.3.4]: https://github.com/thephpleague/commonmark/compare/2.3.3...2.3.4
|
||||
[2.3.3]: https://github.com/thephpleague/commonmark/compare/2.3.2...2.3.3
|
||||
[2.3.2]: https://github.com/thephpleague/commonmark/compare/2.3.2...main
|
||||
[2.3.1]: https://github.com/thephpleague/commonmark/compare/2.3.0...2.3.1
|
||||
[2.3.0]: https://github.com/thephpleague/commonmark/compare/2.2.3...2.3.0
|
||||
[2.2.5]: https://github.com/thephpleague/commonmark/compare/2.2.4...2.2.5
|
||||
[2.2.4]: https://github.com/thephpleague/commonmark/compare/2.2.3...2.2.4
|
||||
[2.2.3]: https://github.com/thephpleague/commonmark/compare/2.2.2...2.2.3
|
||||
[2.2.2]: https://github.com/thephpleague/commonmark/compare/2.2.1...2.2.2
|
||||
[2.2.1]: https://github.com/thephpleague/commonmark/compare/2.2.0...2.2.1
|
||||
[2.2.0]: https://github.com/thephpleague/commonmark/compare/2.1.1...2.2.0
|
||||
[2.1.3]: https://github.com/thephpleague/commonmark/compare/2.1.2...2.1.3
|
||||
[2.1.2]: https://github.com/thephpleague/commonmark/compare/2.1.1...2.1.2
|
||||
[2.1.1]: https://github.com/thephpleague/commonmark/compare/2.0.2...2.1.1
|
||||
[2.1.0]: https://github.com/thephpleague/commonmark/compare/2.0.2...2.1.0
|
||||
[2.0.4]: https://github.com/thephpleague/commonmark/compare/2.0.3...2.0.4
|
||||
[2.0.3]: https://github.com/thephpleague/commonmark/compare/2.0.2...2.0.3
|
||||
[2.0.2]: https://github.com/thephpleague/commonmark/compare/2.0.1...2.0.2
|
||||
[2.0.1]: https://github.com/thephpleague/commonmark/compare/2.0.0...2.0.1
|
||||
[2.0.0]: https://github.com/thephpleague/commonmark/compare/2.0.0-rc2...2.0.0
|
||||
[2.0.0-rc2]: https://github.com/thephpleague/commonmark/compare/2.0.0-rc1...2.0.0-rc2
|
||||
[2.0.0-rc1]: https://github.com/thephpleague/commonmark/compare/2.0.0-beta3...2.0.0-rc1
|
||||
[2.0.0-beta3]: https://github.com/thephpleague/commonmark/compare/2.0.0-beta2...2.0.0-beta3
|
||||
[2.0.0-beta2]: https://github.com/thephpleague/commonmark/compare/2.0.0-beta1...2.0.0-beta2
|
||||
[2.0.0-beta1]: https://github.com/thephpleague/commonmark/compare/1.6...2.0.0-beta1
|
||||
28
vendor/league/commonmark/LICENSE
vendored
Normal file
28
vendor/league/commonmark/LICENSE
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2014-2022, Colin O'Dell. All rights reserved. Some code based on commonmark.js (copyright 2014-2018, John MacFarlane) and commonmark-java (copyright 2015-2016, Atlassian Pty Ltd)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
224
vendor/league/commonmark/README.md
vendored
Normal file
224
vendor/league/commonmark/README.md
vendored
Normal file
@ -0,0 +1,224 @@
|
||||
# league/commonmark
|
||||
|
||||
[](https://packagist.org/packages/league/commonmark)
|
||||
[](https://packagist.org/packages/league/commonmark)
|
||||
[](LICENSE)
|
||||
[](https://github.com/thephpleague/commonmark/actions?query=workflow%3ATests+branch%3Amain)
|
||||
[](https://scrutinizer-ci.com/g/thephpleague/commonmark/code-structure)
|
||||
[](https://scrutinizer-ci.com/g/thephpleague/commonmark)
|
||||
[](https://shepherd.dev/github/thephpleague/commonmark)
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/126)
|
||||
[](https://www.colinodell.com/sponsor)
|
||||
|
||||

|
||||
|
||||
**league/commonmark** is a highly-extensible PHP Markdown parser created by [Colin O'Dell][@colinodell] which supports the full [CommonMark] spec and [GitHub-Flavored Markdown]. It is based on the [CommonMark JS reference implementation][commonmark.js] by [John MacFarlane] \([@jgm]\).
|
||||
|
||||
## 📦 Installation & Basic Usage
|
||||
|
||||
This project requires PHP 7.4 or higher with the `mbstring` extension. To install it via [Composer] simply run:
|
||||
|
||||
``` bash
|
||||
$ composer require league/commonmark
|
||||
```
|
||||
|
||||
The `CommonMarkConverter` class provides a simple wrapper for converting CommonMark to HTML:
|
||||
|
||||
```php
|
||||
use League\CommonMark\CommonMarkConverter;
|
||||
|
||||
$converter = new CommonMarkConverter([
|
||||
'html_input' => 'strip',
|
||||
'allow_unsafe_links' => false,
|
||||
]);
|
||||
|
||||
echo $converter->convert('# Hello World!');
|
||||
|
||||
// <h1>Hello World!</h1>
|
||||
```
|
||||
|
||||
Or if you want GitHub-Flavored Markdown, use the `GithubFlavoredMarkdownConverter` class instead:
|
||||
|
||||
```php
|
||||
use League\CommonMark\GithubFlavoredMarkdownConverter;
|
||||
|
||||
$converter = new GithubFlavoredMarkdownConverter([
|
||||
'html_input' => 'strip',
|
||||
'allow_unsafe_links' => false,
|
||||
]);
|
||||
|
||||
echo $converter->convert('# Hello World!');
|
||||
|
||||
// <h1>Hello World!</h1>
|
||||
```
|
||||
|
||||
Please note that only UTF-8 and ASCII encodings are supported. If your Markdown uses a different encoding please convert it to UTF-8 before running it through this library.
|
||||
|
||||
> [!CAUTION]
|
||||
> If you will be parsing untrusted input from users, please consider setting the `html_input` and `allow_unsafe_links` options per the example above. See <https://commonmark.thephpleague.com/security/> for more details. If you also do choose to allow raw HTML input from untrusted users, consider using a library (like [HTML Purifier](https://github.com/ezyang/htmlpurifier)) to provide additional HTML filtering.
|
||||
|
||||
## 📓 Documentation
|
||||
|
||||
Full documentation on advanced usage, configuration, and customization can be found at [commonmark.thephpleague.com][docs].
|
||||
|
||||
## ⏫ Upgrading
|
||||
|
||||
Information on how to upgrade to newer versions of this library can be found at <https://commonmark.thephpleague.com/releases>.
|
||||
|
||||
## 💻 GitHub-Flavored Markdown
|
||||
|
||||
The `GithubFlavoredMarkdownConverter` shown earlier is a drop-in replacement for the `CommonMarkConverter` which adds additional features found in the GFM spec:
|
||||
|
||||
- Autolinks
|
||||
- Disallowed raw HTML
|
||||
- Strikethrough
|
||||
- Tables
|
||||
- Task Lists
|
||||
|
||||
See the [Extensions documentation](https://commonmark.thephpleague.com/customization/extensions/) for more details on how to include only certain GFM features if you don't want them all.
|
||||
|
||||
## 🗃️ Related Packages
|
||||
|
||||
### Integrations
|
||||
|
||||
- [CakePHP 3](https://github.com/gourmet/common-mark)
|
||||
- [Drupal](https://www.drupal.org/project/markdown)
|
||||
- [Laravel 4+](https://github.com/GrahamCampbell/Laravel-Markdown)
|
||||
- [Sculpin](https://github.com/bcremer/sculpin-commonmark-bundle)
|
||||
- [Symfony 2 & 3](https://github.com/webuni/commonmark-bundle)
|
||||
- [Symfony 4](https://github.com/avensome/commonmark-bundle)
|
||||
- [Twig Markdown extension](https://github.com/twigphp/markdown-extension)
|
||||
- [Twig filter and tag](https://github.com/aptoma/twig-markdown)
|
||||
- [Laravel CommonMark Blog](https://github.com/spekulatius/laravel-commonmark-blog)
|
||||
|
||||
### Included Extensions
|
||||
|
||||
See [our extension documentation](https://commonmark.thephpleague.com/extensions/overview) for a full list of extensions bundled with this library.
|
||||
|
||||
### Community Extensions
|
||||
|
||||
Custom parsers/renderers can be bundled into extensions which extend CommonMark. Here are some that you may find interesting:
|
||||
|
||||
- [Emoji extension](https://github.com/ElGigi/CommonMarkEmoji) - UTF-8 emoji extension with Github tag.
|
||||
- [Sup Sub extensions](https://github.com/OWS/commonmark-sup-sub-extensions) - Adds support of superscript and subscript (`<sup>` and `<sub>` HTML tags)
|
||||
- [YouTube iframe extension](https://github.com/zoonru/commonmark-ext-youtube-iframe) - Replaces youtube link with iframe.
|
||||
- [Lazy Image extension](https://github.com/simonvomeyser/commonmark-ext-lazy-image) - Adds various options for lazy loading of images.
|
||||
- [Marker Extension](https://github.com/noah1400/commonmark-marker-extension) - Adds support of highlighted text (`<mark>` HTML tag)
|
||||
- [Pygments Highlighter extension](https://github.com/DanielEScherzer/commonmark-ext-pygments-highlighter) - Adds support for highlighting code with the Pygments library
|
||||
|
||||
Others can be found on [Packagist under the `commonmark-extension` package type](https://packagist.org/packages/league/commonmark?type=commonmark-extension).
|
||||
|
||||
If you build your own, feel free to submit a PR to add it to this list!
|
||||
|
||||
### Others
|
||||
|
||||
Check out the other cool things people are doing with `league/commonmark`: <https://packagist.org/packages/league/commonmark/dependents>
|
||||
|
||||
## 🏷️ Versioning
|
||||
|
||||
[SemVer](http://semver.org/) is followed closely. Minor and patch releases should not introduce breaking changes to the codebase; however, they might change the resulting AST or HTML output of parsed Markdown (due to bug fixes, spec changes, etc.) As a result, you might get slightly different HTML, but any custom code built onto this library should still function correctly.
|
||||
|
||||
Any classes or methods marked `@internal` are not intended for use outside of this library and are subject to breaking changes at any time, so please avoid using them.
|
||||
|
||||
## 🛠️ Maintenance & Support
|
||||
|
||||
When a new **minor** version (e.g. `2.0` -> `2.1`) is released, the previous one (`2.0`) will continue to receive security and critical bug fixes for *at least* 3 months.
|
||||
|
||||
When a new **major** version is released (e.g. `1.6` -> `2.0`), the previous one (`1.6`) will receive critical bug fixes for *at least* 3 months and security updates for 6 months after that new release comes out.
|
||||
|
||||
(This policy may change in the future and exceptions may be made on a case-by-case basis.)
|
||||
|
||||
**Professional support, including notification of new releases and security updates, is available through a [Tidelift Subscription](https://tidelift.com/subscription/pkg/packagist-league-commonmark?utm_source=packagist-league-commonmark&utm_medium=referral&utm_campaign=readme).**
|
||||
|
||||
## 👷♀️ Contributing
|
||||
|
||||
To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure with us.
|
||||
|
||||
If you encounter a bug in the spec, please report it to the [CommonMark] project. Any resulting fix will eventually be implemented in this project as well.
|
||||
|
||||
Contributions to this library are **welcome**, especially ones that:
|
||||
|
||||
* Improve usability or flexibility without compromising our ability to adhere to the [CommonMark spec]
|
||||
* Mirror fixes made to the [reference implementation][commonmark.js]
|
||||
* Optimize performance
|
||||
* Fix issues with adhering to the [CommonMark spec]
|
||||
|
||||
Major refactoring to core parsing logic should be avoided if possible so that we can easily follow updates made to [the reference implementation][commonmark.js]. That being said, we will absolutely consider changes which don't deviate too far from the reference spec or which are favored by other popular CommonMark implementations.
|
||||
|
||||
Please see [CONTRIBUTING](https://github.com/thephpleague/commonmark/blob/main/.github/CONTRIBUTING.md) for additional details.
|
||||
|
||||
## 🧪 Testing
|
||||
|
||||
``` bash
|
||||
$ composer test
|
||||
```
|
||||
|
||||
This will also test league/commonmark against the latest supported spec.
|
||||
|
||||
## 🚀 Performance Benchmarks
|
||||
|
||||
You can compare the performance of **league/commonmark** to other popular parsers by running the included benchmark tool:
|
||||
|
||||
``` bash
|
||||
$ ./tests/benchmark/benchmark.php
|
||||
```
|
||||
|
||||
## 👥 Credits & Acknowledgements
|
||||
|
||||
This code was originally based on the [CommonMark JS reference implementation][commonmark.js] which is written, maintained, and copyrighted by [John MacFarlane]. This project simply wouldn't exist without his work.
|
||||
|
||||
And a huge thanks to all of our amazing contributors:
|
||||
|
||||
<a href="https://github.com/thephpleague/commonmark/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=thephpleague/commonmark" />
|
||||
</a>
|
||||
|
||||
### Sponsors
|
||||
|
||||
We'd also like to extend our sincere thanks the following sponsors who support ongoing development of this project:
|
||||
|
||||
- [Tidelift](https://tidelift.com/subscription/pkg/packagist-league-commonmark?utm_source=packagist-league-commonmark&utm_medium=referral&utm_campaign=readme) for offering support to both the maintainers and end-users through their [professional support](https://tidelift.com/subscription/pkg/packagist-league-commonmark?utm_source=packagist-league-commonmark&utm_medium=referral&utm_campaign=readme) program
|
||||
- [Blackfire](https://www.blackfire.io/) for providing an Open-Source Profiler subscription
|
||||
- [JetBrains](https://www.jetbrains.com/) for supporting this project with complimentary [PhpStorm](https://www.jetbrains.com/phpstorm/) licenses
|
||||
|
||||
Are you interested in sponsoring development of this project? See <https://www.colinodell.com/sponsor> for a list of ways to contribute.
|
||||
|
||||
## 📄 License
|
||||
|
||||
**league/commonmark** is licensed under the BSD-3 license. See the [`LICENSE`](LICENSE) file for more details.
|
||||
|
||||
## 🏛️ Governance
|
||||
|
||||
This project is primarily maintained by [Colin O'Dell][@colinodell]. Members of the [PHP League] Leadership Team may occasionally assist with some of these duties.
|
||||
|
||||
## 🗺️ Who Uses It?
|
||||
|
||||
This project is used by [Drupal](https://www.drupal.org/project/markdown), [Laravel Framework](https://laravel.com/), [Cachet](https://cachethq.io/), [Firefly III](https://firefly-iii.org/), [Neos](https://www.neos.io/), [Daux.io](https://daux.io/), and [more](https://packagist.org/packages/league/commonmark/dependents)!
|
||||
|
||||
---
|
||||
|
||||
<div align="center">
|
||||
<b>
|
||||
<a href="https://tidelift.com/subscription/pkg/packagist-league-commonmark?utm_source=packagist-league-commonmark&utm_medium=referral&utm_campaign=readme">Get professional support for league/commonmark with a Tidelift subscription</a>
|
||||
</b>
|
||||
<br>
|
||||
<sub>
|
||||
Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies.
|
||||
</sub>
|
||||
</div>
|
||||
|
||||
[CommonMark]: http://commonmark.org/
|
||||
[CommonMark spec]: http://spec.commonmark.org/
|
||||
[commonmark.js]: https://github.com/jgm/commonmark.js
|
||||
[GitHub-Flavored Markdown]: https://github.github.com/gfm/
|
||||
[John MacFarlane]: http://johnmacfarlane.net
|
||||
[docs]: https://commonmark.thephpleague.com/
|
||||
[docs-examples]: https://commonmark.thephpleague.com/customization/overview/#examples
|
||||
[docs-example-twitter]: https://commonmark.thephpleague.com/customization/inline-parsing#example-1---twitter-handles
|
||||
[docs-example-smilies]: https://commonmark.thephpleague.com/customization/inline-parsing#example-2---emoticons
|
||||
[All Contributors]: https://github.com/thephpleague/commonmark/contributors
|
||||
[@colinodell]: https://www.twitter.com/colinodell
|
||||
[@jgm]: https://github.com/jgm
|
||||
[jgm/stmd]: https://github.com/jgm/stmd
|
||||
[Composer]: https://getcomposer.org/
|
||||
[PHP League]: https://thephpleague.com
|
||||
129
vendor/league/commonmark/composer.json
vendored
Normal file
129
vendor/league/commonmark/composer.json
vendored
Normal file
@ -0,0 +1,129 @@
|
||||
{
|
||||
"name": "league/commonmark",
|
||||
"type": "library",
|
||||
"description": "Highly-extensible PHP Markdown parser which fully supports the CommonMark spec and GitHub-Flavored Markdown (GFM)",
|
||||
"keywords": ["markdown","parser","commonmark","gfm","github","flavored","github-flavored","md"],
|
||||
"homepage": "https://commonmark.thephpleague.com",
|
||||
"license": "BSD-3-Clause",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Colin O'Dell",
|
||||
"email": "colinodell@gmail.com",
|
||||
"homepage": "https://www.colinodell.com",
|
||||
"role": "Lead Developer"
|
||||
}
|
||||
],
|
||||
"support": {
|
||||
"docs": "https://commonmark.thephpleague.com/",
|
||||
"forum": "https://github.com/thephpleague/commonmark/discussions",
|
||||
"issues": "https://github.com/thephpleague/commonmark/issues",
|
||||
"rss": "https://github.com/thephpleague/commonmark/releases.atom",
|
||||
"source": "https://github.com/thephpleague/commonmark"
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.4 || ^8.0",
|
||||
"ext-mbstring": "*",
|
||||
"league/config": "^1.1.1",
|
||||
"psr/event-dispatcher": "^1.0",
|
||||
"symfony/deprecation-contracts": "^2.1 || ^3.0",
|
||||
"symfony/polyfill-php80": "^1.16"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-json": "*",
|
||||
"cebe/markdown": "^1.0",
|
||||
"commonmark/cmark": "0.31.1",
|
||||
"commonmark/commonmark.js": "0.31.1",
|
||||
"composer/package-versions-deprecated": "^1.8",
|
||||
"embed/embed": "^4.4",
|
||||
"erusev/parsedown": "^1.0",
|
||||
"github/gfm": "0.29.0",
|
||||
"michelf/php-markdown": "^1.4 || ^2.0",
|
||||
"nyholm/psr7": "^1.5",
|
||||
"phpstan/phpstan": "^1.8.2",
|
||||
"phpunit/phpunit": "^9.5.21 || ^10.5.9 || ^11.0.0",
|
||||
"scrutinizer/ocular": "^1.8.1",
|
||||
"symfony/finder": "^5.3 | ^6.0 | ^7.0",
|
||||
"symfony/process": "^5.4 | ^6.0 | ^7.0",
|
||||
"symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0",
|
||||
"unleashedtech/php-coding-standard": "^3.1.1",
|
||||
"vimeo/psalm": "^4.24.0 || ^5.0.0 || ^6.0.0"
|
||||
},
|
||||
"minimum-stability": "beta",
|
||||
"suggest": {
|
||||
"symfony/yaml": "v2.3+ required if using the Front Matter extension"
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
"type": "package",
|
||||
"package": {
|
||||
"name": "commonmark/commonmark.js",
|
||||
"version": "0.31.1",
|
||||
"dist": {
|
||||
"url": "https://github.com/commonmark/commonmark.js/archive/0.31.1.zip",
|
||||
"type": "zip"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "package",
|
||||
"package": {
|
||||
"name": "commonmark/cmark",
|
||||
"version": "0.31.1",
|
||||
"dist": {
|
||||
"url": "https://github.com/commonmark/cmark/archive/0.31.1.zip",
|
||||
"type": "zip"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "package",
|
||||
"package": {
|
||||
"name": "github/gfm",
|
||||
"version": "0.29.0",
|
||||
"dist": {
|
||||
"url": "https://github.com/github/cmark-gfm/archive/0.29.0.gfm.13.zip",
|
||||
"type": "zip"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"League\\CommonMark\\": "src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"League\\CommonMark\\Tests\\Unit\\": "tests/unit",
|
||||
"League\\CommonMark\\Tests\\Functional\\": "tests/functional",
|
||||
"League\\CommonMark\\Tests\\PHPStan\\": "tests/phpstan"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"phpcs": "phpcs",
|
||||
"phpcbf": "phpcbf",
|
||||
"phpstan": "phpstan analyse",
|
||||
"phpunit": "phpunit --no-coverage",
|
||||
"psalm": "psalm --stats",
|
||||
"pathological": "tests/pathological/test.php",
|
||||
"test": [
|
||||
"@phpcs",
|
||||
"@phpstan",
|
||||
"@psalm",
|
||||
"@phpunit",
|
||||
"@pathological"
|
||||
]
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "2.8-dev"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"composer/package-versions-deprecated": true,
|
||||
"dealerdirect/phpcodesniffer-composer-installer": true
|
||||
},
|
||||
"sort-packages": true
|
||||
}
|
||||
}
|
||||
46
vendor/league/commonmark/src/CommonMarkConverter.php
vendored
Normal file
46
vendor/league/commonmark/src/CommonMarkConverter.php
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
|
||||
* - (c) John MacFarlane
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark;
|
||||
|
||||
use League\CommonMark\Environment\Environment;
|
||||
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
|
||||
|
||||
/**
|
||||
* Converts CommonMark-compatible Markdown to HTML.
|
||||
*/
|
||||
final class CommonMarkConverter extends MarkdownConverter
|
||||
{
|
||||
/**
|
||||
* Create a new Markdown converter pre-configured for CommonMark
|
||||
*
|
||||
* @param array<string, mixed> $config
|
||||
*/
|
||||
public function __construct(array $config = [])
|
||||
{
|
||||
$environment = new Environment($config);
|
||||
$environment->addExtension(new CommonMarkCoreExtension());
|
||||
|
||||
parent::__construct($environment);
|
||||
}
|
||||
|
||||
public function getEnvironment(): Environment
|
||||
{
|
||||
\assert($this->environment instanceof Environment);
|
||||
|
||||
return $this->environment;
|
||||
}
|
||||
}
|
||||
30
vendor/league/commonmark/src/ConverterInterface.php
vendored
Normal file
30
vendor/league/commonmark/src/ConverterInterface.php
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark;
|
||||
|
||||
use League\CommonMark\Exception\CommonMarkException;
|
||||
use League\CommonMark\Output\RenderedContentInterface;
|
||||
use League\Config\Exception\ConfigurationExceptionInterface;
|
||||
|
||||
/**
|
||||
* Interface for a service which converts content from one format (like Markdown) to another (like HTML).
|
||||
*/
|
||||
interface ConverterInterface
|
||||
{
|
||||
/**
|
||||
* @throws CommonMarkException
|
||||
* @throws ConfigurationExceptionInterface
|
||||
*/
|
||||
public function convert(string $input): RenderedContentInterface;
|
||||
}
|
||||
83
vendor/league/commonmark/src/Delimiter/Bracket.php
vendored
Normal file
83
vendor/league/commonmark/src/Delimiter/Bracket.php
vendored
Normal file
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Delimiter;
|
||||
|
||||
use League\CommonMark\Node\Node;
|
||||
|
||||
final class Bracket
|
||||
{
|
||||
private Node $node;
|
||||
private ?Bracket $previous;
|
||||
private bool $hasNext = false;
|
||||
private int $position;
|
||||
private bool $image;
|
||||
private bool $active = true;
|
||||
|
||||
public function __construct(Node $node, ?Bracket $previous, int $position, bool $image)
|
||||
{
|
||||
$this->node = $node;
|
||||
$this->previous = $previous;
|
||||
$this->position = $position;
|
||||
$this->image = $image;
|
||||
}
|
||||
|
||||
public function getNode(): Node
|
||||
{
|
||||
return $this->node;
|
||||
}
|
||||
|
||||
public function getPrevious(): ?Bracket
|
||||
{
|
||||
return $this->previous;
|
||||
}
|
||||
|
||||
public function hasNext(): bool
|
||||
{
|
||||
return $this->hasNext;
|
||||
}
|
||||
|
||||
public function getPosition(): int
|
||||
{
|
||||
return $this->position;
|
||||
}
|
||||
|
||||
public function isImage(): bool
|
||||
{
|
||||
return $this->image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only valid in the context of non-images (links)
|
||||
*/
|
||||
public function isActive(): bool
|
||||
{
|
||||
return $this->active;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function setHasNext(bool $hasNext): void
|
||||
{
|
||||
$this->hasNext = $hasNext;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function setActive(bool $active): void
|
||||
{
|
||||
$this->active = $active;
|
||||
}
|
||||
}
|
||||
134
vendor/league/commonmark/src/Delimiter/Delimiter.php
vendored
Normal file
134
vendor/league/commonmark/src/Delimiter/Delimiter.php
vendored
Normal file
@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
|
||||
* - (c) John MacFarlane
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Delimiter;
|
||||
|
||||
use League\CommonMark\Node\Inline\AbstractStringContainer;
|
||||
|
||||
final class Delimiter implements DelimiterInterface
|
||||
{
|
||||
/** @psalm-readonly */
|
||||
private string $char;
|
||||
|
||||
/** @psalm-readonly-allow-private-mutation */
|
||||
private int $length;
|
||||
|
||||
/** @psalm-readonly */
|
||||
private int $originalLength;
|
||||
|
||||
/** @psalm-readonly */
|
||||
private AbstractStringContainer $inlineNode;
|
||||
|
||||
/** @psalm-readonly-allow-private-mutation */
|
||||
private ?DelimiterInterface $previous = null;
|
||||
|
||||
/** @psalm-readonly-allow-private-mutation */
|
||||
private ?DelimiterInterface $next = null;
|
||||
|
||||
/** @psalm-readonly */
|
||||
private bool $canOpen;
|
||||
|
||||
/** @psalm-readonly */
|
||||
private bool $canClose;
|
||||
|
||||
/** @psalm-readonly-allow-private-mutation */
|
||||
private bool $active;
|
||||
|
||||
/** @psalm-readonly */
|
||||
private ?int $index = null;
|
||||
|
||||
public function __construct(string $char, int $numDelims, AbstractStringContainer $node, bool $canOpen, bool $canClose, ?int $index = null)
|
||||
{
|
||||
$this->char = $char;
|
||||
$this->length = $numDelims;
|
||||
$this->originalLength = $numDelims;
|
||||
$this->inlineNode = $node;
|
||||
$this->canOpen = $canOpen;
|
||||
$this->canClose = $canClose;
|
||||
$this->active = true;
|
||||
$this->index = $index;
|
||||
}
|
||||
|
||||
public function canClose(): bool
|
||||
{
|
||||
return $this->canClose;
|
||||
}
|
||||
|
||||
public function canOpen(): bool
|
||||
{
|
||||
return $this->canOpen;
|
||||
}
|
||||
|
||||
public function isActive(): bool
|
||||
{
|
||||
return $this->active;
|
||||
}
|
||||
|
||||
public function setActive(bool $active): void
|
||||
{
|
||||
$this->active = $active;
|
||||
}
|
||||
|
||||
public function getChar(): string
|
||||
{
|
||||
return $this->char;
|
||||
}
|
||||
|
||||
public function getIndex(): ?int
|
||||
{
|
||||
return $this->index;
|
||||
}
|
||||
|
||||
public function getNext(): ?DelimiterInterface
|
||||
{
|
||||
return $this->next;
|
||||
}
|
||||
|
||||
public function setNext(?DelimiterInterface $next): void
|
||||
{
|
||||
$this->next = $next;
|
||||
}
|
||||
|
||||
public function getLength(): int
|
||||
{
|
||||
return $this->length;
|
||||
}
|
||||
|
||||
public function setLength(int $length): void
|
||||
{
|
||||
$this->length = $length;
|
||||
}
|
||||
|
||||
public function getOriginalLength(): int
|
||||
{
|
||||
return $this->originalLength;
|
||||
}
|
||||
|
||||
public function getInlineNode(): AbstractStringContainer
|
||||
{
|
||||
return $this->inlineNode;
|
||||
}
|
||||
|
||||
public function getPrevious(): ?DelimiterInterface
|
||||
{
|
||||
return $this->previous;
|
||||
}
|
||||
|
||||
public function setPrevious(?DelimiterInterface $previous): void
|
||||
{
|
||||
$this->previous = $previous;
|
||||
}
|
||||
}
|
||||
56
vendor/league/commonmark/src/Delimiter/DelimiterInterface.php
vendored
Normal file
56
vendor/league/commonmark/src/Delimiter/DelimiterInterface.php
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
|
||||
* - (c) John MacFarlane
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Delimiter;
|
||||
|
||||
use League\CommonMark\Node\Inline\AbstractStringContainer;
|
||||
|
||||
interface DelimiterInterface
|
||||
{
|
||||
public function canClose(): bool;
|
||||
|
||||
public function canOpen(): bool;
|
||||
|
||||
/**
|
||||
* @deprecated This method is no longer used internally and will be removed in 3.0
|
||||
*/
|
||||
public function isActive(): bool;
|
||||
|
||||
/**
|
||||
* @deprecated This method is no longer used internally and will be removed in 3.0
|
||||
*/
|
||||
public function setActive(bool $active): void;
|
||||
|
||||
public function getChar(): string;
|
||||
|
||||
public function getIndex(): ?int;
|
||||
|
||||
public function getNext(): ?DelimiterInterface;
|
||||
|
||||
public function setNext(?DelimiterInterface $next): void;
|
||||
|
||||
public function getLength(): int;
|
||||
|
||||
public function setLength(int $length): void;
|
||||
|
||||
public function getOriginalLength(): int;
|
||||
|
||||
public function getInlineNode(): AbstractStringContainer;
|
||||
|
||||
public function getPrevious(): ?DelimiterInterface;
|
||||
|
||||
public function setPrevious(?DelimiterInterface $previous): void;
|
||||
}
|
||||
106
vendor/league/commonmark/src/Delimiter/DelimiterParser.php
vendored
Normal file
106
vendor/league/commonmark/src/Delimiter/DelimiterParser.php
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\CommonMark\Delimiter;
|
||||
|
||||
use League\CommonMark\Delimiter\Processor\DelimiterProcessorCollection;
|
||||
use League\CommonMark\Delimiter\Processor\DelimiterProcessorInterface;
|
||||
use League\CommonMark\Node\Inline\Text;
|
||||
use League\CommonMark\Parser\Inline\InlineParserInterface;
|
||||
use League\CommonMark\Parser\Inline\InlineParserMatch;
|
||||
use League\CommonMark\Parser\InlineParserContext;
|
||||
use League\CommonMark\Util\RegexHelper;
|
||||
|
||||
/**
|
||||
* Delimiter parsing is implemented as an Inline Parser with the lowest-possible priority
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class DelimiterParser implements InlineParserInterface
|
||||
{
|
||||
private DelimiterProcessorCollection $collection;
|
||||
|
||||
public function __construct(DelimiterProcessorCollection $collection)
|
||||
{
|
||||
$this->collection = $collection;
|
||||
}
|
||||
|
||||
public function getMatchDefinition(): InlineParserMatch
|
||||
{
|
||||
return InlineParserMatch::oneOf(...$this->collection->getDelimiterCharacters());
|
||||
}
|
||||
|
||||
public function parse(InlineParserContext $inlineContext): bool
|
||||
{
|
||||
$character = $inlineContext->getFullMatch();
|
||||
$numDelims = 0;
|
||||
$cursor = $inlineContext->getCursor();
|
||||
$processor = $this->collection->getDelimiterProcessor($character);
|
||||
|
||||
\assert($processor !== null); // Delimiter processor should never be null here
|
||||
|
||||
$charBefore = $cursor->peek(-1);
|
||||
if ($charBefore === null) {
|
||||
$charBefore = "\n";
|
||||
}
|
||||
|
||||
while ($cursor->peek($numDelims) === $character) {
|
||||
++$numDelims;
|
||||
}
|
||||
|
||||
if ($numDelims < $processor->getMinLength()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$cursor->advanceBy($numDelims);
|
||||
|
||||
$charAfter = $cursor->getCurrentCharacter();
|
||||
if ($charAfter === null) {
|
||||
$charAfter = "\n";
|
||||
}
|
||||
|
||||
[$canOpen, $canClose] = self::determineCanOpenOrClose($charBefore, $charAfter, $character, $processor);
|
||||
|
||||
if (! ($canOpen || $canClose)) {
|
||||
$inlineContext->getContainer()->appendChild(new Text(\str_repeat($character, $numDelims)));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
$node = new Text(\str_repeat($character, $numDelims), [
|
||||
'delim' => true,
|
||||
]);
|
||||
$inlineContext->getContainer()->appendChild($node);
|
||||
|
||||
// Add entry to stack to this opener
|
||||
$delimiter = new Delimiter($character, $numDelims, $node, $canOpen, $canClose, $inlineContext->getCursor()->getPosition());
|
||||
$inlineContext->getDelimiterStack()->push($delimiter);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool[]
|
||||
*/
|
||||
private static function determineCanOpenOrClose(string $charBefore, string $charAfter, string $character, DelimiterProcessorInterface $delimiterProcessor): array
|
||||
{
|
||||
$afterIsWhitespace = \preg_match(RegexHelper::REGEX_UNICODE_WHITESPACE_CHAR, $charAfter);
|
||||
$afterIsPunctuation = \preg_match(RegexHelper::REGEX_PUNCTUATION, $charAfter);
|
||||
$beforeIsWhitespace = \preg_match(RegexHelper::REGEX_UNICODE_WHITESPACE_CHAR, $charBefore);
|
||||
$beforeIsPunctuation = \preg_match(RegexHelper::REGEX_PUNCTUATION, $charBefore);
|
||||
|
||||
$leftFlanking = ! $afterIsWhitespace && (! $afterIsPunctuation || $beforeIsWhitespace || $beforeIsPunctuation);
|
||||
$rightFlanking = ! $beforeIsWhitespace && (! $beforeIsPunctuation || $afterIsWhitespace || $afterIsPunctuation);
|
||||
|
||||
if ($character === '_') {
|
||||
$canOpen = $leftFlanking && (! $rightFlanking || $beforeIsPunctuation);
|
||||
$canClose = $rightFlanking && (! $leftFlanking || $afterIsPunctuation);
|
||||
} else {
|
||||
$canOpen = $leftFlanking && $character === $delimiterProcessor->getOpeningCharacter();
|
||||
$canClose = $rightFlanking && $character === $delimiterProcessor->getClosingCharacter();
|
||||
}
|
||||
|
||||
return [$canOpen, $canClose];
|
||||
}
|
||||
}
|
||||
396
vendor/league/commonmark/src/Delimiter/DelimiterStack.php
vendored
Normal file
396
vendor/league/commonmark/src/Delimiter/DelimiterStack.php
vendored
Normal file
@ -0,0 +1,396 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
|
||||
* - (c) John MacFarlane
|
||||
*
|
||||
* Additional emphasis processing code based on commonmark-java (https://github.com/atlassian/commonmark-java)
|
||||
* - (c) Atlassian Pty Ltd
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Delimiter;
|
||||
|
||||
use League\CommonMark\Delimiter\Processor\CacheableDelimiterProcessorInterface;
|
||||
use League\CommonMark\Delimiter\Processor\DelimiterProcessorCollection;
|
||||
use League\CommonMark\Node\Inline\AdjacentTextMerger;
|
||||
use League\CommonMark\Node\Node;
|
||||
|
||||
final class DelimiterStack
|
||||
{
|
||||
/** @psalm-readonly-allow-private-mutation */
|
||||
private ?DelimiterInterface $top = null;
|
||||
|
||||
/** @psalm-readonly-allow-private-mutation */
|
||||
private ?Bracket $brackets = null;
|
||||
|
||||
/**
|
||||
* @deprecated This property will be removed in 3.0 once all delimiters MUST have an index/position
|
||||
*
|
||||
* @var \SplObjectStorage<DelimiterInterface, int>|\WeakMap<DelimiterInterface, int>
|
||||
*/
|
||||
private $missingIndexCache;
|
||||
|
||||
|
||||
private int $remainingDelimiters = 0;
|
||||
|
||||
public function __construct(int $maximumStackSize = PHP_INT_MAX)
|
||||
{
|
||||
$this->remainingDelimiters = $maximumStackSize;
|
||||
|
||||
if (\PHP_VERSION_ID >= 80000) {
|
||||
/** @psalm-suppress PropertyTypeCoercion */
|
||||
$this->missingIndexCache = new \WeakMap(); // @phpstan-ignore-line
|
||||
} else {
|
||||
$this->missingIndexCache = new \SplObjectStorage(); // @phpstan-ignore-line
|
||||
}
|
||||
}
|
||||
|
||||
public function push(DelimiterInterface $newDelimiter): void
|
||||
{
|
||||
if ($this->remainingDelimiters-- <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$newDelimiter->setPrevious($this->top);
|
||||
|
||||
if ($this->top !== null) {
|
||||
$this->top->setNext($newDelimiter);
|
||||
}
|
||||
|
||||
$this->top = $newDelimiter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function addBracket(Node $node, int $index, bool $image): void
|
||||
{
|
||||
if ($this->brackets !== null) {
|
||||
$this->brackets->setHasNext(true);
|
||||
}
|
||||
|
||||
$this->brackets = new Bracket($node, $this->brackets, $index, $image);
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-immutable
|
||||
*/
|
||||
public function getLastBracket(): ?Bracket
|
||||
{
|
||||
return $this->brackets;
|
||||
}
|
||||
|
||||
private function findEarliest(int $stackBottom): ?DelimiterInterface
|
||||
{
|
||||
// Move back to first relevant delim.
|
||||
$delimiter = $this->top;
|
||||
$lastChecked = null;
|
||||
|
||||
while ($delimiter !== null && self::getIndex($delimiter) > $stackBottom) {
|
||||
$lastChecked = $delimiter;
|
||||
$delimiter = $delimiter->getPrevious();
|
||||
}
|
||||
|
||||
return $lastChecked;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function removeBracket(): void
|
||||
{
|
||||
if ($this->brackets === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->brackets = $this->brackets->getPrevious();
|
||||
|
||||
if ($this->brackets !== null) {
|
||||
$this->brackets->setHasNext(false);
|
||||
}
|
||||
}
|
||||
|
||||
public function removeDelimiter(DelimiterInterface $delimiter): void
|
||||
{
|
||||
if ($delimiter->getPrevious() !== null) {
|
||||
/** @psalm-suppress PossiblyNullReference */
|
||||
$delimiter->getPrevious()->setNext($delimiter->getNext());
|
||||
}
|
||||
|
||||
if ($delimiter->getNext() === null) {
|
||||
// top of stack
|
||||
$this->top = $delimiter->getPrevious();
|
||||
} else {
|
||||
/** @psalm-suppress PossiblyNullReference */
|
||||
$delimiter->getNext()->setPrevious($delimiter->getPrevious());
|
||||
}
|
||||
|
||||
// Nullify all references from the removed delimiter to other delimiters.
|
||||
// All references to this particular delimiter in the linked list should be gone,
|
||||
// but it's possible we're still hanging on to other references to things that
|
||||
// have been (or soon will be) removed, which may interfere with efficient
|
||||
// garbage collection by the PHP runtime.
|
||||
// Explicitly releasing these references should help to avoid possible
|
||||
// segfaults like in https://bugs.php.net/bug.php?id=68606.
|
||||
$delimiter->setPrevious(null);
|
||||
$delimiter->setNext(null);
|
||||
|
||||
// TODO: Remove the line below once PHP 7.4 support is dropped, as WeakMap won't hold onto the reference, making this unnecessary
|
||||
unset($this->missingIndexCache[$delimiter]);
|
||||
}
|
||||
|
||||
private function removeDelimiterAndNode(DelimiterInterface $delimiter): void
|
||||
{
|
||||
$delimiter->getInlineNode()->detach();
|
||||
$this->removeDelimiter($delimiter);
|
||||
}
|
||||
|
||||
private function removeDelimitersBetween(DelimiterInterface $opener, DelimiterInterface $closer): void
|
||||
{
|
||||
$delimiter = $closer->getPrevious();
|
||||
$openerPosition = self::getIndex($opener);
|
||||
while ($delimiter !== null && self::getIndex($delimiter) > $openerPosition) {
|
||||
$previous = $delimiter->getPrevious();
|
||||
$this->removeDelimiter($delimiter);
|
||||
$delimiter = $previous;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DelimiterInterface|int|null $stackBottom
|
||||
*/
|
||||
public function removeAll($stackBottom = null): void
|
||||
{
|
||||
$stackBottomPosition = \is_int($stackBottom) ? $stackBottom : self::getIndex($stackBottom);
|
||||
|
||||
while ($this->top && $this->getIndex($this->top) > $stackBottomPosition) {
|
||||
$this->removeDelimiter($this->top);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method is no longer used internally and will be removed in 3.0
|
||||
*/
|
||||
public function removeEarlierMatches(string $character): void
|
||||
{
|
||||
$opener = $this->top;
|
||||
while ($opener !== null) {
|
||||
if ($opener->getChar() === $character) {
|
||||
$opener->setActive(false);
|
||||
}
|
||||
|
||||
$opener = $opener->getPrevious();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function deactivateLinkOpeners(): void
|
||||
{
|
||||
$opener = $this->brackets;
|
||||
while ($opener !== null && $opener->isActive()) {
|
||||
$opener->setActive(false);
|
||||
$opener = $opener->getPrevious();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method is no longer used internally and will be removed in 3.0
|
||||
*
|
||||
* @param string|string[] $characters
|
||||
*/
|
||||
public function searchByCharacter($characters): ?DelimiterInterface
|
||||
{
|
||||
if (! \is_array($characters)) {
|
||||
$characters = [$characters];
|
||||
}
|
||||
|
||||
$opener = $this->top;
|
||||
while ($opener !== null) {
|
||||
if (\in_array($opener->getChar(), $characters, true)) {
|
||||
break;
|
||||
}
|
||||
|
||||
$opener = $opener->getPrevious();
|
||||
}
|
||||
|
||||
return $opener;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DelimiterInterface|int|null $stackBottom
|
||||
*
|
||||
* @todo change $stackBottom to an int in 3.0
|
||||
*/
|
||||
public function processDelimiters($stackBottom, DelimiterProcessorCollection $processors): void
|
||||
{
|
||||
/** @var array<string, int> $openersBottom */
|
||||
$openersBottom = [];
|
||||
|
||||
$stackBottomPosition = \is_int($stackBottom) ? $stackBottom : self::getIndex($stackBottom);
|
||||
|
||||
// Find first closer above stackBottom
|
||||
$closer = $this->findEarliest($stackBottomPosition);
|
||||
|
||||
// Move forward, looking for closers, and handling each
|
||||
while ($closer !== null) {
|
||||
$closingDelimiterChar = $closer->getChar();
|
||||
|
||||
$delimiterProcessor = $processors->getDelimiterProcessor($closingDelimiterChar);
|
||||
if (! $closer->canClose() || $delimiterProcessor === null) {
|
||||
$closer = $closer->getNext();
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($delimiterProcessor instanceof CacheableDelimiterProcessorInterface) {
|
||||
$openersBottomCacheKey = $delimiterProcessor->getCacheKey($closer);
|
||||
} else {
|
||||
$openersBottomCacheKey = $closingDelimiterChar;
|
||||
}
|
||||
|
||||
$openingDelimiterChar = $delimiterProcessor->getOpeningCharacter();
|
||||
|
||||
$useDelims = 0;
|
||||
$openerFound = false;
|
||||
$potentialOpenerFound = false;
|
||||
$opener = $closer->getPrevious();
|
||||
while ($opener !== null && ($openerPosition = self::getIndex($opener)) > $stackBottomPosition && $openerPosition >= ($openersBottom[$openersBottomCacheKey] ?? 0)) {
|
||||
if ($opener->canOpen() && $opener->getChar() === $openingDelimiterChar) {
|
||||
$potentialOpenerFound = true;
|
||||
$useDelims = $delimiterProcessor->getDelimiterUse($opener, $closer);
|
||||
if ($useDelims > 0) {
|
||||
$openerFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$opener = $opener->getPrevious();
|
||||
}
|
||||
|
||||
if (! $openerFound) {
|
||||
// Set lower bound for future searches
|
||||
// TODO: Remove this conditional check in 3.0. It only exists to prevent behavioral BC breaks in 2.x.
|
||||
if ($potentialOpenerFound === false || $delimiterProcessor instanceof CacheableDelimiterProcessorInterface) {
|
||||
$openersBottom[$openersBottomCacheKey] = self::getIndex($closer);
|
||||
}
|
||||
|
||||
if (! $potentialOpenerFound && ! $closer->canOpen()) {
|
||||
// We can remove a closer that can't be an opener,
|
||||
// once we've seen there's no matching opener.
|
||||
$next = $closer->getNext();
|
||||
$this->removeDelimiter($closer);
|
||||
$closer = $next;
|
||||
} else {
|
||||
$closer = $closer->getNext();
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
\assert($opener !== null);
|
||||
|
||||
$openerNode = $opener->getInlineNode();
|
||||
$closerNode = $closer->getInlineNode();
|
||||
|
||||
// Remove number of used delimiters from stack and inline nodes.
|
||||
$opener->setLength($opener->getLength() - $useDelims);
|
||||
$closer->setLength($closer->getLength() - $useDelims);
|
||||
|
||||
$openerNode->setLiteral(\substr($openerNode->getLiteral(), 0, -$useDelims));
|
||||
$closerNode->setLiteral(\substr($closerNode->getLiteral(), 0, -$useDelims));
|
||||
|
||||
$this->removeDelimitersBetween($opener, $closer);
|
||||
// The delimiter processor can re-parent the nodes between opener and closer,
|
||||
// so make sure they're contiguous already. Exclusive because we want to keep opener/closer themselves.
|
||||
AdjacentTextMerger::mergeTextNodesBetweenExclusive($openerNode, $closerNode);
|
||||
$delimiterProcessor->process($openerNode, $closerNode, $useDelims);
|
||||
|
||||
// No delimiter characters left to process, so we can remove delimiter and the now empty node.
|
||||
if ($opener->getLength() === 0) {
|
||||
$this->removeDelimiterAndNode($opener);
|
||||
}
|
||||
|
||||
// phpcs:disable SlevomatCodingStandard.ControlStructures.EarlyExit.EarlyExitNotUsed
|
||||
if ($closer->getLength() === 0) {
|
||||
$next = $closer->getNext();
|
||||
$this->removeDelimiterAndNode($closer);
|
||||
$closer = $next;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove all delimiters
|
||||
$this->removeAll($stackBottomPosition);
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
while ($this->top) {
|
||||
$this->removeDelimiter($this->top);
|
||||
}
|
||||
|
||||
while ($this->brackets) {
|
||||
$this->removeBracket();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method will be dropped in 3.0 once all delimiters MUST have an index/position
|
||||
*/
|
||||
private function getIndex(?DelimiterInterface $delimiter): int
|
||||
{
|
||||
if ($delimiter === null) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (($index = $delimiter->getIndex()) !== null) {
|
||||
return $index;
|
||||
}
|
||||
|
||||
if (isset($this->missingIndexCache[$delimiter])) {
|
||||
return $this->missingIndexCache[$delimiter];
|
||||
}
|
||||
|
||||
$prev = $delimiter->getPrevious();
|
||||
$next = $delimiter->getNext();
|
||||
|
||||
$i = 0;
|
||||
do {
|
||||
$i++;
|
||||
if ($prev === null) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ($prev->getIndex() !== null) {
|
||||
return $this->missingIndexCache[$delimiter] = $prev->getIndex() + $i;
|
||||
}
|
||||
} while ($prev = $prev->getPrevious());
|
||||
|
||||
$j = 0;
|
||||
do {
|
||||
$j++;
|
||||
if ($next === null) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ($next->getIndex() !== null) {
|
||||
return $this->missingIndexCache[$delimiter] = $next->getIndex() - $j;
|
||||
}
|
||||
} while ($next = $next->getNext());
|
||||
|
||||
// No index was defined on this delimiter, and none could be guesstimated based on the stack.
|
||||
return $this->missingIndexCache[$delimiter] = $this->getIndex($delimiter->getPrevious()) + 1;
|
||||
}
|
||||
}
|
||||
46
vendor/league/commonmark/src/Delimiter/Processor/CacheableDelimiterProcessorInterface.php
vendored
Normal file
46
vendor/league/commonmark/src/Delimiter/Processor/CacheableDelimiterProcessorInterface.php
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Delimiter\Processor;
|
||||
|
||||
use League\CommonMark\Delimiter\DelimiterInterface;
|
||||
|
||||
/**
|
||||
* Special marker interface for delimiter processors that return dynamic values from getDelimiterUse()
|
||||
*
|
||||
* In order to guarantee linear performance of delimiter processing, the delimiter stack must be able to
|
||||
* cache the lower bound when searching for a matching opener. This gets complicated for delimiter processors
|
||||
* that use a dynamic number of characters (like with emphasis and its "multiple of 3" rule).
|
||||
*/
|
||||
interface CacheableDelimiterProcessorInterface extends DelimiterProcessorInterface
|
||||
{
|
||||
/**
|
||||
* Returns a cache key of the factors that determine the number of characters to use.
|
||||
*
|
||||
* In order to guarantee linear performance of delimiter processing, the delimiter stack must be able to
|
||||
* cache the lower bound when searching for a matching opener. This lower bound is usually quite simple;
|
||||
* for example, with quotes, it's just the last opener with that characted. However, this gets complicated
|
||||
* for delimiter processors that use a dynamic number of characters (like with emphasis and its "multiple
|
||||
* of 3" rule), because the delimiter length being considered may change during processing because of that
|
||||
* dynamic logic in getDelimiterUse(). Therefore, we cannot safely cache the lower bound for these dynamic
|
||||
* processors without knowing the factors that determine the number of characters to use.
|
||||
*
|
||||
* At a minimum, this should include the delimiter character, plus any other factors used to determine
|
||||
* the result of getDelimiterUse(). The format of the string is not important so long as it is unique
|
||||
* (compared to other processors) and consistent for a given set of factors.
|
||||
*
|
||||
* If getDelimiterUse() always returns the same hard-coded value, this method should return just
|
||||
* the delimiter character.
|
||||
*/
|
||||
public function getCacheKey(DelimiterInterface $closer): string;
|
||||
}
|
||||
89
vendor/league/commonmark/src/Delimiter/Processor/DelimiterProcessorCollection.php
vendored
Normal file
89
vendor/league/commonmark/src/Delimiter/Processor/DelimiterProcessorCollection.php
vendored
Normal file
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
|
||||
* - (c) John MacFarlane
|
||||
*
|
||||
* Additional emphasis processing code based on commonmark-java (https://github.com/atlassian/commonmark-java)
|
||||
* - (c) Atlassian Pty Ltd
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Delimiter\Processor;
|
||||
|
||||
use League\CommonMark\Exception\InvalidArgumentException;
|
||||
|
||||
final class DelimiterProcessorCollection implements DelimiterProcessorCollectionInterface
|
||||
{
|
||||
/**
|
||||
* @var array<string,DelimiterProcessorInterface>|DelimiterProcessorInterface[]
|
||||
*
|
||||
* @psalm-readonly-allow-private-mutation
|
||||
*/
|
||||
private array $processorsByChar = [];
|
||||
|
||||
public function add(DelimiterProcessorInterface $processor): void
|
||||
{
|
||||
$opening = $processor->getOpeningCharacter();
|
||||
$closing = $processor->getClosingCharacter();
|
||||
|
||||
if ($opening === $closing) {
|
||||
$old = $this->processorsByChar[$opening] ?? null;
|
||||
if ($old !== null && $old->getOpeningCharacter() === $old->getClosingCharacter()) {
|
||||
$this->addStaggeredDelimiterProcessorForChar($opening, $old, $processor);
|
||||
} else {
|
||||
$this->addDelimiterProcessorForChar($opening, $processor);
|
||||
}
|
||||
} else {
|
||||
$this->addDelimiterProcessorForChar($opening, $processor);
|
||||
$this->addDelimiterProcessorForChar($closing, $processor);
|
||||
}
|
||||
}
|
||||
|
||||
public function getDelimiterProcessor(string $char): ?DelimiterProcessorInterface
|
||||
{
|
||||
return $this->processorsByChar[$char] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getDelimiterCharacters(): array
|
||||
{
|
||||
return \array_keys($this->processorsByChar);
|
||||
}
|
||||
|
||||
private function addDelimiterProcessorForChar(string $delimiterChar, DelimiterProcessorInterface $processor): void
|
||||
{
|
||||
if (isset($this->processorsByChar[$delimiterChar])) {
|
||||
throw new InvalidArgumentException(\sprintf('Delim processor for character "%s" already exists', $processor->getOpeningCharacter()));
|
||||
}
|
||||
|
||||
$this->processorsByChar[$delimiterChar] = $processor;
|
||||
}
|
||||
|
||||
private function addStaggeredDelimiterProcessorForChar(string $opening, DelimiterProcessorInterface $old, DelimiterProcessorInterface $new): void
|
||||
{
|
||||
if ($old instanceof StaggeredDelimiterProcessor) {
|
||||
$s = $old;
|
||||
} else {
|
||||
$s = new StaggeredDelimiterProcessor($opening, $old);
|
||||
}
|
||||
|
||||
$s->add($new);
|
||||
$this->processorsByChar[$opening] = $s;
|
||||
}
|
||||
|
||||
public function count(): int
|
||||
{
|
||||
return \count($this->processorsByChar);
|
||||
}
|
||||
}
|
||||
46
vendor/league/commonmark/src/Delimiter/Processor/DelimiterProcessorCollectionInterface.php
vendored
Normal file
46
vendor/league/commonmark/src/Delimiter/Processor/DelimiterProcessorCollectionInterface.php
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
|
||||
* - (c) John MacFarlane
|
||||
*
|
||||
* Additional emphasis processing code based on commonmark-java (https://github.com/atlassian/commonmark-java)
|
||||
* - (c) Atlassian Pty Ltd
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Delimiter\Processor;
|
||||
|
||||
use League\CommonMark\Exception\InvalidArgumentException;
|
||||
|
||||
interface DelimiterProcessorCollectionInterface extends \Countable
|
||||
{
|
||||
/**
|
||||
* Add the given delim processor to the collection
|
||||
*
|
||||
* @param DelimiterProcessorInterface $processor The delim processor to add
|
||||
*
|
||||
* @throws InvalidArgumentException Exception will be thrown if attempting to add multiple processors for the same character
|
||||
*/
|
||||
public function add(DelimiterProcessorInterface $processor): void;
|
||||
|
||||
/**
|
||||
* Returns the delim processor which handles the given character if one exists
|
||||
*/
|
||||
public function getDelimiterProcessor(string $char): ?DelimiterProcessorInterface;
|
||||
|
||||
/**
|
||||
* Returns an array of delimiter characters who have associated processors
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function getDelimiterCharacters(): array;
|
||||
}
|
||||
81
vendor/league/commonmark/src/Delimiter/Processor/DelimiterProcessorInterface.php
vendored
Normal file
81
vendor/league/commonmark/src/Delimiter/Processor/DelimiterProcessorInterface.php
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
|
||||
* - (c) John MacFarlane
|
||||
*
|
||||
* Additional emphasis processing code based on commonmark-java (https://github.com/atlassian/commonmark-java)
|
||||
* - (c) Atlassian Pty Ltd
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Delimiter\Processor;
|
||||
|
||||
use League\CommonMark\Delimiter\DelimiterInterface;
|
||||
use League\CommonMark\Node\Inline\AbstractStringContainer;
|
||||
|
||||
/**
|
||||
* Interface for a delimiter processor
|
||||
*/
|
||||
interface DelimiterProcessorInterface
|
||||
{
|
||||
/**
|
||||
* Returns the character that marks the beginning of a delimited node.
|
||||
*
|
||||
* This must not clash with any other processors being added to the environment.
|
||||
*/
|
||||
public function getOpeningCharacter(): string;
|
||||
|
||||
/**
|
||||
* Returns the character that marks the ending of a delimited node.
|
||||
*
|
||||
* This must not clash with any other processors being added to the environment.
|
||||
*
|
||||
* Note that for a symmetric delimiter such as "*", this is the same as the opening.
|
||||
*/
|
||||
public function getClosingCharacter(): string;
|
||||
|
||||
/**
|
||||
* Minimum number of delimiter characters that are needed to active this.
|
||||
*
|
||||
* Must be at least 1.
|
||||
*/
|
||||
public function getMinLength(): int;
|
||||
|
||||
/**
|
||||
* Determine how many (if any) of the delimiter characters should be used.
|
||||
*
|
||||
* This allows implementations to decide how many characters to be used
|
||||
* based on the properties of the delimiter runs. An implementation can also
|
||||
* return 0 when it doesn't want to allow this particular combination of
|
||||
* delimiter runs.
|
||||
*
|
||||
* IMPORTANT: Unless this method returns the same hard-coded value in all cases,
|
||||
* you MUST implement the CacheableDelimiterProcessorInterface interface instead.
|
||||
*
|
||||
* @param DelimiterInterface $opener The opening delimiter run
|
||||
* @param DelimiterInterface $closer The closing delimiter run
|
||||
*/
|
||||
public function getDelimiterUse(DelimiterInterface $opener, DelimiterInterface $closer): int;
|
||||
|
||||
/**
|
||||
* Process the matched delimiters, e.g. by wrapping the nodes between opener
|
||||
* and closer in a new node, or appending a new node after the opener.
|
||||
*
|
||||
* Note that removal of the delimiter from the delimiter nodes and detaching
|
||||
* them is done by the caller.
|
||||
*
|
||||
* @param AbstractStringContainer $opener The node that contained the opening delimiter
|
||||
* @param AbstractStringContainer $closer The node that contained the closing delimiter
|
||||
* @param int $delimiterUse The number of delimiters that were used
|
||||
*/
|
||||
public function process(AbstractStringContainer $opener, AbstractStringContainer $closer, int $delimiterUse): void;
|
||||
}
|
||||
111
vendor/league/commonmark/src/Delimiter/Processor/StaggeredDelimiterProcessor.php
vendored
Normal file
111
vendor/league/commonmark/src/Delimiter/Processor/StaggeredDelimiterProcessor.php
vendored
Normal file
@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* Additional emphasis processing code based on commonmark-java (https://github.com/atlassian/commonmark-java)
|
||||
* - (c) Atlassian Pty Ltd
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Delimiter\Processor;
|
||||
|
||||
use League\CommonMark\Delimiter\DelimiterInterface;
|
||||
use League\CommonMark\Exception\InvalidArgumentException;
|
||||
use League\CommonMark\Node\Inline\AbstractStringContainer;
|
||||
|
||||
/**
|
||||
* An implementation of DelimiterProcessorInterface that dispatches all calls to two or more other DelimiterProcessors
|
||||
* depending on the length of the delimiter run. All child DelimiterProcessors must have different minimum
|
||||
* lengths. A given delimiter run is dispatched to the child with the largest acceptable minimum length. If no
|
||||
* child is applicable, the one with the largest minimum length is chosen.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class StaggeredDelimiterProcessor implements DelimiterProcessorInterface
|
||||
{
|
||||
/** @psalm-readonly */
|
||||
private string $delimiterChar;
|
||||
|
||||
/** @psalm-readonly-allow-private-mutation */
|
||||
private int $minLength = 0;
|
||||
|
||||
/**
|
||||
* @var array<int, DelimiterProcessorInterface>|DelimiterProcessorInterface[]
|
||||
*
|
||||
* @psalm-readonly-allow-private-mutation
|
||||
*/
|
||||
private array $processors = []; // keyed by minLength in reverse order
|
||||
|
||||
public function __construct(string $char, DelimiterProcessorInterface $processor)
|
||||
{
|
||||
$this->delimiterChar = $char;
|
||||
$this->add($processor);
|
||||
}
|
||||
|
||||
public function getOpeningCharacter(): string
|
||||
{
|
||||
return $this->delimiterChar;
|
||||
}
|
||||
|
||||
public function getClosingCharacter(): string
|
||||
{
|
||||
return $this->delimiterChar;
|
||||
}
|
||||
|
||||
public function getMinLength(): int
|
||||
{
|
||||
return $this->minLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given processor to this staggered delimiter processor
|
||||
*
|
||||
* @throws InvalidArgumentException if attempting to add another processors for the same character and minimum length
|
||||
*/
|
||||
public function add(DelimiterProcessorInterface $processor): void
|
||||
{
|
||||
$len = $processor->getMinLength();
|
||||
|
||||
if (isset($this->processors[$len])) {
|
||||
throw new InvalidArgumentException(\sprintf('Cannot add two delimiter processors for char "%s" and minimum length %d', $this->delimiterChar, $len));
|
||||
}
|
||||
|
||||
$this->processors[$len] = $processor;
|
||||
\krsort($this->processors);
|
||||
|
||||
$this->minLength = \min($this->minLength, $len);
|
||||
}
|
||||
|
||||
public function getDelimiterUse(DelimiterInterface $opener, DelimiterInterface $closer): int
|
||||
{
|
||||
return $this->findProcessor($opener->getLength())->getDelimiterUse($opener, $closer);
|
||||
}
|
||||
|
||||
public function process(AbstractStringContainer $opener, AbstractStringContainer $closer, int $delimiterUse): void
|
||||
{
|
||||
$this->findProcessor($delimiterUse)->process($opener, $closer, $delimiterUse);
|
||||
}
|
||||
|
||||
private function findProcessor(int $len): DelimiterProcessorInterface
|
||||
{
|
||||
// Find the "longest" processor which can handle this length
|
||||
foreach ($this->processors as $processor) {
|
||||
if ($processor->getMinLength() <= $len) {
|
||||
return $processor;
|
||||
}
|
||||
}
|
||||
|
||||
// Just use the first one in our list
|
||||
$first = \reset($this->processors);
|
||||
\assert($first instanceof DelimiterProcessorInterface);
|
||||
|
||||
return $first;
|
||||
}
|
||||
}
|
||||
448
vendor/league/commonmark/src/Environment/Environment.php
vendored
Normal file
448
vendor/league/commonmark/src/Environment/Environment.php
vendored
Normal file
@ -0,0 +1,448 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
|
||||
* - (c) John MacFarlane
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Environment;
|
||||
|
||||
use League\CommonMark\Delimiter\DelimiterParser;
|
||||
use League\CommonMark\Delimiter\Processor\DelimiterProcessorCollection;
|
||||
use League\CommonMark\Delimiter\Processor\DelimiterProcessorInterface;
|
||||
use League\CommonMark\Event\DocumentParsedEvent;
|
||||
use League\CommonMark\Event\ListenerData;
|
||||
use League\CommonMark\Exception\AlreadyInitializedException;
|
||||
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
|
||||
use League\CommonMark\Extension\ConfigurableExtensionInterface;
|
||||
use League\CommonMark\Extension\ExtensionInterface;
|
||||
use League\CommonMark\Extension\GithubFlavoredMarkdownExtension;
|
||||
use League\CommonMark\Normalizer\SlugNormalizer;
|
||||
use League\CommonMark\Normalizer\TextNormalizerInterface;
|
||||
use League\CommonMark\Normalizer\UniqueSlugNormalizer;
|
||||
use League\CommonMark\Normalizer\UniqueSlugNormalizerInterface;
|
||||
use League\CommonMark\Parser\Block\BlockStartParserInterface;
|
||||
use League\CommonMark\Parser\Block\SkipLinesStartingWithLettersParser;
|
||||
use League\CommonMark\Parser\Inline\InlineParserInterface;
|
||||
use League\CommonMark\Renderer\NodeRendererInterface;
|
||||
use League\CommonMark\Util\HtmlFilter;
|
||||
use League\CommonMark\Util\PrioritizedList;
|
||||
use League\Config\Configuration;
|
||||
use League\Config\ConfigurationAwareInterface;
|
||||
use League\Config\ConfigurationInterface;
|
||||
use Nette\Schema\Expect;
|
||||
use Psr\EventDispatcher\EventDispatcherInterface;
|
||||
use Psr\EventDispatcher\ListenerProviderInterface;
|
||||
use Psr\EventDispatcher\StoppableEventInterface;
|
||||
|
||||
final class Environment implements EnvironmentInterface, EnvironmentBuilderInterface, ListenerProviderInterface
|
||||
{
|
||||
/**
|
||||
* @var ExtensionInterface[]
|
||||
*
|
||||
* @psalm-readonly-allow-private-mutation
|
||||
*/
|
||||
private array $extensions = [];
|
||||
|
||||
/**
|
||||
* @var ExtensionInterface[]
|
||||
*
|
||||
* @psalm-readonly-allow-private-mutation
|
||||
*/
|
||||
private array $uninitializedExtensions = [];
|
||||
|
||||
/** @psalm-readonly-allow-private-mutation */
|
||||
private bool $extensionsInitialized = false;
|
||||
|
||||
/**
|
||||
* @var PrioritizedList<BlockStartParserInterface>
|
||||
*
|
||||
* @psalm-readonly
|
||||
*/
|
||||
private PrioritizedList $blockStartParsers;
|
||||
|
||||
/**
|
||||
* @var PrioritizedList<InlineParserInterface>
|
||||
*
|
||||
* @psalm-readonly
|
||||
*/
|
||||
private PrioritizedList $inlineParsers;
|
||||
|
||||
/** @psalm-readonly */
|
||||
private DelimiterProcessorCollection $delimiterProcessors;
|
||||
|
||||
/**
|
||||
* @var array<string, PrioritizedList<NodeRendererInterface>>
|
||||
*
|
||||
* @psalm-readonly-allow-private-mutation
|
||||
*/
|
||||
private array $renderersByClass = [];
|
||||
|
||||
/**
|
||||
* @var PrioritizedList<ListenerData>
|
||||
*
|
||||
* @psalm-readonly-allow-private-mutation
|
||||
*/
|
||||
private PrioritizedList $listenerData;
|
||||
|
||||
private ?EventDispatcherInterface $eventDispatcher = null;
|
||||
|
||||
/** @psalm-readonly */
|
||||
private Configuration $config;
|
||||
|
||||
private ?TextNormalizerInterface $slugNormalizer = null;
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $config
|
||||
*/
|
||||
public function __construct(array $config = [])
|
||||
{
|
||||
$this->config = self::createDefaultConfiguration();
|
||||
$this->config->merge($config);
|
||||
|
||||
$this->blockStartParsers = new PrioritizedList();
|
||||
$this->inlineParsers = new PrioritizedList();
|
||||
$this->listenerData = new PrioritizedList();
|
||||
$this->delimiterProcessors = new DelimiterProcessorCollection();
|
||||
|
||||
// Performance optimization: always include a block "parser" that aborts parsing if a line starts with a letter
|
||||
// and is therefore unlikely to match any lines as a block start.
|
||||
$this->addBlockStartParser(new SkipLinesStartingWithLettersParser(), 249);
|
||||
}
|
||||
|
||||
public function getConfiguration(): ConfigurationInterface
|
||||
{
|
||||
return $this->config->reader();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Environment::mergeConfig() is deprecated since league/commonmark v2.0 and will be removed in v3.0. Configuration should be set when instantiating the environment instead.
|
||||
*
|
||||
* @param array<string, mixed> $config
|
||||
*/
|
||||
public function mergeConfig(array $config): void
|
||||
{
|
||||
@\trigger_error('Environment::mergeConfig() is deprecated since league/commonmark v2.0 and will be removed in v3.0. Configuration should be set when instantiating the environment instead.', \E_USER_DEPRECATED);
|
||||
|
||||
$this->assertUninitialized('Failed to modify configuration.');
|
||||
|
||||
$this->config->merge($config);
|
||||
}
|
||||
|
||||
public function addBlockStartParser(BlockStartParserInterface $parser, int $priority = 0): EnvironmentBuilderInterface
|
||||
{
|
||||
$this->assertUninitialized('Failed to add block start parser.');
|
||||
|
||||
$this->blockStartParsers->add($parser, $priority);
|
||||
$this->injectEnvironmentAndConfigurationIfNeeded($parser);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addInlineParser(InlineParserInterface $parser, int $priority = 0): EnvironmentBuilderInterface
|
||||
{
|
||||
$this->assertUninitialized('Failed to add inline parser.');
|
||||
|
||||
$this->inlineParsers->add($parser, $priority);
|
||||
$this->injectEnvironmentAndConfigurationIfNeeded($parser);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addDelimiterProcessor(DelimiterProcessorInterface $processor): EnvironmentBuilderInterface
|
||||
{
|
||||
$this->assertUninitialized('Failed to add delimiter processor.');
|
||||
$this->delimiterProcessors->add($processor);
|
||||
$this->injectEnvironmentAndConfigurationIfNeeded($processor);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addRenderer(string $nodeClass, NodeRendererInterface $renderer, int $priority = 0): EnvironmentBuilderInterface
|
||||
{
|
||||
$this->assertUninitialized('Failed to add renderer.');
|
||||
|
||||
if (! isset($this->renderersByClass[$nodeClass])) {
|
||||
$this->renderersByClass[$nodeClass] = new PrioritizedList();
|
||||
}
|
||||
|
||||
$this->renderersByClass[$nodeClass]->add($renderer, $priority);
|
||||
$this->injectEnvironmentAndConfigurationIfNeeded($renderer);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getBlockStartParsers(): iterable
|
||||
{
|
||||
if (! $this->extensionsInitialized) {
|
||||
$this->initializeExtensions();
|
||||
}
|
||||
|
||||
return $this->blockStartParsers->getIterator();
|
||||
}
|
||||
|
||||
public function getDelimiterProcessors(): DelimiterProcessorCollection
|
||||
{
|
||||
if (! $this->extensionsInitialized) {
|
||||
$this->initializeExtensions();
|
||||
}
|
||||
|
||||
return $this->delimiterProcessors;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getRenderersForClass(string $nodeClass): iterable
|
||||
{
|
||||
if (! $this->extensionsInitialized) {
|
||||
$this->initializeExtensions();
|
||||
}
|
||||
|
||||
// If renderers are defined for this specific class, return them immediately
|
||||
if (isset($this->renderersByClass[$nodeClass])) {
|
||||
return $this->renderersByClass[$nodeClass];
|
||||
}
|
||||
|
||||
/** @psalm-suppress TypeDoesNotContainType -- Bug: https://github.com/vimeo/psalm/issues/3332 */
|
||||
while (\class_exists($parent ??= $nodeClass) && $parent = \get_parent_class($parent)) {
|
||||
if (! isset($this->renderersByClass[$parent])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// "Cache" this result to avoid future loops
|
||||
return $this->renderersByClass[$nodeClass] = $this->renderersByClass[$parent];
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getExtensions(): iterable
|
||||
{
|
||||
return $this->extensions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a single extension
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addExtension(ExtensionInterface $extension): EnvironmentBuilderInterface
|
||||
{
|
||||
$this->assertUninitialized('Failed to add extension.');
|
||||
|
||||
$this->extensions[] = $extension;
|
||||
$this->uninitializedExtensions[] = $extension;
|
||||
|
||||
if ($extension instanceof ConfigurableExtensionInterface) {
|
||||
$extension->configureSchema($this->config);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function initializeExtensions(): void
|
||||
{
|
||||
// Initialize the slug normalizer
|
||||
$this->getSlugNormalizer();
|
||||
|
||||
// Ask all extensions to register their components
|
||||
while (\count($this->uninitializedExtensions) > 0) {
|
||||
foreach ($this->uninitializedExtensions as $i => $extension) {
|
||||
$extension->register($this);
|
||||
unset($this->uninitializedExtensions[$i]);
|
||||
}
|
||||
}
|
||||
|
||||
$this->extensionsInitialized = true;
|
||||
|
||||
// Create the special delimiter parser if any processors were registered
|
||||
if ($this->delimiterProcessors->count() > 0) {
|
||||
$this->inlineParsers->add(new DelimiterParser($this->delimiterProcessors), PHP_INT_MIN);
|
||||
}
|
||||
}
|
||||
|
||||
private function injectEnvironmentAndConfigurationIfNeeded(object $object): void
|
||||
{
|
||||
if ($object instanceof EnvironmentAwareInterface) {
|
||||
$object->setEnvironment($this);
|
||||
}
|
||||
|
||||
if ($object instanceof ConfigurationAwareInterface) {
|
||||
$object->setConfiguration($this->config->reader());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Instantiate the environment and add the extension yourself
|
||||
*
|
||||
* @param array<string, mixed> $config
|
||||
*/
|
||||
public static function createCommonMarkEnvironment(array $config = []): Environment
|
||||
{
|
||||
$environment = new self($config);
|
||||
$environment->addExtension(new CommonMarkCoreExtension());
|
||||
|
||||
return $environment;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Instantiate the environment and add the extension yourself
|
||||
*
|
||||
* @param array<string, mixed> $config
|
||||
*/
|
||||
public static function createGFMEnvironment(array $config = []): Environment
|
||||
{
|
||||
$environment = new self($config);
|
||||
$environment->addExtension(new CommonMarkCoreExtension());
|
||||
$environment->addExtension(new GithubFlavoredMarkdownExtension());
|
||||
|
||||
return $environment;
|
||||
}
|
||||
|
||||
public function addEventListener(string $eventClass, callable $listener, int $priority = 0): EnvironmentBuilderInterface
|
||||
{
|
||||
$this->assertUninitialized('Failed to add event listener.');
|
||||
|
||||
$this->listenerData->add(new ListenerData($eventClass, $listener), $priority);
|
||||
|
||||
if (\is_object($listener)) {
|
||||
$this->injectEnvironmentAndConfigurationIfNeeded($listener);
|
||||
} elseif (\is_array($listener) && \is_object($listener[0])) {
|
||||
$this->injectEnvironmentAndConfigurationIfNeeded($listener[0]);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function dispatch(object $event): object
|
||||
{
|
||||
if (! $this->extensionsInitialized) {
|
||||
$this->initializeExtensions();
|
||||
}
|
||||
|
||||
if ($this->eventDispatcher !== null) {
|
||||
return $this->eventDispatcher->dispatch($event);
|
||||
}
|
||||
|
||||
foreach ($this->getListenersForEvent($event) as $listener) {
|
||||
if ($event instanceof StoppableEventInterface && $event->isPropagationStopped()) {
|
||||
return $event;
|
||||
}
|
||||
|
||||
$listener($event);
|
||||
}
|
||||
|
||||
return $event;
|
||||
}
|
||||
|
||||
public function setEventDispatcher(EventDispatcherInterface $dispatcher): void
|
||||
{
|
||||
$this->eventDispatcher = $dispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @return iterable<callable>
|
||||
*/
|
||||
public function getListenersForEvent(object $event): iterable
|
||||
{
|
||||
foreach ($this->listenerData as $listenerData) {
|
||||
\assert($listenerData instanceof ListenerData);
|
||||
|
||||
/** @psalm-suppress ArgumentTypeCoercion */
|
||||
if (! \is_a($event, $listenerData->getEvent())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
yield function (object $event) use ($listenerData) {
|
||||
if (! $this->extensionsInitialized) {
|
||||
$this->initializeExtensions();
|
||||
}
|
||||
|
||||
return \call_user_func($listenerData->getListener(), $event);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return iterable<InlineParserInterface>
|
||||
*/
|
||||
public function getInlineParsers(): iterable
|
||||
{
|
||||
if (! $this->extensionsInitialized) {
|
||||
$this->initializeExtensions();
|
||||
}
|
||||
|
||||
return $this->inlineParsers->getIterator();
|
||||
}
|
||||
|
||||
public function getSlugNormalizer(): TextNormalizerInterface
|
||||
{
|
||||
if ($this->slugNormalizer === null) {
|
||||
$normalizer = $this->config->get('slug_normalizer/instance');
|
||||
\assert($normalizer instanceof TextNormalizerInterface);
|
||||
$this->injectEnvironmentAndConfigurationIfNeeded($normalizer);
|
||||
|
||||
if ($this->config->get('slug_normalizer/unique') !== UniqueSlugNormalizerInterface::DISABLED && ! $normalizer instanceof UniqueSlugNormalizer) {
|
||||
$normalizer = new UniqueSlugNormalizer($normalizer);
|
||||
}
|
||||
|
||||
if ($normalizer instanceof UniqueSlugNormalizer) {
|
||||
if ($this->config->get('slug_normalizer/unique') === UniqueSlugNormalizerInterface::PER_DOCUMENT) {
|
||||
$this->addEventListener(DocumentParsedEvent::class, [$normalizer, 'clearHistory'], -1000);
|
||||
}
|
||||
}
|
||||
|
||||
$this->slugNormalizer = $normalizer;
|
||||
}
|
||||
|
||||
return $this->slugNormalizer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws AlreadyInitializedException
|
||||
*/
|
||||
private function assertUninitialized(string $message): void
|
||||
{
|
||||
if ($this->extensionsInitialized) {
|
||||
throw new AlreadyInitializedException($message . ' Extensions have already been initialized.');
|
||||
}
|
||||
}
|
||||
|
||||
public static function createDefaultConfiguration(): Configuration
|
||||
{
|
||||
return new Configuration([
|
||||
'html_input' => Expect::anyOf(HtmlFilter::STRIP, HtmlFilter::ALLOW, HtmlFilter::ESCAPE)->default(HtmlFilter::ALLOW),
|
||||
'allow_unsafe_links' => Expect::bool(true),
|
||||
'max_nesting_level' => Expect::type('int')->default(PHP_INT_MAX),
|
||||
'max_delimiters_per_line' => Expect::type('int')->default(PHP_INT_MAX),
|
||||
'renderer' => Expect::structure([
|
||||
'block_separator' => Expect::string("\n"),
|
||||
'inner_separator' => Expect::string("\n"),
|
||||
'soft_break' => Expect::string("\n"),
|
||||
]),
|
||||
'slug_normalizer' => Expect::structure([
|
||||
'instance' => Expect::type(TextNormalizerInterface::class)->default(new SlugNormalizer()),
|
||||
'max_length' => Expect::int()->min(0)->default(255),
|
||||
'unique' => Expect::anyOf(UniqueSlugNormalizerInterface::DISABLED, UniqueSlugNormalizerInterface::PER_ENVIRONMENT, UniqueSlugNormalizerInterface::PER_DOCUMENT)->default(UniqueSlugNormalizerInterface::PER_DOCUMENT),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
}
|
||||
19
vendor/league/commonmark/src/Environment/EnvironmentAwareInterface.php
vendored
Normal file
19
vendor/league/commonmark/src/Environment/EnvironmentAwareInterface.php
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Environment;
|
||||
|
||||
interface EnvironmentAwareInterface
|
||||
{
|
||||
public function setEnvironment(EnvironmentInterface $environment): void;
|
||||
}
|
||||
97
vendor/league/commonmark/src/Environment/EnvironmentBuilderInterface.php
vendored
Normal file
97
vendor/league/commonmark/src/Environment/EnvironmentBuilderInterface.php
vendored
Normal file
@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Environment;
|
||||
|
||||
use League\CommonMark\Delimiter\Processor\DelimiterProcessorInterface;
|
||||
use League\CommonMark\Exception\AlreadyInitializedException;
|
||||
use League\CommonMark\Extension\ExtensionInterface;
|
||||
use League\CommonMark\Node\Node;
|
||||
use League\CommonMark\Parser\Block\BlockStartParserInterface;
|
||||
use League\CommonMark\Parser\Inline\InlineParserInterface;
|
||||
use League\CommonMark\Renderer\NodeRendererInterface;
|
||||
use League\Config\ConfigurationProviderInterface;
|
||||
|
||||
/**
|
||||
* Interface for building the Environment with any extensions, parsers, listeners, etc. that it may need
|
||||
*/
|
||||
interface EnvironmentBuilderInterface extends ConfigurationProviderInterface
|
||||
{
|
||||
/**
|
||||
* Registers the given extension with the Environment
|
||||
*
|
||||
* @throws AlreadyInitializedException if the Environment has already been initialized
|
||||
*/
|
||||
public function addExtension(ExtensionInterface $extension): EnvironmentBuilderInterface;
|
||||
|
||||
/**
|
||||
* Registers the given block start parser with the Environment
|
||||
*
|
||||
* @param BlockStartParserInterface $parser Block parser instance
|
||||
* @param int $priority Priority (a higher number will be executed earlier)
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @throws AlreadyInitializedException if the Environment has already been initialized
|
||||
*/
|
||||
public function addBlockStartParser(BlockStartParserInterface $parser, int $priority = 0): EnvironmentBuilderInterface;
|
||||
|
||||
/**
|
||||
* Registers the given inline parser with the Environment
|
||||
*
|
||||
* @param InlineParserInterface $parser Inline parser instance
|
||||
* @param int $priority Priority (a higher number will be executed earlier)
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @throws AlreadyInitializedException if the Environment has already been initialized
|
||||
*/
|
||||
public function addInlineParser(InlineParserInterface $parser, int $priority = 0): EnvironmentBuilderInterface;
|
||||
|
||||
/**
|
||||
* Registers the given delimiter processor with the Environment
|
||||
*
|
||||
* @param DelimiterProcessorInterface $processor Delimiter processors instance
|
||||
*
|
||||
* @throws AlreadyInitializedException if the Environment has already been initialized
|
||||
*/
|
||||
public function addDelimiterProcessor(DelimiterProcessorInterface $processor): EnvironmentBuilderInterface;
|
||||
|
||||
/**
|
||||
* Registers the given node renderer with the Environment
|
||||
*
|
||||
* @param string $nodeClass The fully-qualified node element class name the renderer below should handle
|
||||
* @param NodeRendererInterface $renderer The renderer responsible for rendering the type of element given above
|
||||
* @param int $priority Priority (a higher number will be executed earlier)
|
||||
*
|
||||
* @psalm-param class-string<Node> $nodeClass
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @throws AlreadyInitializedException if the Environment has already been initialized
|
||||
*/
|
||||
public function addRenderer(string $nodeClass, NodeRendererInterface $renderer, int $priority = 0): EnvironmentBuilderInterface;
|
||||
|
||||
/**
|
||||
* Registers the given event listener
|
||||
*
|
||||
* @param class-string $eventClass Fully-qualified class name of the event this listener should respond to
|
||||
* @param callable $listener Listener to be executed
|
||||
* @param int $priority Priority (a higher number will be executed earlier)
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* @throws AlreadyInitializedException if the Environment has already been initialized
|
||||
*/
|
||||
public function addEventListener(string $eventClass, callable $listener, int $priority = 0): EnvironmentBuilderInterface;
|
||||
}
|
||||
55
vendor/league/commonmark/src/Environment/EnvironmentInterface.php
vendored
Normal file
55
vendor/league/commonmark/src/Environment/EnvironmentInterface.php
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Environment;
|
||||
|
||||
use League\CommonMark\Delimiter\Processor\DelimiterProcessorCollection;
|
||||
use League\CommonMark\Extension\ExtensionInterface;
|
||||
use League\CommonMark\Node\Node;
|
||||
use League\CommonMark\Normalizer\TextNormalizerInterface;
|
||||
use League\CommonMark\Parser\Block\BlockStartParserInterface;
|
||||
use League\CommonMark\Parser\Inline\InlineParserInterface;
|
||||
use League\CommonMark\Renderer\NodeRendererInterface;
|
||||
use League\Config\ConfigurationProviderInterface;
|
||||
use Psr\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
interface EnvironmentInterface extends ConfigurationProviderInterface, EventDispatcherInterface
|
||||
{
|
||||
/**
|
||||
* Get all registered extensions
|
||||
*
|
||||
* @return ExtensionInterface[]
|
||||
*/
|
||||
public function getExtensions(): iterable;
|
||||
|
||||
/**
|
||||
* @return iterable<BlockStartParserInterface>
|
||||
*/
|
||||
public function getBlockStartParsers(): iterable;
|
||||
|
||||
/**
|
||||
* @return iterable<InlineParserInterface>
|
||||
*/
|
||||
public function getInlineParsers(): iterable;
|
||||
|
||||
public function getDelimiterProcessors(): DelimiterProcessorCollection;
|
||||
|
||||
/**
|
||||
* @psalm-param class-string<Node> $nodeClass
|
||||
*
|
||||
* @return iterable<NodeRendererInterface>
|
||||
*/
|
||||
public function getRenderersForClass(string $nodeClass): iterable;
|
||||
|
||||
public function getSlugNormalizer(): TextNormalizerInterface;
|
||||
}
|
||||
54
vendor/league/commonmark/src/Event/AbstractEvent.php
vendored
Normal file
54
vendor/league/commonmark/src/Event/AbstractEvent.php
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* Original code based on the Symfony EventDispatcher "Event" contract
|
||||
* - (c) 2018-2019 Fabien Potencier
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Event;
|
||||
|
||||
use Psr\EventDispatcher\StoppableEventInterface;
|
||||
|
||||
/**
|
||||
* Base class for classes containing event data.
|
||||
*
|
||||
* This class contains no event data. It is used by events that do not pass
|
||||
* state information to an event handler when an event is raised.
|
||||
*
|
||||
* You can call the method stopPropagation() to abort the execution of
|
||||
* further listeners in your event listener.
|
||||
*/
|
||||
abstract class AbstractEvent implements StoppableEventInterface
|
||||
{
|
||||
/** @psalm-readonly-allow-private-mutation */
|
||||
private bool $propagationStopped = false;
|
||||
|
||||
/**
|
||||
* Returns whether further event listeners should be triggered.
|
||||
*/
|
||||
final public function isPropagationStopped(): bool
|
||||
{
|
||||
return $this->propagationStopped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the propagation of the event to further event listeners.
|
||||
*
|
||||
* If multiple event listeners are connected to the same event, no
|
||||
* further event listener will be triggered once any trigger calls
|
||||
* stopPropagation().
|
||||
*/
|
||||
final public function stopPropagation(): void
|
||||
{
|
||||
$this->propagationStopped = true;
|
||||
}
|
||||
}
|
||||
35
vendor/league/commonmark/src/Event/DocumentParsedEvent.php
vendored
Normal file
35
vendor/league/commonmark/src/Event/DocumentParsedEvent.php
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Event;
|
||||
|
||||
use League\CommonMark\Node\Block\Document;
|
||||
|
||||
/**
|
||||
* Event dispatched when the document has been fully parsed
|
||||
*/
|
||||
final class DocumentParsedEvent extends AbstractEvent
|
||||
{
|
||||
/** @psalm-readonly */
|
||||
private Document $document;
|
||||
|
||||
public function __construct(Document $document)
|
||||
{
|
||||
$this->document = $document;
|
||||
}
|
||||
|
||||
public function getDocument(): Document
|
||||
{
|
||||
return $this->document;
|
||||
}
|
||||
}
|
||||
49
vendor/league/commonmark/src/Event/DocumentPreParsedEvent.php
vendored
Normal file
49
vendor/league/commonmark/src/Event/DocumentPreParsedEvent.php
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Event;
|
||||
|
||||
use League\CommonMark\Input\MarkdownInputInterface;
|
||||
use League\CommonMark\Node\Block\Document;
|
||||
|
||||
/**
|
||||
* Event dispatched when the document is about to be parsed
|
||||
*/
|
||||
final class DocumentPreParsedEvent extends AbstractEvent
|
||||
{
|
||||
/** @psalm-readonly */
|
||||
private Document $document;
|
||||
|
||||
private MarkdownInputInterface $markdown;
|
||||
|
||||
public function __construct(Document $document, MarkdownInputInterface $markdown)
|
||||
{
|
||||
$this->document = $document;
|
||||
$this->markdown = $markdown;
|
||||
}
|
||||
|
||||
public function getDocument(): Document
|
||||
{
|
||||
return $this->document;
|
||||
}
|
||||
|
||||
public function getMarkdown(): MarkdownInputInterface
|
||||
{
|
||||
return $this->markdown;
|
||||
}
|
||||
|
||||
public function replaceMarkdown(MarkdownInputInterface $markdownInput): void
|
||||
{
|
||||
$this->markdown = $markdownInput;
|
||||
}
|
||||
}
|
||||
44
vendor/league/commonmark/src/Event/DocumentPreRenderEvent.php
vendored
Normal file
44
vendor/league/commonmark/src/Event/DocumentPreRenderEvent.php
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Event;
|
||||
|
||||
use League\CommonMark\Node\Block\Document;
|
||||
|
||||
/**
|
||||
* Event dispatched just before rendering begins
|
||||
*/
|
||||
final class DocumentPreRenderEvent extends AbstractEvent
|
||||
{
|
||||
/** @psalm-readonly */
|
||||
private Document $document;
|
||||
|
||||
/** @psalm-readonly */
|
||||
private string $format;
|
||||
|
||||
public function __construct(Document $document, string $format)
|
||||
{
|
||||
$this->document = $document;
|
||||
$this->format = $format;
|
||||
}
|
||||
|
||||
public function getDocument(): Document
|
||||
{
|
||||
return $this->document;
|
||||
}
|
||||
|
||||
public function getFormat(): string
|
||||
{
|
||||
return $this->format;
|
||||
}
|
||||
}
|
||||
42
vendor/league/commonmark/src/Event/DocumentRenderedEvent.php
vendored
Normal file
42
vendor/league/commonmark/src/Event/DocumentRenderedEvent.php
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\CommonMark\Event;
|
||||
|
||||
use League\CommonMark\Output\RenderedContentInterface;
|
||||
|
||||
final class DocumentRenderedEvent extends AbstractEvent
|
||||
{
|
||||
private RenderedContentInterface $output;
|
||||
|
||||
public function __construct(RenderedContentInterface $output)
|
||||
{
|
||||
$this->output = $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-mutation-free
|
||||
*/
|
||||
public function getOutput(): RenderedContentInterface
|
||||
{
|
||||
return $this->output;
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-external-mutation-free
|
||||
*/
|
||||
public function replaceOutput(RenderedContentInterface $output): void
|
||||
{
|
||||
$this->output = $output;
|
||||
}
|
||||
}
|
||||
50
vendor/league/commonmark/src/Event/ListenerData.php
vendored
Normal file
50
vendor/league/commonmark/src/Event/ListenerData.php
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Event;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
final class ListenerData
|
||||
{
|
||||
/** @var class-string */
|
||||
private string $event;
|
||||
|
||||
/** @var callable */
|
||||
private $listener;
|
||||
|
||||
/**
|
||||
* @param class-string $event
|
||||
*/
|
||||
public function __construct(string $event, callable $listener)
|
||||
{
|
||||
$this->event = $event;
|
||||
$this->listener = $listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return class-string
|
||||
*/
|
||||
public function getEvent(): string
|
||||
{
|
||||
return $this->event;
|
||||
}
|
||||
|
||||
public function getListener(): callable
|
||||
{
|
||||
return $this->listener;
|
||||
}
|
||||
}
|
||||
18
vendor/league/commonmark/src/Exception/AlreadyInitializedException.php
vendored
Normal file
18
vendor/league/commonmark/src/Exception/AlreadyInitializedException.php
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Exception;
|
||||
|
||||
class AlreadyInitializedException extends LogicException implements CommonMarkException
|
||||
{
|
||||
}
|
||||
21
vendor/league/commonmark/src/Exception/CommonMarkException.php
vendored
Normal file
21
vendor/league/commonmark/src/Exception/CommonMarkException.php
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Exception;
|
||||
|
||||
/**
|
||||
* Marker interface for all exceptions thrown by this library.
|
||||
*/
|
||||
interface CommonMarkException extends \Throwable
|
||||
{
|
||||
}
|
||||
18
vendor/league/commonmark/src/Exception/IOException.php
vendored
Normal file
18
vendor/league/commonmark/src/Exception/IOException.php
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Exception;
|
||||
|
||||
class IOException extends \RuntimeException implements CommonMarkException
|
||||
{
|
||||
}
|
||||
18
vendor/league/commonmark/src/Exception/InvalidArgumentException.php
vendored
Normal file
18
vendor/league/commonmark/src/Exception/InvalidArgumentException.php
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Exception;
|
||||
|
||||
class InvalidArgumentException extends \InvalidArgumentException implements CommonMarkException
|
||||
{
|
||||
}
|
||||
18
vendor/league/commonmark/src/Exception/LogicException.php
vendored
Normal file
18
vendor/league/commonmark/src/Exception/LogicException.php
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Exception;
|
||||
|
||||
class LogicException extends \LogicException implements CommonMarkException
|
||||
{
|
||||
}
|
||||
18
vendor/league/commonmark/src/Exception/MissingDependencyException.php
vendored
Normal file
18
vendor/league/commonmark/src/Exception/MissingDependencyException.php
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Exception;
|
||||
|
||||
class MissingDependencyException extends \RuntimeException implements CommonMarkException
|
||||
{
|
||||
}
|
||||
18
vendor/league/commonmark/src/Exception/UnexpectedEncodingException.php
vendored
Normal file
18
vendor/league/commonmark/src/Exception/UnexpectedEncodingException.php
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Exception;
|
||||
|
||||
final class UnexpectedEncodingException extends \RuntimeException implements CommonMarkException
|
||||
{
|
||||
}
|
||||
44
vendor/league/commonmark/src/Extension/Attributes/AttributesExtension.php
vendored
Normal file
44
vendor/league/commonmark/src/Extension/Attributes/AttributesExtension.php
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
* (c) 2015 Martin Hasoň <martin.hason@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\CommonMark\Extension\Attributes;
|
||||
|
||||
use League\CommonMark\Environment\EnvironmentBuilderInterface;
|
||||
use League\CommonMark\Event\DocumentParsedEvent;
|
||||
use League\CommonMark\Extension\Attributes\Event\AttributesListener;
|
||||
use League\CommonMark\Extension\Attributes\Parser\AttributesBlockStartParser;
|
||||
use League\CommonMark\Extension\Attributes\Parser\AttributesInlineParser;
|
||||
use League\CommonMark\Extension\ConfigurableExtensionInterface;
|
||||
use League\Config\ConfigurationBuilderInterface;
|
||||
use Nette\Schema\Expect;
|
||||
|
||||
final class AttributesExtension implements ConfigurableExtensionInterface
|
||||
{
|
||||
public function configureSchema(ConfigurationBuilderInterface $builder): void
|
||||
{
|
||||
$builder->addSchema('attributes', Expect::structure([
|
||||
'allow' => Expect::arrayOf('string')->default([]),
|
||||
]));
|
||||
}
|
||||
|
||||
public function register(EnvironmentBuilderInterface $environment): void
|
||||
{
|
||||
$allowList = $environment->getConfiguration()->get('attributes.allow');
|
||||
$allowUnsafeLinks = $environment->getConfiguration()->get('allow_unsafe_links');
|
||||
|
||||
$environment->addBlockStartParser(new AttributesBlockStartParser());
|
||||
$environment->addInlineParser(new AttributesInlineParser());
|
||||
$environment->addEventListener(DocumentParsedEvent::class, [new AttributesListener($allowList, $allowUnsafeLinks), 'processDocument']);
|
||||
}
|
||||
}
|
||||
152
vendor/league/commonmark/src/Extension/Attributes/Event/AttributesListener.php
vendored
Normal file
152
vendor/league/commonmark/src/Extension/Attributes/Event/AttributesListener.php
vendored
Normal file
@ -0,0 +1,152 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
* (c) 2015 Martin Hasoň <martin.hason@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\CommonMark\Extension\Attributes\Event;
|
||||
|
||||
use League\CommonMark\Event\DocumentParsedEvent;
|
||||
use League\CommonMark\Extension\Attributes\Node\Attributes;
|
||||
use League\CommonMark\Extension\Attributes\Node\AttributesInline;
|
||||
use League\CommonMark\Extension\Attributes\Util\AttributesHelper;
|
||||
use League\CommonMark\Extension\CommonMark\Node\Block\FencedCode;
|
||||
use League\CommonMark\Extension\CommonMark\Node\Block\ListBlock;
|
||||
use League\CommonMark\Extension\CommonMark\Node\Block\ListItem;
|
||||
use League\CommonMark\Node\Inline\AbstractInline;
|
||||
use League\CommonMark\Node\Node;
|
||||
|
||||
final class AttributesListener
|
||||
{
|
||||
private const DIRECTION_PREFIX = 'prefix';
|
||||
private const DIRECTION_SUFFIX = 'suffix';
|
||||
|
||||
/** @var list<string> */
|
||||
private array $allowList;
|
||||
private bool $allowUnsafeLinks;
|
||||
|
||||
/**
|
||||
* @param list<string> $allowList
|
||||
*/
|
||||
public function __construct(array $allowList = [], bool $allowUnsafeLinks = true)
|
||||
{
|
||||
$this->allowList = $allowList;
|
||||
$this->allowUnsafeLinks = $allowUnsafeLinks;
|
||||
}
|
||||
|
||||
public function processDocument(DocumentParsedEvent $event): void
|
||||
{
|
||||
foreach ($event->getDocument()->iterator() as $node) {
|
||||
if (! ($node instanceof Attributes || $node instanceof AttributesInline)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
[$target, $direction] = self::findTargetAndDirection($node);
|
||||
|
||||
if ($target instanceof Node) {
|
||||
$parent = $target->parent();
|
||||
if ($parent instanceof ListItem && $parent->parent() instanceof ListBlock && $parent->parent()->isTight()) {
|
||||
$target = $parent;
|
||||
}
|
||||
|
||||
if ($direction === self::DIRECTION_SUFFIX) {
|
||||
$attributes = AttributesHelper::mergeAttributes($target, $node->getAttributes());
|
||||
} else {
|
||||
$attributes = AttributesHelper::mergeAttributes($node->getAttributes(), $target);
|
||||
}
|
||||
|
||||
$target->data->set('attributes', AttributesHelper::filterAttributes($attributes, $this->allowList, $this->allowUnsafeLinks));
|
||||
}
|
||||
|
||||
$node->detach();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Attributes|AttributesInline $node
|
||||
*
|
||||
* @return array<Node|string|null>
|
||||
*/
|
||||
private static function findTargetAndDirection($node): array
|
||||
{
|
||||
$target = null;
|
||||
$direction = null;
|
||||
$previous = $next = $node;
|
||||
while (true) {
|
||||
$previous = self::getPrevious($previous);
|
||||
$next = self::getNext($next);
|
||||
|
||||
if ($previous === null && $next === null) {
|
||||
if (! $node->parent() instanceof FencedCode) {
|
||||
$target = $node->parent();
|
||||
$direction = self::DIRECTION_SUFFIX;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if ($node instanceof AttributesInline && ($previous === null || ($previous instanceof AbstractInline && $node->isBlock()))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($previous !== null && ! self::isAttributesNode($previous)) {
|
||||
$target = $previous;
|
||||
$direction = self::DIRECTION_SUFFIX;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if ($next !== null && ! self::isAttributesNode($next)) {
|
||||
$target = $next;
|
||||
$direction = self::DIRECTION_PREFIX;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return [$target, $direction];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get any previous block (sibling or parent) this might apply to
|
||||
*/
|
||||
private static function getPrevious(?Node $node = null): ?Node
|
||||
{
|
||||
if ($node instanceof Attributes) {
|
||||
if ($node->getTarget() === Attributes::TARGET_NEXT) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($node->getTarget() === Attributes::TARGET_PARENT) {
|
||||
return $node->parent();
|
||||
}
|
||||
}
|
||||
|
||||
return $node instanceof Node ? $node->previous() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get any previous block (sibling or parent) this might apply to
|
||||
*/
|
||||
private static function getNext(?Node $node = null): ?Node
|
||||
{
|
||||
if ($node instanceof Attributes && $node->getTarget() !== Attributes::TARGET_NEXT) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $node instanceof Node ? $node->next() : null;
|
||||
}
|
||||
|
||||
private static function isAttributesNode(Node $node): bool
|
||||
{
|
||||
return $node instanceof Attributes || $node instanceof AttributesInline;
|
||||
}
|
||||
}
|
||||
65
vendor/league/commonmark/src/Extension/Attributes/Node/Attributes.php
vendored
Normal file
65
vendor/league/commonmark/src/Extension/Attributes/Node/Attributes.php
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
* (c) 2015 Martin Hasoň <martin.hason@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\CommonMark\Extension\Attributes\Node;
|
||||
|
||||
use League\CommonMark\Node\Block\AbstractBlock;
|
||||
|
||||
final class Attributes extends AbstractBlock
|
||||
{
|
||||
public const TARGET_PARENT = 0;
|
||||
public const TARGET_PREVIOUS = 1;
|
||||
public const TARGET_NEXT = 2;
|
||||
|
||||
/** @var array<string, mixed> */
|
||||
private array $attributes;
|
||||
|
||||
private int $target = self::TARGET_NEXT;
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $attributes
|
||||
*/
|
||||
public function __construct(array $attributes)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->attributes = $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function getAttributes(): array
|
||||
{
|
||||
return $this->attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $attributes
|
||||
*/
|
||||
public function setAttributes(array $attributes): void
|
||||
{
|
||||
$this->attributes = $attributes;
|
||||
}
|
||||
|
||||
public function getTarget(): int
|
||||
{
|
||||
return $this->target;
|
||||
}
|
||||
|
||||
public function setTarget(int $target): void
|
||||
{
|
||||
$this->target = $target;
|
||||
}
|
||||
}
|
||||
57
vendor/league/commonmark/src/Extension/Attributes/Node/AttributesInline.php
vendored
Normal file
57
vendor/league/commonmark/src/Extension/Attributes/Node/AttributesInline.php
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
* (c) 2015 Martin Hasoň <martin.hason@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\CommonMark\Extension\Attributes\Node;
|
||||
|
||||
use League\CommonMark\Node\Inline\AbstractInline;
|
||||
|
||||
final class AttributesInline extends AbstractInline
|
||||
{
|
||||
/** @var array<string, mixed> */
|
||||
private array $attributes;
|
||||
|
||||
private bool $block;
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $attributes
|
||||
*/
|
||||
public function __construct(array $attributes, bool $block)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->attributes = $attributes;
|
||||
$this->block = $block;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function getAttributes(): array
|
||||
{
|
||||
return $this->attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $attributes
|
||||
*/
|
||||
public function setAttributes(array $attributes): void
|
||||
{
|
||||
$this->attributes = $attributes;
|
||||
}
|
||||
|
||||
public function isBlock(): bool
|
||||
{
|
||||
return $this->block;
|
||||
}
|
||||
}
|
||||
92
vendor/league/commonmark/src/Extension/Attributes/Parser/AttributesBlockContinueParser.php
vendored
Normal file
92
vendor/league/commonmark/src/Extension/Attributes/Parser/AttributesBlockContinueParser.php
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
* (c) 2015 Martin Hasoň <martin.hason@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\CommonMark\Extension\Attributes\Parser;
|
||||
|
||||
use League\CommonMark\Extension\Attributes\Node\Attributes;
|
||||
use League\CommonMark\Extension\Attributes\Util\AttributesHelper;
|
||||
use League\CommonMark\Node\Block\AbstractBlock;
|
||||
use League\CommonMark\Parser\Block\AbstractBlockContinueParser;
|
||||
use League\CommonMark\Parser\Block\BlockContinue;
|
||||
use League\CommonMark\Parser\Block\BlockContinueParserInterface;
|
||||
use League\CommonMark\Parser\Cursor;
|
||||
|
||||
final class AttributesBlockContinueParser extends AbstractBlockContinueParser
|
||||
{
|
||||
private Attributes $block;
|
||||
|
||||
private AbstractBlock $container;
|
||||
|
||||
private bool $hasSubsequentLine = false;
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $attributes The attributes identified by the block start parser
|
||||
* @param AbstractBlock $container The node we were in when these attributes were discovered
|
||||
*/
|
||||
public function __construct(array $attributes, AbstractBlock $container)
|
||||
{
|
||||
$this->block = new Attributes($attributes);
|
||||
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
public function getBlock(): AbstractBlock
|
||||
{
|
||||
return $this->block;
|
||||
}
|
||||
|
||||
public function tryContinue(Cursor $cursor, BlockContinueParserInterface $activeBlockParser): ?BlockContinue
|
||||
{
|
||||
$this->hasSubsequentLine = true;
|
||||
|
||||
$cursor->advanceToNextNonSpaceOrTab();
|
||||
|
||||
// Does this next line also have attributes?
|
||||
$attributes = AttributesHelper::parseAttributes($cursor);
|
||||
$cursor->advanceToNextNonSpaceOrTab();
|
||||
if ($cursor->isAtEnd() && $attributes !== []) {
|
||||
// It does! Merge them into what we parsed previously
|
||||
$this->block->setAttributes(AttributesHelper::mergeAttributes(
|
||||
$this->block->getAttributes(),
|
||||
$attributes
|
||||
));
|
||||
|
||||
// Tell the core parser we've consumed everything
|
||||
return BlockContinue::at($cursor);
|
||||
}
|
||||
|
||||
// Okay, so there are no attributes on the next line
|
||||
// If this next line is blank we know we can't target the next node, it must be a previous one
|
||||
if ($cursor->isBlank()) {
|
||||
$this->block->setTarget(Attributes::TARGET_PREVIOUS);
|
||||
}
|
||||
|
||||
return BlockContinue::none();
|
||||
}
|
||||
|
||||
public function closeBlock(): void
|
||||
{
|
||||
// Attributes appearing at the very end of the document won't have any last lines to check
|
||||
// so we can make that determination here
|
||||
if (! $this->hasSubsequentLine) {
|
||||
$this->block->setTarget(Attributes::TARGET_PREVIOUS);
|
||||
}
|
||||
|
||||
// We know this block must apply to the "previous" block, but that could be a sibling or parent,
|
||||
// so we check the containing block to see which one it might be.
|
||||
if ($this->block->getTarget() === Attributes::TARGET_PREVIOUS && $this->block->parent() === $this->container) {
|
||||
$this->block->setTarget(Attributes::TARGET_PARENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
40
vendor/league/commonmark/src/Extension/Attributes/Parser/AttributesBlockStartParser.php
vendored
Normal file
40
vendor/league/commonmark/src/Extension/Attributes/Parser/AttributesBlockStartParser.php
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
* (c) 2015 Martin Hasoň <martin.hason@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\CommonMark\Extension\Attributes\Parser;
|
||||
|
||||
use League\CommonMark\Extension\Attributes\Util\AttributesHelper;
|
||||
use League\CommonMark\Parser\Block\BlockStart;
|
||||
use League\CommonMark\Parser\Block\BlockStartParserInterface;
|
||||
use League\CommonMark\Parser\Cursor;
|
||||
use League\CommonMark\Parser\MarkdownParserStateInterface;
|
||||
|
||||
final class AttributesBlockStartParser implements BlockStartParserInterface
|
||||
{
|
||||
public function tryStart(Cursor $cursor, MarkdownParserStateInterface $parserState): ?BlockStart
|
||||
{
|
||||
$originalPosition = $cursor->getPosition();
|
||||
$attributes = AttributesHelper::parseAttributes($cursor);
|
||||
|
||||
if ($attributes === [] && $originalPosition === $cursor->getPosition()) {
|
||||
return BlockStart::none();
|
||||
}
|
||||
|
||||
if ($cursor->getNextNonSpaceCharacter() !== null) {
|
||||
return BlockStart::none();
|
||||
}
|
||||
|
||||
return BlockStart::of(new AttributesBlockContinueParser($attributes, $parserState->getActiveBlockParser()->getBlock()))->at($cursor);
|
||||
}
|
||||
}
|
||||
54
vendor/league/commonmark/src/Extension/Attributes/Parser/AttributesInlineParser.php
vendored
Normal file
54
vendor/league/commonmark/src/Extension/Attributes/Parser/AttributesInlineParser.php
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
* (c) 2015 Martin Hasoň <martin.hason@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\CommonMark\Extension\Attributes\Parser;
|
||||
|
||||
use League\CommonMark\Extension\Attributes\Node\AttributesInline;
|
||||
use League\CommonMark\Extension\Attributes\Util\AttributesHelper;
|
||||
use League\CommonMark\Node\StringContainerInterface;
|
||||
use League\CommonMark\Parser\Inline\InlineParserInterface;
|
||||
use League\CommonMark\Parser\Inline\InlineParserMatch;
|
||||
use League\CommonMark\Parser\InlineParserContext;
|
||||
|
||||
final class AttributesInlineParser implements InlineParserInterface
|
||||
{
|
||||
public function getMatchDefinition(): InlineParserMatch
|
||||
{
|
||||
return InlineParserMatch::string('{');
|
||||
}
|
||||
|
||||
public function parse(InlineParserContext $inlineContext): bool
|
||||
{
|
||||
$cursor = $inlineContext->getCursor();
|
||||
$char = (string) $cursor->peek(-1);
|
||||
|
||||
$attributes = AttributesHelper::parseAttributes($cursor);
|
||||
if ($attributes === []) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($char === ' ' && ($prev = $inlineContext->getContainer()->lastChild()) instanceof StringContainerInterface) {
|
||||
$prev->setLiteral(\rtrim($prev->getLiteral(), ' '));
|
||||
}
|
||||
|
||||
if ($char === '') {
|
||||
$cursor->advanceToNextNonSpaceOrNewline();
|
||||
}
|
||||
|
||||
$node = new AttributesInline($attributes, $char === ' ' || $char === '');
|
||||
$inlineContext->getContainer()->appendChild($node);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
180
vendor/league/commonmark/src/Extension/Attributes/Util/AttributesHelper.php
vendored
Normal file
180
vendor/league/commonmark/src/Extension/Attributes/Util/AttributesHelper.php
vendored
Normal file
@ -0,0 +1,180 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
* (c) 2015 Martin Hasoň <martin.hason@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace League\CommonMark\Extension\Attributes\Util;
|
||||
|
||||
use League\CommonMark\Node\Node;
|
||||
use League\CommonMark\Parser\Cursor;
|
||||
use League\CommonMark\Util\RegexHelper;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class AttributesHelper
|
||||
{
|
||||
private const SINGLE_ATTRIBUTE = '\s*([.]-?[_a-z][^\s.}]*|[#][^\s}]+|' . RegexHelper::PARTIAL_ATTRIBUTENAME . RegexHelper::PARTIAL_ATTRIBUTEVALUESPEC . ')\s*';
|
||||
private const ATTRIBUTE_LIST = '/^{:?(' . self::SINGLE_ATTRIBUTE . ')+}/i';
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public static function parseAttributes(Cursor $cursor): array
|
||||
{
|
||||
$state = $cursor->saveState();
|
||||
$cursor->advanceToNextNonSpaceOrNewline();
|
||||
|
||||
// Quick check to see if we might have attributes
|
||||
if ($cursor->getCharacter() !== '{') {
|
||||
$cursor->restoreState($state);
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
// Attempt to match the entire attribute list expression
|
||||
// While this is less performant than checking for '{' now and '}' later, it simplifies
|
||||
// matching individual attributes since they won't need to look ahead for the closing '}'
|
||||
// while dealing with the fact that attributes can technically contain curly braces.
|
||||
// So we'll just match the start and end braces up front.
|
||||
$attributeExpression = $cursor->match(self::ATTRIBUTE_LIST);
|
||||
if ($attributeExpression === null) {
|
||||
$cursor->restoreState($state);
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
// Trim the leading '{' or '{:' and the trailing '}'
|
||||
$attributeExpression = \ltrim(\substr($attributeExpression, 1, -1), ':');
|
||||
$attributeCursor = new Cursor($attributeExpression);
|
||||
|
||||
/** @var array<string, mixed> $attributes */
|
||||
$attributes = [];
|
||||
while ($attribute = \trim((string) $attributeCursor->match('/^' . self::SINGLE_ATTRIBUTE . '/i'))) {
|
||||
if ($attribute[0] === '#') {
|
||||
$attributes['id'] = \substr($attribute, 1);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($attribute[0] === '.') {
|
||||
$attributes['class'][] = \substr($attribute, 1);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/** @psalm-suppress PossiblyUndefinedArrayOffset */
|
||||
[$name, $value] = \explode('=', $attribute, 2);
|
||||
|
||||
if ($value === 'true') {
|
||||
$attributes[$name] = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
$first = $value[0];
|
||||
$last = \substr($value, -1);
|
||||
if (($first === '"' && $last === '"') || ($first === "'" && $last === "'") && \strlen($value) > 1) {
|
||||
$value = \substr($value, 1, -1);
|
||||
}
|
||||
|
||||
if (\strtolower(\trim($name)) === 'class') {
|
||||
foreach (\array_filter(\explode(' ', \trim($value))) as $class) {
|
||||
$attributes['class'][] = $class;
|
||||
}
|
||||
} else {
|
||||
$attributes[\trim($name)] = \trim($value);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($attributes['class'])) {
|
||||
$attributes['class'] = \implode(' ', (array) $attributes['class']);
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Node|array<string, mixed> $attributes1
|
||||
* @param Node|array<string, mixed> $attributes2
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public static function mergeAttributes($attributes1, $attributes2): array
|
||||
{
|
||||
$attributes = [];
|
||||
foreach ([$attributes1, $attributes2] as $arg) {
|
||||
if ($arg instanceof Node) {
|
||||
$arg = $arg->data->get('attributes');
|
||||
}
|
||||
|
||||
/** @var array<string, mixed> $arg */
|
||||
$arg = (array) $arg;
|
||||
if (isset($arg['class'])) {
|
||||
if (\is_string($arg['class'])) {
|
||||
$arg['class'] = \array_filter(\explode(' ', \trim($arg['class'])));
|
||||
}
|
||||
|
||||
foreach ($arg['class'] as $class) {
|
||||
$attributes['class'][] = $class;
|
||||
}
|
||||
|
||||
unset($arg['class']);
|
||||
}
|
||||
|
||||
$attributes = \array_merge($attributes, $arg);
|
||||
}
|
||||
|
||||
if (isset($attributes['class'])) {
|
||||
$attributes['class'] = \implode(' ', $attributes['class']);
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $attributes
|
||||
* @param list<string> $allowList
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public static function filterAttributes(array $attributes, array $allowList, bool $allowUnsafeLinks): array
|
||||
{
|
||||
$allowList = \array_fill_keys($allowList, true);
|
||||
|
||||
foreach ($attributes as $name => $value) {
|
||||
$attrNameLower = \strtolower($name);
|
||||
|
||||
// Remove any unsafe links
|
||||
if (! $allowUnsafeLinks && ($attrNameLower === 'href' || $attrNameLower === 'src') && \is_string($value) && RegexHelper::isLinkPotentiallyUnsafe($value)) {
|
||||
unset($attributes[$name]);
|
||||
continue;
|
||||
}
|
||||
|
||||
// No allowlist?
|
||||
if ($allowList === []) {
|
||||
// Just remove JS event handlers
|
||||
if (\str_starts_with($attrNameLower, 'on')) {
|
||||
unset($attributes[$name]);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Remove any attributes not in that allowlist (case-sensitive)
|
||||
if (! isset($allowList[$name])) {
|
||||
unset($attributes[$name]);
|
||||
}
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
}
|
||||
39
vendor/league/commonmark/src/Extension/Autolink/AutolinkExtension.php
vendored
Normal file
39
vendor/league/commonmark/src/Extension/Autolink/AutolinkExtension.php
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Extension\Autolink;
|
||||
|
||||
use League\CommonMark\Environment\EnvironmentBuilderInterface;
|
||||
use League\CommonMark\Extension\ConfigurableExtensionInterface;
|
||||
use League\Config\ConfigurationBuilderInterface;
|
||||
use Nette\Schema\Expect;
|
||||
|
||||
final class AutolinkExtension implements ConfigurableExtensionInterface
|
||||
{
|
||||
public function configureSchema(ConfigurationBuilderInterface $builder): void
|
||||
{
|
||||
$builder->addSchema('autolink', Expect::structure([
|
||||
'allowed_protocols' => Expect::listOf('string')->default(['http', 'https', 'ftp'])->mergeDefaults(false),
|
||||
'default_protocol' => Expect::string()->default('http'),
|
||||
]));
|
||||
}
|
||||
|
||||
public function register(EnvironmentBuilderInterface $environment): void
|
||||
{
|
||||
$environment->addInlineParser(new EmailAutolinkParser());
|
||||
$environment->addInlineParser(new UrlAutolinkParser(
|
||||
$environment->getConfiguration()->get('autolink.allowed_protocols'),
|
||||
$environment->getConfiguration()->get('autolink.default_protocol'),
|
||||
));
|
||||
}
|
||||
}
|
||||
48
vendor/league/commonmark/src/Extension/Autolink/EmailAutolinkParser.php
vendored
Normal file
48
vendor/league/commonmark/src/Extension/Autolink/EmailAutolinkParser.php
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Extension\Autolink;
|
||||
|
||||
use League\CommonMark\Extension\CommonMark\Node\Inline\Link;
|
||||
use League\CommonMark\Parser\Inline\InlineParserInterface;
|
||||
use League\CommonMark\Parser\Inline\InlineParserMatch;
|
||||
use League\CommonMark\Parser\InlineParserContext;
|
||||
|
||||
final class EmailAutolinkParser implements InlineParserInterface
|
||||
{
|
||||
private const REGEX = '[A-Za-z0-9.\-_+]+@[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_.]+';
|
||||
|
||||
public function getMatchDefinition(): InlineParserMatch
|
||||
{
|
||||
return InlineParserMatch::regex(self::REGEX);
|
||||
}
|
||||
|
||||
public function parse(InlineParserContext $inlineContext): bool
|
||||
{
|
||||
$email = $inlineContext->getFullMatch();
|
||||
// The last character cannot be - or _
|
||||
if (\in_array(\substr($email, -1), ['-', '_'], true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Does the URL end with punctuation that should be stripped?
|
||||
if (\substr($email, -1) === '.') {
|
||||
$email = \substr($email, 0, -1);
|
||||
}
|
||||
|
||||
$inlineContext->getCursor()->advanceBy(\strlen($email));
|
||||
$inlineContext->getContainer()->appendChild(new Link('mailto:' . $email, $email));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
157
vendor/league/commonmark/src/Extension/Autolink/UrlAutolinkParser.php
vendored
Normal file
157
vendor/league/commonmark/src/Extension/Autolink/UrlAutolinkParser.php
vendored
Normal file
@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Extension\Autolink;
|
||||
|
||||
use League\CommonMark\Extension\CommonMark\Node\Inline\Link;
|
||||
use League\CommonMark\Parser\Inline\InlineParserInterface;
|
||||
use League\CommonMark\Parser\Inline\InlineParserMatch;
|
||||
use League\CommonMark\Parser\InlineParserContext;
|
||||
|
||||
final class UrlAutolinkParser implements InlineParserInterface
|
||||
{
|
||||
private const ALLOWED_AFTER = [null, ' ', "\t", "\n", "\x0b", "\x0c", "\x0d", '*', '_', '~', '('];
|
||||
|
||||
// RegEx adapted from https://github.com/symfony/symfony/blob/6.3/src/Symfony/Component/Validator/Constraints/UrlValidator.php
|
||||
private const REGEX = '~
|
||||
(
|
||||
# Must start with a supported scheme + auth, or "www"
|
||||
(?:
|
||||
(?:%s):// # protocol
|
||||
(?:(?:(?:[\_\.\pL\pN-]|%%[0-9A-Fa-f]{2})+:)?((?:[\_\.\pL\pN-]|%%[0-9A-Fa-f]{2})+)@)? # basic auth
|
||||
|www\.)
|
||||
(?:
|
||||
(?:
|
||||
(?:xn--[a-z0-9-]++\.)*+xn--[a-z0-9-]++ # a domain name using punycode
|
||||
|
|
||||
(?:[\pL\pN\pS\pM\-\_]++\.){1,127}[\pL\pN\pM]++ # a multi-level domain name; total length must be 253 bytes or less
|
||||
|
|
||||
[a-z0-9\-\_]++ # a single-level domain name
|
||||
)\.?
|
||||
| # or
|
||||
\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} # an IP address
|
||||
| # or
|
||||
\[
|
||||
(?:(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){6})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:::(?:(?:(?:[0-9a-f]{1,4})):){5})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){4})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,1}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){3})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,2}(?:(?:[0-9a-f]{1,4})))?::(?:(?:(?:[0-9a-f]{1,4})):){2})(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,3}(?:(?:[0-9a-f]{1,4})))?::(?:(?:[0-9a-f]{1,4})):)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,4}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:(?:(?:(?:[0-9a-f]{1,4})):(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9]))\.){3}(?:(?:25[0-5]|(?:[1-9]|1[0-9]|2[0-4])?[0-9])))))))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,5}(?:(?:[0-9a-f]{1,4})))?::)(?:(?:[0-9a-f]{1,4})))|(?:(?:(?:(?:(?:(?:[0-9a-f]{1,4})):){0,6}(?:(?:[0-9a-f]{1,4})))?::))))
|
||||
\] # an IPv6 address
|
||||
)
|
||||
(?::[0-9]+)? # a port (optional)
|
||||
(?:/ (?:[\pL\pN\-._\~!$&\'()*+,;=:@]|%%[0-9A-Fa-f]{2})* )* # a path
|
||||
(?:\? (?:[\pL\pN\-._\~!$&\'\[\]()*+,;=:@/?]|%%[0-9A-Fa-f]{2})* )? # a query (optional)
|
||||
(?:\# (?:[\pL\pN\-._\~!$&\'()*+,;=:@/?]|%%[0-9A-Fa-f]{2})* )? # a fragment (optional)
|
||||
)~ixu';
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*
|
||||
* @psalm-readonly
|
||||
*/
|
||||
private array $prefixes = ['www.'];
|
||||
|
||||
/**
|
||||
* @psalm-var non-empty-string
|
||||
*
|
||||
* @psalm-readonly
|
||||
*/
|
||||
private string $finalRegex;
|
||||
|
||||
private string $defaultProtocol;
|
||||
|
||||
/**
|
||||
* @param array<int, string> $allowedProtocols
|
||||
*/
|
||||
public function __construct(array $allowedProtocols = ['http', 'https', 'ftp'], string $defaultProtocol = 'http')
|
||||
{
|
||||
/**
|
||||
* @psalm-suppress PropertyTypeCoercion
|
||||
*/
|
||||
$this->finalRegex = \sprintf(self::REGEX, \implode('|', $allowedProtocols));
|
||||
|
||||
foreach ($allowedProtocols as $protocol) {
|
||||
$this->prefixes[] = $protocol . '://';
|
||||
}
|
||||
|
||||
$this->defaultProtocol = $defaultProtocol;
|
||||
}
|
||||
|
||||
public function getMatchDefinition(): InlineParserMatch
|
||||
{
|
||||
return InlineParserMatch::oneOf(...$this->prefixes);
|
||||
}
|
||||
|
||||
public function parse(InlineParserContext $inlineContext): bool
|
||||
{
|
||||
$cursor = $inlineContext->getCursor();
|
||||
|
||||
// Autolinks can only come at the beginning of a line, after whitespace, or certain delimiting characters
|
||||
$previousChar = $cursor->peek(-1);
|
||||
if (! \in_array($previousChar, self::ALLOWED_AFTER, true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if we have a valid URL
|
||||
if (! \preg_match($this->finalRegex, $cursor->getRemainder(), $matches)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$url = $matches[0];
|
||||
|
||||
// Does the URL end with punctuation that should be stripped?
|
||||
if (\preg_match('/(.+?)([?!.,:*_~]+)$/', $url, $matches)) {
|
||||
// Add the punctuation later
|
||||
$url = $matches[1];
|
||||
}
|
||||
|
||||
// Does the URL end with something that looks like an entity reference?
|
||||
if (\preg_match('/(.+)(&[A-Za-z0-9]+;)$/', $url, $matches)) {
|
||||
$url = $matches[1];
|
||||
}
|
||||
|
||||
// Does the URL need unmatched parens chopped off?
|
||||
if (\substr($url, -1) === ')' && ($diff = self::diffParens($url)) > 0) {
|
||||
$url = \substr($url, 0, -$diff);
|
||||
}
|
||||
|
||||
$cursor->advanceBy(\mb_strlen($url, 'UTF-8'));
|
||||
|
||||
// Auto-prefix 'http(s)://' onto 'www' URLs
|
||||
if (\substr($url, 0, 4) === 'www.') {
|
||||
$inlineContext->getContainer()->appendChild(new Link($this->defaultProtocol . '://' . $url, $url));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
$inlineContext->getContainer()->appendChild(new Link($url, $url));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-pure
|
||||
*/
|
||||
private static function diffParens(string $content): int
|
||||
{
|
||||
// Scan the entire autolink for the total number of parentheses.
|
||||
// If there is a greater number of closing parentheses than opening ones,
|
||||
// we don’t consider ANY of the last characters as part of the autolink,
|
||||
// in order to facilitate including an autolink inside a parenthesis.
|
||||
\preg_match_all('/[()]/', $content, $matches);
|
||||
|
||||
$charCount = ['(' => 0, ')' => 0];
|
||||
foreach ($matches[0] as $char) {
|
||||
$charCount[$char]++;
|
||||
}
|
||||
|
||||
return $charCount[')'] - $charCount['('];
|
||||
}
|
||||
}
|
||||
92
vendor/league/commonmark/src/Extension/CommonMark/CommonMarkCoreExtension.php
vendored
Normal file
92
vendor/league/commonmark/src/Extension/CommonMark/CommonMarkCoreExtension.php
vendored
Normal file
@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
|
||||
* - (c) John MacFarlane
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Extension\CommonMark;
|
||||
|
||||
use League\CommonMark\Environment\EnvironmentBuilderInterface;
|
||||
use League\CommonMark\Extension\CommonMark\Delimiter\Processor\EmphasisDelimiterProcessor;
|
||||
use League\CommonMark\Extension\ConfigurableExtensionInterface;
|
||||
use League\CommonMark\Node as CoreNode;
|
||||
use League\CommonMark\Parser as CoreParser;
|
||||
use League\CommonMark\Renderer as CoreRenderer;
|
||||
use League\Config\ConfigurationBuilderInterface;
|
||||
use Nette\Schema\Expect;
|
||||
|
||||
final class CommonMarkCoreExtension implements ConfigurableExtensionInterface
|
||||
{
|
||||
public function configureSchema(ConfigurationBuilderInterface $builder): void
|
||||
{
|
||||
$builder->addSchema('commonmark', Expect::structure([
|
||||
'use_asterisk' => Expect::bool(true),
|
||||
'use_underscore' => Expect::bool(true),
|
||||
'enable_strong' => Expect::bool(true),
|
||||
'enable_em' => Expect::bool(true),
|
||||
'unordered_list_markers' => Expect::listOf('string')->min(1)->default(['*', '+', '-'])->mergeDefaults(false),
|
||||
]));
|
||||
}
|
||||
|
||||
// phpcs:disable Generic.Functions.FunctionCallArgumentSpacing.TooMuchSpaceAfterComma,Squiz.WhiteSpace.SemicolonSpacing.Incorrect
|
||||
public function register(EnvironmentBuilderInterface $environment): void
|
||||
{
|
||||
$environment
|
||||
->addBlockStartParser(new Parser\Block\BlockQuoteStartParser(), 70)
|
||||
->addBlockStartParser(new Parser\Block\HeadingStartParser(), 60)
|
||||
->addBlockStartParser(new Parser\Block\FencedCodeStartParser(), 50)
|
||||
->addBlockStartParser(new Parser\Block\HtmlBlockStartParser(), 40)
|
||||
->addBlockStartParser(new Parser\Block\ThematicBreakStartParser(), 20)
|
||||
->addBlockStartParser(new Parser\Block\ListBlockStartParser(), 10)
|
||||
->addBlockStartParser(new Parser\Block\IndentedCodeStartParser(), -100)
|
||||
|
||||
->addInlineParser(new CoreParser\Inline\NewlineParser(), 200)
|
||||
->addInlineParser(new Parser\Inline\BacktickParser(), 150)
|
||||
->addInlineParser(new Parser\Inline\EscapableParser(), 80)
|
||||
->addInlineParser(new Parser\Inline\EntityParser(), 70)
|
||||
->addInlineParser(new Parser\Inline\AutolinkParser(), 50)
|
||||
->addInlineParser(new Parser\Inline\HtmlInlineParser(), 40)
|
||||
->addInlineParser(new Parser\Inline\CloseBracketParser(), 30)
|
||||
->addInlineParser(new Parser\Inline\OpenBracketParser(), 20)
|
||||
->addInlineParser(new Parser\Inline\BangParser(), 10)
|
||||
|
||||
->addRenderer(Node\Block\BlockQuote::class, new Renderer\Block\BlockQuoteRenderer(), 0)
|
||||
->addRenderer(CoreNode\Block\Document::class, new CoreRenderer\Block\DocumentRenderer(), 0)
|
||||
->addRenderer(Node\Block\FencedCode::class, new Renderer\Block\FencedCodeRenderer(), 0)
|
||||
->addRenderer(Node\Block\Heading::class, new Renderer\Block\HeadingRenderer(), 0)
|
||||
->addRenderer(Node\Block\HtmlBlock::class, new Renderer\Block\HtmlBlockRenderer(), 0)
|
||||
->addRenderer(Node\Block\IndentedCode::class, new Renderer\Block\IndentedCodeRenderer(), 0)
|
||||
->addRenderer(Node\Block\ListBlock::class, new Renderer\Block\ListBlockRenderer(), 0)
|
||||
->addRenderer(Node\Block\ListItem::class, new Renderer\Block\ListItemRenderer(), 0)
|
||||
->addRenderer(CoreNode\Block\Paragraph::class, new CoreRenderer\Block\ParagraphRenderer(), 0)
|
||||
->addRenderer(Node\Block\ThematicBreak::class, new Renderer\Block\ThematicBreakRenderer(), 0)
|
||||
|
||||
->addRenderer(Node\Inline\Code::class, new Renderer\Inline\CodeRenderer(), 0)
|
||||
->addRenderer(Node\Inline\Emphasis::class, new Renderer\Inline\EmphasisRenderer(), 0)
|
||||
->addRenderer(Node\Inline\HtmlInline::class, new Renderer\Inline\HtmlInlineRenderer(), 0)
|
||||
->addRenderer(Node\Inline\Image::class, new Renderer\Inline\ImageRenderer(), 0)
|
||||
->addRenderer(Node\Inline\Link::class, new Renderer\Inline\LinkRenderer(), 0)
|
||||
->addRenderer(CoreNode\Inline\Newline::class, new CoreRenderer\Inline\NewlineRenderer(), 0)
|
||||
->addRenderer(Node\Inline\Strong::class, new Renderer\Inline\StrongRenderer(), 0)
|
||||
->addRenderer(CoreNode\Inline\Text::class, new CoreRenderer\Inline\TextRenderer(), 0)
|
||||
;
|
||||
|
||||
if ($environment->getConfiguration()->get('commonmark/use_asterisk')) {
|
||||
$environment->addDelimiterProcessor(new EmphasisDelimiterProcessor('*'));
|
||||
}
|
||||
|
||||
if ($environment->getConfiguration()->get('commonmark/use_underscore')) {
|
||||
$environment->addDelimiterProcessor(new EmphasisDelimiterProcessor('_'));
|
||||
}
|
||||
}
|
||||
}
|
||||
119
vendor/league/commonmark/src/Extension/CommonMark/Delimiter/Processor/EmphasisDelimiterProcessor.php
vendored
Normal file
119
vendor/league/commonmark/src/Extension/CommonMark/Delimiter/Processor/EmphasisDelimiterProcessor.php
vendored
Normal file
@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
|
||||
* - (c) John MacFarlane
|
||||
*
|
||||
* Additional emphasis processing code based on commonmark-java (https://github.com/atlassian/commonmark-java)
|
||||
* - (c) Atlassian Pty Ltd
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Extension\CommonMark\Delimiter\Processor;
|
||||
|
||||
use League\CommonMark\Delimiter\DelimiterInterface;
|
||||
use League\CommonMark\Delimiter\Processor\CacheableDelimiterProcessorInterface;
|
||||
use League\CommonMark\Extension\CommonMark\Node\Inline\Emphasis;
|
||||
use League\CommonMark\Extension\CommonMark\Node\Inline\Strong;
|
||||
use League\CommonMark\Node\Inline\AbstractStringContainer;
|
||||
use League\Config\ConfigurationAwareInterface;
|
||||
use League\Config\ConfigurationInterface;
|
||||
|
||||
final class EmphasisDelimiterProcessor implements CacheableDelimiterProcessorInterface, ConfigurationAwareInterface
|
||||
{
|
||||
/** @psalm-readonly */
|
||||
private string $char;
|
||||
|
||||
/** @psalm-readonly-allow-private-mutation */
|
||||
private ConfigurationInterface $config;
|
||||
|
||||
/**
|
||||
* @param string $char The emphasis character to use (typically '*' or '_')
|
||||
*/
|
||||
public function __construct(string $char)
|
||||
{
|
||||
$this->char = $char;
|
||||
}
|
||||
|
||||
public function getOpeningCharacter(): string
|
||||
{
|
||||
return $this->char;
|
||||
}
|
||||
|
||||
public function getClosingCharacter(): string
|
||||
{
|
||||
return $this->char;
|
||||
}
|
||||
|
||||
public function getMinLength(): int
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public function getDelimiterUse(DelimiterInterface $opener, DelimiterInterface $closer): int
|
||||
{
|
||||
// "Multiple of 3" rule for internal delimiter runs
|
||||
if (($opener->canClose() || $closer->canOpen()) && $closer->getOriginalLength() % 3 !== 0 && ($opener->getOriginalLength() + $closer->getOriginalLength()) % 3 === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Calculate actual number of delimiters used from this closer
|
||||
if ($opener->getLength() >= 2 && $closer->getLength() >= 2) {
|
||||
if ($this->config->get('commonmark/enable_strong')) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ($this->config->get('commonmark/enable_em')) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function process(AbstractStringContainer $opener, AbstractStringContainer $closer, int $delimiterUse): void
|
||||
{
|
||||
if ($delimiterUse === 1) {
|
||||
$emphasis = new Emphasis($this->char);
|
||||
} elseif ($delimiterUse === 2) {
|
||||
$emphasis = new Strong($this->char . $this->char);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
$next = $opener->next();
|
||||
while ($next !== null && $next !== $closer) {
|
||||
$tmp = $next->next();
|
||||
$emphasis->appendChild($next);
|
||||
$next = $tmp;
|
||||
}
|
||||
|
||||
$opener->insertAfter($emphasis);
|
||||
}
|
||||
|
||||
public function setConfiguration(ConfigurationInterface $configuration): void
|
||||
{
|
||||
$this->config = $configuration;
|
||||
}
|
||||
|
||||
public function getCacheKey(DelimiterInterface $closer): string
|
||||
{
|
||||
return \sprintf(
|
||||
'%s-%s-%d-%d',
|
||||
$this->char,
|
||||
$closer->canOpen() ? 'canOpen' : 'cannotOpen',
|
||||
$closer->getOriginalLength() % 3,
|
||||
$closer->getLength(),
|
||||
);
|
||||
}
|
||||
}
|
||||
20
vendor/league/commonmark/src/Extension/CommonMark/Node/Block/BlockQuote.php
vendored
Normal file
20
vendor/league/commonmark/src/Extension/CommonMark/Node/Block/BlockQuote.php
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Extension\CommonMark\Node\Block;
|
||||
|
||||
use League\CommonMark\Node\Block\AbstractBlock;
|
||||
|
||||
class BlockQuote extends AbstractBlock
|
||||
{
|
||||
}
|
||||
100
vendor/league/commonmark/src/Extension/CommonMark/Node/Block/FencedCode.php
vendored
Normal file
100
vendor/league/commonmark/src/Extension/CommonMark/Node/Block/FencedCode.php
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
|
||||
* - (c) John MacFarlane
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Extension\CommonMark\Node\Block;
|
||||
|
||||
use League\CommonMark\Node\Block\AbstractBlock;
|
||||
use League\CommonMark\Node\StringContainerInterface;
|
||||
|
||||
final class FencedCode extends AbstractBlock implements StringContainerInterface
|
||||
{
|
||||
private ?string $info = null;
|
||||
|
||||
private string $literal = '';
|
||||
|
||||
private int $length;
|
||||
|
||||
private string $char;
|
||||
|
||||
private int $offset;
|
||||
|
||||
public function __construct(int $length, string $char, int $offset)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->length = $length;
|
||||
$this->char = $char;
|
||||
$this->offset = $offset;
|
||||
}
|
||||
|
||||
public function getInfo(): ?string
|
||||
{
|
||||
return $this->info;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getInfoWords(): array
|
||||
{
|
||||
return \preg_split('/\s+/', $this->info ?? '') ?: [];
|
||||
}
|
||||
|
||||
public function setInfo(string $info): void
|
||||
{
|
||||
$this->info = $info;
|
||||
}
|
||||
|
||||
public function getLiteral(): string
|
||||
{
|
||||
return $this->literal;
|
||||
}
|
||||
|
||||
public function setLiteral(string $literal): void
|
||||
{
|
||||
$this->literal = $literal;
|
||||
}
|
||||
|
||||
public function getChar(): string
|
||||
{
|
||||
return $this->char;
|
||||
}
|
||||
|
||||
public function setChar(string $char): void
|
||||
{
|
||||
$this->char = $char;
|
||||
}
|
||||
|
||||
public function getLength(): int
|
||||
{
|
||||
return $this->length;
|
||||
}
|
||||
|
||||
public function setLength(int $length): void
|
||||
{
|
||||
$this->length = $length;
|
||||
}
|
||||
|
||||
public function getOffset(): int
|
||||
{
|
||||
return $this->offset;
|
||||
}
|
||||
|
||||
public function setOffset(int $offset): void
|
||||
{
|
||||
$this->offset = $offset;
|
||||
}
|
||||
}
|
||||
41
vendor/league/commonmark/src/Extension/CommonMark/Node/Block/Heading.php
vendored
Normal file
41
vendor/league/commonmark/src/Extension/CommonMark/Node/Block/Heading.php
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
|
||||
* - (c) John MacFarlane
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Extension\CommonMark\Node\Block;
|
||||
|
||||
use League\CommonMark\Node\Block\AbstractBlock;
|
||||
|
||||
final class Heading extends AbstractBlock
|
||||
{
|
||||
private int $level;
|
||||
|
||||
public function __construct(int $level)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->level = $level;
|
||||
}
|
||||
|
||||
public function getLevel(): int
|
||||
{
|
||||
return $this->level;
|
||||
}
|
||||
|
||||
public function setLevel(int $level): void
|
||||
{
|
||||
$this->level = $level;
|
||||
}
|
||||
}
|
||||
79
vendor/league/commonmark/src/Extension/CommonMark/Node/Block/HtmlBlock.php
vendored
Normal file
79
vendor/league/commonmark/src/Extension/CommonMark/Node/Block/HtmlBlock.php
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Extension\CommonMark\Node\Block;
|
||||
|
||||
use League\CommonMark\Node\Block\AbstractBlock;
|
||||
use League\CommonMark\Node\RawMarkupContainerInterface;
|
||||
|
||||
final class HtmlBlock extends AbstractBlock implements RawMarkupContainerInterface
|
||||
{
|
||||
// Any changes to these constants should be reflected in .phpstorm.meta.php
|
||||
public const TYPE_1_CODE_CONTAINER = 1;
|
||||
public const TYPE_2_COMMENT = 2;
|
||||
public const TYPE_3 = 3;
|
||||
public const TYPE_4 = 4;
|
||||
public const TYPE_5_CDATA = 5;
|
||||
public const TYPE_6_BLOCK_ELEMENT = 6;
|
||||
public const TYPE_7_MISC_ELEMENT = 7;
|
||||
|
||||
/**
|
||||
* @psalm-var self::TYPE_* $type
|
||||
* @phpstan-var self::TYPE_* $type
|
||||
*/
|
||||
private int $type;
|
||||
|
||||
private string $literal = '';
|
||||
|
||||
/**
|
||||
* @psalm-param self::TYPE_* $type
|
||||
*
|
||||
* @phpstan-param self::TYPE_* $type
|
||||
*/
|
||||
public function __construct(int $type)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->type = $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-return self::TYPE_*
|
||||
*
|
||||
* @phpstan-return self::TYPE_*
|
||||
*/
|
||||
public function getType(): int
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-param self::TYPE_* $type
|
||||
*
|
||||
* @phpstan-param self::TYPE_* $type
|
||||
*/
|
||||
public function setType(int $type): void
|
||||
{
|
||||
$this->type = $type;
|
||||
}
|
||||
|
||||
public function getLiteral(): string
|
||||
{
|
||||
return $this->literal;
|
||||
}
|
||||
|
||||
public function setLiteral(string $literal): void
|
||||
{
|
||||
$this->literal = $literal;
|
||||
}
|
||||
}
|
||||
32
vendor/league/commonmark/src/Extension/CommonMark/Node/Block/IndentedCode.php
vendored
Normal file
32
vendor/league/commonmark/src/Extension/CommonMark/Node/Block/IndentedCode.php
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Extension\CommonMark\Node\Block;
|
||||
|
||||
use League\CommonMark\Node\Block\AbstractBlock;
|
||||
use League\CommonMark\Node\StringContainerInterface;
|
||||
|
||||
final class IndentedCode extends AbstractBlock implements StringContainerInterface
|
||||
{
|
||||
private string $literal = '';
|
||||
|
||||
public function getLiteral(): string
|
||||
{
|
||||
return $this->literal;
|
||||
}
|
||||
|
||||
public function setLiteral(string $literal): void
|
||||
{
|
||||
$this->literal = $literal;
|
||||
}
|
||||
}
|
||||
56
vendor/league/commonmark/src/Extension/CommonMark/Node/Block/ListBlock.php
vendored
Normal file
56
vendor/league/commonmark/src/Extension/CommonMark/Node/Block/ListBlock.php
vendored
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
|
||||
* - (c) John MacFarlane
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Extension\CommonMark\Node\Block;
|
||||
|
||||
use League\CommonMark\Node\Block\AbstractBlock;
|
||||
use League\CommonMark\Node\Block\TightBlockInterface;
|
||||
|
||||
class ListBlock extends AbstractBlock implements TightBlockInterface
|
||||
{
|
||||
public const TYPE_BULLET = 'bullet';
|
||||
public const TYPE_ORDERED = 'ordered';
|
||||
|
||||
public const DELIM_PERIOD = 'period';
|
||||
public const DELIM_PAREN = 'paren';
|
||||
|
||||
protected bool $tight = false; // TODO Make lists tight by default in v3
|
||||
|
||||
/** @psalm-readonly */
|
||||
protected ListData $listData;
|
||||
|
||||
public function __construct(ListData $listData)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->listData = $listData;
|
||||
}
|
||||
|
||||
public function getListData(): ListData
|
||||
{
|
||||
return $this->listData;
|
||||
}
|
||||
|
||||
public function isTight(): bool
|
||||
{
|
||||
return $this->tight;
|
||||
}
|
||||
|
||||
public function setTight(bool $tight): void
|
||||
{
|
||||
$this->tight = $tight;
|
||||
}
|
||||
}
|
||||
47
vendor/league/commonmark/src/Extension/CommonMark/Node/Block/ListData.php
vendored
Normal file
47
vendor/league/commonmark/src/Extension/CommonMark/Node/Block/ListData.php
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
|
||||
* - (c) John MacFarlane
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Extension\CommonMark\Node\Block;
|
||||
|
||||
class ListData
|
||||
{
|
||||
public ?int $start = null;
|
||||
|
||||
public int $padding = 0;
|
||||
|
||||
/**
|
||||
* @psalm-var ListBlock::TYPE_*
|
||||
* @phpstan-var ListBlock::TYPE_*
|
||||
*/
|
||||
public string $type;
|
||||
|
||||
/**
|
||||
* @psalm-var ListBlock::DELIM_*|null
|
||||
* @phpstan-var ListBlock::DELIM_*|null
|
||||
*/
|
||||
public ?string $delimiter = null;
|
||||
|
||||
public ?string $bulletChar = null;
|
||||
|
||||
public int $markerOffset;
|
||||
|
||||
public function equals(ListData $data): bool
|
||||
{
|
||||
return $this->type === $data->type &&
|
||||
$this->delimiter === $data->delimiter &&
|
||||
$this->bulletChar === $data->bulletChar;
|
||||
}
|
||||
}
|
||||
37
vendor/league/commonmark/src/Extension/CommonMark/Node/Block/ListItem.php
vendored
Normal file
37
vendor/league/commonmark/src/Extension/CommonMark/Node/Block/ListItem.php
vendored
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* Original code based on the CommonMark JS reference parser (https://bitly.com/commonmark-js)
|
||||
* - (c) John MacFarlane
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Extension\CommonMark\Node\Block;
|
||||
|
||||
use League\CommonMark\Node\Block\AbstractBlock;
|
||||
|
||||
class ListItem extends AbstractBlock
|
||||
{
|
||||
/** @psalm-readonly */
|
||||
protected ListData $listData;
|
||||
|
||||
public function __construct(ListData $listData)
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->listData = $listData;
|
||||
}
|
||||
|
||||
public function getListData(): ListData
|
||||
{
|
||||
return $this->listData;
|
||||
}
|
||||
}
|
||||
20
vendor/league/commonmark/src/Extension/CommonMark/Node/Block/ThematicBreak.php
vendored
Normal file
20
vendor/league/commonmark/src/Extension/CommonMark/Node/Block/ThematicBreak.php
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the league/commonmark package.
|
||||
*
|
||||
* (c) Colin O'Dell <colinodell@gmail.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace League\CommonMark\Extension\CommonMark\Node\Block;
|
||||
|
||||
use League\CommonMark\Node\Block\AbstractBlock;
|
||||
|
||||
class ThematicBreak extends AbstractBlock
|
||||
{
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user