Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
3cd96eb
Update to version 2.3.15
shrimp2t Sep 19, 2025
4684469
Fix security issues.
shrimp2t Nov 24, 2025
db80da7
Update alert copy text
shrimp2t Nov 24, 2025
d845a1b
Add phpcs comment
shrimp2t Nov 25, 2025
c95e10a
Update sanitize.php
shrimp2t Feb 26, 2026
2373106
Merge branch 'new_frontendjs' into dev
shrimp2t Feb 26, 2026
246c032
Improve assets files, use webpack to build bundle assets files
shrimp2t Feb 27, 2026
a46588a
Fix Onepress_Bully undefined issue
shrimp2t Mar 21, 2026
2d1aa3c
Rebuild assets files
shrimp2t Apr 2, 2026
a7e5812
Load fontawesome to customizer
shrimp2t Apr 4, 2026
c771550
Fixed #491
shrimp2t Apr 5, 2026
778f090
Improve customizer controls, support svg icon, fixed #481, #Status: …
shrimp2t Apr 6, 2026
11e3a63
Improve repeatable customizer sync and inputs
shrimp2t Apr 6, 2026
93391a4
Support self-hosted video lightbox & media control, fixed #471
shrimp2t Apr 6, 2026
e1f4a0e
Reorder sanitization and adjust escaping, fixed #480
shrimp2t Apr 7, 2026
0646420
Update frontend theme Bootstrap
shrimp2t Apr 7, 2026
9888b40
Rebuild assets files
shrimp2t Apr 7, 2026
b0de2a3
Add site name to hero image alt attribute, #470
shrimp2t Apr 7, 2026
56dbb35
Update changelog.md
shrimp2t Apr 7, 2026
589ff46
Support grid blog layout; add Bootstrap SCSS, #493
shrimp2t Apr 7, 2026
13449de
Rebuild frontend assets, use minified RTL CSS
shrimp2t Apr 7, 2026
111d93e
Rebuild assets files
shrimp2t Apr 8, 2026
440f872
Update build files
shrimp2t Apr 8, 2026
003790e
docs: add agent guide with feature-grouped spec files
shrimp2t May 26, 2026
b65ed87
build: exclude assets/ from git (webpack output)
shrimp2t May 26, 2026
9920c3b
fix(features): wire SVG icon bg to primary/secondary color
shrimp2t May 26, 2026
ec4e2e2
feat(editor): block-editor parity for 2.4.1
shrimp2t May 29, 2026
759ce72
docs: add block-editor spec and 2.4.1 plan files
shrimp2t May 29, 2026
19578e0
fix(blog): use CSS grid for WP [gallery] shortcode layout
shrimp2t May 30, 2026
a43d610
refactor(typography): semantic font-family aliases at :root
shrimp2t May 30, 2026
046df75
fix(hero): preserve HTML tags inside .js-rotating phrases
shrimp2t May 30, 2026
2a0258c
chore(release): bump version to 2.4.1
shrimp2t May 30, 2026
f4e8a47
docs(changelog): add 2.4.1 entries
shrimp2t May 30, 2026
5707595
chore(release): correct version to 2.3.18
shrimp2t May 31, 2026
34cd460
Merge pull request #504 from FameThemes/dev-fix-editor
shrimp2t May 31, 2026
2442912
fix(controls): always show every row in Section Order & Styling list
shrimp2t May 31, 2026
f982a27
Merge pull request #506 from FameThemes/dev-fix-editor
shrimp2t May 31, 2026
62fe85a
build(release): exclude docs/ and plan-*.md from release zip
shrimp2t Jun 2, 2026
79692b3
build(release): also exclude plans/ from release zip
shrimp2t Jun 2, 2026
69c2989
build(release): add gh_release task
shrimp2t Jun 2, 2026
f9ea387
fix(theme-json): rename Text color slug to avoid .has-text-color coll…
shrimp2t Jun 17, 2026
f08cc43
chore(release): bump version to 2.3.19
shrimp2t Jun 19, 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
72 changes: 72 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/**
* ESLint for OnePress theme.
* @wordpress/scripts `lint:js` only picks up `.eslintrc.js` (not `.eslintrc.cjs`).
* Webpack production build does not run ESLint.
*/
module.exports = {
root: true,
extends: [ 'plugin:@wordpress/eslint-plugin/recommended' ],
env: {
browser: true,
es2021: true,
jquery: true,
},
globals: {
C_Icon_Picker: 'readonly',
Color: 'readonly',
QTags: 'readonly',
_: 'readonly',
switchEditors: 'readonly',
tinymce: 'readonly',
tinyMCEPreInit: 'readonly',
wp: 'readonly',
},
ignorePatterns: [
'**/node_modules/**',
'**/assets/**/*.js',
'**/vendor/**',
],
overrides: [
{
files: [ 'src/admin/**/*.js', 'src/admin/**/*.jsx' ],
globals: {
ONEPRESS_CUSTOMIZER_DATA: 'readonly',
_wpCustomizeSettings: 'readonly',
_wpEditor: 'readonly',
onepress_customizer_settings: 'readonly',
quicktags: 'readonly',
tinyMCE: 'readonly',
},
rules: {
'@wordpress/no-unused-vars-before-return': 'off',
'array-callback-return': 'off',
'dot-notation': 'off',
eqeqeq: 'off',
'jsdoc/check-tag-names': 'off',
'jsdoc/no-undefined-types': 'off',
'jsdoc/require-param': 'off',
'jsdoc/require-param-type': 'off',
'no-alert': 'off',
'no-cond-assign': 'off',
'no-else-return': 'off',
'no-implicit-globals': 'off',
'no-lonely-if': 'off',
'no-nested-ternary': 'off',
'no-shadow': 'off',
'no-undef': 'off',
'no-unreachable': 'off',
'no-unused-vars': 'off',
'no-var': 'off',
'object-shorthand': 'off',
'prefer-const': 'off',
camelcase: 'off',
'prettier/prettier': 'off',
'vars-on-top': 'off',
'jsx-a11y/anchor-has-content': 'off',
'jsx-a11y/anchor-is-valid': 'off',
'jsx-a11y/label-has-associated-control': 'off',
'react-hooks/exhaustive-deps': 'off',
},
},
],
};
40 changes: 21 additions & 19 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
# Sass cache
.sass-cache

