Extension:TopicTags

Under Development

This works if installed as directed. But seeking feedback and improvements before release.

This page is under development, and may contain errors or omissions.

=Introduction= This extension provides inline topic-tags, which are completely independent of Categories. Wiki editors can insert topic-tags inline anyplace on a wikipage. The new, unique feature of these topic-tags, is they are not just page-level tags. They can be scoped to specific locations within the body of a page.

(Note this extension is unrelated to MediaWiki edit-tags)

Why Not Use Categories?
Category scope is limited to the page-level. TopicTags can pinpoint specific text-locations in the page. Categories can't do that.

Feature-Complete
Functionally, the current implementation does everything i want, in terms of user-experience and behaviors. Just two high-risk, high-impact issues to resolve.

=Appearance= Topic-tags have 2 formats:
 * Inline, where the tag is associated with a specific location on a page.
 * Page-level, where the tag is associated with an entire page.

For each unique tag-name, there's a Tag Page, containing a description of the tag, and a list of all pages containing the tag.

Inline Tags
An inline tag appears as a very small, super-script text-link. The font is extra-small, to differentiate from other common superscript text. When clicked, reader is directed to the Tag-Page.

Page Tags
A page tag appears at the bottom of the page in full-size text. Also displayed are "Related Pages": a list of links to all other pages containing the same tag.

Tag Page
For each tag, there's a Tag Page, containing a description of the tag, and a list of all pages containing the same tag.

=Usage=

Clicking the tag-name in a tagged article
Click a tag-link to be directed to the Tag-Page.

Clicking a related-page link
Click a related-page link to be directed to a related wiki-page:
 * If the tag is inline on the related wiki-page, the reader will be directed to the specific tagged location in the body text.
 * If the tag is page-level tag on the related wiki-page, the reader will be directed to the top of the tagged page.

Inserting Tags
Tagging syntax was designed to be as simple as possible. Two topic-tag formats can be used in articles. The only difference is the trailing pipe | character. A tag-name may not contain an embedded space.

Inline Tags
Use the following syntax to insert an inline tag. Displays as a small superscript in the article, with NO list of related articles. : 

Page Tags
Use the following syntax to insert a page-level tag. Intended to be inserted at bottom-of-article. Displays normal-size bold, with list of related articles: 

Creating Tag Names
To create a new tag-name:
 * 1) Browse to YOUR-WIKI-URL/Form:Tag
 * 2) Enter tag-name, and click "Create tag".
 * 3) Enter tag-description, and click "Save page".

=Installation= The current version of this extension is php-free, and can be installed manually. FTP is needed to install the depended-extensions, but not needed to install any part of this extension.

Done.
 * 1) Install all
 * 2) Create the.

Dependencies

 * Extension:Page_Forms
 * Extension:UrlGetParameters
 * Extension:DynamicPageList3
 * Extension:HTML_Tags
 * Extension:Labeled Section Transclusion

Extension Pages
To create these pages, you need only to paste in the wikitext provided at the links below:
 * /Form-CreateTag
 * /Template-Tag
 * /Template-Tag/Preload
 * /Page-Tag
 * /Page-Tags
 * /Template-Pin

=Implementation=

Simple, Yet Complicated
This extension does something pretty simple. I think it's features ought to be handled by MW core. But due to limitations of MediaWiki, the implementation is more complicated than i would like. To achieve it's simple goals requires some funky workarounds, and depends on about five different extensions.

Still, it's pretty simple. There's no php (yet), and very little wiki-text. It's not at all large. I try to separate functional blocks into different pages, for clearer understanding and easier maintenance/upgrades.

Secret Sauce: Anchors
The secret sauce is anchors. Inline tags render as an HTML-anchor-- that makes it possible to link directly to the tag-location in the body of the wiki-page.

Inline tags will render HTML like this:

Nested Transclusion
A topic tag is a tranclusion of a static Tag page, eg: 

That transclusion contains a secondary transclusion to Template:Tag. So the HTML that gets rendered on the tagged host-page is ultimately delivered by Template:Tag, even though the user enters a transclude to Tag:Green (or whatever is the desired tag-name).

Why is nested transclusion necessary? Because pipes.

