Skip to content

Commit 538d320

Browse files
zackkatzclaude
andcommitted
feat: Auto-link parameter types to external documentation
- Add type-links.json configuration file mapping PHP types to doc URLs - Add linkParameterTypes() function to generate-hooks.mjs - Types like GF_Field_Address, WP_Post, etc. now link to their docs - Supports both `TypeName` and `\TypeName` formats in parameter tables Example: `\GF_Field_Address` becomes a link to https://docs.gravityforms.com/gf_field_address/ 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent c1ba2ab commit 538d320

File tree

2 files changed

+127
-0
lines changed

2 files changed

+127
-0
lines changed

scripts/generate-hooks.mjs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,75 @@ function addTagsToHooks(outputDir) {
254254
}
255255
}
256256

257+
/**
258+
* Load type links configuration
259+
*/
260+
function loadTypeLinks() {
261+
const typeLinksPath = path.join(PROJECT_ROOT, 'type-links.json');
262+
if (!fs.existsSync(typeLinksPath)) {
263+
return {};
264+
}
265+
try {
266+
const config = JSON.parse(fs.readFileSync(typeLinksPath, 'utf8'));
267+
return config.types || {};
268+
} catch (err) {
269+
console.warn('Warning: Could not parse type-links.json:', err.message);
270+
return {};
271+
}
272+
}
273+
274+
/**
275+
* Link parameter types in hook markdown files to their documentation
276+
* Converts `GF_Field_Address` or `\GF_Field_Address` to linked versions
277+
*/
278+
function linkParameterTypes(outputDir) {
279+
const typeLinks = loadTypeLinks();
280+
if (Object.keys(typeLinks).length === 0) return;
281+
282+
const dirs = ['actions', 'filters'];
283+
284+
for (const subdir of dirs) {
285+
const dirPath = path.join(outputDir, subdir);
286+
if (!fs.existsSync(dirPath)) continue;
287+
288+
const files = fs.readdirSync(dirPath).filter(f => f.endsWith('.md') && f !== 'index.md');
289+
290+
for (const file of files) {
291+
const filePath = path.join(dirPath, file);
292+
let content = fs.readFileSync(filePath, 'utf8');
293+
let modified = false;
294+
295+
// Process each type in the configuration
296+
for (const [typeName, url] of Object.entries(typeLinks)) {
297+
// Match `TypeName` or `\TypeName` in parameter tables
298+
// The backticks indicate it's a type in the markdown table
299+
const patterns = [
300+
new RegExp('`\\\\?' + escapeRegExp(typeName) + '`', 'g'),
301+
];
302+
303+
for (const pattern of patterns) {
304+
if (pattern.test(content)) {
305+
// Replace with linked version, preserving the backticks around the link
306+
content = content.replace(pattern, `[\`${typeName}\`](${url})`);
307+
modified = true;
308+
}
309+
}
310+
}
311+
312+
if (modified) {
313+
fs.writeFileSync(filePath, content);
314+
}
315+
}
316+
}
317+
}
318+
319+
/**
320+
* Escape special regex characters in a string
321+
*/
322+
function escapeRegExp(string) {
323+
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
324+
}
325+
257326
/**
258327
* Run wp-hooks-documentor for a product
259328
*/
@@ -396,6 +465,9 @@ function generateHooksDocs(product, config, options) {
396465
// Add tags to hook files based on @since versions
397466
addTagsToHooks(finalOutputDir);
398467

468+
// Link parameter types to their documentation
469+
linkParameterTypes(finalOutputDir);
470+
399471
// Generate index.md for the product and subdirectories
400472
generateProductIndex(product, finalOutputDir);
401473
generateActionsIndex(product, finalOutputDir);

type-links.json

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema#",
3+
"$comment": "Maps PHP class/type names to their documentation URLs. Types can include leading backslash or not - both will be matched.",
4+
"types": {
5+
"GF_Field": "https://docs.gravityforms.com/gf_field/",
6+
"GF_Field_Address": "https://docs.gravityforms.com/gf_field_address/",
7+
"GF_Field_Calculation": "https://docs.gravityforms.com/gf_field_calculation/",
8+
"GF_Field_Captcha": "https://docs.gravityforms.com/gf_field_captcha/",
9+
"GF_Field_Checkbox": "https://docs.gravityforms.com/gf_field_checkbox/",
10+
"GF_Field_Consent": "https://docs.gravityforms.com/gf_field_consent/",
11+
"GF_Field_Date": "https://docs.gravityforms.com/gf_field_date/",
12+
"GF_Field_Email": "https://docs.gravityforms.com/gf_field_email/",
13+
"GF_Field_FileUpload": "https://docs.gravityforms.com/gf_field_fileupload/",
14+
"GF_Field_Hidden": "https://docs.gravityforms.com/gf_field_hidden/",
15+
"GF_Field_HTML": "https://docs.gravityforms.com/gf_field_html/",
16+
"GF_Field_List": "https://docs.gravityforms.com/gf_field_list/",
17+
"GF_Field_MultiSelect": "https://docs.gravityforms.com/gf_field_multiselect/",
18+
"GF_Field_Name": "https://docs.gravityforms.com/gf_field_name/",
19+
"GF_Field_Number": "https://docs.gravityforms.com/gf_field_number/",
20+
"GF_Field_Page": "https://docs.gravityforms.com/gf_field_page/",
21+
"GF_Field_Password": "https://docs.gravityforms.com/gf_field_password/",
22+
"GF_Field_Phone": "https://docs.gravityforms.com/gf_field_phone/",
23+
"GF_Field_Post_Category": "https://docs.gravityforms.com/gf_field_post_category/",
24+
"GF_Field_Post_Content": "https://docs.gravityforms.com/gf_field_post_content/",
25+
"GF_Field_Post_Custom_Field": "https://docs.gravityforms.com/gf_field_post_custom_field/",
26+
"GF_Field_Post_Excerpt": "https://docs.gravityforms.com/gf_field_post_excerpt/",
27+
"GF_Field_Post_Image": "https://docs.gravityforms.com/gf_field_post_image/",
28+
"GF_Field_Post_Tags": "https://docs.gravityforms.com/gf_field_post_tags/",
29+
"GF_Field_Post_Title": "https://docs.gravityforms.com/gf_field_post_title/",
30+
"GF_Field_Product": "https://docs.gravityforms.com/gf_field_product/",
31+
"GF_Field_Quantity": "https://docs.gravityforms.com/gf_field_quantity/",
32+
"GF_Field_Radio": "https://docs.gravityforms.com/gf_field_radio/",
33+
"GF_Field_Section": "https://docs.gravityforms.com/gf_field_section/",
34+
"GF_Field_Select": "https://docs.gravityforms.com/gf_field_select/",
35+
"GF_Field_Shipping": "https://docs.gravityforms.com/gf_field_shipping/",
36+
"GF_Field_Signature": "https://docs.gravityforms.com/gf_field_signature/",
37+
"GF_Field_Text": "https://docs.gravityforms.com/gf_field_text/",
38+
"GF_Field_Textarea": "https://docs.gravityforms.com/gf_field_textarea/",
39+
"GF_Field_Time": "https://docs.gravityforms.com/gf_field_time/",
40+
"GF_Field_Total": "https://docs.gravityforms.com/gf_field_total/",
41+
"GF_Field_Website": "https://docs.gravityforms.com/gf_field_website/",
42+
"GF_Entry": "https://docs.gravityforms.com/entry-object/",
43+
"GF_Form": "https://docs.gravityforms.com/form-object/",
44+
"GFAPI": "https://docs.gravityforms.com/api-functions/",
45+
"GFFormsModel": "https://docs.gravityforms.com/gfformsmodel/",
46+
"GFCommon": "https://docs.gravityforms.com/gfcommon/",
47+
"WP_Post": "https://developer.wordpress.org/reference/classes/wp_post/",
48+
"WP_User": "https://developer.wordpress.org/reference/classes/wp_user/",
49+
"WP_Query": "https://developer.wordpress.org/reference/classes/wp_query/",
50+
"WP_Error": "https://developer.wordpress.org/reference/classes/wp_error/",
51+
"WP_REST_Request": "https://developer.wordpress.org/reference/classes/wp_rest_request/",
52+
"WP_REST_Response": "https://developer.wordpress.org/reference/classes/wp_rest_response/",
53+
"wpdb": "https://developer.wordpress.org/reference/classes/wpdb/"
54+
}
55+
}

0 commit comments

Comments
 (0)