# Grunt
/node_modules/
/releases/
npm-debug.log

# PhpStorm
.idea

# macOS
.DS_Store

# SASS Source Map
*.css.map

# Dist file
*.zip
# Build output — regenerated by `npm run build` from src/ via webpack.
# See webpack.config.js: output.path = path.resolve(__dirname, "assets")
assets/

# Node
/node_modules/
npm-debug.log

# Legacy Sass cache
.sass-cache

# Legacy SASS source maps (now inside assets/, but defensive)
*.css.map

# IDE / OS
.idea
.DS_Store

# Release artifacts
/releases/
*.zip
67 changes: 67 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# OnePress — Agent Guide

OnePress is a Bootstrap-4–based, one-page WordPress theme by FameThemes, derived from Underscores. It targets PHP ≥ 7.4 and WP ≤ 6.9, text domain `onepress`. The front page is composed of independently toggleable **sections** wired through the Customizer; the rest of the site uses a conventional `_s`-style template hierarchy. WooCommerce is first-class.

## ⚠️ Production theme — 60,000+ active installs

OnePress is published on WordPress.org with **60,000+ active installations**. **Every code change must be evaluated against the installed base.** A "small cleanup" that renames a theme mod, drops a default value, changes default CSS, or removes a hook can silently break tens of thousands of live customer sites — there is no staged rollout and no recall mechanism.

**Default operating mode is additive-only and conservative:**

