Extension:TopicTags

Under Development

This should work 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.
 * We don't want any process or extension related to Categories to interfere with, or be interefered with, by these TopicTags (eg, Extension:CategoryTree). Topic-tags should never appear in CategoryTrees or category lists.
 * TopicTags are intended to provide a finer-grained taxonomy than Categories.
 * Where wiki curators may use Categories as a hierarchical organizing system (see Extension:CategoryTree), TopicTags are non-hierarchical.

Feature-Complete
Functionally, the current implementation does just about everything i want, in terms of user-experience and behaviors.

=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. (see image, above).

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 tagged with that tag-name.

=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:
 * Key feature: 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-section (Startall,Start,End,Endall).

In this extension, only one format-section has formatting: the Start section. 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= Must-haves before publishing this extension:
 * Resolve  issue, so that we can eliminate static tag pages.
 * Resolve two high-risk, high-impact issues.

Rationale

 * To allow tags to be auto-created the instant they are inserted into a page. Currently, the NewTag form must be used to create a dedicated page for each new tag.
 * Editors won't be forced to enter a description immediately on creating a new tag.
 * Centralized editing of all tag-descriptions.

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 be able to transclude Template:Tag for all embedded-tags. Then can simply pass tag-name as parameter to Template:Tag. Eg., <Green ></Green> instead of transcluding a static tag-page, as is currently required: <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. 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

 * DPL can match transclusion parameter (i just discovered this). Current most-likely solution.
 * https://help.gamepedia.com/DPL:Parameters:_Criteria_for_Page_Selection#includematch
 * Requires that we include that actual transclusion wikitext in DPL output. But, we only want visitor to see a link to the found page-- we don't want visitor to see the transclusion wikitext in the found page. How to hide? Manual says:
 * Use API 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.
 * How_to_add_Google_search_to_your_MediaWiki_Search_Results_Page
 * 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.)
 * Extension:Page_Forms/Defining_forms: Page_Forms can add/edit sections in a page. Current most promising solution.
 * 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.
 * Don't want to redirect user to full tag-descriptions list after submitting. Ideally, want to stay on Template:Tag page. Or, get redirected back to Template:Tag after description is saved.
 * Want to avoid user having to click "Save" after submitting the form.
 * 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.

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= "Risk" as used here means "likelihood of occurring."

"Impact" as used here means "how bad is it, if it happens."

Top-priority should be given to items which are both high-risk and high-impact.

(Priority shall not be based on whether or not someone volunteered to work on it. In software dev, that's an invalid definition of "Priority".)

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