Gitea migration
This commit is contained in:
1 parent
e5dbe43002
commit
3ef3ec2a6e
4 files changed
+1
-418
No files matched your search
@@ -4,5 +4,6 @@
|
|||||||
/dist/
|
/dist/
|
||||||
/.phpunit.cache/
|
/.phpunit.cache/
|
||||||
/.idea/
|
/.idea/
|
||||||
|
/notes/
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
Desktop.ini
|
Desktop.ini
|
||||||
@@ -1,384 +0,0 @@
|
|||||||
# AGENTS.md — Codex Playbook for Building a WordPress Plugin
|
|
||||||
|
|
||||||
> A precise, no-nonsense blueprint for orchestrating autonomous and semi-autonomous coding agents to plan, scaffold, implement, test, and ship a production‑grade WordPress plugin.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 0) Purpose & Scope
|
|
||||||
|
|
||||||
This document defines the **agents**, **tools**, **workflows**, **constraints**, and **acceptance criteria** for using an agentic coding system ("Codex") to create and maintain a WordPress plugin. It is optimized for **real, shippable code**, not demos.
|
|
||||||
|
|
||||||
Outcomes:
|
|
||||||
|
|
||||||
* A production‑ready WordPress plugin following WP Coding Standards.
|
|
||||||
* Clean, testable PHP, JS (React) admin UI, i18n, security hardening, and CI.
|
|
||||||
* Repeatable pipelines from idea → release (with versioning & changelog).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 1) High-Level Task Graph
|
|
||||||
|
|
||||||
1. **Discovery & Planning**
|
|
||||||
Requirements intake → constraints → feature list → milestones → risk register.
|
|
||||||
2. **Scaffolding**
|
|
||||||
Repo init → plugin headers → file structure → build tooling.
|
|
||||||
3. **Implementation**
|
|
||||||
Core PHP features → admin screens (React) → REST endpoints → WP‑CLI.
|
|
||||||
4. **Quality & Hardening**
|
|
||||||
PHPCS/WPCS → unit/integration tests → e2e (Playwright) → security checks.
|
|
||||||
5. **Docs & Demos**
|
|
||||||
README, inline docs, usage guide, screenshots/GIFs, sample data.
|
|
||||||
6. **Release**
|
|
||||||
Semantic versioning → tagged release → changelog → release assets.
|
|
||||||
7. **Maintenance**
|
|
||||||
Issue triage → patch releases → perf audits → dependency updates.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 2) Agents & Ownership
|
|
||||||
|
|
||||||
### A. PlannerAgent (Lead)
|
|
||||||
|
|
||||||
* **Goal:** Convert business requirements into a concrete implementation plan.
|
|
||||||
* **Inputs:** Product brief, constraints, compatibility targets.
|
|
||||||
* **Outputs:** `PLAN.md` with MVP scope, milestones, risks, success metrics.
|
|
||||||
* **Key checks:** Feasibility, risk mitigation, timeline, test strategy alignment.
|
|
||||||
|
|
||||||
### B. ScaffolderAgent
|
|
||||||
|
|
||||||
* **Goal:** Create plugin skeleton and development toolchain.
|
|
||||||
* **Outputs:**
|
|
||||||
|
|
||||||
* `plugin-name/plugin-name.php` with proper headers
|
|
||||||
* `src/` (PHP), `includes/`, `assets/`, `admin/`, `languages/`
|
|
||||||
* `composer.json`, `package.json`, `webpack.config.js` or `vite.config.ts`
|
|
||||||
* `phpcs.xml`, `.editorconfig`, `.gitattributes`, `.gitignore`
|
|
||||||
* `README.md`, `CHANGELOG.md`, `LICENSE`
|
|
||||||
* **Standards:** PSR-4 autoloading, WPCS ruleset, PHPCS baseline if needed.
|
|
||||||
|
|
||||||
### C. BackendAgent (PHP)
|
|
||||||
|
|
||||||
* **Goal:** Implement core plugin features with hooks, filters, REST, cron, WP‑CLI.
|
|
||||||
* **Constraints:**
|
|
||||||
|
|
||||||
* **Security first:** Nonces, `current_user_can`, prepared SQL, sanitize/escape.
|
|
||||||
* **Compatibility:** PHP 7.4–8.3, WP 6.1+, multisite-safe where relevant.
|
|
||||||
* **Artifacts:** `src/` classes, `includes/`, `uninstall.php`, activation/deactivation hooks.
|
|
||||||
|
|
||||||
### D. FrontendAgent (Admin UI)
|
|
||||||
|
|
||||||
* **Goal:** Build admin screens with React + WP Scripts (or Vite w/ WP deps externals).
|
|
||||||
* **Artifacts:** `admin/` React app, enqueue via `wp_enqueue_script/style`, settings pages, components, forms with wp.data/wc.data if Woo, and REST integration.
|
|
||||||
|
|
||||||
### E. APIGatewayAgent (REST & Webhooks)
|
|
||||||
|
|
||||||
* **Goal:** Define REST routes, permissions callbacks, and (optionally) webhooks.
|
|
||||||
* **Checks:** Nonces or auth tokens, caps mapping, rate limiting where applicable.
|
|
||||||
|
|
||||||
### F. CLIAgent (WP‑CLI)
|
|
||||||
|
|
||||||
* **Goal:** Add WP‑CLI commands for power users & CI automation.
|
|
||||||
* **Artifacts:** `src/CLI/Commands.php` with subcommands, argument validation, exit codes.
|
|
||||||
|
|
||||||
### G. TestAgent (QA)
|
|
||||||
|
|
||||||
* **Goal:** Unit, integration (WP core bootstrap), e2e (Playwright) with headless Chromium.
|
|
||||||
* **Artifacts:** `tests/phpunit.xml`, `tests/`, GitHub Actions CI templates.
|
|
||||||
|
|
||||||
### H. SecPerfAgent (Security & Performance)
|
|
||||||
|
|
||||||
* **Goal:** Threat modeling, perf budgets, db/indexing strategy, cache headers.
|
|
||||||
* **Checks:** Nonce coverage, XSS/CSRF/SQLi audit, escaping map, memory/time profiles.
|
|
||||||
|
|
||||||
### I. DocsAgent
|
|
||||||
|
|
||||||
* **Goal:** Build crisp docs: README, usage, configuration, troubleshooting, examples.
|
|
||||||
|
|
||||||
### J. ReleaseAgent
|
|
||||||
|
|
||||||
* **Goal:** Version bump, changelog, Git tag, GitHub Release, packaged zip artifact.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 3) Repository Structure
|
|
||||||
|
|
||||||
```
|
|
||||||
logo-soup/
|
|
||||||
├─ logo-soup.php # Main plugin file (headers + bootstrap)
|
|
||||||
├─ composer.json # PSR-4 autoload, dev tools
|
|
||||||
├─ package.json # Build scripts, lint, test
|
|
||||||
├─ vite.config.ts | webpack.config.js
|
|
||||||
├─ phpcs.xml # WPCS rules
|
|
||||||
├─ phpstan.neon # Static analysis (level 6–max)
|
|
||||||
├─ .editorconfig / .gitattributes / .gitignore
|
|
||||||
├─ README.md / CHANGELOG.md / LICENSE / CONTRIBUTING.md
|
|
||||||
├─ src/ # PHP business logic (PSR-4)
|
|
||||||
│ ├─ Admin/ # Settings pages, controllers
|
|
||||||
│ ├─ REST/ # Endpoints & permissions
|
|
||||||
│ ├─ CLI/ # WP-CLI commands
|
|
||||||
│ ├─ Cron/ # Scheduled events
|
|
||||||
│ └─ Infrastructure/ # Services, DI container, logger
|
|
||||||
├─ includes/ # Legacy-style helpers (thin shims only)
|
|
||||||
├─ admin/ # React app (built → dist)
|
|
||||||
│ ├─ src/ # TS/JS, components
|
|
||||||
│ └─ dist/ # Built assets (git-ignored)
|
|
||||||
├─ assets/ # CSS, images, icons
|
|
||||||
├─ languages/ # .pot and translations
|
|
||||||
├─ tests/
|
|
||||||
│ ├─ phpunit.xml.dist # Bootstrapped with WP test suite
|
|
||||||
│ ├─ php/ # Unit/integration tests
|
|
||||||
│ └─ e2e/ # Playwright tests
|
|
||||||
└─ uninstall.php # Hard removal of options/data when required
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 4) Coding Standards & Quality Gates
|
|
||||||
|
|
||||||
* **PHP:** PHPCS with **WordPress Coding Standards** (`wpcs`), PHPStan level ≥ 6.
|
|
||||||
* **JS/TS:** ESLint (airbnb/base), TypeScript strict mode where used, Prettier.
|
|
||||||
* **Commits:** Conventional Commits.
|
|
||||||
* **Branches:** `main` (stable), `develop`, feature branches → PRs.
|
|
||||||
* **CI Required Checks:** lint, static analysis, unit/integration tests, e2e (smoke), `composer validate`. No merge to `main` without green.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 5) Security Model
|
|
||||||
|
|
||||||
* Enforce **capability checks** on every privileged action. Prefer granular custom caps.
|
|
||||||
* **Nonces** on all state‑changing forms/requests; **verify before mutate**.
|
|
||||||
* Always **sanitize input** (`sanitize_text_field`, `sanitize_key`, `absint`, custom) and **escape output** (`esc_html`, `esc_attr`, `wp_kses`).
|
|
||||||
* **DB access:** `wpdb->prepare`, avoid dynamic table names; consider custom tables with schema migrations when needed.
|
|
||||||
* **Files:** Validate MIME types/size, use WP Filesystem API.
|
|
||||||
* **Settings:** Use `register_setting` with `sanitize_callback`.
|
|
||||||
* **Secrets:** Never commit secrets; use environment variables or WP constants via `.env` with `vlucas/phpdotenv` (optional).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 6) Build & Tooling
|
|
||||||
|
|
||||||
**Composer dev deps (suggested):**
|
|
||||||
|
|
||||||
* `dealerdirect/phpcodesniffer-composer-installer`
|
|
||||||
* `squizlabs/php_codesniffer`
|
|
||||||
* `wp-coding-standards/wpcs`
|
|
||||||
* `phpstan/phpstan`
|
|
||||||
* `phpunit/phpunit`
|
|
||||||
|
|
||||||
**NPM dev deps (suggested):**
|
|
||||||
|
|
||||||
* `@wordpress/scripts` *or* `vite` + `@wordpress/dependency-extraction-webpack-plugin` equivalent via externals
|
|
||||||
* `typescript`, `eslint`, `prettier`, `playwright`
|
|
||||||
|
|
||||||
**Makefile (optional) targets:**
|
|
||||||
|
|
||||||
```
|
|
||||||
make setup # composer install, npm install
|
|
||||||
make build # build admin assets
|
|
||||||
make lint # phpcs, eslint, phpstan
|
|
||||||
make test # phpunit, e2e (smoke)
|
|
||||||
make zip # generate distributable zip under ./dist
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 7) CI/CD (GitHub Actions templates)
|
|
||||||
|
|
||||||
* **php.yml:** matrix {php: \[7.4, 8.0, 8.1, 8.2, 8.3]}, run phpcs, phpstan, phpunit.
|
|
||||||
* **js.yml:** node LTS, run eslint, typecheck, build.
|
|
||||||
* **e2e.yml:** spin WP (wp-env/docker), run Playwright smoke on admin.
|
|
||||||
* **release.yml:** on tag `v*`, bump version in headers, generate zip, create release, attach artifact.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 8) Implementation Checklists
|
|
||||||
|
|
||||||
### 8.1 Plugin Bootstrap
|
|
||||||
|
|
||||||
* [ ] Header with `Plugin Name`, `Version`, `Requires at least`, `Requires PHP`, `Text Domain`.
|
|
||||||
* [ ] Autoloader (Composer) + safe early exit if direct access.
|
|
||||||
* [ ] Activation/Deactivation hooks; network‑aware.
|
|
||||||
* [ ] Service container bootstrap (optional) for loose coupling.
|
|
||||||
|
|
||||||
### 8.2 Admin UI
|
|
||||||
|
|
||||||
* [ ] Single‑page admin screen registered via `add_menu_page`/`add_submenu_page`.
|
|
||||||
* [ ] Nonce embedded into page for REST mutations.
|
|
||||||
* [ ] `wp_enqueue_script` with dependencies (`wp-element`, `wp-components`, etc.).
|
|
||||||
* [ ] Accessible components, keyboard navigation, focus styles.
|
|
||||||
|
|
||||||
### 8.3 REST API
|
|
||||||
|
|
||||||
* [ ] `register_rest_route` with namespaced routes and `permission_callback`.
|
|
||||||
* [ ] Input validation and output normalization.
|
|
||||||
* [ ] Pagination and error shapes consistent.
|
|
||||||
|
|
||||||
### 8.4 Data Layer
|
|
||||||
|
|
||||||
* [ ] Options API with schema, or custom tables via dbDelta + migrations.
|
|
||||||
* [ ] Caching using transients or object cache; set TTLs.
|
|
||||||
* [ ] Background tasks via Action Scheduler or WP Cron when needed.
|
|
||||||
|
|
||||||
### 8.5 Internationalization (i18n)
|
|
||||||
|
|
||||||
* [ ] Load text domain, generate `.pot`.
|
|
||||||
* [ ] Wrap strings with translation functions, no string concatenation with HTML.
|
|
||||||
|
|
||||||
### 8.6 Uninstall
|
|
||||||
|
|
||||||
* [ ] `uninstall.php` handles irreversible deletion when user opts-in.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 9) Prompts & Guardrails for Agents
|
|
||||||
|
|
||||||
**General guardrails** (apply to all agents):
|
|
||||||
|
|
||||||
* Prefer stable, framework‑agnostic PHP for plugin core; keep vendor size small.
|
|
||||||
* Follow WPCS; do not bypass lints without justification.
|
|
||||||
* Avoid over‑engineering; MVP first, extensibility second.
|
|
||||||
* Provide diffs/patches or exact file paths in outputs.
|
|
||||||
* Every change must include: rationale → code → tests → docs.
|
|
||||||
|
|
||||||
**Prompt scaffolds**:
|
|
||||||
|
|
||||||
* **PlannerAgent:**
|
|
||||||
|
|
||||||
* *"Given this brief: `project-brief.md`, enumerate functional/non‑functional requirements, risks, milestones, metrics, and a phased MVP plan. Output `PLAN.md` with tables and a Gantt‑style milestone list."*
|
|
||||||
|
|
||||||
* **ScaffolderAgent:**
|
|
||||||
|
|
||||||
* *"Generate a WordPress plugin skeleton named `logo-soup`. Include Composer (PSR‑4), Vite (or @wordpress/scripts), PHPCS (WPCS), PHPStan. Produce file tree and initial file contents. No placeholder TODOs—write minimal viable code."*
|
|
||||||
|
|
||||||
* **BackendAgent:**
|
|
||||||
|
|
||||||
* *"Implement feature `<feature>` behind capability `<cap>`. Add actions/filters, sanitize/validate, and unit tests. Return diff with file paths. Include acceptance tests for edge cases."*
|
|
||||||
|
|
||||||
* **FrontendAgent:**
|
|
||||||
|
|
||||||
* *"Create admin view `<view>` with React, using WP components. Implement controlled inputs, form validation, REST calls with nonce, and optimistic updates. Provide Playwright tests."*
|
|
||||||
|
|
||||||
* **APIGatewayAgent:**
|
|
||||||
|
|
||||||
* *"Define REST endpoint `<method> /<ns>/<route>` with schema, permission callback respecting `<cap>`. Include unit tests for auth and validation failures."*
|
|
||||||
|
|
||||||
* **CLIAgent:**
|
|
||||||
|
|
||||||
* *"Add WP‑CLI command `wp <ns> <cmd>` with flags `<flags>`. Validate args, handle errors gracefully, and return exit codes. Provide usage examples."*
|
|
||||||
|
|
||||||
* **TestAgent:**
|
|
||||||
|
|
||||||
* *"Write PHPUnit tests for `<class>` with edge cases. Bootstrap WP test suite. Add Playwright test for `<user flow>`. Ensure CI green."*
|
|
||||||
|
|
||||||
* **ReleaseAgent:**
|
|
||||||
|
|
||||||
* *"Prepare release `<version>`. Update plugin header + `readme.txt` stable tag, generate changelog (Conventional Commits), build zip, create Git tag and GitHub Release with assets."*
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 10) Acceptance Criteria (Definition of Done)
|
|
||||||
|
|
||||||
* ✅ Linting: PHPCS (WPCS) and ESLint pass with 0 errors.
|
|
||||||
* ✅ Tests: PHP unit/integration ≥ 80% critical path coverage; e2e smoke green.
|
|
||||||
* ✅ Security: Nonces, caps, sanitization/escaping verified; no direct SQL without prepare.
|
|
||||||
* ✅ Docs: README with install/usage, configuration, screenshots/GIFs; CHANGELOG.
|
|
||||||
* ✅ Release: Tagged semantic version; distributable zip attached to release.
|
|
||||||
* ✅ Performance: First meaningful paint in admin ≤ 2s on mid hardware; queries indexed.
|
|
||||||
* ✅ Accessibility: Admin UI meets WCAG AA basics (labels, contrast, keyboard nav).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 11) Example: Minimal Plugin Header & Bootstrap
|
|
||||||
|
|
||||||
```php
|
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* Plugin Name: Example Plugin
|
|
||||||
* Description: Minimal bootstrap showing headers, autoloading, and safety guards.
|
|
||||||
* Version: 0.1.0
|
|
||||||
* Requires at least: 6.1
|
|
||||||
* Requires PHP: 7.4
|
|
||||||
* Author: Your Org
|
|
||||||
* License: GPL-2.0-or-later
|
|
||||||
* Text Domain: example-plugin
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ( ! defined( 'ABSPATH' ) ) {
|
|
||||||
exit; // Exit if accessed directly.
|
|
||||||
}
|
|
||||||
|
|
||||||
// Composer autoload (if present).
|
|
||||||
$autoload = __DIR__ . '/vendor/autoload.php';
|
|
||||||
if ( file_exists( $autoload ) ) {
|
|
||||||
require_once $autoload;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bootstrap.
|
|
||||||
add_action( 'plugins_loaded', static function () {
|
|
||||||
// Initialize services, hooks, etc.
|
|
||||||
} );
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 12) Local Dev Environments
|
|
||||||
|
|
||||||
* **wp-env (official):** Zero-config local WP; good for e2e.
|
|
||||||
* **Docker Compose:** MySQL + WP + phpMyAdmin; seed data via WP‑CLI.
|
|
||||||
* **Valet/Local/Lando:** Developer preference; ensure parity with CI PHP versions.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 13) Release Engineering
|
|
||||||
|
|
||||||
* **Versioning:** `MAJOR.MINOR.PATCH`, align PHP headers and `readme.txt` `Stable tag`.
|
|
||||||
* **Dist:** Production build, vendor‑prefixed if shipping SDKs, no dev files.
|
|
||||||
* **SVN (wp.org) optional:** Mirror release using `svn cp` into `/tags/<version>`.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 14) Risk Register (starter)
|
|
||||||
|
|
||||||
| Risk | Impact | Likelihood | Mitigation |
|
|
||||||
| -------------------- | ------ | ---------- | ------------------------------------------ |
|
|
||||||
| WP Core API changes | Medium | Low | Pin compatibility, test on latest beta |
|
|
||||||
| PHP 7.4 deprecations | Medium | Medium | Polyfills, conditionals, CI matrix |
|
|
||||||
| Admin UI bloat | Medium | Medium | Perf budgets, code splitting, audit |
|
|
||||||
| Security regressions | High | Low | Threat model, security checklist, CI gates |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 15) Contribution Guide (short)
|
|
||||||
|
|
||||||
* Fork + feature branch; keep PRs < 500 lines when possible.
|
|
||||||
* Add/adjust tests and docs with any functional change.
|
|
||||||
* Keep public API stable; mark internal APIs with `@internal`.
|
|
||||||
* Link issues to PRs; include before/after screenshots for UI.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 16) Quickstart Commands
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1) Setup
|
|
||||||
git init && git commit --allow-empty -m "chore: repo init"
|
|
||||||
composer install
|
|
||||||
npm install
|
|
||||||
|
|
||||||
# 2) Develop
|
|
||||||
npm run dev # or: npm run start
|
|
||||||
|
|
||||||
# 3) Lint & test
|
|
||||||
composer phpcs
|
|
||||||
composer phpstan
|
|
||||||
npm run lint
|
|
||||||
npm run test
|
|
||||||
|
|
||||||
# 4) Build & package
|
|
||||||
npm run build
|
|
||||||
make zip # or custom script to produce ./dist/plugin-name-vX.Y.Z.zip
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**End of AGENTS.md**
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
# Logo Soup Plan
|
|
||||||
|
|
||||||
## MVP
|
|
||||||
|
|
||||||
- Register a dynamic `Logo Soup` Gutenberg block.
|
|
||||||
- Let editors upload logos, add optional links, and choose display behavior in the editor.
|
|
||||||
- Provide frontend styles for a static grid and a marquee-style carousel.
|
|
||||||
- Add plugin defaults under `Settings > Logo Soup`.
|
|
||||||
- Expose defaults through a secure REST endpoint for future admin UI expansion.
|
|
||||||
|
|
||||||
## Constraints
|
|
||||||
|
|
||||||
- WordPress 6.1+
|
|
||||||
- PHP 7.4+
|
|
||||||
- Input must be sanitized and output escaped.
|
|
||||||
- State-changing requests must verify capability and nonce.
|
|
||||||
|
|
||||||
## Risks
|
|
||||||
|
|
||||||
| Risk | Impact | Mitigation |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| Logo aspect ratios vary heavily | Medium | Normalize row height and image fit in CSS |
|
|
||||||
| Large logo lists create noisy output | Medium | Limit render to sanitized image/link fields only |
|
|
||||||
| Editor-side UX can sprawl quickly | Low | Keep controls focused on upload, link, and layout |
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
# Logo Soup WordPress Block
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
The Logo Soup WordPress plugin is designed to provide users with an easy way to create and manage a collection of logos on their WordPress site. The plugin allows users to upload logos, add links, and display them in a format that implements the library found here: https://github.com/sanity-labs/logo-soup. The plugin is user-friendly and can be easily integrated into any WordPress theme.
|
|
||||||
|
|
||||||
## Features
|
|
||||||
- **Logo Upload**: Users can upload logos directly from the WordPress post/page editor.
|
|
||||||
- **Link Management**: Each logo can have an associated link that directs users to a specified URL when clicked.
|
|
||||||
- **Customizable Display**: Users can choose how the logos are displayed on their site, including options for layout and styling.
|
|
||||||
- **Responsive Design**: The plugin ensures that logos are displayed correctly on all devices, including desktops, tablets, and smartphones.
|
|
||||||
Reference in new issue
Block a user