Skip to content

Commit fb5961d

Browse files
authored
Merge pull request #467 from BeAPI/feat/theme-json-base
add base theme.json to use alignment size, spacings and colors
2 parents 33afea0 + cdc2b68 commit fb5961d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+520
-518
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,7 @@ package-lock.json
8484

8585
### conf-img
8686
assets/conf-img/*.json
87+
88+
### theme.json
89+
src/scss/01-abstract/_theme-json.scss
90+
theme.json

config/plugins.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,14 @@ const DependencyExtractionWebpackPlugin = require('@wordpress/dependency-extract
1010
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
1111

1212
const WebpackImageSizesPlugin = require('./webpack-image-sizes-plugin')
13+
const WebpackThemeJsonPlugin = require('./webpack-theme-json-plugin')
1314

1415
module.exports = {
1516
get: function (mode) {
1617
const plugins = [
18+
new WebpackThemeJsonPlugin({
19+
watch: mode !== 'production',
20+
}),
1721
new CleanWebpackPlugin({
1822
cleanOnceBeforeBuildPatterns: ['**/*', '!images', '!images/**'],
1923
}),
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
const chalk = require('chalk')
2+
const path = require('path')
3+
const fs = require('fs')
4+
5+
const logId = '[' + chalk.blue('WebpackThemeJsonPlugin') + ']'
6+
7+
class WebpackThemeJsonPlugin {
8+
/**
9+
* constructor
10+
* @param {Object} options = {
11+
* context: string - default: '../src/theme-json'
12+
* output: string - default: '../theme.json'
13+
* scssOutput: string - default: '../src/scss/00-variables/_theme-json.scss'
14+
* watch: boolean - default: false
15+
* }
16+
*/
17+
constructor(options) {
18+
// folders
19+
this._context = options.context || path.resolve(__dirname, '../src/theme-json') + '/'
20+
this._output = options.output || path.resolve(__dirname, '../theme.json')
21+
this._scssOutput = options.scssOutput || path.resolve(__dirname, '../src/scss/01-abstract/_theme-json.scss')
22+
23+
if (options.watch) {
24+
fs.watch(this._context, () => {
25+
this.refresh()
26+
})
27+
}
28+
29+
this.refresh()
30+
}
31+
32+
/**
33+
* apply
34+
*/
35+
apply() {}
36+
37+
/**
38+
* Generate theme json file
39+
*/
40+
generateThemeJson() {
41+
const jsonFiles = fs.readdirSync(this._context, {
42+
withFileTypes: true,
43+
})
44+
const themeJson = {}
45+
46+
jsonFiles.forEach((file) => {
47+
if (file.isFile() && file.name.endsWith('.json')) {
48+
let json = fs.readFileSync(this._context + file.name, 'utf8')
49+
50+
try {
51+
json = JSON.parse(json)
52+
} catch (e) {
53+
// eslint-disable-next-line no-console
54+
console.error(logId, 'Error parsing JSON file:', file.name)
55+
}
56+
57+
if (isPlainObject(json)) {
58+
extend(true, themeJson, json)
59+
} else {
60+
// eslint-disable-next-line no-console
61+
console.error(logId, 'JSON file is not a plain object:', file.name)
62+
}
63+
}
64+
})
65+
66+
fs.writeFileSync(this._output, JSON.stringify(themeJson, null, 2))
67+
// eslint-disable-next-line no-console
68+
console.log(logId, 'JSON files successfully generated !')
69+
70+
return this
71+
}
72+
73+
/**
74+
* Generate scss variables file
75+
*/
76+
generateScssVariables() {
77+
const comment = [
78+
'/**',
79+
' * Theme JSON',
80+
' * scss variables are extracted from theme.json',
81+
' *',
82+
" * !!! DON'T EDIT THIS FILE !!!",
83+
' *',
84+
' */',
85+
]
86+
const tasks = {
87+
'settings-color-palette'(key, value) {
88+
let result = ''
89+
const palette = []
90+
91+
for (const color of value) {
92+
const colorVar = getVariableName('settings-color-' + color.slug)
93+
result += `${colorVar}: ${color.color};\n`
94+
palette.push(`${color.slug}: ${colorVar}`)
95+
}
96+
97+
return result + `$settings-palette: (\n\t${palette.join(',\n\t')}\n);\n`
98+
},
99+
'settings-custom': 'default',
100+
'settings-spacing-spacingSizes'(key, value) {
101+
let result = ''
102+
103+
for (const spacing of value) {
104+
result += `${getVariableName('settings-spacing-' + spacing.slug)}: ${spacing.size};\n`
105+
}
106+
107+
return result
108+
},
109+
}
110+
// eslint-disable-next-line @wordpress/no-unused-vars-before-return
111+
const taskNames = Object.keys(tasks)
112+
let jsonFile = fs.readFileSync(this._output, 'utf8')
113+
114+
// check if the theme.json file is valid
115+
try {
116+
jsonFile = JSON.parse(jsonFile)
117+
} catch (e) {
118+
// eslint-disable-next-line no-console
119+
console.error(logId, 'Error parsing JSON file:', this._output)
120+
return this
121+
}
122+
123+
// format the scss variable name
124+
function getVariableName(id) {
125+
return `$${id.replace(/([A-Z])/g, '-$1').toLowerCase()}`
126+
}
127+
128+
// traverse the theme.json file and generate the scss variables
129+
function traverse(obj, parents = [], result = '') {
130+
for (const key in obj) {
131+
const id = (parents.length > 0 ? parents.join('-') + '-' : '') + key
132+
const taskName = taskNames.filter((t) => (id.startsWith(t) ? t : null))[0]
133+
const task = taskName ? tasks[taskName] : null
134+
135+
if (isPlainObject(obj[key])) {
136+
result += traverse(obj[key], [...parents, key])
137+
} else if (task) {
138+
if (task === 'default' && typeof obj[key] === 'string') {
139+
result += `${getVariableName(id)}: ${obj[key]};\n`
140+
} else if (typeof task === 'function') {
141+
result += task(key, obj[key])
142+
}
143+
}
144+
}
145+
146+
return result
147+
}
148+
149+
fs.writeFileSync(this._scssOutput, comment.join('\n') + '\n' + traverse(jsonFile))
150+
151+
return this
152+
}
153+
154+
/**
155+
* Refresh the theme json and scss variables files
156+
*/
157+
refresh() {
158+
this.generateThemeJson()
159+
this.generateScssVariables()
160+
return this
161+
}
162+
}
163+
164+
// ----
165+
// utils
166+
// ----
167+
function isPlainObject(o) {
168+
return o?.constructor === Object || Object.getPrototypeOf(o ?? 0) === null
169+
}
170+
171+
function extend() {
172+
const args = arguments
173+
const firstArgIsBool = typeof args[0] === 'boolean'
174+
const deep = firstArgIsBool ? args[0] : false
175+
const start = firstArgIsBool ? 1 : 0
176+
const rt = isPlainObject(args[start]) ? args[start] : {}
177+
178+
for (let i = start + 1; i < args.length; i++) {
179+
for (const prop in args[i]) {
180+
if (deep && isPlainObject(args[i][prop])) {
181+
rt[prop] = extend(true, {}, rt[prop], args[i][prop])
182+
} else if (typeof args[i][prop] !== 'undefined') {
183+
rt[prop] = args[i][prop]
184+
}
185+
}
186+
}
187+
188+
return rt
189+
}
190+
191+
module.exports = WebpackThemeJsonPlugin

