[pmwiki-devel] Update Re: Using "!#anchor heading" markup

John Rankin john.rankin at affinity.co.nz
Sun May 31 18:58:21 PDT 2026


On 31/05/2026 8:16 pm, Petko Yotov wrote:

> On 30/05/2026 04:45, John Rankin wrote:
> <snip>
>> 3. !!##anchor heading produces a visible anchor, again for
>> consistency.
>
> The core "!!#anchor..." produces:
>   <h2 id="anchor">...</h2>
>
> not:
>   <h2><a id="anchor"></a>...</h2>
>
> so in !!#anchor there is no actual anchor tag. I guess you can have a 
> markup rule that rewrites !!##anchor into !![[##anchor]] for it to be 
> made visible.

The pagetoc recipe has always used !!# and !!## as shorthand for 
"generate a unique anchor id and insert an anchor". So, from the point 
of view of the recipe:

!!#idName as shorthand for !![[#idName]]

is an equally valid interpretation as:

!!#idName as shorthand for !!%id=idName apply=block%

I think !!#idName and !!##idName should both produce either an id or an 
anchor, not one of each.

I modified pagetoc to generate %id=idName apply=block% instead of 
[[#idName]] and encountered 2 problems:

- %id=CamelCase apply=block% treats CamelCase as a WikiWord if WikiWords 
are enabled

- !!%id=idName apply=block% works as expected, but Q:%id=idName 
apply=block% (pmwiki's Q: and A: markup) ignores the id under my (older) 
version of pmwiki

At that point I reverted to converting ^(!+|Q:)(##?idName) into 
[[##?idName]].

Perhaps !!%idName would be better than !!#idName to designate idName 
will produce <h2 id='idName'> ... </h2>?

>
>> 5. Is there a case for making duplicate anchor ids visible as part of
>> the pmwiki core?
>
> Currently, !!#anchor does not check for duplicates, maybe it should, 
> but should we also do something about all possible elements with an 
> identifier like:
>
>   (:input id=something:) planned (:input#something.className:)
>   (:div id=something:)   planned (:div#something.className:)
>   (:details id=something:)
>   %list id=something%
My feeling is to do minimum unless there is user demand. So if authors 
use anchor markup, they can rely on pmwiki to detect a duplicate anchor 
id, but if they use an id=idName attribute, they are on their own. This 
leave !!#idName in a grey area. My preferred option would be !!#idName 
produces an anchor that pmwiki checks, while !!%idName produces an id 
attribute that pmwiki does not check.
>
> What if a writer adds to a page [[#wikitext]] when the skin already 
> defines <div id="wikitext">? At some point we might want say PmWiki is 
> not an HTML standards validator and leave the responsibility with the 
> writers. A recipe may use output buffering and htmltidy to remove 
> duplicate ids when this is required.

I think if the skin uses [[#wikitext]], a writer's use of [[#wikitext]] 
will be tracked. Yes? If the skin uses id='wikitext', then since (see 
above) pmwiki doesn't check id attributes, the duplicate will not be 
found. And I think that's OK.

If some future pmwiki release checks all id attributes, then it will 
find the duplicate at that time.

>
> If there are duplicate identifiers, which one should win? The 
> different markups are processed in order one after another, even if in 
> the page !!#anchor is before [[#anchor]], the engine will see the 
> latter first.
This problem goes away if !!#idName produces [[#idName]]. And if pmwiki 
doesn't check id attributes for duplicates, the problem doesn't go away, 
but pmwiki ignores it.
>
> If both are in the page and both are rendered, a link to Page#anchor 
> will focus the one that is earlier in the page.
>
> If both are in the page, using (:include Page#anchor:) will include 
> from [[#anchor]] not from !!#anchor because of the order of 
> $TextSectionAnchorPatterns.
If !!#anchor produces an [[#anchor]] and pmwiki detects and reports 
duplicate anchors, this problem goes away, as the writer is given an 
opportunity to correct the problem. If the author chooses not to correct 
the problem, that's their choice.
>
> I would not render a character for a removed anchor with duplicate 
> identifiers, because recipes and pagelists can include parts of 
> multiple pages that are wrapped in the same anchors:
>
>   (:include {=$FullName}#start#end:)
>   (:b3-list:)
>
> If duplicate anchors are replaced with �, these will appear as new 
> weird characters in pagelists that worked fine before.

Yes, I agree. The purpose of displaying � for duplicate idNames is to 
make it easier for writers to create a correct page table of contents. 
So I think pagetoc should limit its error reporting to 
^(!!|Q:)(##?idName|[[##?idName]]) instances.

That would significantly reduce (but probably not eliminate) the 
instance of anomalies. So if a page contains

[[#idName]] foo

followed by

!![[#idName]]

the second instance will be flagged. If the page contains

!![[#idName]]

followed by

[[#idName]] bar

the second instance will be ignored.

>
>> 6. Should I be separating out visible and duplicate anchor markup
>> processing into its own separate recipe?
>
> If someone needs visible anchors but prefers one of the several other 
> table-of-contents recipes, it may be good to split them.
Unless people ask, I'm inclined to leave well alone.
>
>> Should such a recipe be an optional part of the pmwiki core?
>
> If visible anchors are popular, we can consider adding them to the 
> core. I know of a single wiki that is using these extensively.
>
> The core already matches [[##anchor]] as well as !!#anchor for 
> inclusion of sections in (:include Page#anchor:).
Does the optional table-of-contents recipe that's now part of the core 
recognise visible anchors? If so, perhaps this recipe should handle 
[[##visible]] markup, rather than rely on a cookbook recipe.
>
>> 4. (:toc anchors=visible:) makes all anchors in the toc headings
>> visible (overriding any !![[#anchor]] markup); a new option (:toc
>> anchors=!visible:) hides all anchors (overriding any !![[##anchor]]
>> markup), except for any duplicate ids; (:toc:) processes anchors as
>> written.
>
> <snip>

Thanks.

JR




More information about the pmwiki-devel mailing list