Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 5 additions & 5 deletions .claude/skills/release/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ argument-hint: [patch|minor|major]

# Release Process

Create a new release of the pp-glossary plugin. The argument `$ARGUMENTS` specifies the version bump type: `patch`, `minor`, or `major`. If no argument is given, ask the user which type of bump they want.
Create a new release of the inline-glossary plugin. The argument `$ARGUMENTS` specifies the version bump type: `patch`, `minor`, or `major`. If no argument is given, ask the user which type of bump they want.

## Step 0: Preflight checks

- Ensure we are on the `develop` branch. If not, switch to it.
- Run `git pull origin develop` to ensure we're up to date.
- Run `git status` to ensure the working tree is clean. If not, stop and ask the user to commit or stash changes.
- Determine the current version from `pp-glossary.php` (the `Version:` header).
- Determine the current version from `inline-glossary.php` (the `Version:` header).
- Calculate the new version based on the bump type (`$ARGUMENTS`):
- `patch`: increment the patch number (e.g., 1.3.0 -> 1.3.1)
- `minor`: increment the minor number, reset patch (e.g., 1.3.1 -> 1.4.0)
Expand All @@ -33,8 +33,8 @@ Create a new release of the pp-glossary plugin. The argument `$ARGUMENTS` specif

Update the version in these locations (all in one commit):

1. `pp-glossary.php` line with `* Version: X.Y.Z` - update to new version
2. `pp-glossary.php` line with `define( 'PP_GLOSSARY_VERSION', 'X.Y.Z' )` - update to new version
1. `inline-glossary.php` line with `* Version: X.Y.Z` - update to new version
2. `inline-glossary.php` line with `define( 'INLINE_GLOSSARY_VERSION', 'X.Y.Z' )` - update to new version
3. `readme.txt` line with `Stable tag: X.Y.Z` - update to new version

## Step 3: Update changelogs
Expand All @@ -58,7 +58,7 @@ If any fail, fix the issues before proceeding. All three must pass.

## Step 5: Commit and push

- Stage all changed files: `pp-glossary.php`, `readme.txt`, `README.md`
- Stage all changed files: `inline-glossary.php`, `readme.txt`, `README.md`
- Commit with message: `Bump version to X.Y.Z and update changelogs for release`
- Push to `origin develop`