inc/Services/Editor.php

Lines changed: 20 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ public function get_service_name(): string {
3737
* @param Service_Container $container
3838
*/
3939
public function boot( Service_Container $container ): void {
40-
$this->after_theme_setup();
4140
/**
4241
* Load editor style css for admin and frontend
4342
*/
@@ -48,11 +47,6 @@ public function boot( Service_Container $container ): void {
4847
*/
4948
$this->register_custom_block_styles();
5049

51-
/**
52-
* Customize theme.json settings
53-
*/
54-
add_filter( 'wp_theme_json_data_theme', [ $this, 'filter_theme_json_theme' ], 10, 1 );
55-
5650
/**
5751
* Load editor JS for ADMIN
5852
*/
@@ -63,86 +57,6 @@ public function boot( Service_Container $container ): void {
6357
add_filter( 'allowed_block_types_all', [ $this, 'gutenberg_blocks_allowed' ], 10, 2 );
6458
}
6559

66-
/**
67-
* Register :
68-
* - theme_supports
69-
* - color palettes
70-
* - font sizes
71-
* - etc.
72-
*
73-
*/
74-
private function after_theme_setup(): void {
75-
76-
//color palettes
77-
add_theme_support(
78-
'editor-color-palette',
79-
[
80-
[
81-
'name' => __( 'Dark', 'beapi-frontend-framework' ),
82-
'slug' => 'dark',
83-
'color' => '#000000',
84-
],
85-
[
86-
'name' => __( 'Light', 'beapi-frontend-framework' ),
87-
'slug' => 'light',
88-
'color' => '#ffffff',
89-
],
90-
[
91-
'name' => __( 'Primary', 'beapi-frontend-framework' ),
92-
'slug' => 'primary',
93-
'color' => '#ffff00',
94-
],
95-
[
96-
'name' => __( 'Secondary', 'beapi-frontend-framework' ),
97-
'slug' => 'secondary',
98-
'color' => '#00ffff',
99-
],
100-
]
101-
);
102-
// font sizes
103-
add_theme_support(
104-
'editor-font-sizes',
105-
[
106-
[
107-
'name' => __( 'Title 6', 'beapi-frontend-framework' ),
108-
'shortName' => 'h6',
109-
'size' => 14,
110-
'slug' => 'h6',
111-
],
112-
[
113-
'name' => __( 'Title 5', 'beapi-frontend-framework' ),
114-
'shortName' => 'h5',
115-
'size' => 16,
116-
'slug' => 'h5',
117-
],
118-
[
119-
'name' => __( 'Title 4', 'beapi-frontend-framework' ),
120-
'shortName' => 'h4',
121-
'size' => 18,
122-
'slug' => 'h4',
123-
],
124-
[
125-
'name' => __( 'Title 3', 'beapi-frontend-framework' ),
126-
'shortName' => 'h3',
127-
'size' => 24,
128-
'slug' => 'h3',
129-
],
130-
[
131-
'name' => __( 'Title 2', 'beapi-frontend-framework' ),
132-
'shortName' => 'h2',
133-
'size' => 40,
134-
'slug' => 'h2',
135-
],
136-
[
137-
'name' => __( 'Title 1', 'beapi-frontend-framework' ),
138-
'shortName' => 'h1',
139-
'size' => 58,
140-
'slug' => 'h1',
141-
],
142-
]
143-
);
144-
}
145-
14660
/**
14761
* editor style
14862
*/
@@ -159,27 +73,6 @@ private function style(): void {
15973
add_editor_style( 'dist/' . $file );
16074
}
16175

162-
/**
163-
* Theme.json settings
164-
* See https://developer.wordpress.org/block-editor/reference-guides/theme-json-reference/theme-json-living/
165-
*
166-
* @param \WP_Theme_JSON_Data $theme_json Class to access and update the underlying data.
167-
*
168-
* @return \WP_Theme_JSON_Data
169-
*/
170-
public function filter_theme_json_theme( \WP_Theme_JSON_Data $theme_json ): \WP_Theme_JSON_Data {
171-
$custom_theme_json = [
172-
'version' => 2,
173-
'settings' => [
174-
'typography' => [
175-
'dropCap' => false,
176-
],
177-
],
178-
];
179-
180-
return $theme_json->update_with( $custom_theme_json );
181-
}
182-
18376
/**
18477
* Editor script
18578
*/
@@ -267,6 +160,26 @@ private function register_custom_block_styles() {
267160
'label' => __( 'Huge', 'beapi-frontend-framework' ),
268161
]
269162
);
163+
164+
for ( $i = 1; $i <= 6; $i++ ) {
165+
$style = [
166+
'name' => 'h' . $i,
167+
/* translators: %s: heading number */
168+
'label' => sprintf( __( 'Style H%s', 'beapi-frontend-framework' ), $i ),
169+
];
170+
171+
// heading
172+
register_block_style(
173+
'core/heading',
174+
$style
175+
);
176+
177+
// paragraph
178+
register_block_style(
179+
'core/paragraph',
180+
$style
181+
);
182+
}
270183
}
271184

272185
/**

page.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<header class="container">
99
<h1><?php the_title(); ?></h1>
1010
</header>
11-
<div class="blocks-container">
11+
<div class="blocks-container is-layout-constrained has-global-padding">
1212
<?php the_content(); ?>
1313
</div>
1414
<?php

single.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<header class="container">
99
<h1><?php the_title(); ?></h1>
1010
</header>
11-
<div class="blocks-container">
11+
<div class="blocks-container is-layout-constrained has-global-padding">
1212
<?php the_content(); ?>
1313
</div>
1414
<?php

0 commit comments

Comments
 (0)