{eac}Readme Extension Plugin

{eac}Readme loads and translates a WordPress markdown 'readme.txt' file providing shortcodes to access header lines and section blocks.

Document Header

Homepage:https://eacdoojigger.earthasylum.com/eacreadme/ Author:EarthAsylum Consulting Current Version:1.4.2 Last Updated:04-Apr-2024 Requires WordPress Version:5.5.0 Compatible up to:6.5 Requires PHP Version:7.4 Requires {eac}Doojigger:2.0 Contributors:Kevin Burkholder License:GPLv3 or later License URI:https://www.gnu.org/licenses/gpl.html Tags:readme, markdown, parsedown, {eac}Doojigger, code-highlighting, github, svn WordPress URI:https://wordpress.org/plugins/eacreadme GitHub URI:https://github.com/EarthAsylum/eacReadme

Description

{eac}Readme is an {eac}Doojigger extension which loads and translates a WordPress markdown 'readme.txt' file providing shortcodes to access header lines and section blocks.

Shortcode Usage

The first used shortcode must indicate the file to load...

[eacReadme file='/docfolder/readme.txt']        # file is relative to the WordPress document root folder
[eacReadme content='/contentfolder/readme.txt'] # content file is relative to the WordPress content folder (wp-content/)
[eacReadme plugin='/pluginfolder/readme.txt']   # plugin file is relative to the WordPress plugins folder (wp-content/plugins/)
[eacReadme theme='/themefolder/readme.txt']     # theme file is relative to the WordPress themes folder (wp-content/themes/)
[eacReadme wpsvn='/slugname/trunk/readme.txt']  # load file from WordPress SVN repository
[eacReadme github='/owner/repository/main/readme.txt']        # load file from github repository

After which, headers and sections may be pulled from that file...

[eacReadme]All Headers[/eacReadme]              # parses all header lines
[eacReadme]headerName[/eacReadme]               # gets the value of the named header line

[eacReadme]All Sections[/eacReadme]             # parses all section blocks
[eacReadme]sectionName[/eacReadme]              # parses the content of the named section block
[eacReadme]sectionName/sub-section[/eacReadme]  # parses the content of the named sub-section within section block

One shortcode can do it all...

[eacReadme plugin='/pluginfolder/readme.txt']Document[/eacReadme]    # loads the file and parses the entire document

Or load the entire file as a single code block...

[eacReadme theme='/themefolder/functions.php']Code File[/eacReadme]

Shortcode Examples

Get header values...

[eacReadme]Contributors[/eacReadme]
[eacReadme]Donate link[/eacReadme]
[eacReadme]Requires at least[/eacReadme]
[eacReadme]Stable tag[/eacReadme]

Get unnamed segments...

[eacReadme]Title[/eacReadme]                    # gets the '=== plugin name ===' line (before headers)
[eacReadme]Short Description[/eacReadme]        # gets the short description (between headers and first section block)

Get section blocks...

[eacReadme]Description[/eacReadme]
[eacReadme]Installation[/eacReadme]
[eacReadme]Screenshots[/eacReadme]
[eacReadme]Changelog[/eacReadme]

Get multiple blocks and/or sub-sections...

[eacReadme plugin='/eacReadme/readme.txt']Short Description,Description[/eacReadme]
[eacReadme plugin='/eacReadme/readme.txt']Short Description,Description/Shortcode Examples[/eacReadme]

Get a file as a code block...

[eacReadme theme='//dilh86bklvv63.cloudfront.net/my-child-theme/functions.js' lang='js']Code File[/eacReadme]
[eacReadme theme='//dilh86bklvv63.cloudfront.net/my-child-theme/style.css' lang='css']Code File[/eacReadme]

Other Options

Change the default cache time-to-live by adding to wp-config.php:

define('EAC_README_CACHE_LIFETIME',$seconds);   # default: 1-day (DAY_IN_SECONDS).

Override the default cache time-to-live

