Skip to content

Commit 50a75fa

Browse files
committed
Add scripts for generating a changelog and list of issues.
1 parent ba6285c commit 50a75fa

File tree

5 files changed

+288
-30
lines changed

5 files changed

+288
-30
lines changed

composer.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,14 @@
1818
}
1919
},
2020
"scripts": {
21-
"generate": "wp-hooks-generator --input=vendor/wordpress/wordpress --output=hooks"
21+
"generate": [
22+
"wp-hooks-generator --input=vendor/wordpress/wordpress --output=hooks",
23+
"./scripts/generate-changelog.sh",
24+
"./scripts/generate-issues.sh"
25+
]
2226
},
2327
"scripts-descriptions": {
24-
"generate": "Generates the hook files for WordPress core"
28+
"generate": "Generates the hook files, changelog, and issues report for WordPress core"
2529
},
2630
"require-dev": {
2731
"erusev/parsedown": "1.8.0-beta-7",

package.json

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,7 @@
2525
"npm-run-all": "^4.1.5"
2626
},
2727
"scripts": {
28-
"check": "npm-run-all validate:** check:**",
29-
"show": "npm-run-all show:**",
30-
"check:duplicate-actions": "jq --exit-status '[reduce .hooks[].name as $n ({}; .[$n] += 1) | to_entries[] | select(.value > 1)] == []' hooks/actions.json",
31-
"check:duplicate-filters": "jq --exit-status '[reduce .hooks[].name as $n ({}; .[$n] += 1) | to_entries[] | select(.value > 1)] == []' hooks/filters.json",
32-
"show:empty-variables-in-actions": "jq '.hooks[] | select(.doc.tags[] .variable == \"\")' hooks/actions.json",
33-
"show:empty-variables-in-filters": "jq '.hooks[] | select(.doc.tags[] .variable == \"\")' hooks/filters.json",
34-
"show:duplicate-actions": "jq '[reduce .hooks[].name as $n ({}; .[$n] += 1) | to_entries[] | select(.value > 1)]' hooks/actions.json",
35-
"show:duplicate-filters": "jq '[reduce .hooks[].name as $n ({}; .[$n] += 1) | to_entries[] | select(.value > 1)]' hooks/filters.json",
28+
"check": "npm-run-all --continue-on-error validate:**",
3629
"validate:schema": "ajv validate -s node_modules/ajv/lib/refs/json-schema-draft-07.json -d hooks/schema.json",
3730
"validate:actions": "ajv validate -s hooks/schema.json -d hooks/actions.json",
3831
"validate:filters": "ajv validate -s hooks/schema.json -d hooks/filters.json"

readme.md

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -97,26 +97,7 @@ Then run:
9797
composer generate
9898
```
9999
100-
Some scripts are available for checking the data:
101-
102-
* Check everything:
103-
```shell
104-
npm run check
105-
```
106-
* Find hooks with missing `@since` tags:
107-
```shell
108-
jq '.hooks[] | . as $d | .doc .tags | map(.name) | select( contains(["since"]) | not ) | $d' hooks/filters.json
109-
```
110-
```shell
111-
jq '.hooks[] | . as $d | .doc .tags | map(.name) | select( contains(["since"]) | not ) | $d' hooks/actions.json
112-
```
113-
* Find hooks with incorrect number of `@param` tags (not completely accurate, not sure why):
114-
```shell
115-
jq '.hooks[] | select( .args == ( .doc.tags | map(.name) | select( contains(["param"]) ) | length ) ) | .name' hooks/filters.json
116-
```
117-
```shell
118-
jq '.hooks[] | select( .args == ( .doc.tags | map(.name) | select( contains(["param"]) ) | length ) ) | .name' hooks/actions.json
119-
```
100+
During generation, a change and data integrity issues are saved in CHANGELOG.md and ISSUES.md respectively.
120101
121102
## Hook Files for Plugins
122103

scripts/generate-changelog.sh

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
#!/bin/bash
2+
3+
# Generate a markdown changelog for WordPress hooks
4+
# Lists new actions, new filters, and parameter changes for specified versions
5+
6+
ACTIONS_FILE="hooks/actions.json"
7+
FILTERS_FILE="hooks/filters.json"
8+
OUTPUT_FILE="CHANGELOG.md"
9+
10+
# Extract all versions from both files and sort them in descending order
11+
VERSIONS=($(jq -r '
12+
[.hooks[].doc.tags[] | select(.name == "since") | .content]
13+
| unique
14+
| map(select(test("^[0-9]+\\.[0-9]+\\.?[0-9]*$")))
15+
| map(split(".")[0:2] | join("."))
16+
| unique
17+
| .[]
18+
' "$ACTIONS_FILE" "$FILTERS_FILE" | sort -u | while read v; do
19+
# Convert to sortable format and print
20+
major=$(echo "$v" | cut -d. -f1)
21+
minor=$(echo "$v" | cut -d. -f2)
22+
printf "%03d.%03d %s\n" "$major" "$minor" "$v"
23+
done | sort -rn | cut -d' ' -f2))
24+
25+
echo "# WordPress Hooks Changelog" > "$OUTPUT_FILE"
26+
echo "" >> "$OUTPUT_FILE"
27+
echo "This document lists new actions, new filters, and parameter changes by WordPress version." >> "$OUTPUT_FILE"
28+
echo "" >> "$OUTPUT_FILE"
29+
30+
for VERSION in "${VERSIONS[@]}"; do
31+
echo "Processing version $VERSION..."
32+
33+
echo "## WordPress $VERSION" >> "$OUTPUT_FILE"
34+
echo "" >> "$OUTPUT_FILE"
35+
36+
# Find new actions (first @since tag matches the version)
37+
echo "### New Actions" >> "$OUTPUT_FILE"
38+
echo "" >> "$OUTPUT_FILE"
39+
40+
NEW_ACTIONS=$(jq -r --arg ver "${VERSION}" '
41+
# Function to convert hook name to URL slug
42+
def slug: gsub("\\{\\$"; "") | gsub("\\}"; "") | gsub("\\$"; "") | gsub("->"; "-") | gsub("<"; "") | gsub(">"; "");
43+
.hooks[]
44+
| select(
45+
.doc.tags
46+
| map(select(.name == "since"))
47+
| .[0].content
48+
| startswith($ver)
49+
)
50+
| . as $hook
51+
| ($hook.doc.tags | map(select(.name == "since")) | .[0].content) as $since
52+
| ($hook.name | slug) as $url_slug
53+
| if ($since | test("^[0-9]+\\.[0-9]+\\.[1-9]")) then
54+
"- [`\($hook.name)`](https://developer.wordpress.org/reference/hooks/\($url_slug)/) (\($since)) - \($hook.doc.description)"
55+
else
56+
"- [`\($hook.name)`](https://developer.wordpress.org/reference/hooks/\($url_slug)/) - \($hook.doc.description)"
57+
end
58+
' "$ACTIONS_FILE")
59+
60+
if [ -n "$NEW_ACTIONS" ]; then
61+
echo "$NEW_ACTIONS" >> "$OUTPUT_FILE"
62+
else
63+
echo "_No new actions in this version._" >> "$OUTPUT_FILE"
64+
fi
65+
66+
echo "" >> "$OUTPUT_FILE"
67+
68+
# Find new filters (first @since tag matches the version)
69+
echo "### New Filters" >> "$OUTPUT_FILE"
70+
echo "" >> "$OUTPUT_FILE"
71+
72+
NEW_FILTERS=$(jq -r --arg ver "${VERSION}" '
73+
# Function to convert hook name to URL slug
74+
def slug: gsub("\\{\\$"; "") | gsub("\\}"; "") | gsub("\\$"; "") | gsub("->"; "-") | gsub("<"; "") | gsub(">"; "");
75+
.hooks[]
76+
| select(
77+
.doc.tags
78+
| map(select(.name == "since"))
79+
| .[0].content
80+
| startswith($ver)
81+
)
82+
| . as $hook
83+
| ($hook.doc.tags | map(select(.name == "since")) | .[0].content) as $since
84+
| ($hook.name | slug) as $url_slug
85+
| if ($since | test("^[0-9]+\\.[0-9]+\\.[1-9]")) then
86+
"- [`\($hook.name)`](https://developer.wordpress.org/reference/hooks/\($url_slug)/) (\($since)) - \($hook.doc.description)"
87+
else
88+
"- [`\($hook.name)`](https://developer.wordpress.org/reference/hooks/\($url_slug)/) - \($hook.doc.description)"
89+
end
90+
' "$FILTERS_FILE")
91+
92+
if [ -n "$NEW_FILTERS" ]; then
93+
echo "$NEW_FILTERS" >> "$OUTPUT_FILE"
94+
else
95+
echo "_No new filters in this version._" >> "$OUTPUT_FILE"
96+
fi
97+
98+
echo "" >> "$OUTPUT_FILE"
99+
100+
# Find changes from both actions and filters
101+
echo "### Changes" >> "$OUTPUT_FILE"
102+
echo "" >> "$OUTPUT_FILE"
103+
104+
ACTION_PARAM_CHANGES=$(jq -r --arg ver "${VERSION}" '
105+
# Function to convert hook name to URL slug
106+
def slug: gsub("\\{\\$"; "") | gsub("\\}"; "") | gsub("\\$"; "") | gsub("->"; "-") | gsub("<"; "") | gsub(">"; "");
107+
# Function to wrap $param style strings in <code> tags if not already wrapped
108+
def format_params: gsub("(?<p>\\$[a-z_]+)"; "<code>\(.p)</code>") | gsub("<code><code>"; "<code>") | gsub("</code></code>"; "</code>");
109+
.hooks[]
110+
| select(
111+
.doc.tags
112+
| any(.name == "since" and .description != null and (.content | startswith($ver)))
113+
)
114+
| . as $hook
115+
| ($hook.name | slug) as $url_slug
116+
| .doc.tags
117+
| map(select(.name == "since" and .description != null and (.content | startswith($ver))))
118+
| map(
119+
(.description | format_params) as $desc
120+
| if (.content | test("^[0-9]+\\.[0-9]+\\.[1-9]")) then
121+
"- [`\($hook.name)`](https://developer.wordpress.org/reference/hooks/\($url_slug)/) (\(.content)) - \($desc)"
122+
else
123+
"- [`\($hook.name)`](https://developer.wordpress.org/reference/hooks/\($url_slug)/) - \($desc)"
124+
end
125+
)
126+
| .[]
127+
' "$ACTIONS_FILE")
128+
129+
FILTER_PARAM_CHANGES=$(jq -r --arg ver "${VERSION}" '
130+
# Function to convert hook name to URL slug
131+
def slug: gsub("\\{\\$"; "") | gsub("\\}"; "") | gsub("\\$"; "") | gsub("->"; "-") | gsub("<"; "") | gsub(">"; "");
132+
# Function to wrap $param style strings in <code> tags if not already wrapped
133+
def format_params: gsub("(?<p>\\$[a-z_]+)"; "<code>\(.p)</code>") | gsub("<code><code>"; "<code>") | gsub("</code></code>"; "</code>");
134+
.hooks[]
135+
| select(
136+
.doc.tags
137+
| any(.name == "since" and .description != null and (.content | startswith($ver)))
138+
)
139+
| . as $hook
140+
| ($hook.name | slug) as $url_slug
141+
| .doc.tags
142+
| map(select(.name == "since" and .description != null and (.content | startswith($ver))))
143+
| map(
144+
(.description | format_params) as $desc
145+
| if (.content | test("^[0-9]+\\.[0-9]+\\.[1-9]")) then
146+
"- [`\($hook.name)`](https://developer.wordpress.org/reference/hooks/\($url_slug)/) (\(.content)) - \($desc)"
147+
else
148+
"- [`\($hook.name)`](https://developer.wordpress.org/reference/hooks/\($url_slug)/) - \($desc)"
149+
end
150+
)
151+
| .[]
152+
' "$FILTERS_FILE")
153+
154+
PARAM_CHANGES=$(echo -e "${ACTION_PARAM_CHANGES}\n${FILTER_PARAM_CHANGES}" | grep -v '^$' | sort)
155+
156+
if [ -n "$PARAM_CHANGES" ]; then
157+
echo "$PARAM_CHANGES" >> "$OUTPUT_FILE"
158+
else
159+
echo "_No changes in this version._" >> "$OUTPUT_FILE"
160+
fi
161+
162+
echo "" >> "$OUTPUT_FILE"
163+
done
164+
165+
echo "Generated $OUTPUT_FILE"

scripts/generate-issues.sh

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
#!/bin/bash
2+
3+
# Generate a markdown document listing all hook data issues
4+
# Uses the npm show:* scripts to gather data
5+
6+
OUTPUT_FILE="ISSUES.md"
7+
8+
echo "# WordPress Hooks Data Issues" > "$OUTPUT_FILE"
9+
echo "" >> "$OUTPUT_FILE"
10+
echo "This document lists known data quality issues in the hooks JSON files." >> "$OUTPUT_FILE"
11+
echo "" >> "$OUTPUT_FILE"
12+
13+
# Duplicate Actions
14+
echo "## Duplicate Actions" >> "$OUTPUT_FILE"
15+
echo "" >> "$OUTPUT_FILE"
16+
17+
DUPLICATE_ACTIONS=$(jq -r '[reduce .hooks[].name as $n ({}; .[$n] += 1) | to_entries[] | select(.value > 1) | .key] | .[]' hooks/actions.json)
18+
19+
if [ -n "$DUPLICATE_ACTIONS" ]; then
20+
echo "$DUPLICATE_ACTIONS" | while read -r name; do
21+
echo "- \`$name\`" >> "$OUTPUT_FILE"
22+
done
23+
else
24+
echo "_No duplicate actions._" >> "$OUTPUT_FILE"
25+
fi
26+
27+
echo "" >> "$OUTPUT_FILE"
28+
29+
# Duplicate Filters
30+
echo "## Duplicate Filters" >> "$OUTPUT_FILE"
31+
echo "" >> "$OUTPUT_FILE"
32+
33+
DUPLICATE_FILTERS=$(jq -r '[reduce .hooks[].name as $n ({}; .[$n] += 1) | to_entries[] | select(.value > 1) | .key] | .[]' hooks/filters.json)
34+
35+
if [ -n "$DUPLICATE_FILTERS" ]; then
36+
echo "$DUPLICATE_FILTERS" | while read -r name; do
37+
echo "- \`$name\`" >> "$OUTPUT_FILE"
38+
done
39+
else
40+
echo "_No duplicate filters._" >> "$OUTPUT_FILE"
41+
fi
42+
43+
echo "" >> "$OUTPUT_FILE"
44+
45+
# Missing @since Tags
46+
echo "## Missing @since Tags" >> "$OUTPUT_FILE"
47+
echo "" >> "$OUTPUT_FILE"
48+
49+
MISSING_SINCE_ACTIONS=$(jq -r '.hooks[] | select(.doc.tags | map(.name) | contains(["since"]) | not) | "- `\(.name)` (\(.file))"' hooks/actions.json)
50+
MISSING_SINCE_FILTERS=$(jq -r '.hooks[] | select(.doc.tags | map(.name) | contains(["since"]) | not) | "- `\(.name)` (\(.file))"' hooks/filters.json)
51+
52+
MISSING_SINCE=$(echo -e "${MISSING_SINCE_ACTIONS}\n${MISSING_SINCE_FILTERS}" | grep -v '^$' | sort)
53+
54+
if [ -n "$MISSING_SINCE" ]; then
55+
echo "$MISSING_SINCE" >> "$OUTPUT_FILE"
56+
else
57+
echo "_No hooks with missing @since tags._" >> "$OUTPUT_FILE"
58+
fi
59+
60+
echo "" >> "$OUTPUT_FILE"
61+
62+
# Empty Descriptions
63+
echo "## Empty Descriptions" >> "$OUTPUT_FILE"
64+
echo "" >> "$OUTPUT_FILE"
65+
66+
EMPTY_DESC_ACTIONS=$(jq -r '.hooks[] | select(.doc.description == "" or .doc.description == null) | "- `\(.name)` (\(.file))"' hooks/actions.json)
67+
EMPTY_DESC_FILTERS=$(jq -r '.hooks[] | select(.doc.description == "" or .doc.description == null) | "- `\(.name)` (\(.file))"' hooks/filters.json)
68+
69+
EMPTY_DESC=$(echo -e "${EMPTY_DESC_ACTIONS}\n${EMPTY_DESC_FILTERS}" | grep -v '^$' | sort)
70+
71+
if [ -n "$EMPTY_DESC" ]; then
72+
echo "$EMPTY_DESC" >> "$OUTPUT_FILE"
73+
else
74+
echo "_No hooks with empty descriptions._" >> "$OUTPUT_FILE"
75+
fi
76+
77+
echo "" >> "$OUTPUT_FILE"
78+
79+
# Empty Variables
80+
echo "## Empty Variables" >> "$OUTPUT_FILE"
81+
echo "" >> "$OUTPUT_FILE"
82+
echo "Hooks with \`@param\` tags that have an empty variable name." >> "$OUTPUT_FILE"
83+
echo "" >> "$OUTPUT_FILE"
84+
85+
EMPTY_VARS_ACTIONS=$(jq -r '.hooks[] | select(.doc.tags[] | select(.name == "param" and .variable == "")) | "- `\(.name)` (\(.file))"' hooks/actions.json 2>/dev/null | sort -u)
86+
EMPTY_VARS_FILTERS=$(jq -r '.hooks[] | select(.doc.tags[] | select(.name == "param" and .variable == "")) | "- `\(.name)` (\(.file))"' hooks/filters.json 2>/dev/null | sort -u)
87+
88+
EMPTY_VARS=$(echo -e "${EMPTY_VARS_ACTIONS}\n${EMPTY_VARS_FILTERS}" | grep -v '^$' | sort -u)
89+
90+
if [ -n "$EMPTY_VARS" ]; then
91+
echo "$EMPTY_VARS" >> "$OUTPUT_FILE"
92+
else
93+
echo "_No hooks with empty variables._" >> "$OUTPUT_FILE"
94+
fi
95+
96+
echo "" >> "$OUTPUT_FILE"
97+
98+
# Param Count Mismatches
99+
echo "## Param Count Mismatches" >> "$OUTPUT_FILE"
100+
echo "" >> "$OUTPUT_FILE"
101+
echo "Hooks where the number of \`@param\` tags does not match the \`args\` count." >> "$OUTPUT_FILE"
102+
echo "" >> "$OUTPUT_FILE"
103+
104+
PARAM_MISMATCH_ACTIONS=$(jq -r '.hooks[] | select(.args != ([.doc.tags[] | select(.name == "param")] | length)) | "- `\(.name)` — args: \(.args), params: \([.doc.tags[] | select(.name == "param")] | length) (\(.file))"' hooks/actions.json)
105+
PARAM_MISMATCH_FILTERS=$(jq -r '.hooks[] | select(.args != ([.doc.tags[] | select(.name == "param")] | length)) | "- `\(.name)` — args: \(.args), params: \([.doc.tags[] | select(.name == "param")] | length) (\(.file))"' hooks/filters.json)
106+
107+
PARAM_MISMATCH=$(echo -e "${PARAM_MISMATCH_ACTIONS}\n${PARAM_MISMATCH_FILTERS}" | grep -v '^$' | sort)
108+
109+
if [ -n "$PARAM_MISMATCH" ]; then
110+
echo "$PARAM_MISMATCH" >> "$OUTPUT_FILE"
111+
else
112+
echo "_No hooks with param count mismatches._" >> "$OUTPUT_FILE"
113+
fi
114+
115+
echo "Generated $OUTPUT_FILE"

0 commit comments

Comments
 (0)