- **Additive-only.** Do not delete, rename, or repurpose any existing PHP function, class, method, template file, section, hook, theme mod, option, post meta, image size, or CSS class shipped in any prior release. Add new code alongside old code. The old code path must keep working with its original behavior — forever, or at minimum until an explicit major-version removal that ships a migration. See [spec-conventions.md → Additive-only mandate](docs/spec-conventions.md#additive-only-mandate).
- **New supersedes old via delegation, not replacement.** When you introduce an improved version of a helper, the old helper stays and either (a) calls the new one with the legacy arguments, or (b) is left untouched and the new helper is what new callers use. Either way: **the old symbol still resolves and still does what it always did.**
- **Do not change defaults** that affect visual output without a back-compat shim that preserves the old behavior on existing sites (use a version-gated migration if you must).
- **Every PR/commit message must state the BC impact** in one line: `BC: none — additive helper`, `BC: none — internal refactor, all old symbols preserved`, `BC: deprecation — old key still read indefinitely`, etc.

The full BC contract and deprecation patterns are in [spec-conventions.md → Backward Compatibility](docs/spec-conventions.md#backward-compatibility). Read it before any non-trivial change.

---

This file is an **index**. Detailed specs live under [docs/](docs/) — open the one matching your task.

> Site-level rules (WP Studio CLI, SQLite, do-not-edit-core, etc.) live in [/CLAUDE.md](../../../CLAUDE.md) and [/STUDIO.md](../../../STUDIO.md). The specs below only cover the theme.

## Spec index

| Spec | Read when you need to … |
|---|---|
| [spec-architecture.md](docs/spec-architecture.md) | Find where any concern lives — file map with deep links |
| [spec-build.md](docs/spec-build.md) | Understand `npm` scripts, webpack entries, RTL, asset enqueuing, line-ending normalizer plugin |
| [spec-sections.md](docs/spec-sections.md) | Add/modify a front-page section, understand activation state, render flow, dots-nav |
| [spec-customizer.md](docs/spec-customizer.md) | Add a Customizer setting, pick the right custom control or sanitizer, wire selective refresh, register sidebars, theme supports, image sizes |
| [spec-hooks.md](docs/spec-hooks.md) | Look up an action/filter, use loop props, copy a hook recipe |
| [spec-admin.md](docs/spec-admin.md) | Touch the page meta box, the theme dashboard, recommended actions, or block-editor styles |
| [spec-block-editor.md](docs/spec-block-editor.md) | Editor ↔ frontend parity architecture, color palette + font size filters, block-specific styling, theme supports |
| [spec-naming.md](docs/spec-naming.md) | Pick the right name for a function, class, theme mod, hook, CSS class, image size, etc. — also lists known frozen inconsistencies |
| [spec-conventions.md](docs/spec-conventions.md) | Check sanitize/escape rules, i18n, RTL, WC gating, Plus detection, public API stability, additive-only mandate |
| [spec-line-endings.md](docs/spec-line-endings.md) | Audit / fix CRLF — LF-only policy and playbook |
| [spec-commits.md](docs/spec-commits.md) | Commit rules — anatomy, scopes, BC footer, release checklist |

## Active plans

| Plan | Status |
|---|---|
| [plan-block-editor-parity.md](docs/plan-block-editor-parity.md) | ✅ Phases 0–4, 6 complete in working tree; pending review for `2.4.0` tag |
| [plan-css-var-integration.md](docs/plan-css-var-integration.md) | 📋 Drafted — one-shot refactor: layout + colors (Customizer→theme.json bridge) + font sizes + font families + spacing; awaits review |

## First-time orientation (60 seconds)

1. Read this file + [spec-architecture.md](docs/spec-architecture.md).
2. Before naming **anything new** (function, class, hook, theme mod, CSS class, …): [spec-naming.md](docs/spec-naming.md).
3. If working on the front page: [spec-sections.md](docs/spec-sections.md).
4. If adding settings: [spec-customizer.md](docs/spec-customizer.md).
5. If editing JS/CSS: [spec-build.md](docs/spec-build.md) — never edit `assets/` directly.
6. Before committing: [spec-line-endings.md](docs/spec-line-endings.md) + [spec-commits.md](docs/spec-commits.md).

## Hard rules (must-know, always)

- **Treat every change as touching 60,000+ live sites.** See banner above and [spec-conventions.md → Backward Compatibility](docs/spec-conventions.md#backward-compatibility).
- **Additive-only: never delete or remove** an existing public PHP function, class, method, template, hook, theme mod, option, post meta, image size, or CSS class. Add new code; leave old code in place as a working fallback. See [spec-conventions.md → Additive-only mandate](docs/spec-conventions.md#additive-only-mandate).
- **Never rename** any of the above — rename = remove + add, which violates the additive rule.
- **Never change a default value** that alters rendered output without a back-compat shim or version-gated upgrade.
- **Never edit `wp-includes/` or `wp-admin/`** — see [/STUDIO.md](../../../STUDIO.md).
- **Never edit `assets/`** — it's build output. Edit `src/` and rebuild. See [spec-build.md](docs/spec-build.md).
- **Never edit `node_modules/`** — CRLF is normalized at bundle time. See [spec-line-endings.md](docs/spec-line-endings.md).
- **Never use `sed -i`** for normalization — use `perl -i -pe`. See [spec-line-endings.md](docs/spec-line-endings.md).
- **Never `git add -A`** — stage files by name. See [spec-commits.md](docs/spec-commits.md).
- **Never bypass nonces** on admin POST handlers. See [spec-admin.md](docs/spec-admin.md).
178 changes: 175 additions & 3 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,18 +73,28 @@ module.exports = function (grunt) {
"!phpunit.xml.dist",
"!*.sh",
"!*.map",
"!**/*.map",
"!Gruntfile.js",
"!package.json",
"!.gitignore",
"!phpunit.xml",
"!README.md",
"!sass/**",
"!src/**",
"!codesniffer.ruleset.xml",
"!vendor/**",
"!composer.json",
"!composer.lock",
"!package-lock.json",
"!phpcs.xml.dist",
"!webpack.config.js",
"!.babelrc",
// Since 2.3.18: dev-only documentation should not ship in the
// distributable zip. `docs/` and `plans/` hold spec / plan /
// agent guides; `plan-*.md` anywhere is a development artifact.
"!docs/**",
"!plans/**",
"!**/plan-*.md",
],
dest: "onepress/",
},
Expand Down Expand Up @@ -122,8 +132,6 @@ module.exports = function (grunt) {
theme_main: {
src: [
"style.css",
"assets/**/*.css",
"src/**/*.scss",
],
overwrite: true,
replacements: [
Expand Down Expand Up @@ -199,12 +207,176 @@ module.exports = function (grunt) {
"compress:main",
"clean:main",
]);

/**
* Create or update the `v<version>` GitHub release for this theme.
*
* Behaviour:
* - If `v<version>` already exists on GitHub, the task refreshes the
* release notes (re-extracted from changelog.md) and replaces the
* attached zip via `--clobber`.
* - If `v<version>` doesn't exist, the task creates the release and
* tags HEAD of the current branch.
*
* Notes:
* - Release notes come from the matching `# <version>` block in
* changelog.md; falls back to "Release <version>" if not found.
* - Requires `gh` CLI authenticated (`gh auth login`). The task
* fails fast with a clear message if `gh` is missing or unauth'd.
* - Push local commits first — the tag will reference HEAD; an
* unpushed HEAD makes the release point at a commit origin
* hasn't seen.
*/
grunt.registerTask(
"gh_release",
"Create/update GitHub release for current version",
function () {
const done = this.async();
const os = require("os");
const { execSync } = require("child_process");

const version = pkgInfo.version;
const tag = "v" + version;
// Theme zip drops the `v` prefix that the plugin uses
// (see compress:main config above — `onepress-<version>.zip`).
const zip = "onepress-" + version + ".zip";

if (!fs.existsSync(zip)) {
grunt.fail.fatal(
"Release zip not found: " + zip + " — run `zipfile` first."
);
return done(false);
}

try {
execSync("gh --version", { stdio: ["ignore", "ignore", "ignore"] });
} catch (e) {
grunt.fail.fatal(
"`gh` CLI not found. Install from https://cli.github.com and run `gh auth login`."
);
return done(false);
}

try {
execSync("gh auth status", { stdio: ["ignore", "ignore", "ignore"] });
} catch (e) {
grunt.fail.fatal(
"`gh` CLI is not authenticated — run `gh auth login`."
);
return done(false);
}

// Pull the matching changelog block from changelog.md.
// Match `# 2.3.18` heading up to next `# <next-version>` or EOF.
// No /m flag — `$` must mean end-of-string here so the lookahead
// only terminates at the next version header or true EOF.
// `(?:^|\n)` handles the heading anywhere in the file.
let notes = "";
try {
const changelog = fs.readFileSync("changelog.md", "utf8");
const versionEsc = version.replace(/\./g, "\\.");
const re = new RegExp(
"(?:^|\\n)#\\s*" +
versionEsc +
"\\s*\\n([\\s\\S]*?)(?=\\n#\\s+[\\w\\.]|$)"
);
const m = changelog.match(re);
if (m) {
notes = m[1].replace(/\r/g, "").trim();
}
} catch (e) {
// best-effort; fall through to default notes below
}
if (!notes) {
notes = "Release " + version;
}

const notesPath = path.join(
os.tmpdir(),
"onepress-gh-release-notes-" + Date.now() + ".md"
);
fs.writeFileSync(notesPath, notes);

function shellEscape(s) {
return "'" + String(s).replace(/'/g, "'\\''") + "'";
}

function runVisible(cmd) {
grunt.log.writeln("$ " + cmd);
execSync(cmd, { stdio: ["inherit", "inherit", "inherit"] });
}

// Probe for existing release. Non-zero exit = doesn't exist.
let exists = false;
try {
execSync(
"gh release view " + shellEscape(tag) + " --json tagName -q .tagName",
{ stdio: ["ignore", "pipe", "ignore"] }
);
exists = true;
} catch (e) {
exists = false;
}

try {
if (exists) {
grunt.log.writeln(
"Release " + tag + " exists — updating notes + replacing zip."
);
runVisible(
"gh release edit " +
shellEscape(tag) +
" --notes-file " +
shellEscape(notesPath)
);
runVisible(
"gh release upload " +
shellEscape(tag) +
" " +
shellEscape(zip) +
" --clobber"
);
} else {
grunt.log.writeln(
"Release " + tag + " does not exist — creating."
);
runVisible(
"gh release create " +
shellEscape(tag) +
" " +
shellEscape(zip) +
" --title " +
shellEscape(tag) +
" --notes-file " +
shellEscape(notesPath)
);
}
grunt.log.ok(
"GitHub release " + tag + " synced (asset: " + zip + ")."
);
done();
} catch (e) {
grunt.log.error(String((e && e.message) || e));
grunt.fail.fatal("`gh` command failed — see output above.");
done(false);
} finally {
try {
fs.unlinkSync(notesPath);
} catch (_) {
/* ignore */
}
}
}
);

grunt.registerTask("release", function (ver) {
let newVersion = pkgInfo.version;
grunt.task.run("shell:build");
grunt.task.run("bumpup:" + newVersion);
grunt.task.run("replace");

grunt.task.run("zipfile");
grunt.task.run("gh_release");

// i18n
// grunt.task.run(['addtextdomain', 'makepot']);
// re create css file and min
Expand Down
Loading