diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index f2fb405..0000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1 +0,0 @@ -github: [smnandre] \ No newline at end of file diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index e972665..21c8d6d 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -2,9 +2,9 @@ name: CI on: push: - branches: [ "*" ] + branches: ["*"] pull_request: - branches: [ "*" ] + branches: ["*"] workflow_dispatch: permissions: @@ -15,26 +15,17 @@ concurrency: cancel-in-progress: true jobs: - cs: uses: altophp/.github/.github/workflows/CS.yml@main - with: - php-version: '8.4' - # composer-validate: true - # php-cs-fixer-args: '--diff --dry-run' sa: uses: altophp/.github/.github/workflows/SA.yml@main - with: - php-version: '8.4' - # phpstan-args: 'analyse --no-progress --memory-limit=-1' tests: strategy: fail-fast: false matrix: - php: ['8.4', '8.5'] + php: ["8.4", "8.5"] uses: altophp/.github/.github/workflows/tests.yml@main with: php-version: ${{ matrix.php }} - # phpunit-args: '--colors=never' diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index d815334..0000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,32 +0,0 @@ -# Contributing to Alto Code Highlight - -Contributions should preserve the public API, escaped output, semantic scopes, -and deterministic highlighting. - -## Prepare a checkout - -```bash -composer install -composer qa -``` - -`composer qa` runs PHP CS Fixer, PHPStan, and PHPUnit. Run coverage separately -when a change affects executable code: - -```bash -composer coverage -``` - -## Propose a change - -Add or update tests for observable behavior. Update `docs/` and `CHANGELOG.md` -when the public contract changes. Keep language aliases, embedded parsing, -semantic scopes, and generated HTML compatibility explicit. - -Documentation preview tooling is maintained in -[`tools/docs-showcase/`](tools/docs-showcase/README.md). It is contributor -infrastructure and is not part of the package's public API. - -Open a pull request against `main` only after the complete quality gate passes. -Describe the user-visible result and any compatibility, security, or -performance impact. diff --git a/SECURITY.md b/SECURITY.md deleted file mode 100644 index bf1b62a..0000000 --- a/SECURITY.md +++ /dev/null @@ -1,8 +0,0 @@ -# Security policy - -Do not report a suspected vulnerability through a public GitHub issue. Email -[security@altocoda.com](mailto:security@altocoda.com) with the affected -version, impact, reproduction, and any known mitigation. - -Reports are accepted in English or French and handled through coordinated -disclosure. Avoid including secrets or unrelated personal data. diff --git a/SUPPORT.md b/SUPPORT.md deleted file mode 100644 index ce51306..0000000 --- a/SUPPORT.md +++ /dev/null @@ -1,10 +0,0 @@ -# Support - -Use GitHub issues for reproducible bugs and focused feature proposals. Include -the PHP and package versions, language identifier, selected theme, minimal -source input, expected result, and actual result. - -Usage questions should include the smallest complete code example and identify -whether the problem concerns parsing, rendering, embedded languages, or theme -integration. Do not post security vulnerabilities in a public issue; follow -the private process in `SECURITY.md`. diff --git a/composer.json b/composer.json index 2fc6c1b..607785d 100644 --- a/composer.json +++ b/composer.json @@ -38,14 +38,14 @@ "ext-mbstring": "*", "ext-tokenizer": "*" }, - "suggest": { - "ext-simplexml": "Required by the optional TextMate theme adapter" - }, "require-dev": { "friendsofphp/php-cs-fixer": "^3.94", "phpstan/phpstan": "^2.1", "phpunit/phpunit": "^12.5" }, + "suggest": { + "ext-simplexml": "Required by the optional TextMate theme adapter" + }, "autoload": { "psr-4": { "Alto\\Code\\Highlight\\": "src/" @@ -60,6 +60,7 @@ "sort-packages": true }, "scripts": { + "coverage": "vendor/bin/phpunit --coverage-text", "cs": "vendor/bin/php-cs-fixer fix --dry-run --diff --sequential", "cs:fix": "vendor/bin/php-cs-fixer fix --sequential", "docs:capture": "npm --prefix tools/docs-showcase run capture", @@ -76,7 +77,6 @@ "@test" ], "sa": "vendor/bin/phpstan analyse --memory-limit=-1", - "test": "phpunit", - "coverage": "vendor/bin/phpunit --coverage-text" + "test": "phpunit" } } diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 106e8b7..776ccd8 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -1,5 +1,4 @@ parameters: - level: 10 + level: max paths: - src - treatPhpDocTypesAsCertain: false diff --git a/src/CodeParser.php b/src/CodeParser.php index 576b800..9abfe8b 100644 --- a/src/CodeParser.php +++ b/src/CodeParser.php @@ -51,13 +51,7 @@ public function __construct( $this->embeddedRegistry = $embeddedRegistry ?? new EmbeddedLanguageRegistry(); $languages ??= Languages::getDefaultLanguages(); - foreach ($languages as $language) { - if (!$language instanceof LanguageInterface) { - throw new \InvalidArgumentException('All languages must implement LanguageInterface.'); - } - - $this->registerLanguage($language); - } + $this->registerLanguages($languages); } /** @@ -110,6 +104,20 @@ private function getLanguage(string $identifier): LanguageInterface return $this->languages[$identifier]; } + /** + * @param array $languages + */ + private function registerLanguages(array $languages): void + { + foreach ($languages as $language) { + if (!$language instanceof LanguageInterface) { + throw new \InvalidArgumentException('All languages must implement LanguageInterface.'); + } + + $this->registerLanguage($language); + } + } + private function parseWithLanguage(LanguageInterface $language, string $code): ParsedStream { if ($language instanceof EmbeddedLanguageCapable) { diff --git a/src/Embedded/EmbeddedTrigger.php b/src/Embedded/EmbeddedTrigger.php index e41d405..2e3b795 100644 --- a/src/Embedded/EmbeddedTrigger.php +++ b/src/Embedded/EmbeddedTrigger.php @@ -129,7 +129,7 @@ private static function normalizeAttributeConstraints(array $constraints): array continue; } - $normalized[$key] = array_values($allowedValues); + $normalized[$key] = $allowedValues; } return $normalized; diff --git a/src/Language/CssLanguage.php b/src/Language/CssLanguage.php index 9ff5b20..d56e9e1 100644 --- a/src/Language/CssLanguage.php +++ b/src/Language/CssLanguage.php @@ -371,13 +371,7 @@ protected function getTextBefore(array $tokens): string return ''; } - $last = end($tokens); - - if (false === $last) { - return ''; - } - - return $last->getText(); + return $tokens[count($tokens) - 1]->getText(); } protected function isPseudoClass(string $text): bool diff --git a/src/Language/TypeScriptLanguage.php b/src/Language/TypeScriptLanguage.php index c45c5b3..9e6103b 100644 --- a/src/Language/TypeScriptLanguage.php +++ b/src/Language/TypeScriptLanguage.php @@ -651,10 +651,7 @@ private function isRegexContext(array $tokens): bool return true; } - $lastToken = end($tokens); - if (false === $lastToken) { - return true; - } + $lastToken = $tokens[count($tokens) - 1]; if (Scope::Whitespace === $lastToken->getScope()) { for ($i = count($tokens) - 1; $i >= 0; --$i) {