[eacReadme ttl=$seconds ...]                    # minimum: 1-minute (MINUTE_IN_SECONDS).

Set the default GitHub access token (for private repositories):

define('GITHUB_ACCESS_TOKEN',$token);

Set/override the GitHub access token

[eacReadme token=$token ...]

Override option to parse markdown when retrieving a segment

[eacReadme parse='true|false' ...]

Set class='language-*' on code blocks

[eacReadme lang='php|js|css|html' ...]

Translating Header/Section Names

Translate header/section names when retrieving All Headers, All Sections, or Document

[eacReadme translate='name=newname,...']
[eacReadme translate='Requires at least=Requires WordPress Version,Screenshots=Screen Shots']

Erase default translation table

[eacReadme translate='no|none|false']

Default translation table

[
    'Headers'               => 'Document Header',
    'Plugin URI'            => 'Homepage',
    'Stable tag'            => 'Current Version',
    'Requires at least'     => 'Requires WordPress Version',
    'Tested up to'          => 'Compatible up to',
    'Requires PHP'          => 'Requires PHP Version',
    'WC requires at least'  => 'Requires WooCommerce',
    'Requires EAC'          => 'Requires {eac}Doojigger',
    'Changelog'             => 'Change Log',
    'Screenshots'           => 'Screen Shots',
];

Readme Format

{eac}Readme expects a well-formed readme.txt file that follows the WordPress readme file standard...

=== title ===
header: value
header: value
short Description
== section ==
= sub-section =

