Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
3a1f931
3.0 Alpha-1
mambax7 Mar 26, 2026
6424d35
Enhancements
mambax7 Mar 27, 2026
512296a
feat(cssholmes): preserve designer and analyzer development
mambax7 Oct 26, 2026
480c469
ci(cssholmes): add shared quality and release checks
mambax7 Oct 26, 2026
cd8f41a
feat(cssholmes): preview gallery drafts and protect set revisions
mambax7 Oct 26, 2026
d9c32b5
chore(cssholmes): prepare 3.3.0 alpha 1 release
mambax7 Oct 27, 2026
e4e3fa5
test(cssholmes): use portable select keyboard navigation
mambax7 Oct 27, 2026
f8b403c
test(cssholmes): report selected palette rendering failures
mambax7 Oct 27, 2026
9b75e84
fix(cssholmes): retain selected palette content after refresh
mambax7 Oct 27, 2026
7b4d611
build(cssholmes): exclude local workbench records from releases
mambax7 Oct 27, 2026
cc4e24a
fix: protect workbench history and patch operations
mambax7 Oct 27, 2026
9b18b83
docs: correct the module tutorial link
mambax7 Oct 27, 2026
63488c1
docs: clarify generic scans and private history migration
mambax7 Oct 27, 2026
89483a6
test: cover review findings and concurrent history updates
mambax7 Oct 27, 2026
affb463
test: restore valid data before linked storage checks
mambax7 Oct 27, 2026
d773681
ci: select release notes for the tagged version
mambax7 Oct 27, 2026
a84250d
security(cssholmes): enforce export access and bound workbench history
mambax7 Oct 27, 2026
2ad9ca5
fix(cssholmes): correct overlay diagnostics and export controls
mambax7 Oct 27, 2026
b70c5f5
docs(cssholmes): clarify permissions and diagnostic limits
mambax7 Oct 27, 2026
441fd3a
test(cssholmes): cover review follow-up regressions
mambax7 Oct 27, 2026
484d152
security(cssholmes): escape overlay values and constrain asset URLs
mambax7 Oct 27, 2026
c7438c1
test(cssholmes): reject hostile overlay values and malformed fonts
mambax7 Oct 27, 2026
e6d8904
docs(cssholmes): record overlay security corrections
mambax7 Oct 27, 2026
c4c6620
docs(cssholmes): align tutorial with overlay behavior and QA scope
mambax7 Oct 27, 2026
d026e85
docs(cssholmes): clarify exports token inspection and setup examples
mambax7 Oct 27, 2026
561bf23
docs(cssholmes): qualify widget detection and theme discovery
mambax7 Oct 27, 2026
e542901
test: make optional browser checks portable
mambax7 Oct 27, 2026
09bb565
test: select gallery example and await frame styles
mambax7 Oct 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,5 +1,29 @@
# Auto detect text files and perform LF normalization
* text=auto
*.php text eol=lf
*.yml text eol=lf