Expand Down
4 changes: 2 additions & 2 deletions .wordpress-org/blueprints/blueprint.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"networking": true
},
"plugins": [
"pp-glossary"
"inline-glossary"
],
"steps": [
{
Expand All @@ -19,7 +19,7 @@
},
{
"step": "runPHP",
"code": "<?php require_once '/wordpress/wp-load.php'; update_option( 'pp_glossary_settings', array( 'glossary_page' => 10 ) ); ?>"
"code": "<?php require_once '/wordpress/wp-load.php'; update_option( 'inline_glossary_settings', array( 'glossary_page' => 10 ) ); ?>"
}
]
}
18 changes: 9 additions & 9 deletions .wordpress-org/blueprints/blueprint.xml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@
<dc:creator><![CDATA[admin]]></dc:creator>
<guid isPermaLink="false">https://example.com//?page_id=10</guid>
<description></description>
<content:encoded><![CDATA[<!-- wp:pp-glossary/glossary-list /-->]]></content:encoded>
<content:encoded><![CDATA[<!-- wp:inline-glossary/glossary-list /-->]]></content:encoded>
<excerpt:encoded><![CDATA[]]></excerpt:encoded>
<wp:post_id>10</wp:post_id>
<wp:post_date><![CDATA[2025-11-11 13:20:34]]></wp:post_date>
Expand Down Expand Up @@ -120,10 +120,10 @@
</item>
<item>
<title><![CDATA[Link]]></title>
<link>https://example.com/?pp_glossary=link</link>
<link>https://example.com/?inline_glossary=link</link>
<pubDate>Fri, 12 Dec 2025 13:54:50 +0000</pubDate>
<dc:creator><![CDATA[admin]]></dc:creator>
<guid isPermaLink="false">https://example.com/?post_type=pp_glossary&#038;p=17</guid>
<guid isPermaLink="false">https://example.com/?post_type=inline_glossary&#038;p=17</guid>
<description></description>
<content:encoded><![CDATA[]]></content:encoded>
<excerpt:encoded><![CDATA[]]></excerpt:encoded>
Expand All @@ -138,24 +138,24 @@
<wp:status><![CDATA[publish]]></wp:status>
<wp:post_parent>0</wp:post_parent>
<wp:menu_order>0</wp:menu_order>
<wp:post_type><![CDATA[pp_glossary]]></wp:post_type>
<wp:post_type><![CDATA[inline_glossary]]></wp:post_type>
<wp:post_password><![CDATA[]]></wp:post_password>
<wp:is_sticky>0</wp:is_sticky>
<wp:postmeta>
<wp:meta_key><![CDATA[_edit_last]]></wp:meta_key>
<wp:meta_value><![CDATA[1]]></wp:meta_value>
</wp:postmeta>
<wp:postmeta>
<wp:meta_key><![CDATA[_pp_glossary_data]]></wp:meta_key>
<wp:meta_key><![CDATA[_inline_glossary_data]]></wp:meta_key>
<wp:meta_value><![CDATA[a:5:{s:14:"case_sensitive";b:0;s:16:"disable_autolink";b:1;s:17:"short_description";s:60:"This is a glossary item for a link, that is not auto-linked.";s:16:"long_description";s:0:"";s:8:"synonyms";a:0:{}}]]></wp:meta_value>
</wp:postmeta>
</item>
<item>
<title><![CDATA[FAIR]]></title>
<link>https://example.com/?pp_glossary=fair</link>
<link>https://example.com/?inline_glossary=fair</link>
<pubDate>Tue, 11 Nov 2025 13:20:06 +0000</pubDate>
<dc:creator><![CDATA[admin]]></dc:creator>
<guid isPermaLink="false">https://example.com/?post_type=pp_glossary&#038;p=5</guid>
<guid isPermaLink="false">https://example.com/?post_type=inline_glossary&#038;p=5</guid>
<description></description>
<content:encoded><![CDATA[]]></content:encoded>
<excerpt:encoded><![CDATA[]]></excerpt:encoded>
Expand All @@ -170,11 +170,11 @@
<wp:status><![CDATA[publish]]></wp:status>
<wp:post_parent>0</wp:post_parent>
<wp:menu_order>0</wp:menu_order>
<wp:post_type><![CDATA[pp_glossary]]></wp:post_type>
<wp:post_type><![CDATA[inline_glossary]]></wp:post_type>
<wp:post_password><![CDATA[]]></wp:post_password>
<wp:is_sticky>0</wp:is_sticky>
<wp:postmeta>
<wp:meta_key><![CDATA[_pp_glossary_data]]></wp:meta_key>
<wp:meta_key><![CDATA[_inline_glossary_data]]></wp:meta_key>
<wp:meta_value><![CDATA[a:5:{s:14:"case_sensitive";b:1;s:16:"disable_autolink";b:0;s:17:"short_description";s:36:"Federated and Indepent Repositories.";s:16:"long_description";s:261:"FAIR stands for Federated And Independent Repositories. It is a groundbreaking new way of distributing (WordPress) software like plugins and themes from a decentralized group of repositories. You can read all about it at <a href="https://fair.pm/">fair.pm</a>.";s:8:"synonyms";a:0:{}}]]></wp:meta_value>
</wp:postmeta>
</item>
Expand Down
54 changes: 27 additions & 27 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ Keep documentation in sync with code changes to ensure accuracy for future devel

## Project Overview

**Glossary by Progress Planner (pp-glossary)** is a WordPress plugin that automatically links glossary terms to accessible, semantic popovers that appear on click. Uses native WordPress custom fields for field management and includes a Gutenberg block for displaying the full glossary.
**Inline Glossary by Progress Planner (inline-glossary)** is a WordPress plugin that automatically links glossary terms to accessible, semantic popovers that appear on click. Uses native WordPress custom fields for field management and includes a Gutenberg block for displaying the full glossary.

### Core Functionality

- Registers a custom post type (`pp_glossary`) for glossary entries (title + custom fields only, no editor)
- Registers a custom post type (`inline_glossary`) for glossary entries (title + custom fields only, no editor)
- Uses native WordPress meta boxes for field management (short description, long description, synonyms)
- Automatically transforms first mentions of glossary terms in content into click-triggered popovers
- Provides a Gutenberg block to display the full glossary with alphabetical navigation
Expand All @@ -50,8 +50,8 @@ Keep documentation in sync with code changes to ensure accuracy for future devel
### File Structure

```
pp-glossary/
├── pp-glossary.php # Main plugin file, initialization, hooks
inline-glossary/
├── inline-glossary.php # Main plugin file, initialization, hooks
├── includes/
│ ├── functions.php # Helper functions
│ ├── class-post-type.php # Post_Type class - CPT registration
Expand All @@ -74,7 +74,7 @@ pp-glossary/
### Key Components

1. **Post Type Registration** (`includes/class-post-type.php`)
- Post type slug: `pp_glossary`
- Post type slug: `inline_glossary`
- Supports: `title` only (no editor, no revisions - all data is in post meta)
- `has_archive` set to `false` (uses block instead)
- `publicly_queryable` set to `false` (no individual entry pages)
Expand All @@ -83,7 +83,7 @@ pp-glossary/

2. **Meta Boxes** (`includes/class-meta-boxes.php`)
- Native WordPress meta boxes (no external dependencies)
- All fields stored in a single post meta key `_pp_glossary_data` (array)
- All fields stored in a single post meta key `_inline_glossary_data` (array)
- Fields (in display order):
- `short_description` (textarea, required)
- `long_description` (wp_editor)
Expand All @@ -103,7 +103,7 @@ pp-glossary/

4. **Settings Page** (`includes/class-settings.php`)
- Submenu under Glossary CPT menu
- Stores settings in `pp_glossary_settings` option
- Stores settings in `inline_glossary_settings` option
- Settings fields:
- `glossary_page` (int) - ID of the page containing the glossary block
- `excluded_tags` (array) - HTML tags where terms should not be highlighted (default: `a`, `h1`-`h6`)
Expand All @@ -127,7 +127,7 @@ pp-glossary/

## Data Storage

All custom field data is stored in a single WordPress post meta key `_pp_glossary_data` as an associative array:
All custom field data is stored in a single WordPress post meta key `_inline_glossary_data` as an associative array:

```php
[
Expand All @@ -149,7 +149,7 @@ The plugin generates highly semantic, accessible HTML with click triggers and CS

```html
<dfn id="dfn-{term}-{counter}"
class="pp-glossary-term"
class="inline-glossary-term"
style="anchor-name: --dfn-{term}-{counter};">
<button data-glossary-popover="pop-{term}-{counter}"
type="button"
Expand Down Expand Up @@ -263,7 +263,7 @@ When Yoast SEO is NOT active:

**HTML Output (Microdata):**
```html
<div class="pp-glossary-block" itemscope itemtype="https://schema.org/DefinedTermSet" itemid="...">
<div class="inline-glossary-block" itemscope itemtype="https://schema.org/DefinedTermSet" itemid="...">
<meta itemprop="name" content="Glossary Title">

<article itemscope itemtype="https://schema.org/DefinedTerm" itemprop="hasDefinedTerm">
Expand All @@ -284,25 +284,25 @@ When Yoast SEO is NOT active:
| Schema Property | WordPress Data | Location |
|----------------|----------------|----------|
| `name` | Entry title | `get_the_title()` |
| `description` | Short description or Long description | `_pp_glossary_short_description` or `_pp_glossary_long_description` meta |
| `description` | Short description or Long description | `_inline_glossary_short_description` or `_inline_glossary_long_description` meta |
| `url` | Anchor link | `{glossary_page_url}#{slug}` |
| `alternateName` | Array of synonyms | `_pp_glossary_synonyms` meta |
| `alternateName` | Array of synonyms | `_inline_glossary_synonyms` meta |

### Key Methods

**`PP_Glossary_Schema::add_to_yoast_schema_graph($graph, $context)`**
**`Inline_Glossary_Schema::add_to_yoast_schema_graph($graph, $context)`**
- Adds glossary to Yoast's schema graph
- Returns modified `$graph` array with DefinedTermSet added

**`PP_Glossary_Schema::get_microdata_attributes($entries, $page_id)`**
**`Inline_Glossary_Schema::get_microdata_attributes($entries, $page_id)`**
- Returns microdata attributes for glossary container
- Empty string if Yoast SEO is active

**`PP_Glossary_Schema::get_entry_microdata_attributes($entry)`**
**`Inline_Glossary_Schema::get_entry_microdata_attributes($entry)`**
- Returns microdata attributes for individual entry
- Empty string if Yoast SEO is active

**`PP_Glossary_Schema::get_itemprop($prop)`**
**`Inline_Glossary_Schema::get_itemprop($prop)`**
- Returns itemprop attribute for a property name
- Empty string if Yoast SEO is active

Expand Down Expand Up @@ -365,23 +365,23 @@ composer run phpcbf # Fix coding standards

### State Management

`PP_Glossary_Content_Filter` uses static properties during filtering:
`Inline_Glossary_Content_Filter` uses static properties during filtering:
- `$popover_counter` - ensures unique IDs
- `$popovers` - stores popover HTML for end-of-content appending
- These reset on each `filter_content()` call

### Settings Integration

- `PP_Glossary_Settings::get_glossary_page_url()` returns the URL of the page containing the glossary block
- `Inline_Glossary_Settings::get_glossary_page_url()` returns the URL of the page containing the glossary block
- "Read more" links use this URL + `#{slug}` anchor (slug-based, not ID-based)
- If no glossary page is set, "Read more" link is omitted
- `PP_Glossary_Settings::get_excluded_tags()` returns array of HTML tags to skip (default: `['a', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6']`)
- `PP_Glossary_Settings::get_excluded_post_types()` returns array of post types to skip (default: `[]`)
- `Inline_Glossary_Settings::get_excluded_tags()` returns array of HTML tags to skip (default: `['a', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6']`)
- `Inline_Glossary_Settings::get_excluded_post_types()` returns array of post types to skip (default: `[]`)

### Block Registration

- Block registered using `register_block_type()` with JSON file
- `render_callback` points to `PP_Glossary_Blocks::render_glossary_list_block()`
- `render_callback` points to `Inline_Glossary_Blocks::render_glossary_list_block()`
- Editor script uses vanilla JavaScript (no JSX, no build)
- Block shows: entry title (H4), synonyms, description (long description with fallback to short)
- Shows edit link for logged-in users with edit capabilities
Expand Down Expand Up @@ -435,11 +435,11 @@ JavaScript checks for both features and logs warnings if unavailable. Consider:

## Common Modification Points

1. **Change term matching behavior**: Edit `PP_Glossary_Content_Filter::replace_first_occurrence()`
2. **Modify popover HTML**: Edit `PP_Glossary_Content_Filter::create_popover()`
3. **Adjust which content types are processed**: Use Settings page or `pp_glossary_disabled_post_types` filter
4. **Adjust which HTML tags are excluded**: Use Settings page or `pp_glossary_excluded_tags` filter
5. **Customize block output**: Edit `PP_Glossary_Blocks::render_glossary_list_block()`
1. **Change term matching behavior**: Edit `Inline_Glossary_Content_Filter::replace_first_occurrence()`
2. **Modify popover HTML**: Edit `Inline_Glossary_Content_Filter::create_popover()`
3. **Adjust which content types are processed**: Use Settings page or `inline_glossary_disabled_post_types` filter
4. **Adjust which HTML tags are excluded**: Use Settings page or `inline_glossary_excluded_tags` filter
5. **Customize block output**: Edit `Inline_Glossary_Blocks::render_glossary_list_block()`
6. **Add more custom fields**: Modify `Meta_Boxes::render_meta_box()` and `save_meta_boxes()`
7. **Change popover positioning**: Modify CSS anchor positioning rules in `assets/css/glossary.css` (see `aside[popover]` and `@position-try` rules)

Expand All @@ -463,7 +463,7 @@ JavaScript checks for both features and logs warnings if unavailable. Consider:
- `plugins_loaded` - Initialize plugin components
- `init` (via post-type) - Register post type and block
- `add_meta_boxes` - Register custom meta boxes
- `save_post_pp_glossary` - Save custom field data
- `save_post_inline_glossary` - Save custom field data
- `admin_enqueue_scripts` - Load admin JavaScript for synonyms
- `the_content` (priority 20) - Filter content for term replacement
- `wp_enqueue_scripts` - Load CSS and JavaScript
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Glossary
# Inline Glossary by Progress Planner

[![Try Glossary on WordPress Playground](https://img.shields.io/badge/Try%20Glossary%20on%20WordPress%20Playground-%23117AC9.svg?style=for-the-badge&logo=WordPress&logoColor=fff)](https://playground.wordpress.net/?blueprint-url=https%3A%2F%2Fprogressplanner.com%2Fresearch%2Fblueprint-glossary.php)

Expand Down Expand Up @@ -134,7 +134,7 @@ The plugin uses CSS custom properties for easy theme-level styling.
You can also control where auto-linking runs with filters such as:

```php
add_filter( 'pp_glossary_disabled_post_types', function( $post_types ) {
add_filter( 'inline_glossary_disabled_post_types', function( $post_types ) {
return array( 'product', 'custom_post_type' );
} );
```
Expand Down
24 changes: 12 additions & 12 deletions assets/css/glossary.css
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
/**
* Glossary Styles
*
* @package PP_Glossary
* @package Inline_Glossary
*/

/* ==========================================================================
Screen Reader Only (visually hidden but accessible)
========================================================================== */

.pp-glossary-sr-only {
.inline-glossary-sr-only {
clip: rect(1px, 1px, 1px, 1px);
clip-path: inset(50%);
height: 1px;
Expand All @@ -28,7 +28,7 @@ dfn {
font-style: normal;
}

dfn.pp-glossary-term span {
dfn.inline-glossary-term span {
color: inherit;
text-decoration: underline;
text-decoration-style: dotted;
Expand All @@ -42,12 +42,12 @@ dfn.pp-glossary-term span {
border-bottom: none;
}

dfn.pp-glossary-term span:hover,
dfn.pp-glossary-term span:focus {
dfn.inline-glossary-term span:hover,
dfn.inline-glossary-term span:focus {
text-decoration-color: var(--glossary-underline-hover-color, rgba(0, 0, 0, 0.7));
}

dfn.pp-glossary-term span:focus-visible {
dfn.inline-glossary-term span:focus-visible {
outline: 2px solid var(--glossary-focus-color, #005a87);
outline-offset: 2px;
border-radius: 2px;
Expand All @@ -57,7 +57,7 @@ dfn.pp-glossary-term span:focus-visible {
Nested Glossary Links (within definitions)
========================================================================== */

.pp-glossary-link {
.inline-glossary-link {
color: inherit;
text-decoration: underline;
text-decoration-style: dotted;
Expand All @@ -66,12 +66,12 @@ dfn.pp-glossary-term span:focus-visible {
text-underline-offset: 3px;
}

.pp-glossary-link:hover,
.pp-glossary-link:focus {
.inline-glossary-link:hover,
.inline-glossary-link:focus {
text-decoration-color: var(--glossary-underline-hover-color, rgba(0, 0, 0, 0.7));
}

.pp-glossary-link:focus-visible {
.inline-glossary-link:focus-visible {
outline: 2px solid var(--glossary-focus-color, #005a87);
outline-offset: 2px;
border-radius: 2px;
Expand Down Expand Up @@ -146,7 +146,7 @@ aside[popover] > p a:focus-visible {
Glossary Block Styles
========================================================================== */

.pp-glossary-block {
.inline-glossary-block {
margin: 2rem 0;
}

Expand Down Expand Up @@ -301,7 +301,7 @@ aside[popover] > p a:focus-visible {
display: none;
}

dfn.pp-glossary-term span {
dfn.inline-glossary-term span {
text-decoration: none;
cursor: inherit;
}
Expand Down
Loading
Loading