...but supports some extensions to that standard:

  • Author & Author URI

    • Author header may be a simple name or a markdown link:
      • [Author](Author URI).
    • The Author & Author URI headers, if present, are combined as a markdown [Author](Author URI).
  • Homepage

    • Looks for Homepage or Plugin URI.
  • Version

    • Looks for Version or Stable tag.
  • Contributors

    • profileId - wordpress profile (standard)
    • profileId@youremaildomain.com - gravatar profile
    • profileId@wordpress - wordpress profile
    • profileId@gravatar - gravatar profile
    • profileId@github - github profile
    • [display name](mailto:email@address.com) or [display name](http://www.gravatar.com/profileId/)
    • [display name](http://profiles.wordpress.org/profileId/)
    • [your name]((http://your/profile/url)
  • A "banner" section may be included between the top title line and the first header line.

    === title ===
   [![banner](//image_url)](//link_url)
    header: value
    header: value
    short Description
    == section ==
    = sub-section =
  • The header block may be enclosed in an html <header> or <details> tag, opening and closing each on a single line. These tags are ignored by the eacParseReadme parser but may be beneficial if posting your readme file elseware. See {eac}Readme on Github.

Note: these extensions are not supported by the WordPress Plugin Repository.

{eac}Readme supports standard markdown (readme.md) formatting for section identification.

  • === title === and ## title are equivalent
  • == section == and ### section are equivalent
  • = sub-section = and #### sub-section are equivalent

Output HTML

When retrieving the header block with ...

[eacReadme]All Headers[/eacReadme] or \eacParseReadme::getAllHeaders()

Or when retrieving all sections with ...

[eacReadme]All Sections[/eacReadme] or \eacParseReadme::getAllSections()

Or when retrieving the entire document with ...

[eacReadme]Document[/eacReadme] or \eacParseReadme::getDocument()

Additional html tags and classes are added, including wrapping blocks within a <details> tags, adding readme-* class names, and adding <a> anchor links.

WordPress Actions

3rd-party actors may load and use the parser class included in {eac}Readme...

    do_action('eacReadme_load_parser');     // loads \eacParseReadme static class
    if (class_exists('\eacParseReadme'))
    {
        \eacParseReadme::loadFile($readme,$context);
        $html_document  = \eacParseReadme::getDocument();
        $title          = \eacParseReadme::getTitle();
        $version        = \eacParseReadme::getVersion();
        $donations      = \eacParseReadme::getHeader('donate_link');
        $description    = \eacParseReadme::getSection('description');
    }
Top
Installation

{eac}Doojigger Readme Extension is an extension plugin to and requires installation and registration of {eac}Doojigger.

Automatic Plugin Installation

This plugin is available from the WordPress Plugin Repository and can be installed from the WordPress Dashboard » Plugins » Add New page. Search for 'EarthAsylum', click the plugin's [Install] button and, once installed, click [Activate].

See Managing Plugins -> Automatic Plugin Installation

Upload via WordPress Dashboard

Installation of this plugin can be managed from the WordPress Dashboard » Plugins » Add New page. Click the [Upload Plugin] button, then select the eacreadme.zip file from your computer.

See Managing Plugins -> Upload via WordPress Admin

Manual Plugin Installation

You can install the plugin manually by extracting the eacreadme.zip file and uploading the 'eacreadme' folder to the 'wp-content/plugins' folder on your WordPress server.

See Managing Plugins -> Manual Plugin Installation

Settings

Once installed and activated options for this extension will show in the 'General' tab of {eac}Doojigger settings.

Top
Screen Shots
  1. Readme Extension {eac}Readme Extension

  2. Readme Help {eac}Readme Help

Top
Other Notes

Additional Information

Top Top
Change Log

Version 1.4.2 – April 4, 2024

  • Fix deprecated notice on substr/strpos with null value in parser.
  • Compatible with WordPress 6.5.

Version 1.4.1 – March 1, 2024

  • Additional documentation.
  • Improved isolation of headers and short description.
  • Support readme.md (standard markdown) files.
    • Expects WordPress layout (h2 title, headers, Short Description, h3 sections).
  • Non-standard 'banner' content between === title === and headers.
  • Updated most regular expressions.

Version 1.4.0 – February 9, 2024

  • Added github profile support along with optional profile formats for contributors.
  • Trim tags when tagifying from header.
  • Added new action, 'eacReadme_load_parser', to allow 3rd-party apps to use the parser class.
    • do_action('eacReadme_load_parser'); // loads \eacParseReadme static class
  • Added context to file access for github authentication & WP headers.
  • Changed WordPress svn uri (https://ps.w.org/)

Version 1.3.0 – January 31, 2024

  • Added 'ttl' option to shortcode to set cache time-to-live (min 1 minute).
  • Added WP SVN support:
    • [eacReadme wpsvn='/slugname/trunk/readme.txt']document[/eacReadme]
  • Added GitHub support:
    • [eacReadme github='/owner/repository/main/readme.txt']document[/eacReadme]
    • [eacReadme github='...',token='...']

Version 1.2.6 – January 24, 2024

  • Fixed "preg_match(): Passing null" notice.

Version 1.2.5 – December 8, 2023

  • Fixed caching (yet again) by adding current file name to cache key.
    • subsequent segments could load the wrong cache key when no file given.

Version 1.2.4 – December 4, 2023

  • Added button to flush group cache when using drop-in object cache.
  • Added use of 'EAC_README_CACHE_LIFETIME' constant to set cache life-time (default = 1 day).
    • In wp-config.php: define('EAC_README_CACHE_LIFETIME',3600);
  • md5() cache key name.

Version 1.2.3 – August 30, 2023

  • Improved caching.

Version 1.2.2 – June 6, 2023

  • Removed unnecessary plugin_update_notice trait.
  • Cosmetic changes to option & help titles.

Version 1.2.1 – April 22, 2023

  • Correctly load inline style using wp_add_inline_style()
  • Tested with WordPress 6.2 and {eac}Doojigger 2.2.

Version 1.2.0 – November 16, 2022

  • Updated to / Requires {eac}Doojigger 2.0.
  • Uses 'options_settings_page' action to register options.
  • Added contextual help using 'options_settings_help' action.
  • Renamed extension file(s) and vendor directory.
  • Changed tab name in registerExtension (must be -re-enabled in admin).
  • Moved plugin_action_links hook to eacDoojigger_load_extensions filter.
  • Added use of WP_Object_Cache.
  • Fixed problem with admin page reload when changing style.

Version 1.1.1 – September 25, 2022

  • Fixed potential PHP notice on load (plugin_actionlinks).
  • Added upgrade notice trait for plugins page.
  • Added tagify option: getTags(true) when processing tags to convert to array [slug=>tag]

Version 1.1.0 – September 7, 2022

  • Added ability to get the full file contents as a code block (Code File).
  • Renamed include file eacParseReadme.php to class.readme_parser.php.

Version 1.0.7 – August 28, 2022

  • Updated to / Requires {eac}Doojigger 1.2
  • Added 'Settings', 'Docs' and 'Support' links on plugins page.
  • Fixed admin display error (section not found).

Version 1.0.6 – July 12, 2022

  • Get contributor profile when getting all headers.
  • Move short description before headers in getDocument().

Version 1.0.5 – June 22, 2022

  • Added "{plugin}_eacReadme" filter.
  • Added title attribute to nav links.

Version 1.0.4 – June 9, 2022

  • Updated for {eac}Doojigger 1.1.0

Version 1.0.3 – May 12, 2022

  • Added transient caching of contributor profiles.

Version 1.0.2 – May 10, 2022

  • Added section name translation.

Version 1.0.1 – April 28, 2022

  • Minor changes / enhancements.

Version 1.0.0 – February 26, 2022

  • Initial release.
Top
Upgrade Notice

1.2.0

Requires {eac}Doojigger version 2.0+

Top

This document was generated using {eac}Readme by processing the included ‘readme.txt’ file with this shortcode…
[ eacReadme plugin='/eacreadme/readme.txt' ] document [ /eacReadme ]
With Prism code highlighting enabled and additional CSS styling…

/*
 * Formatting for eacReadme
 */

/* readme content w/tabs */
#readme-head summary {
  float: left;
  padding: .5em 1em;
}
#readme-head summary:after {
  content: '...';
}
#readme-head p {
  float: right;
  font-size: .9em;
  font-style: italic;
  opacity: .8;
  background-color: var(--eac-lighter-background);
  border: .5px solid var(--eac-highlight-text);
  margin-bottom: 2em;
  padding: .5em;
  display: grid;
  grid-template-columns: max-content auto;
  grid-column-gap: .5em;
  overflow: hidden;
  text-overflow: ellipsis;
}
@media (max-width: 767px) {
  #readme-head p {
    grid-template-columns: auto;
  }
}
.readme-head-name {
  font-weight: 500;
}
.readme-head-value {
  max-width: 26em;
}
#readme-short {
  clear: both;
  font-size: 1.25em;
  font-weight: 400;
  font-style: italic;
  letter-spacing: .5px;
  color:  var(--eac-contrast-text);
  background: var(--eac-lighter-background);
  border: dotted .5px;
  border-radius: 4px;
  padding: 0.25em;
  margin-bottom: 0;
}
#readme-nav {
  clear: both;
  margin: 0 2em;
  overflow-y: auto;
  vertical-align: top; /* fixes extra spacing with overflow */
  white-space: nowrap;
}
#readme-content {
  clear: right;
  padding: 0 1em;
}
#readme-content table {
  border-bottom: 2px solid #ddd;
}
#readme-content th:first-child {
  white-space: nowrap;
  min-width: 15em;
}
#readme-nav a {
  font-family: Helvetica, Arial, sans-serif;
  font-size: .9em;
  display: inline-block;
  max-width: 7em;
  overflow: hidden;
  vertical-align: top; /* fixes extra spacing with overflow */
  white-space: nowrap;
  text-overflow: ellipsis;
  margin: .25em 0 0 0;
  padding: .5em;
  color: var(--eac-contrast-text);
  background-color: var(--eac-lighter-background);
  border: .5px solid var(--eac-highlight-text);
  border-radius: 4px 4px 0 0;
}
#readme-nav a.readme-active {
  color: var(--eac-highlight-text);
  background-color: white !important;
  border-bottom-color: white !important;
}
#readme-content details.readme {
  display: none;
}
#readme-content details.readme summary {
  margin: 1em 0;
  font-size: 1.5em;
  font-weight: bold;
  border-bottom: dotted .5px;
}
#readme-content details.readme.readme-active {
  display: block;
  border-top: .5px solid var(--eac-highlight-text);
  border-radius: 1em;
  padding: 0 .5em;
  overflow: auto;
  background: white;
  margin-top: -1px;
}
#readme-content h4 {
  font-weight: bold;
  font-size: 1.1em;
  margin-top: 2em;
}
#readme-content h4:before {
  content: "\f214\20";
  color: #aaa;
  font-family: 'dashicons';
  font-style: normal;
  font-size: 1.25em;
  vertical-align: sub;
}
#readme-content a[href]:after {
  content: "\f504";
  font-family: 'dashicons';
  color: var(--eac-contrast-text);
  font-size: .9em;
  opacity: .5;
  vertical-align: top;
}
#readme-content a[href^='/']:after {
    content: "\f310";
  vertical-align: middle;
}
#readme-content a[href^='#']:after {
    content: "\f316";
  vertical-align: middle;
}