# Development tools and temporary output do not belong in module distributions.
/.github export-ignore
/.build export-ignore
/.qodana export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
/.codeclimate.yml export-ignore
/.scrutinizer.yml export-ignore
/tests export-ignore
/phpstan.neon export-ignore
/phpunit.xml.dist export-ignore
/qodana.yaml export-ignore
/CONTRIBUTING.md export-ignore
/vendor export-ignore
/node_modules export-ignore
/composer.json export-ignore
/composer.lock export-ignore
/package-lock.json export-ignore
/coverage export-ignore
/reports export-ignore
/data/workbench/*.json export-ignore

# Custom for Visual Studio
*.cs diff=csharp
Expand Down
10 changes: 10 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
open-pull-requests-limit: 5
groups:
github-actions:
patterns: ['*']
57 changes: 57 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: CI

on:
workflow_call:
push:
branches: [master, main, 'release/**']
pull_request:

permissions:
contents: read

jobs:
qa:
name: QA (PHP ${{ matrix.php }})
runs-on: ubuntu-latest
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
php: ['8.4', '8.5']
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Setup PHP
uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # v2
with:
php-version: ${{ matrix.php }}
extensions: dom, mbstring, mysqli, xml
coverage: none
tools: composer:v2
- name: Install shared runner tools
run: |
mkdir -p "$RUNNER_TEMP/xoops_lib"
echo "XOOPS_VENDOR_PATH=$RUNNER_TEMP/xoops_lib/vendor" >> "$GITHUB_ENV"
composer --working-dir="$RUNNER_TEMP/xoops_lib" init --name=xoops/ci-tools --no-interaction
composer --working-dir="$RUNNER_TEMP/xoops_lib" require --dev --no-interaction --no-progress \
'phpunit/phpunit:^11.5' 'phpstan/phpstan:^2.0'
- name: PHP syntax and isolated regression suite
run: |
git ls-files -z '*.php' | xargs -0 -n1 php -l
php tests/run.php
- name: Scoped static analysis
run: php "$XOOPS_VENDOR_PATH/bin/phpstan" analyse --configuration=phpstan.neon --no-progress --memory-limit=512M
- name: JavaScript syntax
run: for file in assets/js/*.js tests/*.cjs; do node --check "$file"; done
- name: Install shared browser runner
if: matrix.php == '8.4'
run: |
npm install --prefix "$RUNNER_TEMP/xoops-browser" --no-save --package-lock=false playwright@1.60.0
"$RUNNER_TEMP/xoops-browser/node_modules/.bin/playwright" install --with-deps chromium
echo "PLAYWRIGHT_MODULE=$RUNNER_TEMP/xoops-browser/node_modules/playwright" >> "$GITHUB_ENV"
- name: Browser regressions and real endpoint roundtrip
if: matrix.php == '8.4'
run: |
export CHROME_PATH="$(node -e 'console.log(require(process.env.PLAYWRIGHT_MODULE).chromium.executablePath())')"
php tests/run.php --browser
44 changes: 44 additions & 0 deletions .github/workflows/qodana.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Optional Qodana analysis; shared PHP tooling remains configured separately.
name: Qodana

on:
workflow_dispatch:
pull_request:
push:
branches: [master, main, 'releases/*']

permissions: {}

concurrency:
group: qodana-${{ github.ref }}
cancel-in-progress: true

jobs:
qodana:
runs-on: ubuntu-22.04
timeout-minutes: 30
permissions:
contents: read
checks: write
env:
QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
steps:
- name: Explain skipped scan
if: env.QODANA_TOKEN == ''
run: echo "::notice::QODANA_TOKEN is not available; configure this repository's Qodana project token to enable analysis."

- name: Checkout
if: env.QODANA_TOKEN != ''
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
fetch-depth: 0
persist-credentials: false

- name: Qodana scan
if: env.QODANA_TOKEN != ''
uses: JetBrains/qodana-action@3e8d76ff0e0241618abd808682f426afe84bab3f # v2026.2.2
with:
upload-result: true
post-pr-comment: false
push-fixes: none
51 changes: 51 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: Release

on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
- '[0-9]+.[0-9]+.[0-9]+'
- 'v[0-9]+.[0-9]+.[0-9]+-[0-9A-Za-z]*'
- '[0-9]+.[0-9]+.[0-9]+-[0-9A-Za-z]*'

permissions:
contents: read

concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false

jobs:
qa:
uses: ./.github/workflows/ci.yml
release:
needs: qa
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Build clean module archive
id: archive
run: |
NOTES="docs/RELEASE-${GITHUB_REF_NAME#v}.md"
if [ ! -f "$NOTES" ]; then
echo "::error::Release notes missing: $NOTES"
exit 1
fi
echo "notes=$NOTES" >> "$GITHUB_OUTPUT"
ZIP="cssholmes-${GITHUB_REF_NAME}.zip"
git archive --format=zip --prefix=cssholmes/ -o "$ZIP" HEAD
echo "zip=$ZIP" >> "$GITHUB_OUTPUT"
- name: Create or update GitHub Release
uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3
with:
files: ${{ steps.archive.outputs.zip }}
overwrite_files: false
fail_on_unmatched_files: true
generate_release_notes: true
prerelease: ${{ contains(github.ref_name, '-') }}
make_latest: ${{ !contains(github.ref_name, '-') }}
body_path: ${{ steps.archive.outputs.notes }}
22 changes: 22 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,25 @@
\#*
*.bak
.idea/
/.vscode/
/vendor/
/node_modules/
/composer.lock
/package-lock.json
/.build/
/.qodana/
/.phpunit.cache/
/.phpunit.result.cache
/.php-cs-fixer.cache
/coverage/
/reports/
/data/workbench/*.json
/templates_c/
.env
.env.*
!.env.example
*.log
*.orig
*.rej
.DS_Store
Thumbs.db
8 changes: 5 additions & 3 deletions .scrutinizer.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# language: php
build:
environment:
php: 8.4
nodes:
tests: true
analysis:
Expand All @@ -13,9 +15,9 @@ build:
override: true
tests:
override:
- php-scrutinizer-run --enable-security-analysis
- php-scrutinizer-run --enable-security-analysis
filter:
dependency_paths:
- XoopsCore25/*
- tag/*
- XoopsCore25/*
- tag/*

124 changes: 104 additions & 20 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,104 @@
![alt XOOPS CMS](https://xoops.org/images/logoXoops4GithubRepository.png)
# Contributing to [XOOPS CMS](https://xoops.org)
[![XOOPS CMS Module](https://img.shields.io/badge/XOOPS%20CMS-Module-blue.svg)](https://xoops.org)
[![Software License](https://img.shields.io/badge/license-GPL-brightgreen.svg?style=flat)](https://www.gnu.org/licenses/gpl-2.0.html)

Contributions are **welcome** and will be fully **credited**.

We accept contributions via Pull Requests on [Github](https://github.com/XoopsModules25x/cssholmes).

## Pull Requests

- **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](http://pear.php.net/package/PHP_CodeSniffer).
- **Add tests!** - We encourage providing tests for your contributions.
- **Document any change in behavior** - Make sure the `/docs/changelog.txt` and any other relevant documentation are up-to-date.
- **Consider our release cycle** - We try to follow [Semantic Versioning v2.0.0](http://semver.org/). Randomly breaking public APIs is not an option.
- **Create feature branches** - Don't ask us to pull from your master branch.
- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests.
- **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please squash them before submitting.

**Happy coding, and _May the Source be with You_!**
# Contributing to cssHolmes

Submit focused pull requests to [mambax7/cssholmes](https://github.com/mambax7/cssholmes).
Use PSR-12, preserve public APIs and existing request/CSRF validation, and add a
regression test beside the affected behavior. Describe the problem, behavior
change, compatibility impact and commands actually run. Include screenshots for
visible changes. Use XOOPS Conventional Commits, for example
`fix(designer): preserve preview selection`.

## Shared tools

PHP 8.4 is the module minimum. Keep Composer dependencies in the site's shared
`xoops_lib/vendor`, never under this module. Existing shared PHPUnit and PHPStan
are sufficient; do not run `composer install` in the module. Node/Playwright
also come from an existing shared installation.

From `htdocs/modules/cssholmes`:

```sh
php tests/run.php
```

For an independent checkout (PowerShell example):

```powershell
$env:XOOPS_VENDOR_PATH = 'C:/path/to/htdocs/xoops_lib/vendor'
php tests/run.php
```

The runner stops on the first failed subprocess. It runs storage, sets, access,
preview-context and HTTP endpoint regressions in temporary storage, followed by
`phpunit.xml.dist` (Analyzer, Cli and Diagnostics). Its isolated namespace
bootstrap also supports a checkout whose folder is not named `cssholmes`.
It does not load a configured site's `mainfile.php`, session or database.

To include browser regressions and the HTTP roundtrip:

```powershell
$env:PLAYWRIGHT_MODULE = 'C:/path/to/shared/node_modules/playwright-core'
$env:CHROME_PATH = 'C:/Program Files/Google/Chrome/Application/chrome.exe'
php tests/run.php --browser
```

All independent `tests/*.cjs` run automatically. `designer-roundtrip.cjs` runs
through the temporary HTTP server. `designer-specimens.cjs` additionally needs
installed theme fixtures and is a separate opt-in command:
`php tests/designer-http.php --browser --specimens`.
The XMF/XTF package contract check is separately opt-in:
`php tests/xtf-contract.php /path/to/htdocs/xoops_lib/vendor/xoops`.

## Static analysis

`phpstan.neon` uses standard PHPStan level 5 for framework-independent
Analyzer, Cli, Diagnostics and Designer production classes. It has no baseline
or error ignores. PHPDoc types remain uncertain because manifest/token values
are validated at runtime. Core-dependent entrypoints, preloads, Workbench and
legacy Common helpers are outside this initial analysis scope; the gate does
not claim whole-module static coverage. Increase scope/level with targeted
fixes, not suppression files.

With a shared tool installation that has no automatic PHPStan extensions:

```powershell
php "$env:XOOPS_VENDOR_PATH/bin/phpstan" analyse --configuration=phpstan.neon
```

If the shared installation enables unrelated strict/deprecation extensions,
run its existing self-contained PHAR from a temporary location. This avoids
changing shared Composer settings or copying dependencies into the module:

```powershell
$analysisPhar = Join-Path ([IO.Path]::GetTempPath()) 'xoops-phpstan.phar'
Copy-Item "$env:XOOPS_VENDOR_PATH/phpstan/phpstan/phpstan.phar" $analysisPhar
try {
php $analysisPhar analyse --configuration=phpstan.neon
if ($LASTEXITCODE -ne 0) { throw 'PHPStan failed' }
} finally {
Remove-Item -LiteralPath $analysisPhar
}
```

Keep the temporary PHAR location stable across runs because PHPStan caches
paths to its bundled stubs. CI installs only the required tools in the runner's
shared temporary `xoops_lib` directory and invokes them directly.

## CI, releases and limitations

CI runs syntax checks, the isolated regression suite and scoped static analysis
on PHP 8.4 and 8.5, plus Chromium regressions on PHP 8.4. It does not install or
modify a real XOOPS database. Qodana uses PHP 8.4 and requires the repository's
`QODANA_TOKEN`; missing tokens produce an explicit skip notice. No scan fixes or
PR comments are pushed automatically.

Release tags run CI, then `git archive` creates a ZIP rooted at `cssholmes/`.
`.gitattributes` excludes development tooling and tests while preserving module
assets and runtime data. Existing release assets are not overwritten. Review
the ZIP before installing it on a site. Action updates are proposed weekly by
Dependabot; auto-merge is not enabled.

The historical full `tests/Unit` tree is not the standalone suite. It contains
incomplete Common tests, obsolete `getMockForTrait()` calls, a preload test with
a filename/class mismatch, and Helper tests requiring a real XOOPS runtime.
See [the recorded results](docs/compatibility.md); do not equate the focused
suite's pass with a clean full legacy suite.
Loading
Loading