Template:Tag
Through Transclusion, Template:Tag renders clickable HTML-links in tagged host-pages.

Inserted Topic-Tags are transclusions. When a host wiki-page contains the tag-code for Tag:Purple, it passes a wiki-parameter, by nested transclusion, to Template:Tag. This enables Template:Tag to return HTML to be rendered on the host page. For example, this inline tag-code on a wiki-page:  creates an HTML anchor on the host page. That anchor is the secret to inline-tags. The rendered HTML looks like: CommonGround This page-level tag-code, with trailing pipe,  produces a list of related pages. That enables the user to jump directly to any related page: Tag:CommonGround  <li> Portal:Welcome</a></li> <li> Openers</a></li> <li> Draft:can't blame guns.</a></li> <li> highest gun-homicide rate.</a></li> </ul>

Notice the string "#Tag:" in each related-page link. That causes the link to go directly to the anchor-location in the body-text where the tag appears.

Visible Tag Page
When a tag-name is clicked in a tagged wiki-page, user is directed to visible page "Tag". Tag displays the tag-description and list of related pages. A Url parameter is used to pass the tag-name into page Tag. That's the purpose of Extension:UrlGetParameters.

It would be better, more MediaWiki-ish, if MediaWiki supported page-parameters. Then we could do everything in wikitext, instead of mingling wikitext with HTML. But that was rejected by admins.

Static Tag Pages
Individual tag-pages exist for each tag-name, but the reader never sees them. They are created by the form CreateTag.

Tag-name is hardcoded into these pages. They can be in a hidden namespace. Individual tag-pages have two functions:
 * to store the tag-descriptions. When visible page Tag is viewed for a particular tag, the tag-description is pulled from the static tag-page.
 * to be a search-target for DPL.

Static pages are preloaded with /Template-Tag/Preload. That's done by the /Form-CreateTag.

DPL Format
The DPL3 format syntax is: | format=Startall,Start,End,Endall

In our DPL statement, the commas are placeholders for each format-tag (Startall,Start,End,Endall). In the example given, only one tag has data: the Start tag. Start represents the beginning of each article in the list.

The star resolves to a bullet in the output.

https://help.gamepedia.com/DPL:Parameters:_Controlling_Output_Format#format

To ensure links in the list go to those inline anchors, DPL must include pound-anchor in the links it outputs for found pages. Must output wikitext syntax for anchors: display_as (actually, i think we're currently doing it with html "a" tag and url-params. Should change to wikitext style, if possible).

https://meta.wikimedia.org/wiki/Help:Anchors

DPL format is newline + found-page name linked to tag-anchor on found-page | format  = ,\n* %PAGE%,, }}

Note, if users use same tag in multiple locations on the page, then DPL anchor-links will go to the FIRST tag on the page.

=Release Version= I hope to achieve the following before publishing this extension:

Rationale
To allow tags to be auto-created the instant they are used. Currently, the NewTag form must be used to create a dedicated page for each new tag.

Other Benefits

 * Eliminating hard-coded tag-pages allows us to eliminate the Page_Forms and Labeled Section Transclusion dependencies.
 * Will eliminate nested transclusions, which is just simpler and easier to understand (prolly no functional/performance benefit to that).
 * Code re-use is simply a programming best-practice. It means improvements can be made in one place, and everything that uses it gets the improved version.

Progress
We're partway there. Template:Tag and page Tag help. Through the use of parameters, these two pages serve all named-tags. They generate:
 * Related-page lists
 * HTML for tagged host pages
 * Display of tag description

Blockers
To eliminate hard-coded tag-pages, 2 issues must be solved:
 * The pipe: DPL/API can't find pipes or transclusion parameters.
 * Data-storage: No way yet found to store tag descriptions in a single table or page.