#readme-screenshots {
  font-weight: bold;
  color: var(--eac-detail-text);
}
#readme-screenshots img,
#readme-other-notes img {
  margin: 1em;
  max-width: 95%;
  display: block;
  margin-left: auto;
  margin-right: 0;
  box-shadow: 2px 2px var(--eac-darker-background);
}

And a little JavaScript to manage the tab content…

/*
 * eacReadme adds :
 * - navigation anchor links for each == section == of the readme.txt document.
 *      <nav id='readme-nav' class='readme'>
 *          <a href='#readme-description' class='readme' title='Description'>Description</a>
 *      </nav>
 * - sections are tagged as <details><section>
 *      <div id='readme-content'>
 *          <details id='readme-description' class='readme'>
 *              <summary>Description</summary>
 *              <p>...</P>
 *          </details>
 *      </div>
 *
 * Here, we add click() actions to the above anchor links to use as tabs,
 * and within readme.txt, any link like [click here](#section) will activate the 'section' tab,
 * lastly, we look for a url hash #section to activate the 'section' tab.
 */

jQuery(document).ready(function ()
{
    // remove all content "top" anchor links added by eacReadme
    jQuery("#readme-content a[href=\"#readme-top\"]").remove();

    // add click() to readme-nav anchor links to activate/deactivate tabs
    jQuery("#readme-nav > a").click(function(e) {
        jQuery(this).addClass("readme-active");
        jQuery(this).siblings().removeClass("readme-active");
        index = jQuery(this).index() + 1;
        jQuery("#readme-content > details").removeClass("readme-active");
        jQuery("#readme-content > details:nth-child(" + index + ")").addClass("readme-active");
        return false;
    });

    // add click() to any content anchor links to activate a tab
    jQuery("#readme-content a[href*=\"#\"]").click(function(e) {
        nav = jQuery("#readme-nav a[href=\"#readme-"+this.hash.replace(/(#readme-|#)/i,"")+"\"");
        if (nav.length) {
            nav.click();
            jQuery("html, body").animate({scrollTop: jQuery("#main").offset().top});
            return false;
        }
    });

    // check for tab anchor in url, activate the tab
    if (hash = window.location.hash) {
        nav = jQuery("#readme-nav a[href=\"#readme-"+hash.replace(/(#readme-|#)/i,"")+"\"");
        if (nav.length) {
            return nav.click();
        }
    }

    // activate the first tab
    jQuery("#readme-nav > a:first-child()").click();
});