The pipe
To eliminate tag-pages, we'd need to transclude Template:Tag for all embedded-tags. Eg., <Green ></Green> instead of transcluding a static tag-page: <undefined ></undefined>. For that to work, DPL (or API) would have to be able to tell the difference between <Green ></Green> and <Blue ></Blue> But DPL cannot tell the difference. It will count both as the same transclusion. DPL can't tell the difference, because DPL cannot see pipes. It can only find static pages. The tags inserted must transclude a specific page for DPL to find them (eg, <undefined ></undefined> . It can only tell the difference between <undefined ></undefined> and  <undefined ></undefined> . So far, the MW API struggles with the pipe as well. No solution to this yet.
 * https://www.mediawiki.org/wiki/Topic:Ucmsdl9osvcbes0l
 * https://phabricator.wikimedia.org/T194039

Possible Solutions

 * Most promising: DPL may be able to match transclusion parameter:
 * https://help.gamepedia.com/DPL:Parameters:_Criteria_for_Page_Selection#includematch
 * Would require that we include that actual transclusion wikitext in DPL output. But, don't want visitor to see that transclusion wikitext. How to hide?
 * Use transcludedin to get all pages that transclude Template:Tag. Get snippet of each transclude, so we can see the full transclusion wikitext (including the parameter (tag-name)). Then from that list, get only those containing target parameter (tag-name).
 * Problem: transcludedin doesn't return snippets.
 * https://gunretort.xyz/api.php?action=query&prop=transcludedin&tiprop=pageid&tilimit=500&titles=Template:Tag
 * API:Opensearch: Can't get basic functioning yet. Topic:Uecqa71xa8mlnblu
 * Embedded Google Search, if can search page sources, and be formatted like a raw list.
 * Extension:GoogleSiteSearch
 * Extension:GoogleCustomWikiSearch
 * Extension:RigorousSearch

Unlikely Solutions:

 * wikitext, instead of DPL or API. No known method, just a thought.
 * Extension:CirrusSearch: No go-- Cirrus requires Elastica, which requires Java, which is not available on my shared web-hosting. My requirement is to work on shared web-hosting. Back to the drawing board...
 * RegEx with insource: rejected- Requires CirrusSearch.
 * https://stackoverflow.com/questions/45085911/can-regular-expressions-be-used-with-the-wikipedia-api
 * https://en.wikipedia.org/wiki/Help:Searching/Regex
 * Wikidata Query Service: Not available in core.

Storing Descriptions
The other purpose for tag-pages is to store tag-descriptions. To eliminate individual tag pages, we must find a way to store all tag-descriptions in a db table or a single wikipage. It must be easy to add new ones and edit existing ones.

How to save a list of tag-descriptions in a single table or wiki-page? Some possible and rejected solutions:

Likely Solutions

 * No descriptions: A simple solution would be to eliminate tag-descriptions. That would get us closer to eliminating individual tag-pages. For a first release, i'm fine with that. Then we'd only have to solve the pipe problem. (However, in long-run, descriptions seem an essential feature for Topic-Tags.)
 * MediaWiki Url API: Promising solution. No direct db-access (i believe), but could store tag descriptions as sections on a wikipage. A section-name would be the tag-name, and the section content would be the tag's description.
 * Can use Edit action to append a new record.
 * To retrieve a single description by tag-name, must retrieve the page section-content by section-title:
 * Extension:Labeled_Section_Transclusion, which we're currently using to get descriptions from static tag-pages.
 * Can't use API easily to retrieve tag-description, because Parse action can only retrieve a section by number, not name.
 * Curators can edit the list directly to revise/remove tags.
 * Extension:Page_Forms/Defining_forms: Also promising, as Page_Forms can add/edit sections in a page.
 * Nice feature: Can be used to add new description, or edit existing one. Page_Forms creates a new section if doesn't already exist, or will edit the existing section.
 * This solution would require that Form pages can receive wikitext or url paramaters, as we would need to pass the tagname into the form. That will enable form to create a section for a specific, arbitrary tagname.
 * Want to embed the form in Template:Tag. Ideally, want to avoid redirecting to the target-page-- stay on Template:Tag page. Or, at least get redirected back to Template:Tag after description is saved.
 * Want to avoid user having to click "Save" after submitting the form.

Unlikely Solutions

 * Extension:Cargo: Rejected: Cargo is not appropriate for arbitrarily storing individual records in a list. Can only store the entire list at once.
 * Extension:Semantic_MediaWiki: Avoided, because so large. Also, like Cargo, may be page-centric. On the other hand, Semantic might be able to replace more than one of our current dependencies, so worth investigating.
 * Extension:ExternalData: Could be used to retrieve descriptions, but does not seem to offer a way to store individual records in a table or list. SemantcWiki is suggested
 * Extension:DataTable2: Unknown if feasible, but seems unlikely. Entire table has to be saved together, so adding a single record requires re-saving the entire list. More importantly, can't easily append a single record to end of list, because the table requires a non-data closing tag.
 * https://www.mediawiki.org/wiki/Topic:Udh53bn9qmovy1xd
 * https://www.mediawiki.org/wiki/Topic:Ud1kiswqh0cc1zsy
 * Custom PHP. Most powerful solution, of course, but most time-consuming and labor-intensive to develop, and loses our "php-free" goal. Essentially, php for database access would make sense as a separate, general purpose data-storage extension, separate from TopicTags.
 * Extension:WikiLexicalData

Solve
Solve all high-risk, high-impact issues.

Reduce dependencies

 * That would simplify installation and reduce footprint. But might not be possible, without writing some custom PHP.
 * Maybe we can bundle the dependencies into one installer.
 * Personal opinion: i believe everything this extension does should be doable without any extensions. I feel all behaviors are things that should be part of the MW core-- this extension isn't really doing anything groundbreaking. It all seems very consistent with core MW features. But there are holes in MediaWiki core.
 * Extension:UrlGetParameters: Could be eliminated if MW supported page-parameters. But, feature rejected: https://phabricator.wikimedia.org/T194571

=Known Issues=

Caching causes delays in updating related pages list displayed in transcludes.
Risk: high

Impact: high

As with some other extensions (eg Extension:CategoryTree), caching can muck things up. Still haven't found a solution for this. This only affects the related-pages list displayed on page-level tags, on the tagged page. Does not affect the list displayed in Template:Tag. Possible solutions:
 * Hmm-- how to prevent a transclusion from getting cached, even while the page that hosts it does get cached?
 * Or-- how to force a transclusion to refresh on page-load?
 * Or-- does MediaWiki support partial-page caching?
 * Or partial-page refreshes?

I believe some extensions (maybe even core) do some ajaxy stuff. If MW can't do this, it should :)

Inline tag links incorrectly wherever the inline-tag get included in an unrelated DPL
Risk: low

Impact: high

If some unrelated page contains a DPL list, which in-turn includes text which contains a topic-tag, when clicked that topic-tag will not correctly link to Template:Tag.

(need to confirm, might be working now)

Breaks if non-existent tag inserted.
Risk: high

Impact: high

Possible solutions:
 * Auto-create tag page when tag is clicked. Since tag links to Template:Tag, then Template:Tag would have to execute code to the create page.
 * Eliminate tag-pages.
 * Eliminate tag-descriptions.
 * Figure out pipe DPL

Tag-links on Tags page open in new window
Risk: High

Impact: Low

The Tags page contains a list of all topic-tags in the wiki. When any tags in the list are clicked, user is directed to the tagged-pages list for that tag. Problem is, if the wiki is configured to open external links in a new window, these tag-links will open in a new window. That's because, currently, they are rendered as external links. And that's because each one links to the same Template:Tag page, passing tag-name as a parameter.

Possible solutions:

=Future Enhancements=
 * Stats: Would be cool to display usage stats, click stats, and other info about the tag on the Tag page.
 * There might be advantages to using separate tag-pages, as those pages might display statistics or other data more easily than a dynamic template. Therefor, separate tag-pages can remain an option.

=PHP-Free Experiment= This project is an exploration into the feasibility of php-free extensions, which could be created by non-php programmers, using only wikitext.

Tentatively called "PHP-Free Extensions". A shorter name would be preferrable. Maybe "miniExt", "freelette", "pluglette", etc.

To facilitate non-programmer publishing of php-free extensions, there could be a generic installer, which registers the extension and creates needed pages.. Creation of extension pages could be automated with an API Import action.

Or, even better, the extension pages could themselves transclude model-pages from an external server, enabling extension developers to instantly roll-out improvements to any wiki which uses this extension.

Topic:Ucx3870iubclp1i7