<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[2499] sites/trunk/wordpress.org/public_html/wp-content: Plugins Directory: Adding the initial plugin directory plugin & theme.</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="http://meta.trac.wordpress.org/changeset/2499">2499</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"http://meta.trac.wordpress.org/changeset/2499","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>dd32</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2016-02-13 03:38:51 +0000 (Sat, 13 Feb 2016)</dd>
</dl>
<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Plugins Directory: Adding the initial plugin directory plugin & theme.
These include a lot of hard-coded test data still, which will be iterated upon.</pre>
<h3>Added Paths</h3>
<ul>
<li>sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/</li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentpluginsplugindirectoryplugindirectoryphp">sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/plugin-directory.php</a></li>
<li>sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/readme-parser/</li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentpluginsplugindirectoryreadmeparserReadmeParserphp">sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/readme-parser/ReadmeParser.php</a></li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentpluginsplugindirectoryreadmeparsercompatphp">sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/readme-parser/compat.php</a></li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentpluginsplugindirectoryreadmeparsermarkdownphp">sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/readme-parser/markdown.php</a></li>
<li>sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/</li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgpluginsGruntfilejs">sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/Gruntfile.js</a></li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgpluginsfilterbarphp">sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/filter-bar.php</a></li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgpluginsfooterphp">sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/footer.php</a></li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgpluginsfunctionsphp">sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/functions.php</a></li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgpluginsheaderphp">sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/header.php</a></li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgpluginsindexphp">sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/index.php</a></li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgpluginspagephp">sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/page.php</a></li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgpluginsplugincardphp">sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/plugin-card.php</a></li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgpluginssinglepluginphp">sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/single-plugin.php</a></li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgpluginsstylecss">sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/style.css</a></li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgpluginstemplatetagsphp">sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/template-tags.php</a></li>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgpluginsviewintrophp">sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/view-intro.php</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="sitestrunkwordpressorgpublic_htmlwpcontentpluginsplugindirectoryplugindirectoryphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/plugin-directory.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/plugin-directory.php (rev 0)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/plugin-directory.php 2016-02-13 03:38:51 UTC (rev 2499)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,348 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/*
+ * Plugin Name: Plugin Repository
+ * Plugin URI: http://wordpress.org/plugins/
+ * Description: Transforms a WordPress site in The Official Plugin Directory.
+ * Version: 0.1
+ * Author: wordpressdotorg
+ * Author URI: http://wordpress.org/
+ * Text Domain: wporg-plugins
+ * License: GPLv2
+ * License URI: http://opensource.org/licenses/gpl-2.0.php
+ */
+
+class Plugin_Directory {
+
+ function __construct() {
+ register_activation_hook( __FILE__, array( $this, 'activate' ) );
+ register_deactivation_hook( __FILE__, array( $this, 'deactivate' ) );
+
+ add_action( 'init', array( $this, 'init' ) );
+ add_filter( 'post_type_link', array( $this, 'package_link' ), 10, 2 );
+ add_filter( 'pre_insert_term', array( $this, 'pre_insert_term_prevent' ) );
+ add_action( 'pre_get_posts', array( $this, 'use_plugins_in_query' ) );
+ add_filter( 'the_content', array( $this, 'filter_post_content_to_correct_page' ), 1 );
+ }
+
+ function activate() {
+ global $wp_rewrite;
+
+ // Setup the environment
+ $this->init();
+
+ // %postname% is required
+ $wp_rewrite->set_permalink_structure( '/%postname%/' );
+
+ // /tags/%slug% is required for tags
+ $wp_rewrite->set_tag_base( '/tags' );
+
+ // We require the WordPress.org Ratings plugin also be active
+ if ( ! is_plugin_active( 'wporg-ratings/wporg-ratings.php' ) ) {
+ activate_plugin( 'wporg-ratings/wporg-ratings.php' );
+ }
+
+ // Enable the WordPress.org Theme Repo Theme
+ foreach ( wp_get_themes() as $theme ) {
+ if ( $theme->get( 'Name' ) === 'WordPress.org Plugins' ) {
+ switch_theme( $theme->get_stylesheet() );
+ break;
+ }
+ }
+
+ flush_rewrite_rules();
+
+ do_action( 'wporg_plugins_activation' );
+ }
+
+ function deactivate() {
+ flush_rewrite_rules();
+
+ do_action( 'wporg_plugins_deactivation' );
+ }
+
+
+ function init() {
+ load_plugin_textdomain( 'wporg-plugins' );
+
+ register_post_type( 'plugin', array(
+ 'labels' => array(
+ 'name' => __( 'Plugins', 'wporg-plugins' ),
+ 'singular_name' => __( 'Plugin', 'wporg-plugins' ),
+ 'add_new' => __( 'Add New', 'wporg-plugins' ),
+ 'add_new_item' => __( 'Add New Plugin', 'wporg-plugins' ),
+ 'edit_item' => __( 'Edit Plugin', 'wporg-plugins' ),
+ 'new_item' => __( 'New Plugin', 'wporg-plugins' ),
+ 'view_item' => __( 'View Plugin', 'wporg-plugins' ),
+ 'search_items' => __( 'Search Plugins', 'wporg-plugins' ),
+ 'not_found' => __( 'No plugins found', 'wporg-plugins' ),
+ 'not_found_in_trash' => __( 'No plugins found in Trash', 'wporg-plugins' ),
+ 'menu_name' => __( 'My Plugins', 'wporg-plugins' ),
+ ),
+ 'description' => __( 'A package', 'wporg-plugins' ),
+ 'supports' => array( 'title', 'editor', 'excerpt', 'custom-fields' ),
+ 'taxonomies' => array( 'post_tag', 'category' ),
+ 'public' => true,
+ 'show_ui' => true,
+ 'has_archive' => true,
+ 'rewrite' => false,
+ 'menu_icon' => 'dashicons-admin-plugins',
+ ) );
+
+ register_post_status( 'pending', array(
+ 'label' => _x( 'Pending', 'plugin status', 'wporg-plugins' ),
+ 'public' => false,
+ 'show_in_admin_status_list' => true,
+ 'label_count' => _n_noop( 'Pending <span class="count">(%s)</span>', 'Pending <span class="count">(%s)</span>', 'wporg-plugins' ),
+ ) );
+ register_post_status( 'disabled', array(
+ 'label' => _x( 'Disabled', 'plugin status', 'wporg-plugins' ),
+ 'public' => false,
+ 'show_in_admin_status_list' => true,
+ 'label_count' => _n_noop( 'Disabled <span class="count">(%s)</span>', 'Disabled <span class="count">(%s)</span>', 'wporg-plugins' ),
+ ) );
+ register_post_status( 'closed', array(
+ 'label' => _x( 'Closed', 'plugin status', 'wporg-plugins' ),
+ 'public' => false,
+ 'show_in_admin_status_list' => true,
+ 'label_count' => _n_noop( 'Closed <span class="count">(%s)</span>', 'Closed <span class="count">(%s)</span>', 'wporg-plugins' ),
+ ) );
+
+ // Add the browse/* views
+ add_rewrite_tag( '%browse%', '(featured|popular|beta|new|favorites)' );
+ add_permastruct( 'browse', 'browse/%browse%' );
+
+ add_rewrite_endpoint( 'installation', EP_PERMALINK );
+ add_rewrite_endpoint( 'faq', EP_PERMALINK );
+ add_rewrite_endpoint( 'screenshots', EP_PERMALINK );
+ add_rewrite_endpoint( 'changelog', EP_PERMALINK );
+ add_rewrite_endpoint( 'stats', EP_PERMALINK );
+ add_rewrite_endpoint( 'developers', EP_PERMALINK );
+ add_rewrite_endpoint( 'other_notes', EP_PERMALINK );
+ }
+
+ /**
+ * Filter the permalink for the Packages to be /post_name/
+ *
+ * @param string $link The generated permalink
+ * @param string $post The package object
+ * @return string
+ */
+ function package_link( $link, $post ) {
+ if ( 'plugin' != $post->post_type ) {
+ return $link;
+ }
+
+ return trailingslashit( home_url( $post->post_name ) );
+ }
+
+ /**
+ * Checks if ther current users is a super admin before allowing terms to be added.
+ *
+ * @param string $term The term to add or update.
+ * @return string|WP_Error The term to add or update or WP_Error on failure.
+ */
+ function pre_insert_term_prevent( $term ) {
+ if ( ! is_super_admin() ) {
+ $term = new WP_Error( 'not-allowed', __( 'You are not allowed to add terms.', 'wporg-plugins' ) );
+ }
+
+ return $term;
+ }
+
+ function use_plugins_in_query( $wp_query ) {
+ if ( ! $wp_query->is_main_query() ) {
+ return;
+ }
+
+ if ( empty( $wp_query->query_vars['pagename'] ) &&
+ ( empty( $wp_query->query_vars['post_type'] ) || 'posts' == $wp_query->query_vars['post_type'] ) ) {
+ $wp_query->query_vars['post_type'] = array( 'plugin' );
+ }
+
+ if ( empty( $wp_query->query ) ) {
+ $wp_query->query_vars['browse'] = 'featured';
+ }
+
+ switch ( get_query_var( 'browse' ) ) {
+ case 'beta':
+ $wp_query->query_vars['category_name'] = 'beta';
+ break;
+
+ case 'featured':
+ $wp_query->query_vars['category_name'] = 'featured';
+ break;
+
+ case 'favorites':
+ break;
+
+ case 'popular':
+ break;
+ }
+
+ // Re-route the Endpoints to the `content_page` query var.
+ if ( !empty( $wp_query->query['name'] ) ) {
+ foreach ( array( 'installation', 'faq', 'screenshots', 'changelog', 'stats', 'developers', 'other_notes' ) as $plugin_field ) {
+ if ( isset( $wp_query->query[ $plugin_field ] ) ) {
+ $wp_query->query['content_page'] = $wp_query->query_vars['content_page'] = $plugin_field;
+ unset( $wp_query->query[ $plugin_field ], $wp_query->query_vars[ $plugin_field ] );
+ }
+ }
+ }
+ }
+
+ function filter_post_content_to_correct_page( $content ) {
+ global $content_pages;
+
+ $post = get_post();
+ if ( 'plugin' != $post->post_type ) {
+ return $content;
+ }
+
+ $page = get_query_var( 'content_page' );
+ $content_pages = $this->split_post_content_into_pages( $content );
+
+ if ( ! isset( $content_pages[ $page ] ) ) {
+ $page = 'description';
+ }
+
+ return $content_pages[ $page ];
+ }
+
+ function split_post_content_into_pages( $content ) {
+ $content_pages = array(
+ 'stats' => '[wporg-plugins-stats]',
+ 'developers' => '[wporg-plugins-developer]',
+ );
+ $_pages = preg_split( "#<!--section=(.+?)-->#", $content, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY );
+ for ( $i = 0; $i < count( $_pages ); $i += 2 ) {
+ // Don't overwrite existing tabs.
+ if ( ! isset( $content_pages[ $_pages[ $i ] ] ) ) {
+ $content_pages[ $_pages[ $i ] ] = $_pages[ $i + 1 ];
+ }
+ }
+
+ return $content_pages;
+ }
+
+}
+new Plugin_Directory();
+
+// Various functions used by other processes, will make sense to move to specific classses.
+class Plugin_Directory_Tools {
+ static function get_readme_data( $readme ) {
+ // Uses https://github.com/rmccue/WordPress-Readme-Parser (with modifications)
+ include_once __DIR__ . '/readme-parser/markdown.php';
+ include_once __DIR__ . '/readme-parser/compat.php';
+
+ $data = (object) _WordPress_org_Readme::parse_readme( $readme );
+
+ unset( $data->sections['screenshots'] ); // Useless
+
+ // sanitize contributors.
+ foreach ( $data->contributors as $i => $name ) {
+ if ( get_user_by( 'login', $name ) ) {
+ continue;
+ } elseif ( false !== ( $user = get_user_by( 'slug', $name ) ) ) {
+ $data->contributors[] = $user->user_login;
+ unset( $data->contributors[ $i ] );
+ } else {
+ unset( $data->contributors[ $i ] );
+ }
+ }
+
+ return $data;
+ }
+}
+
+// Various helpers to retrieve data not stored within WordPress
+class Plugin_Directory_Template_Helpers {
+ static function get_active_installs_count( $plugin_slug ) {
+ global $wpdb;
+
+ $count = wp_cache_get( $plugin_slug, 'plugin_active_installs' );
+ if ( false === $count ) {
+ $count = (int) $wpdb->get_var( $wpdb->prepare(
+ "SELECT count FROM rev2_daily_stat_summary WHERE type = 'plugin' AND type_name = %s AND stat = 'active_installs' LIMIT 1",
+ $plugin_slug
+ ) );
+ wp_cache_add( $plugin_slug, $count, 'plugin_active_installs', 1200 );
+ }
+
+ if ( $count < 10 ) {
+ return 0;
+ }
+
+ if ( $count >= 1000000 ) {
+ return 1000000;
+ }
+
+ return strval( $count )[0] * pow( 10, floor( log10( $count ) ) );
+ }
+
+ static function get_total_downloads() {
+ global $wpdb;
+
+ $count = wp_cache_get( 'plugin_download_count', 'plugin_download_count' );
+ if ( false === $count ) {
+ $count = (int) $wpdb->get_var( "SELECT SUM(downloads) FROM `plugin_2_stats`" );
+ wp_cache_add( 'plugin_download_count', $count, 'plugin_download_count', DAY_IN_SECONDS );
+ }
+
+ return $count;
+ }
+
+ static function get_plugin_sections() {
+ $plugin_slug = get_post()->post_name;
+ $raw_sections = get_post_meta( get_the_ID(), 'sections', true );
+ $raw_sections = array_unique( array_merge( $raw_sections, array( 'description', 'stats', 'support', 'reviews', 'developers' ) ) );
+
+ $sections = array();
+ foreach ( $raw_sections as $section_slug ) {
+ $url = get_permalink();
+ switch ( $section_slug ) {
+ case 'description':
+ $title = _x( 'Description', 'plugin tab title', 'wporg-plugins' );
+ break;
+ case 'installation':
+ $title = _x( 'Installation', 'plugin tab title', 'wporg-plugins' );
+ $url = trailingslashit( $url ) . '/' . $section_slug . '/';
+ break;
+ case 'faq':
+ $title = _x( 'FAQ', 'plugin tab title', 'wporg-plugins' );
+ $url = trailingslashit( $url ) . '/' . $section_slug . '/';
+ break;
+ case 'screenshots':
+ $title = _x( 'Screenshots', 'plugin tab title', 'wporg-plugins' );
+ $url = trailingslashit( $url ) . '/' . $section_slug . '/';
+ break;
+ case 'changelog':
+ $title = _x( 'Changelog', 'plugin tab title', 'wporg-plugins' );
+ $url = trailingslashit( $url ) . '/' . $section_slug . '/';
+ break;
+ case 'stats':
+ $title = _x( 'Stats', 'plugin tab title', 'wporg-plugins' );
+ $url = trailingslashit( $url ) . '/' . $section_slug . '/';
+ break;
+ case 'support':
+ $title = _x( 'Support', 'plugin tab title', 'wporg-plugins' );
+ $url = 'https://wordpress.org/support/plugin/' . $plugin_slug;
+ break;
+ case 'reviews':
+ $title = _x( 'Reviews', 'plugin tab title', 'wporg-plugins' );
+ $url = 'https://wordpress.org/support/view/plugin-reviews/' . $plugin_slug;
+ break;
+ case 'developers':
+ $title = _x( 'Developers', 'plugin tab title', 'wporg-plugins' );
+ $url = trailingslashit( $url ) . '/' . $section_slug . '/';
+ break;
+ }
+ $sections[] = array(
+ 'slug' => $section_slug,
+ 'url' => $url,
+ 'title' => $title,
+ );
+ }
+ return $sections;
+ }
+}
+
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/plugin-directory.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="sitestrunkwordpressorgpublic_htmlwpcontentpluginsplugindirectoryreadmeparserReadmeParserphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/readme-parser/ReadmeParser.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/readme-parser/ReadmeParser.php (rev 0)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/readme-parser/ReadmeParser.php 2016-02-13 03:38:51 UTC (rev 2499)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,329 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * Custom readme parser
+ *
+ * Based on Automattic_Readme from http://code.google.com/p/wordpress-plugin-readme-parser/
+ *
+ * Relies on Markdown_Extra
+ *
+ * @todo Handle screenshots section properly
+ * @todo Create validator for this based on http://code.google.com/p/wordpress-plugin-readme-parser/source/browse/trunk/validator.php
+ */
+class Baikonur_ReadmeParser {
+
+ public static function parse_readme($file) {
+ $contents = file($file);
+ return self::parse_readme_contents($contents);
+ }
+
+ public static function parse_readme_contents($contents) {
+ if (is_string($contents)) {
+ $contents = explode("\n", $contents);
+ }
+
+ $this_class = __CLASS__;
+ if (function_exists('get_called_class')) {
+ $this_class = get_called_class();
+ }
+
+ $contents = array_map(array($this_class, 'strip_newlines'), $contents);
+
+ // Strip BOM
+ if (strpos($contents[0], "\xEF\xBB\xBF") === 0) {
+ $contents[0] = substr($contents[0], 3);
+ }
+
+ $data = new stdClass;
+
+ // Defaults
+ $data->is_excerpt = false;
+ $data->is_truncated = false;
+ $data->tags = array();
+ $data->requires = '';
+ $data->tested = '';
+ $data->contributors = array();
+ $data->stable_tag = '';
+ $data->version = '';
+ $data->donate_link = '';
+ $data->short_description = '';
+ $data->sections = array();
+ $data->changelog = array();
+ $data->upgrade_notice = array();
+ $data->screenshots = array();
+ $data->remaining_content = array();
+
+ $line = call_user_func_array(array($this_class, 'get_first_nonwhitespace'), array(&$contents));
+ $data->name = $line;
+ $data->name = trim($data->name, "#= ");
+
+ // Parse headers
+ $headers = array();
+
+ $line = call_user_func_array(array($this_class, 'get_first_nonwhitespace'), array(&$contents));
+ do {
+ $key = $value = null;
+ if (strpos($line, ':') === false) {
+ break;
+ }
+ $bits = explode(':', $line, 2);
+ list($key, $value) = $bits;
+ $key = strtolower(str_replace(array(' ', "\t"), '_', trim($key)));
+ if ($key === 'tags' && isset($headers['tags'])) {
+ $headers[$key] .= ',' . trim($value);
+ }
+ else {
+ $headers[$key] = trim($value);
+ }
+ }
+ while (($line = array_shift($contents)) !== null && ($line = trim($line)) && !empty($line));
+ array_unshift($contents, $line);
+
+ if (!empty($headers['tags'])) {
+ $data->tags = explode(',', $headers['tags']);
+ $data->tags = array_map('trim', $data->tags);
+ }
+ if (!empty($headers['requires'])) {
+ $data->requires = $headers['requires'];
+ }
+ if (!empty($headers['requires_at_least'])) {
+ $data->requires = $headers['requires_at_least'];
+ }
+ if (!empty($headers['tested'])) {
+ $data->tested = $headers['tested'];
+ }
+ if (!empty($headers['tested_up_to'])) {
+ $data->tested = $headers['tested_up_to'];
+ }
+ if (!empty($headers['contributors'])) {
+ $data->contributors = explode(',', $headers['contributors']);
+ $data->contributors = array_map('trim', $data->contributors);
+ }
+ if (!empty($headers['stable_tag'])) {
+ $data->stable_tag = $headers['stable_tag'];
+ }
+ if (!empty($headers['donate_link'])) {
+ $data->donate_link = $headers['donate_link'];
+ }
+ if (!empty($headers['version'])) {
+ $data->version = $headers['version'];
+ }
+ else {
+ $data->version = $data->stable_tag;
+ }
+
+ // Parse the short description
+ while (($line = array_shift($contents)) !== null) {
+ $trimmed = trim($line);
+ if (empty($trimmed)) {
+ $data->short_description .= "\n";
+ continue;
+ }
+ if ($trimmed[0] === '=' && isset($trimmed[1]) && $trimmed[1] === '=') {
+ array_unshift($contents, $line);
+ break;
+ }
+
+ $data->short_description .= $line . "\n";
+ }
+ $data->short_description = trim($data->short_description);
+
+ $data->is_truncated = call_user_func_array(array($this_class, 'trim_short_desc'), array(&$data->short_description));
+
+ // Parse the rest of the body
+ $current = '';
+ $special = array('description', 'installation', 'faq', 'frequently_asked_questions', 'screenshots', 'changelog', 'upgrade_notice');
+
+ while (($line = array_shift($contents)) !== null) {
+ $trimmed = trim($line);
+ if (empty($trimmed)) {
+ $current .= "\n";
+ continue;
+ }
+
+ if ($trimmed[0] === '=' && isset($trimmed[1]) && $trimmed[1] === '=') {
+ if (!empty($title)) {
+ $data->sections[$title] = trim($current);
+ }
+
+ $current = '';
+ $real_title = trim($line, "#= \t");
+ $title = strtolower(str_replace(' ', '_', $real_title));
+ if ($title === 'faq') {
+ $title = 'frequently_asked_questions';
+ }
+ elseif ($title === 'change_log') {
+ $title = 'changelog';
+ }
+ if (!in_array($title, $special)) {
+ $current .= '<h3>' . $real_title . "</h3>";
+ }
+ continue;
+ }
+
+ $current .= $line . "\n";
+ }
+
+ if (!empty($title)) {
+ $data->sections[$title] = trim($current);
+ }
+ $title = null;
+ $current = null;
+
+ if (empty($data->sections['description'])) {
+ $data->sections['description'] = call_user_func(array($this_class, 'parse_markdown'), $data->short_description);
+ }
+
+ // Parse changelog
+ if (!empty($data->sections['changelog'])) {
+ $lines = explode("\n", $data->sections['changelog']);
+ while (($line = array_shift($lines)) !== null) {
+ $trimmed = trim($line);
+ if (empty($trimmed)) {
+ continue;
+ }
+
+ if ($trimmed[0] === '=') {
+ if (!empty($current)) {
+ $data->changelog[$title] = trim($current);
+ }
+
+ $current = '';
+ $title = trim($line, "#= \t");
+ continue;
+ }
+
+ $current .= $line . "\n";
+ }
+
+ $data->changelog[$title] = trim($current);
+ }
+ $title = null;
+ $current = null;
+
+ if (isset($data->sections['upgrade_notice'])) {
+ $lines = explode("\n", $data->sections['upgrade_notice']);
+ while (($line = array_shift($lines)) !== null) {
+ $trimmed = trim($line);
+ if (empty($trimmed)) {
+ continue;
+ }
+
+ if ($trimmed[0] === '=') {
+ if (!empty($current)) {
+ $data->upgrade_notice[$title] = trim($current);
+ }
+
+ $current = '';
+ $title = trim($line, "#= \t");
+ continue;
+ }
+
+ $current .= $line . "\n";
+ }
+
+ if (!empty($title) && !empty($current)) {
+ $data->upgrade_notice[$title] = trim($current);
+ }
+ unset($data->sections['upgrade_notice']);
+ }
+
+ // Markdownify!
+
+ $data->sections = array_map(array($this_class, 'parse_markdown'), $data->sections);
+ $data->changelog = array_map(array($this_class, 'parse_markdown'), $data->changelog);
+ $data->upgrade_notice = array_map(array($this_class, 'parse_markdown'), $data->upgrade_notice);
+
+ if (isset($data->sections['screenshots'])) {
+ preg_match_all('#<li>(.*?)</li>#is', $data->sections['screenshots'], $screenshots, PREG_SET_ORDER);
+ if ($screenshots) {
+ foreach ((array) $screenshots as $ss) {
+ $data->screenshots[] = trim($ss[1]);
+ }
+ }
+ }
+
+ // Rearrange stuff
+
+ $data->remaining_content = $data->sections;
+ $data->sections = array();
+
+ foreach ($special as $spec) {
+ if (isset($data->remaining_content[$spec])) {
+ $data->sections[$spec] = $data->remaining_content[$spec];
+ unset($data->remaining_content[$spec]);
+ }
+ }
+
+ return $data;
+ }
+
+ protected static function get_first_nonwhitespace(&$contents) {
+ while (($line = array_shift($contents)) !== null) {
+ $trimmed = trim($line);
+ if (!empty($line)) {
+ break;
+ }
+ }
+
+ return $line;
+ }
+
+ protected static function strip_newlines($line) {
+ return rtrim($line, "\r\n");
+ }
+
+ protected static function trim_short_desc(&$desc) {
+ if (function_exists('mb_strlen') && function_exists('mb_substr')) {
+ if (mb_strlen($desc) > 150) {
+ $desc = mb_substr($desc, 0, 150);
+ $desc = trim($desc);
+ return true;
+ }
+ }
+ else {
+ if (strlen($desc) > 150) {
+ $desc = substr($desc, 0, 150);
+ $desc = trim($desc);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ protected static function parse_markdown($text) {
+ $text = self::code_trick($text);
+ $text = preg_replace('/^[\s]*=[\s]+(.+?)[\s]+=/m', "\n" . '<h4>$1</h4>' . "\n", $text);
+ $text = Markdown(trim($text));
+ return trim($text);
+ }
+
+ protected static function code_trick($text) {
+ // If doing markdown, first take any user formatted code blocks and turn them into backticks so that
+ // markdown will preserve things like underscores in code blocks
+ $text = preg_replace_callback("!(<pre><code>|<code>)(.*?)(</code></pre>|</code>)!s", array(__CLASS__, 'decodeit'), $text);
+
+ $text = str_replace(array("\r\n", "\r"), "\n", $text);
+ // Markdown can do inline code, we convert bbPress style block level code to Markdown style
+ $text = preg_replace_callback("!(^|\n)([ \t]*?)`(.*?)`!s", array(__CLASS__, 'indent'), $text);
+ return $text;
+ }
+
+ protected static function indent($matches) {
+ $text = $matches[3];
+ $text = preg_replace('|^|m', $matches[2] . ' ', $text);
+ return $matches[1] . $text;
+ }
+
+ protected static function decodeit($matches) {
+ $text = $matches[2];
+ $trans_table = array_flip(get_html_translation_table(HTML_ENTITIES));
+ $text = strtr($text, $trans_table);
+ $text = str_replace('<br />', '', $text);
+ $text = str_replace('&', '&', $text);
+ $text = str_replace(''', "'", $text);
+ if ( '<pre><code>' == $matches[1] )
+ $text = "\n$text\n";
+ return "`$text`";
+ }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/readme-parser/ReadmeParser.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="sitestrunkwordpressorgpublic_htmlwpcontentpluginsplugindirectoryreadmeparsercompatphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/readme-parser/compat.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/readme-parser/compat.php (rev 0)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/readme-parser/compat.php 2016-02-13 03:38:51 UTC (rev 2499)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,95 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+
+if ( !defined('WORDPRESS_README_MARKDOWN') ) {
+ define('WORDPRESS_README_MARKDOWN', dirname(__FILE__) . '/markdown.php');
+}
+
+require_once(dirname(__FILE__) . '/ReadmeParser.php');
+
+class _WordPress_org_Readme extends Baikonur_ReadmeParser {
+ public static function parse_readme($file) {
+ $contents = file($file);
+ return self::parse_readme_contents($contents);
+ }
+
+ public static function parse_readme_contents($contents) {
+ if (empty($contents)) {
+ return array();
+ }
+
+ $result = parent::parse_readme_contents($contents);
+ foreach ($result->sections as &$section) {
+ $section = self::filter_text($section);
+ }
+ if (!empty($result->upgrade_notice)) {
+ foreach ($result->upgrade_notice as &$notice) {
+ $notice = self::sanitize_text($notice);
+ }
+ }
+ if (!empty($result->screenshots)) {
+ foreach ($result->screenshots as &$shot) {
+ $shot = self::filter_text($shot);
+ }
+ }
+
+ if (!empty($result->remaining_content)) {
+ $result->remaining_content = implode("\n", $result->remaining_content);
+ $result->remaining_content = self::filter_text(str_replace("</h3>\n\n", "</h3>\n", $result->remaining_content));
+ }
+ else {
+ $result->remaining_content = '';
+ }
+
+ $result->name = self::sanitize_text($result->name);
+ //$result->short_description = self::sanitize_text($result->short_description);
+ $result->donate_link = esc_url($result->donate_link);
+
+ $result->requires_at_least = $result->requires;
+ $result->tested_up_to = $result->tested;
+ unset($result->requires, $result->tested);
+ $result = ((array) $result);
+ return $result;
+ }
+
+ protected static function trim_short_desc(&$desc) {
+ $desc = self::sanitize_text($desc);
+ return parent::trim_short_desc($desc);
+ }
+
+ protected static function sanitize_text( $text ) { // not fancy
+ $text = strip_tags($text);
+ $text = esc_html($text);
+ $text = trim($text);
+ return $text;
+ }
+
+ protected static function filter_text( $text ) {
+ $text = trim($text);
+ //$text = self::code_trick($text); // A better parser than Markdown's for: backticks -> CODE
+
+ $allowed = array(
+ 'a' => array(
+ 'href' => array(),
+ 'title' => array(),
+ 'rel' => array()),
+ 'blockquote' => array('cite' => array()),
+ 'br' => array(),
+ 'p' => array(),
+ 'code' => array(),
+ 'pre' => array(),
+ 'em' => array(),
+ 'strong' => array(),
+ 'ul' => array(),
+ 'ol' => array(),
+ 'li' => array(),
+ 'h3' => array(),
+ 'h4' => array()
+ );
+
+ $text = balanceTags($text);
+
+ $text = wp_kses( $text, $allowed );
+ $text = trim($text);
+ return $text;
+ }
+}
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span><span class="cx" style="display: block; padding: 0 10px">Property changes on: sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/readme-parser/compat.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="sitestrunkwordpressorgpublic_htmlwpcontentpluginsplugindirectoryreadmeparsermarkdownphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/readme-parser/markdown.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/readme-parser/markdown.php (rev 0)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/readme-parser/markdown.php 2016-02-13 03:38:51 UTC (rev 2499)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,2932 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+#
+# Markdown Extra - A text-to-HTML conversion tool for web writers
+#
+# PHP Markdown & Extra
+# Copyright (c) 2004-2009 Michel Fortin
+# <http://michelf.com/projects/php-markdown/>
+#
+# Original Markdown
+# Copyright (c) 2004-2006 John Gruber
+# <http://daringfireball.net/projects/markdown/>
+#
+
+
+define( 'MARKDOWN_VERSION', "1.0.1n" ); # Sat 10 Oct 2009
+define( 'MARKDOWNEXTRA_VERSION', "1.2.4" ); # Sat 10 Oct 2009
+
+
+#
+# Global default settings:
+#
+
+# Change to ">" for HTML output
+@define( 'MARKDOWN_EMPTY_ELEMENT_SUFFIX', " />");
+
+# Define the width of a tab for code blocks.
+@define( 'MARKDOWN_TAB_WIDTH', 4 );
+
+# Optional title attribute for footnote links and backlinks.
+@define( 'MARKDOWN_FN_LINK_TITLE', "" );
+@define( 'MARKDOWN_FN_BACKLINK_TITLE', "" );
+
+# Optional class attribute for footnote links and backlinks.
+@define( 'MARKDOWN_FN_LINK_CLASS', "" );
+@define( 'MARKDOWN_FN_BACKLINK_CLASS', "" );
+
+
+#
+# WordPress settings:
+#
+
+# Change to false to remove Markdown from posts and/or comments.
+@define( 'MARKDOWN_WP_POSTS', true );
+@define( 'MARKDOWN_WP_COMMENTS', true );
+
+
+
+### Standard Function Interface ###
+
+@define( 'MARKDOWN_PARSER_CLASS', 'MarkdownExtra_Parser' );
+
+function Markdown($text) {
+#
+# Initialize the parser and return the result of its transform method.
+#
+ # Setup static parser variable.
+ static $parser;
+ if (!isset($parser)) {
+ $parser_class = MARKDOWN_PARSER_CLASS;
+ $parser = new $parser_class;
+ }
+
+ # Transform text using parser.
+ return $parser->transform($text);
+}
+
+
+### WordPress Plugin Interface ###
+
+/*
+Plugin Name: Markdown Extra
+Plugin URI: http://michelf.com/projects/php-markdown/
+Description: <a href="http://daringfireball.net/projects/markdown/syntax">Markdown syntax</a> allows you to write using an easy-to-read, easy-to-write plain text format. Based on the original Perl version by <a href="http://daringfireball.net/">John Gruber</a>. <a href="http://michelf.com/projects/php-markdown/">More...</a>
+Version: 1.2.4
+Author: Michel Fortin
+Author URI: http://michelf.com/
+*/
+
+if (isset($wp_version)) {
+ # More details about how it works here:
+ # <http://michelf.com/weblog/2005/wordpress-text-flow-vs-markdown/>
+
+ # Post content and excerpts
+ # - Remove WordPress paragraph generator.
+ # - Run Markdown on excerpt, then remove all tags.
+ # - Add paragraph tag around the excerpt, but remove it for the excerpt rss.
+ if (MARKDOWN_WP_POSTS) {
+ remove_filter('the_content', 'wpautop');
+ remove_filter('the_content_rss', 'wpautop');
+ remove_filter('the_excerpt', 'wpautop');
+ add_filter('the_content', 'mdwp_MarkdownPost', 6);
+ add_filter('the_content_rss', 'mdwp_MarkdownPost', 6);
+ add_filter('get_the_excerpt', 'mdwp_MarkdownPost', 6);
+ add_filter('get_the_excerpt', 'trim', 7);
+ add_filter('the_excerpt', 'mdwp_add_p');
+ add_filter('the_excerpt_rss', 'mdwp_strip_p');
+
+ remove_filter('content_save_pre', 'balanceTags', 50);
+ remove_filter('excerpt_save_pre', 'balanceTags', 50);
+ add_filter('the_content', 'balanceTags', 50);
+ add_filter('get_the_excerpt', 'balanceTags', 9);
+ }
+
+ # Add a footnote id prefix to posts when inside a loop.
+ function mdwp_MarkdownPost($text) {
+ static $parser;
+ if (!$parser) {
+ $parser_class = MARKDOWN_PARSER_CLASS;
+ $parser = new $parser_class;
+ }
+ if (is_single() || is_page() || is_feed()) {
+ $parser->fn_id_prefix = "";
+ } else {
+ $parser->fn_id_prefix = get_the_ID() . ".";
+ }
+ return $parser->transform($text);
+ }
+
+ # Comments
+ # - Remove WordPress paragraph generator.
+ # - Remove WordPress auto-link generator.
+ # - Scramble important tags before passing them to the kses filter.
+ # - Run Markdown on excerpt then remove paragraph tags.
+ if (MARKDOWN_WP_COMMENTS) {
+ remove_filter('comment_text', 'wpautop', 30);
+ remove_filter('comment_text', 'make_clickable');
+ add_filter('pre_comment_content', 'Markdown', 6);
+ add_filter('pre_comment_content', 'mdwp_hide_tags', 8);
+ add_filter('pre_comment_content', 'mdwp_show_tags', 12);
+ add_filter('get_comment_text', 'Markdown', 6);
+ add_filter('get_comment_excerpt', 'Markdown', 6);
+ add_filter('get_comment_excerpt', 'mdwp_strip_p', 7);
+
+ global $mdwp_hidden_tags, $mdwp_placeholders;
+ $mdwp_hidden_tags = explode(' ',
+ '<p> </p> <pre> </pre> <ol> </ol> <ul> </ul> <li> </li>');
+ $mdwp_placeholders = explode(' ', str_rot13(
+ 'pEj07ZbbBZ U1kqgh4w4p pre2zmeN6K QTi31t9pre ol0MP1jzJR '.
+ 'ML5IjmbRol ulANi1NsGY J7zRLJqPul liA8ctl16T K9nhooUHli'));
+ }
+
+ function mdwp_add_p($text) {
+ if (!preg_match('{^$|^<(p|ul|ol|dl|pre|blockquote)>}i', $text)) {
+ $text = '<p>'.$text.'</p>';
+ $text = preg_replace('{\n{2,}}', "</p>\n\n<p>", $text);
+ }
+ return $text;
+ }
+
+ function mdwp_strip_p($t) { return preg_replace('{</?p>}i', '', $t); }
+
+ function mdwp_hide_tags($text) {
+ global $mdwp_hidden_tags, $mdwp_placeholders;
+ return str_replace($mdwp_hidden_tags, $mdwp_placeholders, $text);
+ }
+ function mdwp_show_tags($text) {
+ global $mdwp_hidden_tags, $mdwp_placeholders;
+ return str_replace($mdwp_placeholders, $mdwp_hidden_tags, $text);
+ }
+}
+
+
+### bBlog Plugin Info ###
+
+function identify_modifier_markdown() {
+ return array(
+ 'name' => 'markdown',
+ 'type' => 'modifier',
+ 'nicename' => 'PHP Markdown Extra',
+ 'description' => 'A text-to-HTML conversion tool for web writers',
+ 'authors' => 'Michel Fortin and John Gruber',
+ 'licence' => 'GPL',
+ 'version' => MARKDOWNEXTRA_VERSION,
+ 'help' => '<a href="http://daringfireball.net/projects/markdown/syntax">Markdown syntax</a> allows you to write using an easy-to-read, easy-to-write plain text format. Based on the original Perl version by <a href="http://daringfireball.net/">John Gruber</a>. <a href="http://michelf.com/projects/php-markdown/">More...</a>',
+ );
+}
+
+
+### Smarty Modifier Interface ###
+
+function smarty_modifier_markdown($text) {
+ return Markdown($text);
+}
+
+
+### Textile Compatibility Mode ###
+
+# Rename this file to "classTextile.php" and it can replace Textile everywhere.
+
+if (strcasecmp(substr(__FILE__, -16), "classTextile.php") == 0) {
+ # Try to include PHP SmartyPants. Should be in the same directory.
+ @include_once 'smartypants.php';
+ # Fake Textile class. It calls Markdown instead.
+ class Textile {
+ function TextileThis($text, $lite='', $encode='') {
+ if ($lite == '' && $encode == '') $text = Markdown($text);
+ if (function_exists('SmartyPants')) $text = SmartyPants($text);
+ return $text;
+ }
+ # Fake restricted version: restrictions are not supported for now.
+ function TextileRestricted($text, $lite='', $noimage='') {
+ return $this->TextileThis($text, $lite);
+ }
+ # Workaround to ensure compatibility with TextPattern 4.0.3.
+ function blockLite($text) { return $text; }
+ }
+}
+
+
+
+#
+# Markdown Parser Class
+#
+
+class Markdown_Parser {
+
+ # Regex to match balanced [brackets].
+ # Needed to insert a maximum bracked depth while converting to PHP.
+ var $nested_brackets_depth = 6;
+ var $nested_brackets_re;
+
+ var $nested_url_parenthesis_depth = 4;
+ var $nested_url_parenthesis_re;
+
+ # Table of hash values for escaped characters:
+ var $escape_chars = '\`*_{}[]()>#+-.!';
+ var $escape_chars_re;
+
+ # Change to ">" for HTML output.
+ var $empty_element_suffix = MARKDOWN_EMPTY_ELEMENT_SUFFIX;
+ var $tab_width = MARKDOWN_TAB_WIDTH;
+
+ # Change to `true` to disallow markup or entities.
+ var $no_markup = false;
+ var $no_entities = false;
+
+ # Predefined urls and titles for reference links and images.
+ var $predef_urls = array();
+ var $predef_titles = array();
+
+
+ function Markdown_Parser() {
+ #
+ # Constructor function. Initialize appropriate member variables.
+ #
+ $this->_initDetab();
+ $this->prepareItalicsAndBold();
+
+ $this->nested_brackets_re =
+ str_repeat('(?>[^\[\]]+|\[', $this->nested_brackets_depth).
+ str_repeat('\])*', $this->nested_brackets_depth);
+
+ $this->nested_url_parenthesis_re =
+ str_repeat('(?>[^()\s]+|\(', $this->nested_url_parenthesis_depth).
+ str_repeat('(?>\)))*', $this->nested_url_parenthesis_depth);
+
+ $this->escape_chars_re = '['.preg_quote($this->escape_chars).']';
+
+ # Sort document, block, and span gamut in ascendent priority order.
+ asort($this->document_gamut);
+ asort($this->block_gamut);
+ asort($this->span_gamut);
+ }
+
+
+ # Internal hashes used during transformation.
+ var $urls = array();
+ var $titles = array();
+ var $html_hashes = array();
+
+ # Status flag to avoid invalid nesting.
+ var $in_anchor = false;
+
+
+ function setup() {
+ #
+ # Called before the transformation process starts to setup parser
+ # states.
+ #
+ # Clear global hashes.
+ $this->urls = $this->predef_urls;
+ $this->titles = $this->predef_titles;
+ $this->html_hashes = array();
+
+ $in_anchor = false;
+ }
+
+ function teardown() {
+ #
+ # Called after the transformation process to clear any variable
+ # which may be taking up memory unnecessarly.
+ #
+ $this->urls = array();
+ $this->titles = array();
+ $this->html_hashes = array();
+ }
+
+
+ function transform($text) {
+ #
+ # Main function. Performs some preprocessing on the input text
+ # and pass it through the document gamut.
+ #
+ $this->setup();
+
+ # Remove UTF-8 BOM and marker character in input, if present.
+ $text = preg_replace('{^\xEF\xBB\xBF|\x1A}', '', $text);
+
+ # Standardize line endings:
+ # DOS to Unix and Mac to Unix
+ $text = preg_replace('{\r\n?}', "\n", $text);
+
+ # Make sure $text ends with a couple of newlines:
+ $text .= "\n\n";
+
+ # Convert all tabs to spaces.
+ $text = $this->detab($text);
+
+ # Turn block-level HTML blocks into hash entries
+ $text = $this->hashHTMLBlocks($text);
+
+ # Strip any lines consisting only of spaces and tabs.
+ # This makes subsequent regexen easier to write, because we can
+ # match consecutive blank lines with /\n+/ instead of something
+ # contorted like /[ ]*\n+/ .
+ $text = preg_replace('/^[ ]+$/m', '', $text);
+
+ # Run document gamut methods.
+ foreach ($this->document_gamut as $method => $priority) {
+ $text = $this->$method($text);
+ }
+
+ $this->teardown();
+
+ return $text . "\n";
+ }
+
+ var $document_gamut = array(
+ # Strip link definitions, store in hashes.
+ "stripLinkDefinitions" => 20,
+
+ "runBasicBlockGamut" => 30,
+ );
+
+
+ function stripLinkDefinitions($text) {
+ #
+ # Strips link definitions from text, stores the URLs and titles in
+ # hash references.
+ #
+ $less_than_tab = $this->tab_width - 1;
+
+ # Link defs are in the form: ^[id]: url "optional title"
+ $text = preg_replace_callback('{
+ ^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?: # id = $1
+ [ ]*
+ \n? # maybe *one* newline
+ [ ]*
+ (?:
+ <(.+?)> # url = $2
+ |
+ (\S+?) # url = $3
+ )
+ [ ]*
+ \n? # maybe one newline
+ [ ]*
+ (?:
+ (?<=\s) # lookbehind for whitespace
+ ["(]
+ (.*?) # title = $4
+ [")]
+ [ ]*
+ )? # title is optional
+ (?:\n+|\Z)
+ }xm',
+ array(&$this, '_stripLinkDefinitions_callback'),
+ $text);
+ return $text;
+ }
+ function _stripLinkDefinitions_callback($matches) {
+ $link_id = strtolower($matches[1]);
+ $url = $matches[2] == '' ? $matches[3] : $matches[2];
+ $this->urls[$link_id] = $url;
+ $this->titles[$link_id] =& $matches[4];
+ return ''; # String that will replace the block
+ }
+
+
+ function hashHTMLBlocks($text) {
+ if ($this->no_markup) return $text;
+
+ $less_than_tab = $this->tab_width - 1;
+
+ # Hashify HTML blocks:
+ # We only want to do this for block-level HTML tags, such as headers,
+ # lists, and tables. That's because we still want to wrap <p>s around
+ # "paragraphs" that are wrapped in non-block-level tags, such as anchors,
+ # phrase emphasis, and spans. The list of tags we're looking for is
+ # hard-coded:
+ #
+ # * List "a" is made of tags which can be both inline or block-level.
+ # These will be treated block-level when the start tag is alone on
+ # its line, otherwise they're not matched here and will be taken as
+ # inline later.
+ # * List "b" is made of tags which are always block-level;
+ #
+ $block_tags_a_re = 'ins|del';
+ $block_tags_b_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|'.
+ 'script|noscript|form|fieldset|iframe|math';
+
+ # Regular expression for the content of a block tag.
+ $nested_tags_level = 4;
+ $attr = '
+ (?> # optional tag attributes
+ \s # starts with whitespace
+ (?>
+ [^>"/]+ # text outside quotes
+ |
+ /+(?!>) # slash not followed by ">"
+ |
+ "[^"]*" # text inside double quotes (tolerate ">")
+ |
+ \'[^\']*\' # text inside single quotes (tolerate ">")
+ )*
+ )?
+ ';
+ $content =
+ str_repeat('
+ (?>
+ [^<]+ # content without tag
+ |
+ <\2 # nested opening tag
+ '.$attr.' # attributes
+ (?>
+ />
+ |
+ >', $nested_tags_level). # end of opening tag
+ '.*?'. # last level nested tag content
+ str_repeat('
+ </\2\s*> # closing nested tag
+ )
+ |
+ <(?!/\2\s*> # other tags with a different name
+ )
+ )*',
+ $nested_tags_level);
+ $content2 = str_replace('\2', '\3', $content);
+
+ # First, look for nested blocks, e.g.:
+ # <div>
+ # <div>
+ # tags for inner block must be indented.
+ # </div>
+ # </div>
+ #
+ # The outermost tags must start at the left margin for this to match, and
+ # the inner nested divs must be indented.
+ # We need to do this before the next, more liberal match, because the next
+ # match will start at the first `<div>` and stop at the first `</div>`.
+ $text = preg_replace_callback('{(?>
+ (?>
+ (?<=\n\n) # Starting after a blank line
+ | # or
+ \A\n? # the beginning of the doc
+ )
+ ( # save in $1
+
+ # Match from `\n<tag>` to `</tag>\n`, handling nested tags
+ # in between.
+
+ [ ]{0,'.$less_than_tab.'}
+ <('.$block_tags_b_re.')# start tag = $2
+ '.$attr.'> # attributes followed by > and \n
+ '.$content.' # content, support nesting
+ </\2> # the matching end tag
+ [ ]* # trailing spaces/tabs
+ (?=\n+|\Z) # followed by a newline or end of document
+
+ | # Special version for tags of group a.
+
+ [ ]{0,'.$less_than_tab.'}
+ <('.$block_tags_a_re.')# start tag = $3
+ '.$attr.'>[ ]*\n # attributes followed by >
+ '.$content2.' # content, support nesting
+ </\3> # the matching end tag
+ [ ]* # trailing spaces/tabs
+ (?=\n+|\Z) # followed by a newline or end of document
+
+ | # Special case just for <hr />. It was easier to make a special
+ # case than to make the other regex more complicated.
+
+ [ ]{0,'.$less_than_tab.'}
+ <(hr) # start tag = $2
+ '.$attr.' # attributes
+ /?> # the matching end tag
+ [ ]*
+ (?=\n{2,}|\Z) # followed by a blank line or end of document
+
+ | # Special case for standalone HTML comments:
+
+ [ ]{0,'.$less_than_tab.'}
+ (?s:
+ <!-- .*? -->
+ )
+ [ ]*
+ (?=\n{2,}|\Z) # followed by a blank line or end of document
+
+ | # PHP and ASP-style processor instructions (<? and <%)
+
+ [ ]{0,'.$less_than_tab.'}
+ (?s:
+ <([?%]) # $2
+ .*?
+ \2>
+ )
+ [ ]*
+ (?=\n{2,}|\Z) # followed by a blank line or end of document
+
+ )
+ )}Sxmi',
+ array(&$this, '_hashHTMLBlocks_callback'),
+ $text);
+
+ return $text;
+ }
+ function _hashHTMLBlocks_callback($matches) {
+ $text = $matches[1];
+ $key = $this->hashBlock($text);
+ return "\n\n$key\n\n";
+ }
+
+
+ function hashPart($text, $boundary = 'X') {
+ #
+ # Called whenever a tag must be hashed when a function insert an atomic
+ # element in the text stream. Passing $text to through this function gives
+ # a unique text-token which will be reverted back when calling unhash.
+ #
+ # The $boundary argument specify what character should be used to surround
+ # the token. By convension, "B" is used for block elements that needs not
+ # to be wrapped into paragraph tags at the end, ":" is used for elements
+ # that are word separators and "X" is used in the general case.
+ #
+ # Swap back any tag hash found in $text so we do not have to `unhash`
+ # multiple times at the end.
+ $text = $this->unhash($text);
+
+ # Then hash the block.
+ static $i = 0;
+ $key = "$boundary\x1A" . ++$i . $boundary;
+ $this->html_hashes[$key] = $text;
+ return $key; # String that will replace the tag.
+ }
+
+
+ function hashBlock($text) {
+ #
+ # Shortcut function for hashPart with block-level boundaries.
+ #
+ return $this->hashPart($text, 'B');
+ }
+
+
+ var $block_gamut = array(
+ #
+ # These are all the transformations that form block-level
+ # tags like paragraphs, headers, and list items.
+ #
+ "doHeaders" => 10,
+ "doHorizontalRules" => 20,
+
+ "doLists" => 40,
+ "doCodeBlocks" => 50,
+ "doBlockQuotes" => 60,
+ );
+
+ function runBlockGamut($text) {
+ #
+ # Run block gamut tranformations.
+ #
+ # We need to escape raw HTML in Markdown source before doing anything
+ # else. This need to be done for each block, and not only at the
+ # begining in the Markdown function since hashed blocks can be part of
+ # list items and could have been indented. Indented blocks would have
+ # been seen as a code block in a previous pass of hashHTMLBlocks.
+ $text = $this->hashHTMLBlocks($text);
+
+ return $this->runBasicBlockGamut($text);
+ }
+
+ function runBasicBlockGamut($text) {
+ #
+ # Run block gamut tranformations, without hashing HTML blocks. This is
+ # useful when HTML blocks are known to be already hashed, like in the first
+ # whole-document pass.
+ #
+ foreach ($this->block_gamut as $method => $priority) {
+ $text = $this->$method($text);
+ }
+
+ # Finally form paragraph and restore hashed blocks.
+ $text = $this->formParagraphs($text);
+
+ return $text;
+ }
+
+
+ function doHorizontalRules($text) {
+ # Do Horizontal Rules:
+ return preg_replace(
+ '{
+ ^[ ]{0,3} # Leading space
+ ([-*_]) # $1: First marker
+ (?> # Repeated marker group
+ [ ]{0,2} # Zero, one, or two spaces.
+ \1 # Marker character
+ ){2,} # Group repeated at least twice
+ [ ]* # Tailing spaces
+ $ # End of line.
+ }mx',
+ "\n".$this->hashBlock("<hr$this->empty_element_suffix")."\n",
+ $text);
+ }
+
+
+ var $span_gamut = array(
+ #
+ # These are all the transformations that occur *within* block-level
+ # tags like paragraphs, headers, and list items.
+ #
+ # Process character escapes, code spans, and inline HTML
+ # in one shot.
+ "parseSpan" => -30,
+
+ # Process anchor and image tags. Images must come first,
+ # because ![foo][f] looks like an anchor.
+ "doImages" => 10,
+ "doAnchors" => 20,
+
+ # Make links out of things like `<http://example.com/>`
+ # Must come after doAnchors, because you can use < and >
+ # delimiters in inline links like [this](<url>).
+ "doAutoLinks" => 30,
+ "encodeAmpsAndAngles" => 40,
+
+ "doItalicsAndBold" => 50,
+ "doHardBreaks" => 60,
+ );
+
+ function runSpanGamut($text) {
+ #
+ # Run span gamut tranformations.
+ #
+ foreach ($this->span_gamut as $method => $priority) {
+ $text = $this->$method($text);
+ }
+
+ return $text;
+ }
+
+
+ function doHardBreaks($text) {
+ # Do hard breaks:
+ return preg_replace_callback('/ {2,}\n/',
+ array(&$this, '_doHardBreaks_callback'), $text);
+ }
+ function _doHardBreaks_callback($matches) {
+ return $this->hashPart("<br$this->empty_element_suffix\n");
+ }
+
+
+ function doAnchors($text) {
+ #
+ # Turn Markdown link shortcuts into XHTML <a> tags.
+ #
+ if ($this->in_anchor) return $text;
+ $this->in_anchor = true;
+
+ #
+ # First, handle reference-style links: [link text] [id]
+ #
+ $text = preg_replace_callback('{
+ ( # wrap whole match in $1
+ \[
+ ('.$this->nested_brackets_re.') # link text = $2
+ \]
+
+ [ ]? # one optional space
+ (?:\n[ ]*)? # one optional newline followed by spaces
+
+ \[
+ (.*?) # id = $3
+ \]
+ )
+ }xs',
+ array(&$this, '_doAnchors_reference_callback'), $text);
+
+ #
+ # Next, inline-style links: [link text](url "optional title")
+ #
+ $text = preg_replace_callback('{
+ ( # wrap whole match in $1
+ \[
+ ('.$this->nested_brackets_re.') # link text = $2
+ \]
+ \( # literal paren
+ [ \n]*
+ (?:
+ <(.+?)> # href = $3
+ |
+ ('.$this->nested_url_parenthesis_re.') # href = $4
+ )
+ [ \n]*
+ ( # $5
+ ([\'"]) # quote char = $6
+ (.*?) # Title = $7
+ \6 # matching quote
+ [ \n]* # ignore any spaces/tabs between closing quote and )
+ )? # title is optional
+ \)
+ )
+ }xs',
+ array(&$this, '_doAnchors_inline_callback'), $text);
+
+ #
+ # Last, handle reference-style shortcuts: [link text]
+ # These must come last in case you've also got [link text][1]
+ # or [link text](/foo)
+ #
+ $text = preg_replace_callback('{
+ ( # wrap whole match in $1
+ \[
+ ([^\[\]]+) # link text = $2; can\'t contain [ or ]
+ \]
+ )
+ }xs',
+ array(&$this, '_doAnchors_reference_callback'), $text);
+
+ $this->in_anchor = false;
+ return $text;
+ }
+ function _doAnchors_reference_callback($matches) {
+ $whole_match = $matches[1];
+ $link_text = $matches[2];
+ $link_id =& $matches[3];
+
+ if ($link_id == "") {
+ # for shortcut links like [this][] or [this].
+ $link_id = $link_text;
+ }
+
+ # lower-case and turn embedded newlines into spaces
+ $link_id = strtolower($link_id);
+ $link_id = preg_replace('{[ ]?\n}', ' ', $link_id);
+
+ if (isset($this->urls[$link_id])) {
+ $url = $this->urls[$link_id];
+ $url = $this->encodeAttribute($url);
+
+ $result = "<a href=\"$url\"";
+ if ( isset( $this->titles[$link_id] ) ) {
+ $title = $this->titles[$link_id];
+ $title = $this->encodeAttribute($title);
+ $result .= " title=\"$title\"";
+ }
+
+ $link_text = $this->runSpanGamut($link_text);
+ $result .= ">$link_text</a>";
+ $result = $this->hashPart($result);
+ }
+ else {
+ $result = $whole_match;
+ }
+ return $result;
+ }
+ function _doAnchors_inline_callback($matches) {
+ $whole_match = $matches[1];
+ $link_text = $this->runSpanGamut($matches[2]);
+ $url = $matches[3] == '' ? $matches[4] : $matches[3];
+ $title =& $matches[7];
+
+ $url = $this->encodeAttribute($url);
+
+ $result = "<a href=\"$url\"";
+ if (isset($title)) {
+ $title = $this->encodeAttribute($title);
+ $result .= " title=\"$title\"";
+ }
+
+ $link_text = $this->runSpanGamut($link_text);
+ $result .= ">$link_text</a>";
+
+ return $this->hashPart($result);
+ }
+
+
+ function doImages($text) {
+ #
+ # Turn Markdown image shortcuts into <img> tags.
+ #
+ #
+ # First, handle reference-style labeled images: ![alt text][id]
+ #
+ $text = preg_replace_callback('{
+ ( # wrap whole match in $1
+ !\[
+ ('.$this->nested_brackets_re.') # alt text = $2
+ \]
+
+ [ ]? # one optional space
+ (?:\n[ ]*)? # one optional newline followed by spaces
+
+ \[
+ (.*?) # id = $3
+ \]
+
+ )
+ }xs',
+ array(&$this, '_doImages_reference_callback'), $text);
+
+ #
+ # Next, handle inline images: ![alt text](url "optional title")
+ # Don't forget: encode * and _
+ #
+ $text = preg_replace_callback('{
+ ( # wrap whole match in $1
+ !\[
+ ('.$this->nested_brackets_re.') # alt text = $2
+ \]
+ \s? # One optional whitespace character
+ \( # literal paren
+ [ \n]*
+ (?:
+ <(\S*)> # src url = $3
+ |
+ ('.$this->nested_url_parenthesis_re.') # src url = $4
+ )
+ [ \n]*
+ ( # $5
+ ([\'"]) # quote char = $6
+ (.*?) # title = $7
+ \6 # matching quote
+ [ \n]*
+ )? # title is optional
+ \)
+ )
+ }xs',
+ array(&$this, '_doImages_inline_callback'), $text);
+
+ return $text;
+ }
+ function _doImages_reference_callback($matches) {
+ $whole_match = $matches[1];
+ $alt_text = $matches[2];
+ $link_id = strtolower($matches[3]);
+
+ if ($link_id == "") {
+ $link_id = strtolower($alt_text); # for shortcut links like ![this][].
+ }
+
+ $alt_text = $this->encodeAttribute($alt_text);
+ if (isset($this->urls[$link_id])) {
+ $url = $this->encodeAttribute($this->urls[$link_id]);
+ $result = "<img src=\"$url\" alt=\"$alt_text\"";
+ if (isset($this->titles[$link_id])) {
+ $title = $this->titles[$link_id];
+ $title = $this->encodeAttribute($title);
+ $result .= " title=\"$title\"";
+ }
+ $result .= $this->empty_element_suffix;
+ $result = $this->hashPart($result);
+ }
+ else {
+ # If there's no such link ID, leave intact:
+ $result = $whole_match;
+ }
+
+ return $result;
+ }
+ function _doImages_inline_callback($matches) {
+ $whole_match = $matches[1];
+ $alt_text = $matches[2];
+ $url = $matches[3] == '' ? $matches[4] : $matches[3];
+ $title =& $matches[7];
+
+ $alt_text = $this->encodeAttribute($alt_text);
+ $url = $this->encodeAttribute($url);
+ $result = "<img src=\"$url\" alt=\"$alt_text\"";
+ if (isset($title)) {
+ $title = $this->encodeAttribute($title);
+ $result .= " title=\"$title\""; # $title already quoted
+ }
+ $result .= $this->empty_element_suffix;
+
+ return $this->hashPart($result);
+ }
+
+
+ function doHeaders($text) {
+ # Setext-style headers:
+ # Header 1
+ # ========
+ #
+ # Header 2
+ # --------
+ #
+ $text = preg_replace_callback('{ ^(.+?)[ ]*\n(=+|-+)[ ]*\n+ }mx',
+ array(&$this, '_doHeaders_callback_setext'), $text);
+
+ # atx-style headers:
+ # # Header 1
+ # ## Header 2
+ # ## Header 2 with closing hashes ##
+ # ...
+ # ###### Header 6
+ #
+ $text = preg_replace_callback('{
+ ^(\#{1,6}) # $1 = string of #\'s
+ [ ]*
+ (.+?) # $2 = Header text
+ [ ]*
+ \#* # optional closing #\'s (not counted)
+ \n+
+ }xm',
+ array(&$this, '_doHeaders_callback_atx'), $text);
+
+ return $text;
+ }
+ function _doHeaders_callback_setext($matches) {
+ # Terrible hack to check we haven't found an empty list item.
+ if ($matches[2] == '-' && preg_match('{^-(?: |$)}', $matches[1]))
+ return $matches[0];
+
+ $level = $matches[2]{0} == '=' ? 1 : 2;
+ $block = "<h$level>".$this->runSpanGamut($matches[1])."</h$level>";
+ return "\n" . $this->hashBlock($block) . "\n\n";
+ }
+ function _doHeaders_callback_atx($matches) {
+ $level = strlen($matches[1]);
+ $block = "<h$level>".$this->runSpanGamut($matches[2])."</h$level>";
+ return "\n" . $this->hashBlock($block) . "\n\n";
+ }
+
+
+ function doLists($text) {
+ #
+ # Form HTML ordered (numbered) and unordered (bulleted) lists.
+ #
+ $less_than_tab = $this->tab_width - 1;
+
+ # Re-usable patterns to match list item bullets and number markers:
+ $marker_ul_re = '[*+-]';
+ $marker_ol_re = '\d+[.]';
+ $marker_any_re = "(?:$marker_ul_re|$marker_ol_re)";
+
+ $markers_relist = array(
+ $marker_ul_re => $marker_ol_re,
+ $marker_ol_re => $marker_ul_re,
+ );
+
+ foreach ($markers_relist as $marker_re => $other_marker_re) {
+ # Re-usable pattern to match any entirel ul or ol list:
+ $whole_list_re = '
+ ( # $1 = whole list
+ ( # $2
+ ([ ]{0,'.$less_than_tab.'}) # $3 = number of spaces
+ ('.$marker_re.') # $4 = first list item marker
+ [ ]+
+ )
+ (?s:.+?)
+ ( # $5
+ \z
+ |
+ \n{2,}
+ (?=\S)
+ (?! # Negative lookahead for another list item marker
+ [ ]*
+ '.$marker_re.'[ ]+
+ )
+ |
+ (?= # Lookahead for another kind of list
+ \n
+ \3 # Must have the same indentation
+ '.$other_marker_re.'[ ]+
+ )
+ )
+ )
+ '; // mx
+
+ # We use a different prefix before nested lists than top-level lists.
+ # See extended comment in _ProcessListItems().
+
+ if ($this->list_level) {
+ $text = preg_replace_callback('{
+ ^
+ '.$whole_list_re.'
+ }mx',
+ array(&$this, '_doLists_callback'), $text);
+ }
+ else {
+ $text = preg_replace_callback('{
+ (?:(?<=\n)\n|\A\n?) # Must eat the newline
+ '.$whole_list_re.'
+ }mx',
+ array(&$this, '_doLists_callback'), $text);
+ }
+ }
+
+ return $text;
+ }
+ function _doLists_callback($matches) {
+ # Re-usable patterns to match list item bullets and number markers:
+ $marker_ul_re = '[*+-]';
+ $marker_ol_re = '\d+[.]';
+ $marker_any_re = "(?:$marker_ul_re|$marker_ol_re)";
+
+ $list = $matches[1];
+ $list_type = preg_match("/$marker_ul_re/", $matches[4]) ? "ul" : "ol";
+
+ $marker_any_re = ( $list_type == "ul" ? $marker_ul_re : $marker_ol_re );
+
+ $list .= "\n";
+ $result = $this->processListItems($list, $marker_any_re);
+
+ $result = $this->hashBlock("<$list_type>\n" . $result . "</$list_type>");
+ return "\n". $result ."\n\n";
+ }
+
+ var $list_level = 0;
+
+ function processListItems($list_str, $marker_any_re) {
+ #
+ # Process the contents of a single ordered or unordered list, splitting it
+ # into individual list items.
+ #
+ # The $this->list_level global keeps track of when we're inside a list.
+ # Each time we enter a list, we increment it; when we leave a list,
+ # we decrement. If it's zero, we're not in a list anymore.
+ #
+ # We do this because when we're not inside a list, we want to treat
+ # something like this:
+ #
+ # I recommend upgrading to version
+ # 8. Oops, now this line is treated
+ # as a sub-list.
+ #
+ # As a single paragraph, despite the fact that the second line starts
+ # with a digit-period-space sequence.
+ #
+ # Whereas when we're inside a list (or sub-list), that line will be
+ # treated as the start of a sub-list. What a kludge, huh? This is
+ # an aspect of Markdown's syntax that's hard to parse perfectly
+ # without resorting to mind-reading. Perhaps the solution is to
+ # change the syntax rules such that sub-lists must start with a
+ # starting cardinal number; e.g. "1." or "a.".
+
+ $this->list_level++;
+
+ # trim trailing blank lines:
+ $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str);
+
+ $list_str = preg_replace_callback('{
+ (\n)? # leading line = $1
+ (^[ ]*) # leading whitespace = $2
+ ('.$marker_any_re.' # list marker and space = $3
+ (?:[ ]+|(?=\n)) # space only required if item is not empty
+ )
+ ((?s:.*?)) # list item text = $4
+ (?:(\n+(?=\n))|\n) # tailing blank line = $5
+ (?= \n* (\z | \2 ('.$marker_any_re.') (?:[ ]+|(?=\n))))
+ }xm',
+ array(&$this, '_processListItems_callback'), $list_str);
+
+ $this->list_level--;
+ return $list_str;
+ }
+ function _processListItems_callback($matches) {
+ $item = $matches[4];
+ $leading_line =& $matches[1];
+ $leading_space =& $matches[2];
+ $marker_space = $matches[3];
+ $tailing_blank_line =& $matches[5];
+
+ if ($leading_line || $tailing_blank_line ||
+ preg_match('/\n{2,}/', $item))
+ {
+ # Replace marker with the appropriate whitespace indentation
+ $item = $leading_space . str_repeat(' ', strlen($marker_space)) . $item;
+ $item = $this->runBlockGamut($this->outdent($item)."\n");
+ }
+ else {
+ # Recursion for sub-lists:
+ $item = $this->doLists($this->outdent($item));
+ $item = preg_replace('/\n+$/', '', $item);
+ $item = $this->runSpanGamut($item);
+ }
+
+ return "<li>" . $item . "</li>\n";
+ }
+
+
+ function doCodeBlocks($text) {
+ #
+ # Process Markdown `<pre><code>` blocks.
+ #
+ $text = preg_replace_callback('{
+ (?:\n\n|\A\n?)
+ ( # $1 = the code block -- one or more lines, starting with a space/tab
+ (?>
+ [ ]{'.$this->tab_width.'} # Lines must start with a tab or a tab-width of spaces
+ .*\n+
+ )+
+ )
+ ((?=^[ ]{0,'.$this->tab_width.'}\S)|\Z) # Lookahead for non-space at line-start, or end of doc
+ }xm',
+ array(&$this, '_doCodeBlocks_callback'), $text);
+
+ return $text;
+ }
+ function _doCodeBlocks_callback($matches) {
+ $codeblock = $matches[1];
+
+ $codeblock = $this->outdent($codeblock);
+ $codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
+
+ # trim leading newlines and trailing newlines
+ $codeblock = preg_replace('/\A\n+|\n+\z/', '', $codeblock);
+
+ $codeblock = "<pre><code>$codeblock\n</code></pre>";
+ return "\n\n".$this->hashBlock($codeblock)."\n\n";
+ }
+
+
+ function makeCodeSpan($code) {
+ #
+ # Create a code span markup for $code. Called from handleSpanToken.
+ #
+ $code = htmlspecialchars(trim($code), ENT_NOQUOTES);
+ return $this->hashPart("<code>$code</code>");
+ }
+
+
+ var $em_relist = array(
+ '' => '(?:(?<!\*)\*(?!\*)|(?<!_)_(?!_))(?=\S|$)(?![.,:;]\s)',
+ '*' => '(?<=\S|^)(?<!\*)\*(?!\*)',
+ '_' => '(?<=\S|^)(?<!_)_(?!_)',
+ );
+ var $strong_relist = array(
+ '' => '(?:(?<!\*)\*\*(?!\*)|(?<!_)__(?!_))(?=\S|$)(?![.,:;]\s)',
+ '**' => '(?<=\S|^)(?<!\*)\*\*(?!\*)',
+ '__' => '(?<=\S|^)(?<!_)__(?!_)',
+ );
+ var $em_strong_relist = array(
+ '' => '(?:(?<!\*)\*\*\*(?!\*)|(?<!_)___(?!_))(?=\S|$)(?![.,:;]\s)',
+ '***' => '(?<=\S|^)(?<!\*)\*\*\*(?!\*)',
+ '___' => '(?<=\S|^)(?<!_)___(?!_)',
+ );
+ var $em_strong_prepared_relist;
+
+ function prepareItalicsAndBold() {
+ #
+ # Prepare regular expressions for searching emphasis tokens in any
+ # context.
+ #
+ foreach ($this->em_relist as $em => $em_re) {
+ foreach ($this->strong_relist as $strong => $strong_re) {
+ # Construct list of allowed token expressions.
+ $token_relist = array();
+ if (isset($this->em_strong_relist["$em$strong"])) {
+ $token_relist[] = $this->em_strong_relist["$em$strong"];
+ }
+ $token_relist[] = $em_re;
+ $token_relist[] = $strong_re;
+
+ # Construct master expression from list.
+ $token_re = '{('. implode('|', $token_relist) .')}';
+ $this->em_strong_prepared_relist["$em$strong"] = $token_re;
+ }
+ }
+ }
+
+ function doItalicsAndBold($text) {
+ $token_stack = array('');
+ $text_stack = array('');
+ $em = '';
+ $strong = '';
+ $tree_char_em = false;
+
+ while (1) {
+ #
+ # Get prepared regular expression for seraching emphasis tokens
+ # in current context.
+ #
+ $token_re = $this->em_strong_prepared_relist["$em$strong"];
+
+ #
+ # Each loop iteration search for the next emphasis token.
+ # Each token is then passed to handleSpanToken.
+ #
+ $parts = preg_split($token_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE);
+ $text_stack[0] .= $parts[0];
+ $token =& $parts[1];
+ $text =& $parts[2];
+
+ if (empty($token)) {
+ # Reached end of text span: empty stack without emitting.
+ # any more emphasis.
+ while ($token_stack[0]) {
+ $text_stack[1] .= array_shift($token_stack);
+ $text_stack[0] .= array_shift($text_stack);
+ }
+ break;
+ }
+
+ $token_len = strlen($token);
+ if ($tree_char_em) {
+ # Reached closing marker while inside a three-char emphasis.
+ if ($token_len == 3) {
+ # Three-char closing marker, close em and strong.
+ array_shift($token_stack);
+ $span = array_shift($text_stack);
+ $span = $this->runSpanGamut($span);
+ $span = "<strong><em>$span</em></strong>";
+ $text_stack[0] .= $this->hashPart($span);
+ $em = '';
+ $strong = '';
+ } else {
+ # Other closing marker: close one em or strong and
+ # change current token state to match the other
+ $token_stack[0] = str_repeat($token{0}, 3-$token_len);
+ $tag = $token_len == 2 ? "strong" : "em";
+ $span = $text_stack[0];
+ $span = $this->runSpanGamut($span);
+ $span = "<$tag>$span</$tag>";
+ $text_stack[0] = $this->hashPart($span);
+ $$tag = ''; # $$tag stands for $em or $strong
+ }
+ $tree_char_em = false;
+ } else if ($token_len == 3) {
+ if ($em) {
+ # Reached closing marker for both em and strong.
+ # Closing strong marker:
+ for ($i = 0; $i < 2; ++$i) {
+ $shifted_token = array_shift($token_stack);
+ $tag = strlen($shifted_token) == 2 ? "strong" : "em";
+ $span = array_shift($text_stack);
+ $span = $this->runSpanGamut($span);
+ $span = "<$tag>$span</$tag>";
+ $text_stack[0] .= $this->hashPart($span);
+ $$tag = ''; # $$tag stands for $em or $strong
+ }
+ } else {
+ # Reached opening three-char emphasis marker. Push on token
+ # stack; will be handled by the special condition above.
+ $em = $token{0};
+ $strong = "$em$em";
+ array_unshift($token_stack, $token);
+ array_unshift($text_stack, '');
+ $tree_char_em = true;
+ }
+ } else if ($token_len == 2) {
+ if ($strong) {
+ # Unwind any dangling emphasis marker:
+ if (strlen($token_stack[0]) == 1) {
+ $text_stack[1] .= array_shift($token_stack);
+ $text_stack[0] .= array_shift($text_stack);
+ }
+ # Closing strong marker:
+ array_shift($token_stack);
+ $span = array_shift($text_stack);
+ $span = $this->runSpanGamut($span);
+ $span = "<strong>$span</strong>";
+ $text_stack[0] .= $this->hashPart($span);
+ $strong = '';
+ } else {
+ array_unshift($token_stack, $token);
+ array_unshift($text_stack, '');
+ $strong = $token;
+ }
+ } else {
+ # Here $token_len == 1
+ if ($em) {
+ if (strlen($token_stack[0]) == 1) {
+ # Closing emphasis marker:
+ array_shift($token_stack);
+ $span = array_shift($text_stack);
+ $span = $this->runSpanGamut($span);
+ $span = "<em>$span</em>";
+ $text_stack[0] .= $this->hashPart($span);
+ $em = '';
+ } else {
+ $text_stack[0] .= $token;
+ }
+ } else {
+ array_unshift($token_stack, $token);
+ array_unshift($text_stack, '');
+ $em = $token;
+ }
+ }
+ }
+ return $text_stack[0];
+ }
+
+
+ function doBlockQuotes($text) {
+ $text = preg_replace_callback('/
+ ( # Wrap whole match in $1
+ (?>
+ ^[ ]*>[ ]? # ">" at the start of a line
+ .+\n # rest of the first line
+ (.+\n)* # subsequent consecutive lines
+ \n* # blanks
+ )+
+ )
+ /xm',
+ array(&$this, '_doBlockQuotes_callback'), $text);
+
+ return $text;
+ }
+ function _doBlockQuotes_callback($matches) {
+ $bq = $matches[1];
+ # trim one level of quoting - trim whitespace-only lines
+ $bq = preg_replace('/^[ ]*>[ ]?|^[ ]+$/m', '', $bq);
+ $bq = $this->runBlockGamut($bq); # recurse
+
+ $bq = preg_replace('/^/m', " ", $bq);
+ # These leading spaces cause problem with <pre> content,
+ # so we need to fix that:
+ $bq = preg_replace_callback('{(\s*<pre>.+?</pre>)}sx',
+ array(&$this, '_doBlockQuotes_callback2'), $bq);
+
+ return "\n". $this->hashBlock("<blockquote>\n$bq\n</blockquote>")."\n\n";
+ }
+ function _doBlockQuotes_callback2($matches) {
+ $pre = $matches[1];
+ $pre = preg_replace('/^ /m', '', $pre);
+ return $pre;
+ }
+
+
+ function formParagraphs($text) {
+ #
+ # Params:
+ # $text - string to process with html <p> tags
+ #
+ # Strip leading and trailing lines:
+ $text = preg_replace('/\A\n+|\n+\z/', '', $text);
+
+ $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY);
+
+ #
+ # Wrap <p> tags and unhashify HTML blocks
+ #
+ foreach ($grafs as $key => $value) {
+ if (!preg_match('/^B\x1A[0-9]+B$/', $value)) {
+ # Is a paragraph.
+ $value = $this->runSpanGamut($value);
+ $value = preg_replace('/^([ ]*)/', "<p>", $value);
+ $value .= "</p>";
+ $grafs[$key] = $this->unhash($value);
+ }
+ else {
+ # Is a block.
+ # Modify elements of @grafs in-place...
+ $graf = $value;
+ $block = $this->html_hashes[$graf];
+ $graf = $block;
+// if (preg_match('{
+// \A
+// ( # $1 = <div> tag
+// <div \s+
+// [^>]*
+// \b
+// markdown\s*=\s* ([\'"]) # $2 = attr quote char
+// 1
+// \2
+// [^>]*
+// >
+// )
+// ( # $3 = contents
+// .*
+// )
+// (</div>) # $4 = closing tag
+// \z
+// }xs', $block, $matches))
+// {
+// list(, $div_open, , $div_content, $div_close) = $matches;
+//
+// # We can't call Markdown(), because that resets the hash;
+// # that initialization code should be pulled into its own sub, though.
+// $div_content = $this->hashHTMLBlocks($div_content);
+//
+// # Run document gamut methods on the content.
+// foreach ($this->document_gamut as $method => $priority) {
+// $div_content = $this->$method($div_content);
+// }
+//
+// $div_open = preg_replace(
+// '{\smarkdown\s*=\s*([\'"]).+?\1}', '', $div_open);
+//
+// $graf = $div_open . "\n" . $div_content . "\n" . $div_close;
+// }
+ $grafs[$key] = $graf;
+ }
+ }
+
+ return implode("\n\n", $grafs);
+ }
+
+
+ function encodeAttribute($text) {
+ #
+ # Encode text for a double-quoted HTML attribute. This function
+ # is *not* suitable for attributes enclosed in single quotes.
+ #
+ $text = $this->encodeAmpsAndAngles($text);
+ $text = str_replace('"', '"', $text);
+ return $text;
+ }
+
+
+ function encodeAmpsAndAngles($text) {
+ #
+ # Smart processing for ampersands and angle brackets that need to
+ # be encoded. Valid character entities are left alone unless the
+ # no-entities mode is set.
+ #
+ if ($this->no_entities) {
+ $text = str_replace('&', '&', $text);
+ } else {
+ # Ampersand-encoding based entirely on Nat Irons's Amputator
+ # MT plugin: <http://bumppo.net/projects/amputator/>
+ $text = preg_replace('/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/',
+ '&', $text);;
+ }
+ # Encode remaining <'s
+ $text = str_replace('<', '<', $text);
+
+ return $text;
+ }
+
+
+ function doAutoLinks($text) {
+ $text = preg_replace_callback('{<((https?|ftp|dict):[^\'">\s]+)>}i',
+ array(&$this, '_doAutoLinks_url_callback'), $text);
+
+ # Email addresses: <address@domain.foo>
+ $text = preg_replace_callback('{
+ <
+ (?:mailto:)?
+ (
+ (?:
+ [-!#$%&\'*+/=?^_`.{|}~\w\x80-\xFF]+
+ |
+ ".*?"
+ )
+ \@
+ (?:
+ [-a-z0-9\x80-\xFF]+(\.[-a-z0-9\x80-\xFF]+)*\.[a-z]+
+ |
+ \[[\d.a-fA-F:]+\] # IPv4 & IPv6
+ )
+ )
+ >
+ }xi',
+ array(&$this, '_doAutoLinks_email_callback'), $text);
+
+ return $text;
+ }
+ function _doAutoLinks_url_callback($matches) {
+ $url = $this->encodeAttribute($matches[1]);
+ $link = "<a href=\"$url\">$url</a>";
+ return $this->hashPart($link);
+ }
+ function _doAutoLinks_email_callback($matches) {
+ $address = $matches[1];
+ $link = $this->encodeEmailAddress($address);
+ return $this->hashPart($link);
+ }
+
+
+ function encodeEmailAddress($addr) {
+ #
+ # Input: an email address, e.g. "foo@example.com"
+ #
+ # Output: the email address as a mailto link, with each character
+ # of the address encoded as either a decimal or hex entity, in
+ # the hopes of foiling most address harvesting spam bots. E.g.:
+ #
+ # <p><a href="mailto:foo
+ # @example.co
+ # m">foo@exampl
+ # e.com</a></p>
+ #
+ # Based by a filter by Matthew Wickline, posted to BBEdit-Talk.
+ # With some optimizations by Milian Wolff.
+ #
+ $addr = "mailto:" . $addr;
+ $chars = preg_split('/(?<!^)(?!$)/', $addr);
+ $seed = (int)abs(crc32($addr) / strlen($addr)); # Deterministic seed.
+
+ foreach ($chars as $key => $char) {
+ $ord = ord($char);
+ # Ignore non-ascii chars.
+ if ($ord < 128) {
+ $r = ($seed * (1 + $key)) % 100; # Pseudo-random function.
+ # roughly 10% raw, 45% hex, 45% dec
+ # '@' *must* be encoded. I insist.
+ if ($r > 90 && $char != '@') /* do nothing */;
+ else if ($r < 45) $chars[$key] = '&#x'.dechex($ord).';';
+ else $chars[$key] = '&#'.$ord.';';
+ }
+ }
+
+ $addr = implode('', $chars);
+ $text = implode('', array_slice($chars, 7)); # text without `mailto:`
+ $addr = "<a href=\"$addr\">$text</a>";
+
+ return $addr;
+ }
+
+
+ function parseSpan($str) {
+ #
+ # Take the string $str and parse it into tokens, hashing embeded HTML,
+ # escaped characters and handling code spans.
+ #
+ $output = '';
+
+ $span_re = '{
+ (
+ \\\\'.$this->escape_chars_re.'
+ |
+ (?<![`\\\\])
+ `+ # code span marker
+ '.( $this->no_markup ? '' : '
+ |
+ <!-- .*? --> # comment
+ |
+ <\?.*?\?> | <%.*?%> # processing instruction
+ |
+ <[/!$]?[-a-zA-Z0-9:_]+ # regular tags
+ (?>
+ \s
+ (?>[^"\'>]+|"[^"]*"|\'[^\']*\')*
+ )?
+ >
+ ').'
+ )
+ }xs';
+
+ while (1) {
+ #
+ # Each loop iteration seach for either the next tag, the next
+ # openning code span marker, or the next escaped character.
+ # Each token is then passed to handleSpanToken.
+ #
+ $parts = preg_split($span_re, $str, 2, PREG_SPLIT_DELIM_CAPTURE);
+
+ # Create token from text preceding tag.
+ if ($parts[0] != "") {
+ $output .= $parts[0];
+ }
+
+ # Check if we reach the end.
+ if (isset($parts[1])) {
+ $output .= $this->handleSpanToken($parts[1], $parts[2]);
+ $str = $parts[2];
+ }
+ else {
+ break;
+ }
+ }
+
+ return $output;
+ }
+
+
+ function handleSpanToken($token, &$str) {
+ #
+ # Handle $token provided by parseSpan by determining its nature and
+ # returning the corresponding value that should replace it.
+ #
+ switch ($token{0}) {
+ case "\\":
+ return $this->hashPart("&#". ord($token{1}). ";");
+ case "`":
+ # Search for end marker in remaining text.
+ if (preg_match('/^(.*?[^`])'.preg_quote($token).'(?!`)(.*)$/sm',
+ $str, $matches))
+ {
+ $str = $matches[2];
+ $codespan = $this->makeCodeSpan($matches[1]);
+ return $this->hashPart($codespan);
+ }
+ return $token; // return as text since no ending marker found.
+ default:
+ return $this->hashPart($token);
+ }
+ }
+
+
+ function outdent($text) {
+ #
+ # Remove one level of line-leading tabs or spaces
+ #
+ return preg_replace('/^(\t|[ ]{1,'.$this->tab_width.'})/m', '', $text);
+ }
+
+
+ # String length function for detab. `_initDetab` will create a function to
+ # hanlde UTF-8 if the default function does not exist.
+ var $utf8_strlen = 'mb_strlen';
+
+ function detab($text) {
+ #
+ # Replace tabs with the appropriate amount of space.
+ #
+ # For each line we separate the line in blocks delemited by
+ # tab characters. Then we reconstruct every line by adding the
+ # appropriate number of space between each blocks.
+
+ $text = preg_replace_callback('/^.*\t.*$/m',
+ array(&$this, '_detab_callback'), $text);
+
+ return $text;
+ }
+ function _detab_callback($matches) {
+ $line = $matches[0];
+ $strlen = $this->utf8_strlen; # strlen function for UTF-8.
+
+ # Split in blocks.
+ $blocks = explode("\t", $line);
+ # Add each blocks to the line.
+ $line = $blocks[0];
+ unset($blocks[0]); # Do not add first block twice.
+ foreach ($blocks as $block) {
+ # Calculate amount of space, insert spaces, insert block.
+ $amount = $this->tab_width -
+ $strlen($line, 'UTF-8') % $this->tab_width;
+ $line .= str_repeat(" ", $amount) . $block;
+ }
+ return $line;
+ }
+ function _initDetab() {
+ #
+ # Check for the availability of the function in the `utf8_strlen` property
+ # (initially `mb_strlen`). If the function is not available, create a
+ # function that will loosely count the number of UTF-8 characters with a
+ # regular expression.
+ #
+ if (function_exists($this->utf8_strlen)) return;
+ $this->utf8_strlen = create_function('$text', 'return preg_match_all(
+ "/[\\\\x00-\\\\xBF]|[\\\\xC0-\\\\xFF][\\\\x80-\\\\xBF]*/",
+ $text, $m);');
+ }
+
+
+ function unhash($text) {
+ #
+ # Swap back in all the tags hashed by _HashHTMLBlocks.
+ #
+ return preg_replace_callback('/(.)\x1A[0-9]+\1/',
+ array(&$this, '_unhash_callback'), $text);
+ }
+ function _unhash_callback($matches) {
+ return $this->html_hashes[$matches[0]];
+ }
+
+}
+
+
+#
+# Markdown Extra Parser Class
+#
+
+class MarkdownExtra_Parser extends Markdown_Parser {
+
+ # Prefix for footnote ids.
+ var $fn_id_prefix = "";
+
+ # Optional title attribute for footnote links and backlinks.
+ var $fn_link_title = MARKDOWN_FN_LINK_TITLE;
+ var $fn_backlink_title = MARKDOWN_FN_BACKLINK_TITLE;
+
+ # Optional class attribute for footnote links and backlinks.
+ var $fn_link_class = MARKDOWN_FN_LINK_CLASS;
+ var $fn_backlink_class = MARKDOWN_FN_BACKLINK_CLASS;
+
+ # Predefined abbreviations.
+ var $predef_abbr = array();
+
+
+ function MarkdownExtra_Parser() {
+ #
+ # Constructor function. Initialize the parser object.
+ #
+ # Add extra escapable characters before parent constructor
+ # initialize the table.
+ $this->escape_chars .= ':|';
+
+ # Insert extra document, block, and span transformations.
+ # Parent constructor will do the sorting.
+ $this->document_gamut += array(
+ "doFencedCodeBlocks" => 5,
+ "stripFootnotes" => 15,
+ "stripAbbreviations" => 25,
+ "appendFootnotes" => 50,
+ );
+ $this->block_gamut += array(
+ "doFencedCodeBlocks" => 5,
+ "doTables" => 15,
+ "doDefLists" => 45,
+ );
+ $this->span_gamut += array(
+ "doFootnotes" => 5,
+ "doAbbreviations" => 70,
+ );
+
+ parent::Markdown_Parser();
+ }
+
+
+ # Extra variables used during extra transformations.
+ var $footnotes = array();
+ var $footnotes_ordered = array();
+ var $abbr_desciptions = array();
+ var $abbr_word_re = '';
+
+ # Give the current footnote number.
+ var $footnote_counter = 1;
+
+
+ function setup() {
+ #
+ # Setting up Extra-specific variables.
+ #
+ parent::setup();
+
+ $this->footnotes = array();
+ $this->footnotes_ordered = array();
+ $this->abbr_desciptions = array();
+ $this->abbr_word_re = '';
+ $this->footnote_counter = 1;
+
+ foreach ($this->predef_abbr as $abbr_word => $abbr_desc) {
+ if ($this->abbr_word_re)
+ $this->abbr_word_re .= '|';
+ $this->abbr_word_re .= preg_quote($abbr_word);
+ $this->abbr_desciptions[$abbr_word] = trim($abbr_desc);
+ }
+ }
+
+ function teardown() {
+ #
+ # Clearing Extra-specific variables.
+ #
+ $this->footnotes = array();
+ $this->footnotes_ordered = array();
+ $this->abbr_desciptions = array();
+ $this->abbr_word_re = '';
+
+ parent::teardown();
+ }
+
+
+ ### HTML Block Parser ###
+
+ # Tags that are always treated as block tags:
+ var $block_tags_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|form|fieldset|iframe|hr|legend';
+
+ # Tags treated as block tags only if the opening tag is alone on it's line:
+ var $context_block_tags_re = 'script|noscript|math|ins|del';
+
+ # Tags where markdown="1" default to span mode:
+ var $contain_span_tags_re = 'p|h[1-6]|li|dd|dt|td|th|legend|address';
+
+ # Tags which must not have their contents modified, no matter where
+ # they appear:
+ var $clean_tags_re = 'script|math';
+
+ # Tags that do not need to be closed.
+ var $auto_close_tags_re = 'hr|img';
+
+
+ function hashHTMLBlocks($text) {
+ #
+ # Hashify HTML Blocks and "clean tags".
+ #
+ # We only want to do this for block-level HTML tags, such as headers,
+ # lists, and tables. That's because we still want to wrap <p>s around
+ # "paragraphs" that are wrapped in non-block-level tags, such as anchors,
+ # phrase emphasis, and spans. The list of tags we're looking for is
+ # hard-coded.
+ #
+ # This works by calling _HashHTMLBlocks_InMarkdown, which then calls
+ # _HashHTMLBlocks_InHTML when it encounter block tags. When the markdown="1"
+ # attribute is found whitin a tag, _HashHTMLBlocks_InHTML calls back
+ # _HashHTMLBlocks_InMarkdown to handle the Markdown syntax within the tag.
+ # These two functions are calling each other. It's recursive!
+ #
+ #
+ # Call the HTML-in-Markdown hasher.
+ #
+ list($text, ) = $this->_hashHTMLBlocks_inMarkdown($text);
+
+ return $text;
+ }
+ function _hashHTMLBlocks_inMarkdown($text, $indent = 0,
+ $enclosing_tag_re = '', $span = false)
+ {
+ #
+ # Parse markdown text, calling _HashHTMLBlocks_InHTML for block tags.
+ #
+ # * $indent is the number of space to be ignored when checking for code
+ # blocks. This is important because if we don't take the indent into
+ # account, something like this (which looks right) won't work as expected:
+ #
+ # <div>
+ # <div markdown="1">
+ # Hello World. <-- Is this a Markdown code block or text?
+ # </div> <-- Is this a Markdown code block or a real tag?
+ # <div>
+ #
+ # If you don't like this, just don't indent the tag on which
+ # you apply the markdown="1" attribute.
+ #
+ # * If $enclosing_tag_re is not empty, stops at the first unmatched closing
+ # tag with that name. Nested tags supported.
+ #
+ # * If $span is true, text inside must treated as span. So any double
+ # newline will be replaced by a single newline so that it does not create
+ # paragraphs.
+ #
+ # Returns an array of that form: ( processed text , remaining text )
+ #
+ if ($text === '') return array('', '');
+
+ # Regex to check for the presense of newlines around a block tag.
+ $newline_before_re = '/(?:^\n?|\n\n)*$/';
+ $newline_after_re =
+ '{
+ ^ # Start of text following the tag.
+ (?>[ ]*<!--.*?-->)? # Optional comment.
+ [ ]*\n # Must be followed by newline.
+ }xs';
+
+ # Regex to match any tag.
+ $block_tag_re =
+ '{
+ ( # $2: Capture hole tag.
+ </? # Any opening or closing tag.
+ (?> # Tag name.
+ '.$this->block_tags_re.' |
+ '.$this->context_block_tags_re.' |
+ '.$this->clean_tags_re.' |
+ (?!\s)'.$enclosing_tag_re.'
+ )
+ (?:
+ (?=[\s"\'/a-zA-Z0-9]) # Allowed characters after tag name.
+ (?>
+ ".*?" | # Double quotes (can contain `>`)
+ \'.*?\' | # Single quotes (can contain `>`)
+ .+? # Anything but quotes and `>`.
+ )*?
+ )?
+ > # End of tag.
+ |
+ <!-- .*? --> # HTML Comment
+ |
+ <\?.*?\?> | <%.*?%> # Processing instruction
+ |
+ <!\[CDATA\[.*?\]\]> # CData Block
+ |
+ # Code span marker
+ `+
+ '. ( !$span ? ' # If not in span.
+ |
+ # Indented code block
+ (?: ^[ ]*\n | ^ | \n[ ]*\n )
+ [ ]{'.($indent+4).'}[^\n]* \n
+ (?>
+ (?: [ ]{'.($indent+4).'}[^\n]* | [ ]* ) \n
+ )*
+ |
+ # Fenced code block marker
+ (?> ^ | \n )
+ [ ]{'.($indent).'}~~~+[ ]*\n
+ ' : '' ). ' # End (if not is span).
+ )
+ }xs';
+
+
+ $depth = 0; # Current depth inside the tag tree.
+ $parsed = ""; # Parsed text that will be returned.
+
+ #
+ # Loop through every tag until we find the closing tag of the parent
+ # or loop until reaching the end of text if no parent tag specified.
+ #
+ do {
+ #
+ # Split the text using the first $tag_match pattern found.
+ # Text before pattern will be first in the array, text after
+ # pattern will be at the end, and between will be any catches made
+ # by the pattern.
+ #
+ $parts = preg_split($block_tag_re, $text, 2,
+ PREG_SPLIT_DELIM_CAPTURE);
+
+ # If in Markdown span mode, add a empty-string span-level hash
+ # after each newline to prevent triggering any block element.
+ if ($span) {
+ $void = $this->hashPart("", ':');
+ $newline = "$void\n";
+ $parts[0] = $void . str_replace("\n", $newline, $parts[0]) . $void;
+ }
+
+ $parsed .= $parts[0]; # Text before current tag.
+
+ # If end of $text has been reached. Stop loop.
+ if (count($parts) < 3) {
+ $text = "";
+ break;
+ }
+
+ $tag = $parts[1]; # Tag to handle.
+ $text = $parts[2]; # Remaining text after current tag.
+ $tag_re = preg_quote($tag); # For use in a regular expression.
+
+ #
+ # Check for: Code span marker
+ #
+ if ($tag{0} == "`") {
+ # Find corresponding end marker.
+ $tag_re = preg_quote($tag);
+ if (preg_match('{^(?>.+?|\n(?!\n))*?(?<!`)'.$tag_re.'(?!`)}',
+ $text, $matches))
+ {
+ # End marker found: pass text unchanged until marker.
+ $parsed .= $tag . $matches[0];
+ $text = substr($text, strlen($matches[0]));
+ }
+ else {
+ # Unmatched marker: just skip it.
+ $parsed .= $tag;
+ }
+ }
+ #
+ # Check for: Indented code block.
+ #
+ else if ($tag{0} == "\n" || $tag{0} == " ") {
+ # Indented code block: pass it unchanged, will be handled
+ # later.
+ $parsed .= $tag;
+ }
+ #
+ # Check for: Fenced code block marker.
+ #
+ else if ($tag{0} == "~") {
+ # Fenced code block marker: find matching end marker.
+ $tag_re = preg_quote(trim($tag));
+ if (preg_match('{^(?>.*\n)+?'.$tag_re.' *\n}', $text,
+ $matches))
+ {
+ # End marker found: pass text unchanged until marker.
+ $parsed .= $tag . $matches[0];
+ $text = substr($text, strlen($matches[0]));
+ }
+ else {
+ # No end marker: just skip it.
+ $parsed .= $tag;
+ }
+ }
+ #
+ # Check for: Opening Block level tag or
+ # Opening Context Block tag (like ins and del)
+ # used as a block tag (tag is alone on it's line).
+ #
+ else if (preg_match('{^<(?:'.$this->block_tags_re.')\b}', $tag) ||
+ ( preg_match('{^<(?:'.$this->context_block_tags_re.')\b}', $tag) &&
+ preg_match($newline_before_re, $parsed) &&
+ preg_match($newline_after_re, $text) )
+ )
+ {
+ # Need to parse tag and following text using the HTML parser.
+ list($block_text, $text) =
+ $this->_hashHTMLBlocks_inHTML($tag . $text, "hashBlock", true);
+
+ # Make sure it stays outside of any paragraph by adding newlines.
+ $parsed .= "\n\n$block_text\n\n";
+ }
+ #
+ # Check for: Clean tag (like script, math)
+ # HTML Comments, processing instructions.
+ #
+ else if (preg_match('{^<(?:'.$this->clean_tags_re.')\b}', $tag) ||
+ $tag{1} == '!' || $tag{1} == '?')
+ {
+ # Need to parse tag and following text using the HTML parser.
+ # (don't check for markdown attribute)
+ list($block_text, $text) =
+ $this->_hashHTMLBlocks_inHTML($tag . $text, "hashClean", false);
+
+ $parsed .= $block_text;
+ }
+ #
+ # Check for: Tag with same name as enclosing tag.
+ #
+ else if ($enclosing_tag_re !== '' &&
+ # Same name as enclosing tag.
+ preg_match('{^</?(?:'.$enclosing_tag_re.')\b}', $tag))
+ {
+ #
+ # Increase/decrease nested tag count.
+ #
+ if ($tag{1} == '/') $depth--;
+ else if ($tag{strlen($tag)-2} != '/') $depth++;
+
+ if ($depth < 0) {
+ #
+ # Going out of parent element. Clean up and break so we
+ # return to the calling function.
+ #
+ $text = $tag . $text;
+ break;
+ }
+
+ $parsed .= $tag;
+ }
+ else {
+ $parsed .= $tag;
+ }
+ } while ($depth >= 0);
+
+ return array($parsed, $text);
+ }
+ function _hashHTMLBlocks_inHTML($text, $hash_method, $md_attr) {
+ #
+ # Parse HTML, calling _HashHTMLBlocks_InMarkdown for block tags.
+ #
+ # * Calls $hash_method to convert any blocks.
+ # * Stops when the first opening tag closes.
+ # * $md_attr indicate if the use of the `markdown="1"` attribute is allowed.
+ # (it is not inside clean tags)
+ #
+ # Returns an array of that form: ( processed text , remaining text )
+ #
+ if ($text === '') return array('', '');
+
+ # Regex to match `markdown` attribute inside of a tag.
+ $markdown_attr_re = '
+ {
+ \s* # Eat whitespace before the `markdown` attribute
+ markdown
+ \s*=\s*
+ (?>
+ (["\']) # $1: quote delimiter
+ (.*?) # $2: attribute value
+ \1 # matching delimiter
+ |
+ ([^\s>]*) # $3: unquoted attribute value
+ )
+ () # $4: make $3 always defined (avoid warnings)
+ }xs';
+
+ # Regex to match any tag.
+ $tag_re = '{
+ ( # $2: Capture hole tag.
+ </? # Any opening or closing tag.
+ [\w:$]+ # Tag name.
+ (?:
+ (?=[\s"\'/a-zA-Z0-9]) # Allowed characters after tag name.
+ (?>
+ ".*?" | # Double quotes (can contain `>`)
+ \'.*?\' | # Single quotes (can contain `>`)
+ .+? # Anything but quotes and `>`.
+ )*?
+ )?
+ > # End of tag.
+ |
+ <!-- .*? --> # HTML Comment
+ |
+ <\?.*?\?> | <%.*?%> # Processing instruction
+ |
+ <!\[CDATA\[.*?\]\]> # CData Block
+ )
+ }xs';
+
+ $original_text = $text; # Save original text in case of faliure.
+
+ $depth = 0; # Current depth inside the tag tree.
+ $block_text = ""; # Temporary text holder for current text.
+ $parsed = ""; # Parsed text that will be returned.
+
+ #
+ # Get the name of the starting tag.
+ # (This pattern makes $base_tag_name_re safe without quoting.)
+ #
+ if (preg_match('/^<([\w:$]*)\b/', $text, $matches))
+ $base_tag_name_re = $matches[1];
+
+ #
+ # Loop through every tag until we find the corresponding closing tag.
+ #
+ do {
+ #
+ # Split the text using the first $tag_match pattern found.
+ # Text before pattern will be first in the array, text after
+ # pattern will be at the end, and between will be any catches made
+ # by the pattern.
+ #
+ $parts = preg_split($tag_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE);
+
+ if (count($parts) < 3) {
+ #
+ # End of $text reached with unbalenced tag(s).
+ # In that case, we return original text unchanged and pass the
+ # first character as filtered to prevent an infinite loop in the
+ # parent function.
+ #
+ return array($original_text{0}, substr($original_text, 1));
+ }
+
+ $block_text .= $parts[0]; # Text before current tag.
+ $tag = $parts[1]; # Tag to handle.
+ $text = $parts[2]; # Remaining text after current tag.
+
+ #
+ # Check for: Auto-close tag (like <hr/>)
+ # Comments and Processing Instructions.
+ #
+ if (preg_match('{^</?(?:'.$this->auto_close_tags_re.')\b}', $tag) ||
+ $tag{1} == '!' || $tag{1} == '?')
+ {
+ # Just add the tag to the block as if it was text.
+ $block_text .= $tag;
+ }
+ else {
+ #
+ # Increase/decrease nested tag count. Only do so if
+ # the tag's name match base tag's.
+ #
+ if (preg_match('{^</?'.$base_tag_name_re.'\b}', $tag)) {
+ if ($tag{1} == '/') $depth--;
+ else if ($tag{strlen($tag)-2} != '/') $depth++;
+ }
+
+ #
+ # Check for `markdown="1"` attribute and handle it.
+ #
+ if ($md_attr &&
+ preg_match($markdown_attr_re, $tag, $attr_m) &&
+ preg_match('/^1|block|span$/', $attr_m[2] . $attr_m[3]))
+ {
+ # Remove `markdown` attribute from opening tag.
+ $tag = preg_replace($markdown_attr_re, '', $tag);
+
+ # Check if text inside this tag must be parsed in span mode.
+ $this->mode = $attr_m[2] . $attr_m[3];
+ $span_mode = $this->mode == 'span' || $this->mode != 'block' &&
+ preg_match('{^<(?:'.$this->contain_span_tags_re.')\b}', $tag);
+
+ # Calculate indent before tag.
+ if (preg_match('/(?:^|\n)( *?)(?! ).*?$/', $block_text, $matches)) {
+ $strlen = $this->utf8_strlen;
+ $indent = $strlen($matches[1], 'UTF-8');
+ } else {
+ $indent = 0;
+ }
+
+ # End preceding block with this tag.
+ $block_text .= $tag;
+ $parsed .= $this->$hash_method($block_text);
+
+ # Get enclosing tag name for the ParseMarkdown function.
+ # (This pattern makes $tag_name_re safe without quoting.)
+ preg_match('/^<([\w:$]*)\b/', $tag, $matches);
+ $tag_name_re = $matches[1];
+
+ # Parse the content using the HTML-in-Markdown parser.
+ list ($block_text, $text)
+ = $this->_hashHTMLBlocks_inMarkdown($text, $indent,
+ $tag_name_re, $span_mode);
+
+ # Outdent markdown text.
+ if ($indent > 0) {
+ $block_text = preg_replace("/^[ ]{1,$indent}/m", "",
+ $block_text);
+ }
+
+ # Append tag content to parsed text.
+ if (!$span_mode) $parsed .= "\n\n$block_text\n\n";
+ else $parsed .= "$block_text";
+
+ # Start over a new block.
+ $block_text = "";
+ }
+ else $block_text .= $tag;
+ }
+
+ } while ($depth > 0);
+
+ #
+ # Hash last block text that wasn't processed inside the loop.
+ #
+ $parsed .= $this->$hash_method($block_text);
+
+ return array($parsed, $text);
+ }
+
+
+ function hashClean($text) {
+ #
+ # Called whenever a tag must be hashed when a function insert a "clean" tag
+ # in $text, it pass through this function and is automaticaly escaped,
+ # blocking invalid nested overlap.
+ #
+ return $this->hashPart($text, 'C');
+ }
+
+
+ function doHeaders($text) {
+ #
+ # Redefined to add id attribute support.
+ #
+ # Setext-style headers:
+ # Header 1 {#header1}
+ # ========
+ #
+ # Header 2 {#header2}
+ # --------
+ #
+ $text = preg_replace_callback(
+ '{
+ (^.+?) # $1: Header text
+ (?:[ ]+\{\#([-_:a-zA-Z0-9]+)\})? # $2: Id attribute
+ [ ]*\n(=+|-+)[ ]*\n+ # $3: Header footer
+ }mx',
+ array(&$this, '_doHeaders_callback_setext'), $text);
+
+ # atx-style headers:
+ # # Header 1 {#header1}
+ # ## Header 2 {#header2}
+ # ## Header 2 with closing hashes ## {#header3}
+ # ...
+ # ###### Header 6 {#header2}
+ #
+ $text = preg_replace_callback('{
+ ^(\#{1,6}) # $1 = string of #\'s
+ [ ]*
+ (.+?) # $2 = Header text
+ [ ]*
+ \#* # optional closing #\'s (not counted)
+ (?:[ ]+\{\#([-_:a-zA-Z0-9]+)\})? # id attribute
+ [ ]*
+ \n+
+ }xm',
+ array(&$this, '_doHeaders_callback_atx'), $text);
+
+ return $text;
+ }
+ function _doHeaders_attr($attr) {
+ if (empty($attr)) return "";
+ return " id=\"$attr\"";
+ }
+ function _doHeaders_callback_setext($matches) {
+ if ($matches[3] == '-' && preg_match('{^- }', $matches[1]))
+ return $matches[0];
+ $level = $matches[3]{0} == '=' ? 1 : 2;
+ $attr = $this->_doHeaders_attr($id =& $matches[2]);
+ $block = "<h$level$attr>".$this->runSpanGamut($matches[1])."</h$level>";
+ return "\n" . $this->hashBlock($block) . "\n\n";
+ }
+ function _doHeaders_callback_atx($matches) {
+ $level = strlen($matches[1]);
+ $attr = $this->_doHeaders_attr($id =& $matches[3]);
+ $block = "<h$level$attr>".$this->runSpanGamut($matches[2])."</h$level>";
+ return "\n" . $this->hashBlock($block) . "\n\n";
+ }
+
+
+ function doTables($text) {
+ #
+ # Form HTML tables.
+ #
+ $less_than_tab = $this->tab_width - 1;
+ #
+ # Find tables with leading pipe.
+ #
+ # | Header 1 | Header 2
+ # | -------- | --------
+ # | Cell 1 | Cell 2
+ # | Cell 3 | Cell 4
+ #
+ $text = preg_replace_callback('
+ {
+ ^ # Start of a line
+ [ ]{0,'.$less_than_tab.'} # Allowed whitespace.
+ [|] # Optional leading pipe (present)
+ (.+) \n # $1: Header row (at least one pipe)
+
+ [ ]{0,'.$less_than_tab.'} # Allowed whitespace.
+ [|] ([ ]*[-:]+[-| :]*) \n # $2: Header underline
+
+ ( # $3: Cells
+ (?>
+ [ ]* # Allowed whitespace.
+ [|] .* \n # Row content.
+ )*
+ )
+ (?=\n|\Z) # Stop at final double newline.
+ }xm',
+ array(&$this, '_doTable_leadingPipe_callback'), $text);
+
+ #
+ # Find tables without leading pipe.
+ #
+ # Header 1 | Header 2
+ # -------- | --------
+ # Cell 1 | Cell 2
+ # Cell 3 | Cell 4
+ #
+ $text = preg_replace_callback('
+ {
+ ^ # Start of a line
+ [ ]{0,'.$less_than_tab.'} # Allowed whitespace.
+ (\S.*[|].*) \n # $1: Header row (at least one pipe)
+
+ [ ]{0,'.$less_than_tab.'} # Allowed whitespace.
+ ([-:]+[ ]*[|][-| :]*) \n # $2: Header underline
+
+ ( # $3: Cells
+ (?>
+ .* [|] .* \n # Row content
+ )*
+ )
+ (?=\n|\Z) # Stop at final double newline.
+ }xm',
+ array(&$this, '_DoTable_callback'), $text);
+
+ return $text;
+ }
+ function _doTable_leadingPipe_callback($matches) {
+ $head = $matches[1];
+ $underline = $matches[2];
+ $content = $matches[3];
+
+ # Remove leading pipe for each row.
+ $content = preg_replace('/^ *[|]/m', '', $content);
+
+ return $this->_doTable_callback(array($matches[0], $head, $underline, $content));
+ }
+ function _doTable_callback($matches) {
+ $head = $matches[1];
+ $underline = $matches[2];
+ $content = $matches[3];
+
+ # Remove any tailing pipes for each line.
+ $head = preg_replace('/[|] *$/m', '', $head);
+ $underline = preg_replace('/[|] *$/m', '', $underline);
+ $content = preg_replace('/[|] *$/m', '', $content);
+
+ # Reading alignement from header underline.
+ $separators = preg_split('/ *[|] */', $underline);
+ foreach ($separators as $n => $s) {
+ if (preg_match('/^ *-+: *$/', $s)) $attr[$n] = ' align="right"';
+ else if (preg_match('/^ *:-+: *$/', $s))$attr[$n] = ' align="center"';
+ else if (preg_match('/^ *:-+ *$/', $s)) $attr[$n] = ' align="left"';
+ else $attr[$n] = '';
+ }
+
+ # Parsing span elements, including code spans, character escapes,
+ # and inline HTML tags, so that pipes inside those gets ignored.
+ $head = $this->parseSpan($head);
+ $headers = preg_split('/ *[|] */', $head);
+ $col_count = count($headers);
+
+ # Write column headers.
+ $text = "<table>\n";
+ $text .= "<thead>\n";
+ $text .= "<tr>\n";
+ foreach ($headers as $n => $header)
+ $text .= " <th$attr[$n]>".$this->runSpanGamut(trim($header))."</th>\n";
+ $text .= "</tr>\n";
+ $text .= "</thead>\n";
+
+ # Split content by row.
+ $rows = explode("\n", trim($content, "\n"));
+
+ $text .= "<tbody>\n";
+ foreach ($rows as $row) {
+ # Parsing span elements, including code spans, character escapes,
+ # and inline HTML tags, so that pipes inside those gets ignored.
+ $row = $this->parseSpan($row);
+
+ # Split row by cell.
+ $row_cells = preg_split('/ *[|] */', $row, $col_count);
+ $row_cells = array_pad($row_cells, $col_count, '');
+
+ $text .= "<tr>\n";
+ foreach ($row_cells as $n => $cell)
+ $text .= " <td$attr[$n]>".$this->runSpanGamut(trim($cell))."</td>\n";
+ $text .= "</tr>\n";
+ }
+ $text .= "</tbody>\n";
+ $text .= "</table>";
+
+ return $this->hashBlock($text) . "\n";
+ }
+
+
+ function doDefLists($text) {
+ #
+ # Form HTML definition lists.
+ #
+ $less_than_tab = $this->tab_width - 1;
+
+ # Re-usable pattern to match any entire dl list:
+ $whole_list_re = '(?>
+ ( # $1 = whole list
+ ( # $2
+ [ ]{0,'.$less_than_tab.'}
+ ((?>.*\S.*\n)+) # $3 = defined term
+ \n?
+ [ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition
+ )
+ (?s:.+?)
+ ( # $4
+ \z
+ |
+ \n{2,}
+ (?=\S)
+ (?! # Negative lookahead for another term
+ [ ]{0,'.$less_than_tab.'}
+ (?: \S.*\n )+? # defined term
+ \n?
+ [ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition
+ )
+ (?! # Negative lookahead for another definition
+ [ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition
+ )
+ )
+ )
+ )'; // mx
+
+ $text = preg_replace_callback('{
+ (?>\A\n?|(?<=\n\n))
+ '.$whole_list_re.'
+ }mx',
+ array(&$this, '_doDefLists_callback'), $text);
+
+ return $text;
+ }
+ function _doDefLists_callback($matches) {
+ # Re-usable patterns to match list item bullets and number markers:
+ $list = $matches[1];
+
+ # Turn double returns into triple returns, so that we can make a
+ # paragraph for the last item in a list, if necessary:
+ $result = trim($this->processDefListItems($list));
+ $result = "<dl>\n" . $result . "\n</dl>";
+ return $this->hashBlock($result) . "\n\n";
+ }
+
+
+ function processDefListItems($list_str) {
+ #
+ # Process the contents of a single definition list, splitting it
+ # into individual term and definition list items.
+ #
+ $less_than_tab = $this->tab_width - 1;
+
+ # trim trailing blank lines:
+ $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str);
+
+ # Process definition terms.
+ $list_str = preg_replace_callback('{
+ (?>\A\n?|\n\n+) # leading line
+ ( # definition terms = $1
+ [ ]{0,'.$less_than_tab.'} # leading whitespace
+ (?![:][ ]|[ ]) # negative lookahead for a definition
+ # mark (colon) or more whitespace.
+ (?> \S.* \n)+? # actual term (not whitespace).
+ )
+ (?=\n?[ ]{0,3}:[ ]) # lookahead for following line feed
+ # with a definition mark.
+ }xm',
+ array(&$this, '_processDefListItems_callback_dt'), $list_str);
+
+ # Process actual definitions.
+ $list_str = preg_replace_callback('{
+ \n(\n+)? # leading line = $1
+ ( # marker space = $2
+ [ ]{0,'.$less_than_tab.'} # whitespace before colon
+ [:][ ]+ # definition mark (colon)
+ )
+ ((?s:.+?)) # definition text = $3
+ (?= \n+ # stop at next definition mark,
+ (?: # next term or end of text
+ [ ]{0,'.$less_than_tab.'} [:][ ] |
+ <dt> | \z
+ )
+ )
+ }xm',
+ array(&$this, '_processDefListItems_callback_dd'), $list_str);
+
+ return $list_str;
+ }
+ function _processDefListItems_callback_dt($matches) {
+ $terms = explode("\n", trim($matches[1]));
+ $text = '';
+ foreach ($terms as $term) {
+ $term = $this->runSpanGamut(trim($term));
+ $text .= "\n<dt>" . $term . "</dt>";
+ }
+ return $text . "\n";
+ }
+ function _processDefListItems_callback_dd($matches) {
+ $leading_line = $matches[1];
+ $marker_space = $matches[2];
+ $def = $matches[3];
+
+ if ($leading_line || preg_match('/\n{2,}/', $def)) {
+ # Replace marker with the appropriate whitespace indentation
+ $def = str_repeat(' ', strlen($marker_space)) . $def;
+ $def = $this->runBlockGamut($this->outdent($def . "\n\n"));
+ $def = "\n". $def ."\n";
+ }
+ else {
+ $def = rtrim($def);
+ $def = $this->runSpanGamut($this->outdent($def));
+ }
+
+ return "\n<dd>" . $def . "</dd>\n";
+ }
+
+
+ function doFencedCodeBlocks($text) {
+ #
+ # Adding the fenced code block syntax to regular Markdown:
+ #
+ # ~~~
+ # Code block
+ # ~~~
+ #
+ $less_than_tab = $this->tab_width;
+
+ $text = preg_replace_callback('{
+ (?:\n|\A)
+ # 1: Opening marker
+ (
+ ~{3,} # Marker: three tilde or more.
+ )
+ [ ]* \n # Whitespace and newline following marker.
+
+ # 2: Content
+ (
+ (?>
+ (?!\1 [ ]* \n) # Not a closing marker.
+ .*\n+
+ )+
+ )
+
+ # Closing marker.
+ \1 [ ]* \n
+ }xm',
+ array(&$this, '_doFencedCodeBlocks_callback'), $text);
+
+ return $text;
+ }
+ function _doFencedCodeBlocks_callback($matches) {
+ $codeblock = $matches[2];
+ $codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
+ $codeblock = preg_replace_callback('/^\n+/',
+ array(&$this, '_doFencedCodeBlocks_newlines'), $codeblock);
+ $codeblock = "<pre><code>$codeblock</code></pre>";
+ return "\n\n".$this->hashBlock($codeblock)."\n\n";
+ }
+ function _doFencedCodeBlocks_newlines($matches) {
+ return str_repeat("<br$this->empty_element_suffix",
+ strlen($matches[0]));
+ }
+
+
+ #
+ # Redefining emphasis markers so that emphasis by underscore does not
+ # work in the middle of a word.
+ #
+ var $em_relist = array(
+ '' => '(?:(?<!\*)\*(?!\*)|(?<![a-zA-Z0-9_])_(?!_))(?=\S|$)(?![.,:;]\s)',
+ '*' => '(?<=\S|^)(?<!\*)\*(?!\*)',
+ '_' => '(?<=\S|^)(?<!_)_(?![a-zA-Z0-9_])',
+ );
+ var $strong_relist = array(
+ '' => '(?:(?<!\*)\*\*(?!\*)|(?<![a-zA-Z0-9_])__(?!_))(?=\S|$)(?![.,:;]\s)',
+ '**' => '(?<=\S|^)(?<!\*)\*\*(?!\*)',
+ '__' => '(?<=\S|^)(?<!_)__(?![a-zA-Z0-9_])',
+ );
+ var $em_strong_relist = array(
+ '' => '(?:(?<!\*)\*\*\*(?!\*)|(?<![a-zA-Z0-9_])___(?!_))(?=\S|$)(?![.,:;]\s)',
+ '***' => '(?<=\S|^)(?<!\*)\*\*\*(?!\*)',
+ '___' => '(?<=\S|^)(?<!_)___(?![a-zA-Z0-9_])',
+ );
+
+
+ function formParagraphs($text) {
+ #
+ # Params:
+ # $text - string to process with html <p> tags
+ #
+ # Strip leading and trailing lines:
+ $text = preg_replace('/\A\n+|\n+\z/', '', $text);
+
+ $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY);
+
+ #
+ # Wrap <p> tags and unhashify HTML blocks
+ #
+ foreach ($grafs as $key => $value) {
+ $value = trim($this->runSpanGamut($value));
+
+ # Check if this should be enclosed in a paragraph.
+ # Clean tag hashes & block tag hashes are left alone.
+ $is_p = !preg_match('/^B\x1A[0-9]+B|^C\x1A[0-9]+C$/', $value);
+
+ if ($is_p) {
+ $value = "<p>$value</p>";
+ }
+ $grafs[$key] = $value;
+ }
+
+ # Join grafs in one text, then unhash HTML tags.
+ $text = implode("\n\n", $grafs);
+
+ # Finish by removing any tag hashes still present in $text.
+ $text = $this->unhash($text);
+
+ return $text;
+ }
+
+
+ ### Footnotes
+
+ function stripFootnotes($text) {
+ #
+ # Strips link definitions from text, stores the URLs and titles in
+ # hash references.
+ #
+ $less_than_tab = $this->tab_width - 1;
+
+ # Link defs are in the form: [^id]: url "optional title"
+ $text = preg_replace_callback('{
+ ^[ ]{0,'.$less_than_tab.'}\[\^(.+?)\][ ]?: # note_id = $1
+ [ ]*
+ \n? # maybe *one* newline
+ ( # text = $2 (no blank lines allowed)
+ (?:
+ .+ # actual text
+ |
+ \n # newlines but
+ (?!\[\^.+?\]:\s)# negative lookahead for footnote marker.
+ (?!\n+[ ]{0,3}\S)# ensure line is not blank and followed
+ # by non-indented content
+ )*
+ )
+ }xm',
+ array(&$this, '_stripFootnotes_callback'),
+ $text);
+ return $text;
+ }
+ function _stripFootnotes_callback($matches) {
+ $note_id = $this->fn_id_prefix . $matches[1];
+ $this->footnotes[$note_id] = $this->outdent($matches[2]);
+ return ''; # String that will replace the block
+ }
+
+
+ function doFootnotes($text) {
+ #
+ # Replace footnote references in $text [^id] with a special text-token
+ # which will be replaced by the actual footnote marker in appendFootnotes.
+ #
+ if (!$this->in_anchor) {
+ $text = preg_replace('{\[\^(.+?)\]}', "F\x1Afn:\\1\x1A:", $text);
+ }
+ return $text;
+ }
+
+
+ function appendFootnotes($text) {
+ #
+ # Append footnote list to text.
+ #
+ $text = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}',
+ array(&$this, '_appendFootnotes_callback'), $text);
+
+ if (!empty($this->footnotes_ordered)) {
+ $text .= "\n\n";
+ $text .= "<div class=\"footnotes\">\n";
+ $text .= "<hr". $this->empty_element_suffix ."\n";
+ $text .= "<ol>\n\n";
+
+ $attr = " rev=\"footnote\"";
+ if ($this->fn_backlink_class != "") {
+ $class = $this->fn_backlink_class;
+ $class = $this->encodeAttribute($class);
+ $attr .= " class=\"$class\"";
+ }
+ if ($this->fn_backlink_title != "") {
+ $title = $this->fn_backlink_title;
+ $title = $this->encodeAttribute($title);
+ $attr .= " title=\"$title\"";
+ }
+ $num = 0;
+
+ while (!empty($this->footnotes_ordered)) {
+ $footnote = reset($this->footnotes_ordered);
+ $note_id = key($this->footnotes_ordered);
+ unset($this->footnotes_ordered[$note_id]);
+
+ $footnote .= "\n"; # Need to append newline before parsing.
+ $footnote = $this->runBlockGamut("$footnote\n");
+ $footnote = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}',
+ array(&$this, '_appendFootnotes_callback'), $footnote);
+
+ $attr = str_replace("%%", ++$num, $attr);
+ $note_id = $this->encodeAttribute($note_id);
+
+ # Add backlink to last paragraph; create new paragraph if needed.
+ $backlink = "<a href=\"#fnref:$note_id\"$attr>↩</a>";
+ if (preg_match('{</p>$}', $footnote)) {
+ $footnote = substr($footnote, 0, -4) . " $backlink</p>";
+ } else {
+ $footnote .= "\n\n<p>$backlink</p>";
+ }
+
+ $text .= "<li id=\"fn:$note_id\">\n";
+ $text .= $footnote . "\n";
+ $text .= "</li>\n\n";
+ }
+
+ $text .= "</ol>\n";
+ $text .= "</div>";
+ }
+ return $text;
+ }
+ function _appendFootnotes_callback($matches) {
+ $node_id = $this->fn_id_prefix . $matches[1];
+
+ # Create footnote marker only if it has a corresponding footnote *and*
+ # the footnote hasn't been used by another marker.
+ if (isset($this->footnotes[$node_id])) {
+ # Transfert footnote content to the ordered list.
+ $this->footnotes_ordered[$node_id] = $this->footnotes[$node_id];
+ unset($this->footnotes[$node_id]);
+
+ $num = $this->footnote_counter++;
+ $attr = " rel=\"footnote\"";
+ if ($this->fn_link_class != "") {
+ $class = $this->fn_link_class;
+ $class = $this->encodeAttribute($class);
+ $attr .= " class=\"$class\"";
+ }
+ if ($this->fn_link_title != "") {
+ $title = $this->fn_link_title;
+ $title = $this->encodeAttribute($title);
+ $attr .= " title=\"$title\"";
+ }
+
+ $attr = str_replace("%%", $num, $attr);
+ $node_id = $this->encodeAttribute($node_id);
+
+ return
+ "<sup id=\"fnref:$node_id\">".
+ "<a href=\"#fn:$node_id\"$attr>$num</a>".
+ "</sup>";
+ }
+
+ return "[^".$matches[1]."]";
+ }
+
+
+ ### Abbreviations ###
+
+ function stripAbbreviations($text) {
+ #
+ # Strips abbreviations from text, stores titles in hash references.
+ #
+ $less_than_tab = $this->tab_width - 1;
+
+ # Link defs are in the form: [id]*: url "optional title"
+ $text = preg_replace_callback('{
+ ^[ ]{0,'.$less_than_tab.'}\*\[(.+?)\][ ]?: # abbr_id = $1
+ (.*) # text = $2 (no blank lines allowed)
+ }xm',
+ array(&$this, '_stripAbbreviations_callback'),
+ $text);
+ return $text;
+ }
+ function _stripAbbreviations_callback($matches) {
+ $abbr_word = $matches[1];
+ $abbr_desc = $matches[2];
+ if ($this->abbr_word_re)
+ $this->abbr_word_re .= '|';
+ $this->abbr_word_re .= preg_quote($abbr_word);
+ $this->abbr_desciptions[$abbr_word] = trim($abbr_desc);
+ return ''; # String that will replace the block
+ }
+
+
+ function doAbbreviations($text) {
+ #
+ # Find defined abbreviations in text and wrap them in <abbr> elements.
+ #
+ if ($this->abbr_word_re) {
+ // cannot use the /x modifier because abbr_word_re may
+ // contain significant spaces:
+ $text = preg_replace_callback('{'.
+ '(?<![\w\x1A])'.
+ '(?:'.$this->abbr_word_re.')'.
+ '(?![\w\x1A])'.
+ '}',
+ array(&$this, '_doAbbreviations_callback'), $text);
+ }
+ return $text;
+ }
+ function _doAbbreviations_callback($matches) {
+ $abbr = $matches[0];
+ if (isset($this->abbr_desciptions[$abbr])) {
+ $desc = $this->abbr_desciptions[$abbr];
+ if (empty($desc)) {
+ return $this->hashPart("<abbr>$abbr</abbr>");
+ } else {
+ $desc = $this->encodeAttribute($desc);
+ return $this->hashPart("<abbr title=\"$desc\">$abbr</abbr>");
+ }
+ } else {
+ return $matches[0];
+ }
+ }
+
+}
+
+
+/*
+
+PHP Markdown Extra
+==================
+
+Description
+-----------
+
+This is a PHP port of the original Markdown formatter written in Perl
+by John Gruber. This special "Extra" version of PHP Markdown features
+further enhancements to the syntax for making additional constructs
+such as tables and definition list.
+
+Markdown is a text-to-HTML filter; it translates an easy-to-read /
+easy-to-write structured text format into HTML. Markdown's text format
+is most similar to that of plain text email, and supports features such
+as headers, *emphasis*, code blocks, blockquotes, and links.
+
+Markdown's syntax is designed not as a generic markup language, but
+specifically to serve as a front-end to (X)HTML. You can use span-level
+HTML tags anywhere in a Markdown document, and you can use block level
+HTML tags (like <div> and <table> as well).
+
+For more information about Markdown's syntax, see:
+
+<http://daringfireball.net/projects/markdown/>
+
+
+Bugs
+----
+
+To file bug reports please send email to:
+
+<michel.fortin@michelf.com>
+
+Please include with your report: (1) the example input; (2) the output you
+expected; (3) the output Markdown actually produced.
+
+
+Version History
+---------------
+
+See the readme file for detailed release notes for this version.
+
+
+Copyright and License
+---------------------
+
+PHP Markdown & Extra
+Copyright (c) 2004-2009 Michel Fortin
+<http://michelf.com/>
+All rights reserved.
+
+Based on Markdown
+Copyright (c) 2003-2006 John Gruber
+<http://daringfireball.net/>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+* Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+* Neither the name "Markdown" nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+This software is provided by the copyright holders and contributors "as
+is" and any express or implied warranties, including, but not limited
+to, the implied warranties of merchantability and fitness for a
+particular purpose are disclaimed. In no event shall the copyright owner
+or contributors be liable for any direct, indirect, incidental, special,
+exemplary, or consequential damages (including, but not limited to,
+procurement of substitute goods or services; loss of use, data, or
+profits; or business interruption) however caused and on any theory of
+liability, whether in contract, strict liability, or tort (including
+negligence or otherwise) arising in any way out of the use of this
+software, even if advised of the possibility of such damage.
+
+*/
+?>
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span><span class="cx" style="display: block; padding: 0 10px">Property changes on: sites/trunk/wordpress.org/public_html/wp-content/plugins/plugin-directory/readme-parser/markdown.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgpluginsGruntfilejs"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/Gruntfile.js</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/Gruntfile.js (rev 0)
+++ sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/Gruntfile.js 2016-02-13 03:38:51 UTC (rev 2499)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,89 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/* jshint node:true */
+module.exports = function(grunt) {
+ var path = require('path');
+
+ // Load tasks.
+ require('matchdep').filterDev(['grunt-*']).forEach( grunt.loadNpmTasks );
+
+ // Project configuration.
+ grunt.initConfig({
+ rtlcss: {
+ options: {
+ // rtlcss options
+ config: {
+ swapLeftRightInUrl: false,
+ swapLtrRtlInUrl: false,
+ autoRename: false,
+ preserveDirectives: true,
+ stringMap: [
+ {
+ name: 'import-rtl-stylesheet',
+ search: [ '.css' ],
+ replace: [ '-rtl.css' ],
+ options: {
+ scope: 'url',
+ ignoreCase: false
+ }
+ }
+ ]
+ },
+ properties : [
+ {
+ name: 'swap-dashicons-left-right-arrows',
+ expr: /content/im,
+ action: function( prop, value ) {
+ if ( value === '"\\f141"' ) { // dashicons-arrow-left
+ value = '"\\f139"';
+ } else if ( value === '"\\f340"' ) { // dashicons-arrow-left-alt
+ value = '"\\f344"';
+ } else if ( value === '"\\f341"' ) { // dashicons-arrow-left-alt2
+ value = '"\\f345"';
+ } else if ( value === '"\\f139"' ) { // dashicons-arrow-right
+ value = '"\\f141"';
+ } else if ( value === '"\\f344"' ) { // dashicons-arrow-right-alt
+ value = '"\\f340"';
+ } else if ( value === '"\\f345"' ) { // dashicons-arrow-right-alt2
+ value = '"\\f341"';
+ } else if ( value === '"\\2192"' ) { // Unicode rightwards arrow
+ value = '"\\2190"';
+ } else if ( value === '"\\2190"' ) { // Unicode leftwards arrow
+ value = '"\\2192"';
+ }
+ return { prop: prop, value: value };
+ }
+ }
+ ],
+ saveUnmodified: false
+ },
+ theme: {
+ expand: true,
+ ext: '-rtl.css',
+ src: [
+ 'style.css',
+ ]
+ },
+ },
+ uglify: {
+ options: {
+ ASCIIOnly: true
+ },
+ js: {
+ expand: true,
+ ext: '.min.js',
+ src: [ 'js/theme.js' ]
+ }
+ }
+ });
+
+ // Register tasks.
+
+ grunt.registerTask( 'build', [
+ 'rtlcss',
+ 'uglify'
+ ] );
+
+ // Default task.
+ grunt.registerTask('default', ['build']);
+
+};
+
</ins></span></pre></div>
<a id="sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgpluginsfilterbarphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/filter-bar.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/filter-bar.php (rev 0)
+++ sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/filter-bar.php 2016-02-13 03:38:51 UTC (rev 2499)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,25 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<div class="wrapper">
+ <div class="col-12 filter-bar">
+ <div class="wp-filter">
+ <ul class="filter-links">
+ <?php if ( get_query_var('s' ) ) { ?>
+ <li class="plugin-install-search"><a href="<?php echo esc_url( home_url( 'search/' . urlencode( get_query_var('s') ) . '/' ) ); ?>" class="current"><?php _ex( 'Search Results', 'tab', 'wporg-plugins' ); ?></a></li>
+ <?php } ?>
+ <li class="plugin-install-featured"><a href="<?php echo esc_url( home_url( 'browse/featured/' ) ); ?>" <?php if ( (is_front_page() && !get_query_var('browse') ) || 'featured' == get_query_var('browse') ) { echo 'class="current"'; } ?>><?php _ex( 'Featured', 'plugins', 'wporg-plugins' ); ?></a></li>
+ <li class="plugin-install-popular"><a href="<?php echo esc_url( home_url( 'browse/popular/' ) ); ?>" <?php if ( 'popular' == get_query_var('browse') ) { echo 'class="current"'; } ?>><?php _ex( 'Popular', 'plugins', 'wporg-plugins' ); ?></a> </li>
+ <?php if ( is_user_logged_in() ) { ?>
+ <li class="plugin-install-favorites"><a href="<?php echo esc_url( home_url( 'browse/favorites/' ) ); ?>" <?php if ( 'favorites' == get_query_var('browse') ) { echo 'class="current"'; } ?>><?php _ex( 'Favorites', 'plugins', 'wporg-plugins' ); ?></a></li>
+ <?php } ?>
+ <li class="plugin-install-beta"><a href="<?php echo esc_url( home_url( 'browse/beta/' ) ); ?>" <?php if ( 'beta' == get_query_var('browse') ) { echo 'class="current"'; } ?>><?php _ex( 'Beta Testing', 'plugins', 'wporg-plugins' ); ?></a></li>
+ <li class="plugin-developer"><a href="<?php echo get_permalink( get_page_by_path( 'about' ) ); ?>" <?php if ( 'about' == get_query_var( 'pagename' ) ) { echo 'class="current"'; } ?>><?php _ex( 'Developers', 'plugins', 'wporg-plugins' ); ?></a></li>
+ </ul>
+
+ <form class="search-form search-plugins" method="get" action="<?php echo home_url('/'); ?>">
+ <label><span class="screen-reader-text"><?php _e( 'Search Plugins', 'wporg-plugins' ); ?></span>
+ <input type="search" name="s" value="<?php echo esc_attr( get_query_var('s') ); ?>" class="wp-filter-search" placeholder="<?php esc_attr_e( 'Search plugins...', 'wporg-plugins' ); ?>">
+ </label>
+ <input type="submit" name="" id="search-submit" class="button screen-reader-text" value="<?php esc_attr_e( 'Search Plugins', 'wporg-plugins' ); ?>">
+ </form>
+ </div>
+ </div>
+</div>
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/filter-bar.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgpluginsfooterphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/footer.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/footer.php (rev 0)
+++ sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/footer.php 2016-02-13 03:38:51 UTC (rev 2499)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,10 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * The template for displaying the footer.
+ *
+ * @package wporg-plugins
+ */
+?>
+</div>
+
+<?php require WPORGPATH . 'footer.php';
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/footer.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgpluginsfunctionsphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/functions.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/functions.php (rev 0)
+++ sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/functions.php 2016-02-13 03:38:51 UTC (rev 2499)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,53 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+
+/**
+ * WP.org Themes' functions and definitions.
+ *
+ * @package wporg-plugins
+ */
+
+function wporg_plugins_setup() {
+ global $themes_allowedtags;
+
+ load_theme_textdomain( 'wporg-plugins' );
+
+ include_once __DIR__ . '/template-tags.php';
+
+ add_theme_support( 'html5', array(
+ 'search-form', 'comment-form', 'comment-list', 'gallery', 'caption'
+ ) );
+
+ // No need for canonical lookups
+ //remove_action( 'template_redirect', 'redirect_canonical' );
+ remove_action( 'template_redirect', 'wp_old_slug_redirect' );
+}
+add_action( 'after_setup_theme', 'wporg_plugins_setup' );
+
+/**
+ * Enqueue scripts and styles.
+ */
+function wporg_plugins_scripts() {
+ $script_debug = true || defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG;
+ $suffix = $script_debug ? '' : '.min';
+
+ // Concatenates core scripts when possible.
+ if ( ! $script_debug ) {
+ $GLOBALS['concatenate_scripts'] = true;
+ }
+
+ $stylesheet = get_stylesheet_uri();
+ if ( is_rtl() ) {
+// $stylesheet = str_replace( '.css', '-rtl.css', $stylesheet ); // TODO, not being generated yet
+ }
+ wp_enqueue_style( 'wporg-plugins', $stylesheet, array(), time() );
+
+ // No Jetpack styles needed.
+ add_filter( 'jetpack_implode_frontend_css', '__return_false' );
+}
+add_action( 'wp_enqueue_scripts', 'wporg_plugins_scripts' );
+
+function wporg_plugins_body_class( $classes ) {
+ $classes[] = 'plugins-directory';
+ return $classes;
+}
+add_filter( 'body_class', 'wporg_plugins_body_class' );
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/functions.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgpluginsheaderphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/header.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/header.php (rev 0)
+++ sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/header.php 2016-02-13 03:38:51 UTC (rev 2499)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,39 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+/**
+ * The header for our theme.
+ *
+ * @package wporg-plugins
+ */
+
+$GLOBALS['pagetitle'] = __( 'Plugin Directory — Free WordPress Plugins', 'wporg-plugins' );
+
+require WPORGPATH . 'header.php';
+?>
+
+<div id="headline">
+ <div class="wrapper">
+ <h2><a href="<?php echo home_url('/'); ?>"><?php _e( 'Plugin Directory', 'wporg-plugins' ); ?></a></h2>
+ <?php
+ $items = array();
+ if ( is_user_logged_in() ) {
+ $items[] = sprintf(
+ __( 'Welcome, %s', 'wporg-plugins' ),
+ sprintf(
+ '<a href="https://profiles.wordpress.org/%s">%s</a>',
+ wp_get_current_user()->user_nicename,
+ wp_get_current_user()->display_name
+ )
+ );
+ if ( true /* user_has_plugins */ ) {
+ $items[] = '<a href="' . admin_url( 'edit.php?post_type=plugin' ) . '">' . __( 'Manage My Plugins', 'wporg-plugins' ) . '</a>';
+ }
+ $items[] = '<a href="https://login.wordpress.org/logout">' . __( 'Log Out', 'wporg-plugins' ) . '</a>';
+ } else {
+ $items[] = '<a href="https://login.wordpress.org/?redirect_to=' . urlencode( wporg_plugins_self_link() ) . '">' . __( 'Log In', 'wporg-plugins' ) . '</a>';
+ }
+ echo '<p class="login">' . implode( ' | ', $items ) . '</p>';
+ ?>
+ </div>
+</div>
+
+<div id="pagebody">
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span><span class="cx" style="display: block; padding: 0 10px">Property changes on: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/header.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgpluginsindexphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/index.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/index.php (rev 0)
+++ sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/index.php 2016-02-13 03:38:51 UTC (rev 2499)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,29 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php get_header(); ?>
+
+<?php get_template_part( 'filter-bar' ); ?>
+
+<div class="wrapper">
+ <div class="col-12" itemscope itemtype="http://schema.org/SoftwareApplication">
+ <?php get_template_part( 'view-intro' ); ?>
+
+ <div class="plugin-group">
+
+ <?php
+ if ( have_posts() ) {
+ while ( have_posts() ) {
+ the_post();
+ get_template_part( 'plugin-card' );
+ }
+ } else {
+ echo '<p class="no-plugin-results">No plugins match your request.</p>';
+ }
+ ?>
+
+ </div>
+
+ </div>
+</div>
+
+<br class="clear" />
+<?php
+get_footer();
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/index.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgpluginspagephp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/page.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/page.php (rev 0)
+++ sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/page.php 2016-02-13 03:38:51 UTC (rev 2499)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,16 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php get_header(); ?>
+
+<?php the_post(); ?>
+
+<?php get_template_part( 'filter-bar' ); ?>
+
+<div class="wrapper">
+ <div class="col-12" itemscope itemtype="http://schema.org/SoftwareApplication">
+ <h2><?php the_title(); ?></h2>
+ <?php the_content(); ?>
+ </div>
+</div>
+
+<br class="clear" />
+<?php
+get_footer();
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/page.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgpluginsplugincardphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/plugin-card.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/plugin-card.php (rev 0)
+++ sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/plugin-card.php 2016-02-13 03:38:51 UTC (rev 2499)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,28 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<div class="plugin-card">
+ <div class="plugin-card-top">
+
+ <a href="<?php the_permalink(); ?>" class="plugin-icon"><style>#plugin-icon-<?php echo esc_attr( $post->post_name ); ?> { width:128px; height:128px; background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMTEiIGhlaWdodD0iMTI5IiB2aWV3Ym94PSIwIDAgMTExIDEyOSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0icmdiKDI0MSwgMjQxLCAyNDEpIiAvPjxyZWN0IHg9Ii0xMS44MzMzMzMzMzMzMzMiIHk9Ii0xMS44MzMzMzMzMzMzMzMiIHdpZHRoPSIyMy42NjY2NjY2NjY2NjciIGhlaWdodD0iMjMuNjY2NjY2NjY2NjY3IiBzdHJva2U9IiMwMDAiIHN0cm9rZS1vcGFjaXR5PSIwLjAyIiBmaWxsPSIjZGRkIiBmaWxsLW9wYWNpdHk9IjAuMDg5MzMzMzMzMzMzMzMzIiBzdHJva2Utd2lkdGg9IjEiIC8+PHJlY3QgeD0iMTAwLjE1ODUzNTc3OTEzIiB5PSItMTEuODMzMzMzMzMzMzMzIiB3aWR0aD0iMjMuNjY2NjY2NjY2NjY3IiBoZWlnaHQ9IjIzLjY2NjY2NjY2NjY2NyIgc3Ryb2tlPSIjMDAwIiBzdHJva2Utb3BhY2l0eT0iMC4wMiIgZmlsbD0iI2RkZCIgZmlsbC1vcGFjaXR5PSIwLjA4OTMzMzMzMzMzMzMzMyIgc3
Ryb2tlLXdpZHRoPSIxIiAvPjxyZWN0IHg9Ii0xMS44MzMzMzMzMzMzMzMiIHk9IjExNy40ODM3MzgyMjQ5MyIgd2lkdGg9IjIzLjY2NjY2NjY2NjY2NyIgaGVpZ2h0PSIyMy42NjY2NjY2NjY2NjciIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLW9wYWNpdHk9IjAuMDIiIGZpbGw9IiNkZGQiIGZpbGwtb3BhY2l0eT0iMC4wODkzMzMzMzMzMzMzMzMiIHN0cm9rZS13aWR0aD0iMSIgLz48cmVjdCB4PSIxMDAuMTU4NTM1Nzc5MTMiIHk9IjExNy40ODM3MzgyMjQ5MyIgd2lkdGg9IjIzLjY2NjY2NjY2NjY2NyIgaGVpZ2h0PSIyMy42NjY2NjY2NjY2NjciIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLW9wYWNpdHk9IjAuMDIiIGZpbGw9IiNkZGQiIGZpbGwtb3BhY2l0eT0iMC4wODkzMzMzMzMzMzMzMzMiIHN0cm9rZS13aWR0aD0iMSIgLz48cmVjdCB4PSI0NC4xNjI2MDEyMjI4OTgiIHk9IjIwLjQ5NTkzNDU1NjIzMiIgd2lkdGg9IjIzLjY2NjY2NjY2NjY2NyIgaGVpZ2h0PSIyMy42NjY2NjY2NjY2NjciIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLW9wYWNpdHk9IjAuMDIiIGZpbGw9IiNkZGQiIGZpbGwtb3BhY2l0eT0iMC4xMDY2NjY2NjY2NjY2NyIgc3Ryb2tlLXdpZHRoPSIxIiAvPjxyZWN0IHg9Ii0xMS44MzMzMzMzMzMzMzMiIHk9IjUyLjgyNTIwMjQ0NTc5NyIgd2lkdGg9IjIzLjY2NjY2NjY2NjY2NyIgaGVpZ2h0PSIyMy42NjY2NjY2NjY2NjciIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLW9wYWNpdHk9IjAuMDIiIGZpbGw9IiNkZGQiIGZ
pbGwtb3BhY2l0eT0iMC4xMDY2NjY2NjY2NjY2NyIgc3Ryb2tlLXdpZHRoPSIxIiAvPjxyZWN0IHg9IjEwMC4xNTg1MzU3NzkxMyIgeT0iNTIuODI1MjAyNDQ1Nzk3IiB3aWR0aD0iMjMuNjY2NjY2NjY2NjY3IiBoZWlnaHQ9IjIzLjY2NjY2NjY2NjY2NyIgc3Ryb2tlPSIjMDAwIiBzdHJva2Utb3BhY2l0eT0iMC4wMiIgZmlsbD0iI2RkZCIgZmlsbC1vcGFjaXR5PSIwLjEwNjY2NjY2NjY2NjY3IiBzdHJva2Utd2lkdGg9IjEiIC8+PHJlY3QgeD0iNDQuMTYyNjAxMjIyODk4IiB5PSI4NS4xNTQ0NzAzMzUzNjIiIHdpZHRoPSIyMy42NjY2NjY2NjY2NjciIGhlaWdodD0iMjMuNjY2NjY2NjY2NjY3IiBzdHJva2U9IiMwMDAiIHN0cm9rZS1vcGFjaXR5PSIwLjAyIiBmaWxsPSIjMjIyIiBmaWxsLW9wYWNpdHk9IjAuMTE1MzMzMzMzMzMzMzMiIHN0cm9rZS13aWR0aD0iMSIgLz48cG9seWxpbmUgcG9pbnRzPSIwLCAwLCAyMC40OTU5MzQ1NTYyMzIsIDExLjgzMzMzMzMzMzMzMywgMCwgMjMuNjY2NjY2NjY2NjY3LCAwLCAwIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1vcGFjaXR5PSIwLjAyIiBmaWxsPSIjZGRkIiBmaWxsLW9wYWNpdHk9IjAuMDcyIiBzdHJva2Utd2lkdGg9IjEiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDExLjgzMzMzMzMzMzMzMywgLTExLjgzMzMzMzMzMzMzMykgcm90YXRlKDAsIDExLjgzMzMzMzMzMzMzMywgMTAuMjQ3OTY3Mjc4MTE2KSIgLz48cG9seWxpbmUgcG9pbnRzPSIwLCAwLCAyMC40OTU5MzQ1NTYy
MzIsIDExLjgzMzMzMzMzMzMzMywgMCwgMjMuNjY2NjY2NjY2NjY3LCAwLCAwIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1vcGFjaXR5PSIwLjAyIiBmaWxsPSIjZGRkIiBmaWxsLW9wYWNpdHk9IjAuMDcyIiBzdHJva2Utd2lkdGg9IjEiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDExLjgzMzMzMzMzMzMzMywgMTQxLjE1MDQwNDg5MTU5KSByb3RhdGUoMCwgMTEuODMzMzMzMzMzMzMzLCAxMC4yNDc5NjcyNzgxMTYpIHNjYWxlKDEsIC0xKSIgLz48cG9seWxpbmUgcG9pbnRzPSIwLCAwLCAyMC40OTU5MzQ1NTYyMzIsIDExLjgzMzMzMzMzMzMzMywgMCwgMjMuNjY2NjY2NjY2NjY3LCAwLCAwIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1vcGFjaXR5PSIwLjAyIiBmaWxsPSIjZGRkIiBmaWxsLW9wYWNpdHk9IjAuMDIiIHN0cm9rZS13aWR0aD0iMSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTAwLjE1ODUzNTc3OTEzLCAtMTEuODMzMzMzMzMzMzMzKSByb3RhdGUoMCwgMTEuODMzMzMzMzMzMzMzLCAxMC4yNDc5NjcyNzgxMTYpIHNjYWxlKC0xLCAxKSIgLz48cG9seWxpbmUgcG9pbnRzPSIwLCAwLCAyMC40OTU5MzQ1NTYyMzIsIDExLjgzMzMzMzMzMzMzMywgMCwgMjMuNjY2NjY2NjY2NjY3LCAwLCAwIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1vcGFjaXR5PSIwLjAyIiBmaWxsPSIjZGRkIiBmaWxsLW9wYWNpdHk9IjAuMDIiIHN0cm9rZS13aWR0aD0iMSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTAwLjE1ODUzNTc3OTEzLCAxNDEuMTUwN
DA0ODkxNTkpIHJvdGF0ZSgwLCAxMS44MzMzMzMzMzMzMzMsIDEwLjI0Nzk2NzI3ODExNikgc2NhbGUoLTEsIC0xKSIgLz48cG9seWxpbmUgcG9pbnRzPSIwLCAwLCAyMC40OTU5MzQ1NTYyMzIsIDExLjgzMzMzMzMzMzMzMywgMCwgMjMuNjY2NjY2NjY2NjY3LCAwLCAwIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1vcGFjaXR5PSIwLjAyIiBmaWxsPSIjZGRkIiBmaWxsLW9wYWNpdHk9IjAuMDIiIHN0cm9rZS13aWR0aD0iMSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNjcuODI5MjY3ODg5NTY1LCAyMC40OTU5MzQ1NTYyMzIpIiAvPjxwb2x5bGluZSBwb2ludHM9IjAsIDAsIDIwLjQ5NTkzNDU1NjIzMiwgMTEuODMzMzMzMzMzMzMzLCAwLCAyMy42NjY2NjY2NjY2NjcsIDAsIDAiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLW9wYWNpdHk9IjAuMDIiIGZpbGw9IiNkZGQiIGZpbGwtb3BhY2l0eT0iMC4xMDY2NjY2NjY2NjY2NyIgc3Ryb2tlLXdpZHRoPSIxIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSg0NC4xNjI2MDEyMjI4OTgsIDIwLjQ5NTkzNDU1NjIzMikgc2NhbGUoLTEsIDEpIiAvPjxwb2x5bGluZSBwb2ludHM9IjAsIDAsIDIwLjQ5NTkzNDU1NjIzMiwgMTEuODMzMzMzMzMzMzMzLCAwLCAyMy42NjY2NjY2NjY2NjcsIDAsIDAiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLW9wYWNpdHk9IjAuMDIiIGZpbGw9IiNkZGQiIGZpbGwtb3BhY2l0eT0iMC4xMDY2NjY2NjY2NjY2NyIgc3Ryb2tlLXdpZHRoPSIxIiB0cmFuc2Zvcm09InRyYW5zbG
F0ZSg2Ny44MjkyNjc4ODk1NjUsIDEwOC44MjExMzcwMDIwMykgc2NhbGUoMSwgLTEpIiAvPjxwb2x5bGluZSBwb2ludHM9IjAsIDAsIDIwLjQ5NTkzNDU1NjIzMiwgMTEuODMzMzMzMzMzMzMzLCAwLCAyMy42NjY2NjY2NjY2NjcsIDAsIDAiIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLW9wYWNpdHk9IjAuMDIiIGZpbGw9IiMyMjIiIGZpbGwtb3BhY2l0eT0iMC4wNDYiIHN0cm9rZS13aWR0aD0iMSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoNDQuMTYyNjAxMjIyODk4LCAxMDguODIxMTM3MDAyMDMpIHNjYWxlKC0xLCAtMSkiIC8+PHBvbHlsaW5lIHBvaW50cz0iMCwgMCwgMjAuNDk1OTM0NTU2MjMyLCAxMS44MzMzMzMzMzMzMzMsIDAsIDIzLjY2NjY2NjY2NjY2NywgMCwgMCIgc3Ryb2tlPSIjMDAwIiBzdHJva2Utb3BhY2l0eT0iMC4wMiIgZmlsbD0iI2RkZCIgZmlsbC1vcGFjaXR5PSIwLjE0MTMzMzMzMzMzMzMzIiBzdHJva2Utd2lkdGg9IjEiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDExLjgzMzMzMzMzMzMzMywgNTIuODI1MjAyNDQ1Nzk3KSIgLz48cG9seWxpbmUgcG9pbnRzPSIwLCAwLCAyMC40OTU5MzQ1NTYyMzIsIDExLjgzMzMzMzMzMzMzMywgMCwgMjMuNjY2NjY2NjY2NjY3LCAwLCAwIiBzdHJva2U9IiMwMDAiIHN0cm9rZS1vcGFjaXR5PSIwLjAyIiBmaWxsPSIjMjIyIiBmaWxsLW9wYWNpdHk9IjAuMDQ2IiBzdHJva2Utd2lkdGg9IjEiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEwMC4xNTg1MzU3NzkxMywgNTIuODI
1MjAyNDQ1Nzk3KSBzY2FsZSgtMSwgMSkiIC8+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjIzLjY2NjY2NjY2NjY2NyIgaGVpZ2h0PSIyMy42NjY2NjY2NjY2NjciIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLW9wYWNpdHk9IjAuMDIiIGZpbGw9IiNkZGQiIGZpbGwtb3BhY2l0eT0iMC4xNDEzMzMzMzMzMzMzMyIgc3Ryb2tlLXdpZHRoPSIxIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMS44MzMzMzMzMzMzMzMsIDExLjgzMzMzMzMzMzMzMykgcm90YXRlKC0zMCwgMCwgMCkiIC8+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjIzLjY2NjY2NjY2NjY2NyIgaGVpZ2h0PSIyMy42NjY2NjY2NjY2NjciIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLW9wYWNpdHk9IjAuMDIiIGZpbGw9IiNkZGQiIGZpbGwtb3BhY2l0eT0iMC4xNDEzMzMzMzMzMzMzMyIgc3Ryb2tlLXdpZHRoPSIxIiB0cmFuc2Zvcm09InNjYWxlKC0xLCAxKSB0cmFuc2xhdGUoLTEwMC4xNTg1MzU3NzkxMywgMTEuODMzMzMzMzMzMzMzKSByb3RhdGUoLTMwLCAwLCAwKSIgLz48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMjMuNjY2NjY2NjY2NjY3IiBoZWlnaHQ9IjIzLjY2NjY2NjY2NjY2NyIgc3Ryb2tlPSIjMDAwIiBzdHJva2Utb3BhY2l0eT0iMC4wMiIgZmlsbD0iIzIyMiIgZmlsbC1vcGFjaXR5PSIwLjAyODY2NjY2NjY2NjY2NyIgc3Ryb2tlLXdpZHRoPSIxIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMS44MzMzMzMzMzMzMzMsIDI5LjE1ODUzNTc3OTEzKSByb3RhdGUo
MzAsIDAsIDIzLjY2NjY2NjY2NjY2NykiIC8+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjIzLjY2NjY2NjY2NjY2NyIgaGVpZ2h0PSIyMy42NjY2NjY2NjY2NjciIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLW9wYWNpdHk9IjAuMDIiIGZpbGw9IiNkZGQiIGZpbGwtb3BhY2l0eT0iMC4wNTQ2NjY2NjY2NjY2NjciIHN0cm9rZS13aWR0aD0iMSIgdHJhbnNmb3JtPSJzY2FsZSgtMSwgMSkgdHJhbnNsYXRlKC0xMDAuMTU4NTM1Nzc5MTMsIDI5LjE1ODUzNTc3OTEzKSByb3RhdGUoMzAsIDAsIDIzLjY2NjY2NjY2NjY2NykiIC8+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjIzLjY2NjY2NjY2NjY2NyIgaGVpZ2h0PSIyMy42NjY2NjY2NjY2NjciIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLW9wYWNpdHk9IjAuMDIiIGZpbGw9IiMyMjIiIGZpbGwtb3BhY2l0eT0iMC4xMzI2NjY2NjY2NjY2NyIgc3Ryb2tlLXdpZHRoPSIxIiB0cmFuc2Zvcm09InNjYWxlKDEsIC0xKSB0cmFuc2xhdGUoMTEuODMzMzMzMzMzMzMzLCAtMTAwLjE1ODUzNTc3OTEzKSByb3RhdGUoMzAsIDAsIDIzLjY2NjY2NjY2NjY2NykiIC8+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjIzLjY2NjY2NjY2NjY2NyIgaGVpZ2h0PSIyMy42NjY2NjY2NjY2NjciIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLW9wYWNpdHk9IjAuMDIiIGZpbGw9IiNkZGQiIGZpbGwtb3BhY2l0eT0iMC4wODkzMzMzMzMzMzMzMzMiIHN0cm9rZS13aWR0aD0iMSIgdHJhbnNmb3JtPSJzY2FsZSgtMSwgL
TEpIHRyYW5zbGF0ZSgtMTAwLjE1ODUzNTc3OTEzLCAtMTAwLjE1ODUzNTc3OTEzKSByb3RhdGUoMzAsIDAsIDIzLjY2NjY2NjY2NjY2NykiIC8+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjIzLjY2NjY2NjY2NjY2NyIgaGVpZ2h0PSIyMy42NjY2NjY2NjY2NjciIHN0cm9rZT0iIzAwMCIgc3Ryb2tlLW9wYWNpdHk9IjAuMDIiIGZpbGw9IiMyMjIiIGZpbGwtb3BhY2l0eT0iMC4xNSIgc3Ryb2tlLXdpZHRoPSIxIiB0cmFuc2Zvcm09InNjYWxlKDEsIC0xKSB0cmFuc2xhdGUoMTEuODMzMzMzMzMzMzMzLCAtMTE3LjQ4MzczODIyNDkzKSByb3RhdGUoLTMwLCAwLCAwKSIgLz48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMjMuNjY2NjY2NjY2NjY3IiBoZWlnaHQ9IjIzLjY2NjY2NjY2NjY2NyIgc3Ryb2tlPSIjMDAwIiBzdHJva2Utb3BhY2l0eT0iMC4wMiIgZmlsbD0iIzIyMiIgZmlsbC1vcGFjaXR5PSIwLjA0NiIgc3Ryb2tlLXdpZHRoPSIxIiB0cmFuc2Zvcm09InNjYWxlKC0xLCAtMSkgdHJhbnNsYXRlKC0xMDAuMTU4NTM1Nzc5MTMsIC0xMTcuNDgzNzM4MjI0OTMpIHJvdGF0ZSgtMzAsIDAsIDApIiAvPjwvc3ZnPg==); background-size:128px 128px; }</style><div class='plugin-icon' id='plugin-icon-<?php echo esc_attr( $post->post_name ); ?>' style='float:left; margin: 3px 6px 6px 0px;'></div></a>
+ <div class="name column-name">
+ <h4><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h4>
+ </div>
+ <div class="desc column-description">
+ <p><?php the_excerpt(); ?></p>
+ <p class="authors"><?php echo wporg_plugins_template_authors(); ?></p>
+ </div>
+ </div>
+
+ <div class="plugin-card-bottom">
+ <!-- <div class="vers column-rating">
+ <div class='wporg-ratings' title='4 out of 5 stars' style='color:#ffb900;'><span class="dashicons dashicons-star-filled"></span><span class="dashicons dashicons-star-filled"></span><span class="dashicons dashicons-star-filled"></span><span class="dashicons dashicons-star-filled"></span><span class="dashicons dashicons-star-empty"></span></div><span class="num-ratings" title="Rating based on 813 reviews">(813)</span>
+ </div> -->
+ <div class="column-updated">
+ <strong><?php _e( 'Last Updated:', 'wporg-plugins' ); ?></strong> <?php echo wporg_plugins_template_last_updated(); ?>
+ </div>
+ <div class="column-installs">
+ <?php echo worg_plugins_template_active_installs( true ); ?>
+ </div>
+ <div class="column-compatibility">
+ <strong><?php _e( 'Compatible up to:', 'wporg-plugins' ); ?></strong> <?php echo wporg_plugins_template_compatible_up_to(); ?>
+ </div>
+ </div>
+</div>
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/plugin-card.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgpluginssinglepluginphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/single-plugin.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/single-plugin.php (rev 0)
+++ sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/single-plugin.php 2016-02-13 03:38:51 UTC (rev 2499)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,71 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php the_post(); ?>
+<?php get_header(); ?>
+
+<div class="wrapper">
+
+ <div style="width: 772px; margin: 0 auto;" itemscope itemtype="http://schema.org/SoftwareApplication">
+
+ <div id="plugin-head" class="plugin-head-with-banner">
+
+ <div id="plugin-title" class="with-banner">
+ <div class="vignette"></div>
+ <style type="text/css">
+ #plugin-title { width:772px; height:250px; background-size:772px 250px; background-image: url(//ps.w.org/debug-bar/assets/banner-772x250.png?rev=478338); }
+ </style>
+
+ <h2 itemprop="name"><?php the_title(); ?></h2>
+ </div>
+
+ <div id="plugin-description">
+ <p itemprop="description" class="shortdesc"><?php the_excerpt(); ?></p>
+ <div class="description-right">
+ <p class="button">
+ <a itemprop='downloadUrl' href='<?php echo esc_url( wporg_plugins_download_link() ); ?>'><?php printf( __( 'Download Version %s', 'wporg-plugins' ), wporg_plugins_the_version() ); ?></a>
+ </p>
+ <meta itemprop="softwareVersion" content="<?php echo esc_attr( wporg_plugins_the_version() ); ?>" />
+ <meta itemprop="fileFormat" content="application/zip" />
+ </div>
+ </div>
+
+ <div style="width: 552px; float: left">
+ <div id="plugin-info" class="block description">
+ <div class="head head-big">
+ <ul id="sections">
+ <?php
+ foreach ( Plugin_Directory_Template_Helpers::get_plugin_sections() as $section ) {
+ $current = ( $section['slug'] == get_query_var( 'content_page' ) || ( 'description' == $section['slug'] && ! get_query_var( 'content_page' ) ) );
+ printf(
+ '<li class="%s"><a itemprop="url" href="%s">%s</a></li>',
+ 'section-' . $section['slug'] . ( $current ? ' current' : '' ),
+ $section['url'],
+ $section['title']
+ );
+ }
+ ?>
+ </ul>
+ </div>
+
+ <div class="block-content">
+ <?php the_content(); ?>
+ </div>
+ </div>
+ </div>
+
+ <div class="" style="width: 212px; float: right;">
+ <p>
+ <strong>Requires:</strong> <?php printf( __('%s or higher', 'wporg-plugins' ), wporg_plugins_template_requires() ); ?><br />
+ <strong>Compatible up to:</strong> <?php echo wporg_plugins_template_compatible_up_to(); ?><br />
+ <strong>Last Updated: </strong> <?php echo wporg_plugins_template_last_updated(); ?><br />
+ <strong>Active Installs:</strong> <?php echo worg_plugins_template_active_installs( false ); ?><br />
+ <meta itemprop="dateModified" content="<?php the_time('Y-m-d'); ?>" />
+ </p>
+ </div>
+
+ </div>
+
+ </div>
+</div>
+
+<br class="clear" />
+<?php
+get_footer();
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/single-plugin.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgpluginsstylecss"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/style.css</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/style.css (rev 0)
+++ sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/style.css 2016-02-13 03:38:51 UTC (rev 2499)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,1444 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+/*
+ * Theme Name: WordPress.org Plugins (Temporary theme)
+ * Theme URI: https://wordpress.org/plugins
+ * Author: wordpressdotorg
+ * Author URI: https://wordpress.org
+ * Description: Theme for the WordPress.org plugins directory
+ * Version: 0.1-alpha
+ * License: GNU General Public License v2 or later
+ * License URI: http://www.gnu.org/licenses/gpl-2.0.html
+ * Template: wordpress-wordblog
+*/
+
+body {
+ font-family: "Open Sans", sans-serif;
+}
+
+.error {
+ background-color: #fdd;
+ border: 1px solid #c66;
+ padding: 8px;
+}
+
+.info-marker {
+ color: #555;
+}
+
+#wporg-footer, #footer, #doily {
+ clear: both;
+}
+
+.right {
+ float: right !important;
+
+}
+
+.left {
+ float: left !important;
+}
+
+h4.plugin-tags, ul.column-list { position: relative; }
+
+ul.column-list a.more { right: 3ex; }
+
+#content p a { border-bottom: none; }
+
+h3#count {
+ font: 1em/25px Georgia,"Bitstream Vera Serif","Times New Roman",serif;
+ letter-spacing: 1px;
+ text-transform: uppercase;
+ font-weight: normal;
+ color: #888;
+ float: left;
+}
+
+h3#count strong {
+ font-size: 1.4em;
+ font-weight: normal;
+ color: #000;
+}
+
+#plugins-search {
+ margin-top: 11px;
+}
+
+#plugins-search input.text {
+ width: 300px;
+ font-size: 12px;
+}
+
+#plugins-search label input {
+ margin: 0 .4em;
+ vertical-align: middle;
+}
+
+#side-search {
+ margin: -10px 0 22px;
+ width: 100%;
+ obackground-color: #eee;
+}
+
+#side-search div {
+ padding: 5px 0 0;
+}
+
+#side-search input.text {
+ font-size: 12px;
+ height: 2em;
+ width: 100%;
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ obackground-color: #fff;
+}
+
+#side-search input.button {
+ float: right;
+ margin-top: 5px;
+}
+
+#plugin-info pre {
+ overflow: auto;
+ max-width: 525px;
+ clear: both;
+}
+
+.unmarked-list, .unmarked-list li {
+ text-indent: 0;
+ list-style: none;
+ margin-left: 0;
+}
+
+body #plugin-info .unmarked-list { padding: 0 0 0 2ex; }
+
+#pagebody h2 {
+ font-size: 18px;
+ line-height: 1.2em;
+ color: #333;
+ font-weight: bold;
+ margin-bottom: 11px;
+}
+
+.block h3.head {
+ color: #444;
+ font-weight: bold;
+ height: 12px;
+ line-height: 1;
+ padding: 8px 12px;
+ font-size: 12px !important;
+ margin-bottom: 12px;
+}
+
+.column .head {
+ font-size: 18px;
+ line-height: 1;
+ margin: 1em 0 .5em;
+ padding: 0;
+}
+
+.chart object {
+ margin-left: -18px;
+}
+
+div.column h3.head a, div.column h3.head a:hover span {
+ color: #2D2D2D;
+}
+div.column h3.head a:hover {
+ color: #036;
+ text-decoration: underline;
+}
+div.column h3.head a span {
+ color: #036;
+ font-weight: bold;
+}
+
+/* Blocks */
+
+.block-content {
+ margin-bottom: 2em;
+}
+
+.block-content h4 {
+ border: none !important;
+ margin-bottom: 0;
+ padding-bottom: 0;
+ font-size: 14px;
+}
+
+.block-content .button {
+ font-weight: normal !important;
+ float: right;
+ margin-top: -17px;
+}
+
+.block-content .button a {
+ font-weight: normal !important;
+}
+
+/* Columns */
+
+ul.column-list {
+ list-style: square;
+ font-size: 12px;
+}
+
+/* Buttons */
+
+div.button-holder {
+ position: relative;
+ height: 28px;
+}
+
+div.button-holder-l {
+ height: 48px;
+}
+
+span.btn-s {
+ background: url("btn-s-r.gif") top right no-repeat;
+ width: 80px;
+ float: left;
+ margin-right: 4px;
+}
+
+span.btn-s a {
+ background: url("btn-s-l.gif") top left no-repeat;
+ height: 20px;
+ line-height: 19px;
+}
+
+span.btn-m {
+ background: url("btn-m-r.gif") top right no-repeat;
+}
+
+span.btn-m a {
+ background: url("btn-m-l.gif") top left no-repeat;
+ height: 28px;
+ line-height: 27px;
+}
+
+span.btn-l {
+ background: url("btn-l-r.gif") top right no-repeat;
+}
+
+span.btn-l a {
+ background: url("btn-l-l.gif") top left no-repeat;
+ height: 48px;
+ font-size: 14px;
+ line-height: 47px;
+}
+
+/* Featured */
+
+#featured {
+ background-color: #fffeeb;
+ border-top: 1px solid #d9d8c8;
+ border-bottom: 1px solid #d9d8c8;
+}
+
+#featured .head {
+ background-color: #f2f1df;
+}
+
+#featured h4, #featured h4 a {
+ font-size: 26px;
+ font-weight: normal;
+}
+
+/* Plugin Info */
+.col-10 .col-3 {
+ margin: 0 0 0 28px;
+}
+#plugin-title {
+ position: relative;
+ margin: 0;
+}
+#plugin-title.with-banner {
+ width: 772px;
+ height: 250px;
+}
+#plugin-title.with-banner div {
+ position: absolute;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ padding: 20px 30px;
+ background: rgba( 0, 0, 0, 0.6 );
+}
+#plugin-title.with-banner .vignette {
+ top: 0;
+ background: transparent;
+ -webkit-box-shadow: inset 0 0 50px 4px rgba( 0, 0, 0, 0.2 ), inset 0 -1px 0 rgba( 0, 0, 0, 0.1 );
+ -moz-box-shadow: inset 0 0 50px 4px rgba( 0, 0, 0, 0.2 ), inset 0 -1px 0 rgba( 0, 0, 0, 0.1 );
+ box-shadow: inset 0 0 50px 4px rgba( 0, 0, 0, 0.2 ), inset 0 -1px 0 rgba( 0, 0, 0, 0.1 );
+}
+
+#plugin-title h2 {
+ font-family: "Helvetica Neue", sans-serif;
+ font-size: 24px;
+ font-weight: bold;
+}
+
+#plugin-title.with-banner h2 {
+ font-size: 30px;
+
+ max-width: 682px;
+ position: absolute;
+ left: 30px;
+ bottom: 20px;
+ padding: 8px 15px;
+ margin-bottom: 4px;
+
+ color: #fff;
+ background: rgba( 30, 30, 30, 0.9 );
+ text-shadow: 0 1px 3px rgba( 0, 0, 0, 0.4 );
+
+ -webkit-box-shadow: 0 0 30px rgba( 255, 255, 255, 0.1 );
+ -moz-box-shadow: 0 0 30px rgba( 255, 255, 255, 0.1 );
+ box-shadow: 0 0 30px rgba( 255, 255, 255, 0.1 );
+
+ -webkit-border-radius: 8px;
+ border-radius: 8px;
+}
+
+#plugin-description {
+ overflow: hidden;
+ padding: 30px 15px 55px 30px;
+ font-size: 16px;
+ line-height: 24px;
+ margin: 0 0 30px;
+ background: #eee;
+ border-top: 1px solid #fcfcfc;
+ text-shadow: 0 1px 1px #fff;
+ -webkit-box-shadow: inset 0 0px 42px 0px rgba( 100, 100, 100, 0.1 );
+ -moz-box-shadow: inset 0 0px 42px 0px rgba( 100, 100, 100, 0.1 );
+ box-shadow: inset 0 0px 42px 0px rgba( 100, 100, 100, 0.1 );
+}
+
+#plugin-description .shortdesc {
+ width: 480px;
+ float: left;
+ margin-bottom: 0;
+ font-family: Georgia,"Bitstream Vera Serif","Times New Roman",serif;
+}
+
+#plugin-description p.button,
+body.trac .description-right p,
+.col-3 p.button {
+ display: block;
+ text-align: center;
+ padding: 0 12px;
+ background: #d54e21;
+ color: #fff;
+ -moz-border-radius: 3px;
+ border-radius: 3px;
+ border: none;
+}
+
+#plugin-description p.button a,
+body.trac .description-right p a,
+.col-3 p.button a {
+ font-size: 15px;
+ color: #fff;
+ display: block;
+ text-shadow: rgba(0,0,0,0.5) 0 1px 0;
+}
+
+p.button a:hover {
+ color: #ffac90;
+ border: none;
+}
+
+body.trac #plugin-description p,
+#plugin-description p.button {
+ float: right;
+ min-width: 182px;
+ margin-top: -8px;
+ margin-bottom: 0;
+}
+
+#plugin-info {
+ margin-top: -70px;
+ margin-bottom: 25px;
+}
+
+#plugin-info .head-big {
+ overflow: hidden;
+ width: 743px;
+ height: 30px;
+ padding: 10px 0 0 29px;
+ margin-bottom: 29px;
+}
+
+#plugin-info.theme-info .head-big {
+ background-color: #eee;
+ height: 35px;
+ padding: 0 0 0 6px;
+ margin-bottom: 12px;
+ width: 100%;
+}
+
+#plugin-info.theme-info {
+ margin-top: 10px;
+ width: auto;
+}
+
+#plugin-info ul#sections {
+ margin: 0;
+ padding: 0;
+ list-style: none;
+ text-indent: 0;
+}
+
+#plugin-info.theme-info ul#sections {
+ margin: 5px 0 0;
+}
+
+#plugin-info ul#sections li {
+ font-size: 13px;
+ line-height: 1;
+ display: block;
+ float: left;
+ padding: 8px 8px 9px;
+ margin: 0;
+}
+
+#plugin-info ul#sections li.current {
+ padding-top: 7px;
+ background-color: #fff;
+
+ border-style: solid;
+ border-width: 1px 1px 0 1px;
+ border-color: #d7d7d7;
+
+ -webkit-box-shadow: 0 0 8px 0px rgba( 100, 100, 100, 0.12 );
+ -moz-box-shadow: 0 0 8px 0px rgba( 100, 100, 100, 0.12 );
+ box-shadow: 0 0 8px 0px rgba( 100, 100, 100, 0.12 );
+
+ -webkit-border-top-left-radius: 3px;
+ -webkit-border-top-right-radius: 3px;
+ border-top-left-radius: 3px;
+ border-top-right-radius: 3px;
+}
+
+#plugin-info h4, #plugin-info h3 {
+ color: #111;
+ font-weight: bold;
+ margin-top: 1.5em;
+}
+
+#plugin-info h4 {
+ font-size: 14px;
+ margin: 0;
+}
+
+#plugin-info h4.author {
+ margin: 0 0 12px;
+ border-bottom: none;
+}
+
+#plugin-info.frequently-asked-questions h4, #plugin-info h3 {
+ font-size: 16px;
+}
+
+#plugin-info .block-content, #plugin-info .block-content p {
+ clear: left;
+ font-size: 13px;
+}
+
+#plugin-tags,
+#theme-languages {
+ font-size: 12px;
+ margin: 16px 0;
+}
+
+/* FYI */
+
+#fyi {
+ margin-bottom: 1em;
+}
+
+#fyi .head {
+ padding-left: 0;
+}
+
+#fyi .block-content {
+ font-size: 12px;
+ padding-top: 0;
+}
+
+#fyi ul {
+ list-style: none;
+ padding-bottom: 12px;
+}
+
+#fyi ul li {
+ text-indent: -16px;
+ font-size: 12px;
+ width: 175px;
+}
+
+#fyi ul li.plugin-avatars {
+ text-indent:0px;
+ margin:0 0 0 -9px;
+ padding:0;
+}
+
+.plugin-avatars a img {
+ padding: 0 3px;
+}
+
+.col-3 .postform h3 {
+ font-size: 12px;
+ padding-bottom: 5px;
+ margin-bottom: 10px;
+ border-bottom: 1px solid #dadada;
+}
+
+.col-3 .postform ol li {
+ line-height: 1.6em;
+ font-size: 12px;
+}
+
+.col-3 .postform p {
+ font-size: 10px;
+ line-height: 1.6em;
+ padding-bottom: 22px;
+}
+
+/* Tag and Author Pages */
+div.plugin-block {
+ margin: .5em 0 0;
+}
+
+div.plugin-block h3 {
+ margin-top: 1em;
+}
+
+div.plugin-block p {
+ padding: 0;
+ margin: 0 0 .5em;
+}
+
+div.plugin-block ul.plugin-meta {
+ list-style: none !important;
+ font-size: 12px;
+ line-height: 1;
+ color: #111;
+ margin: .4em 0 0 !important;
+ height: 19px;
+ padding: 0;
+}
+
+div.plugin-block ul.plugin-meta li {
+ float: left;
+ margin: 0 8px 0 0 !important;
+ text-indent: 0;
+ min-height: 19px;
+}
+
+div.plugin-block div.star-holder {
+ float: left;
+ margin: -3px 0 0 .5ex;
+}
+
+/* Tags Page */
+#hottags {
+ font-family: Georgia,"Bitstream Vera Serif","Times New Roman",serif;
+ margin: 2em 0 0;
+ text-align: justify;
+ line-height: 2em;
+}
+
+#hottags a {
+ font-weight: normal;
+}
+
+div#sidebar h3 {
+ position: relative;
+}
+div#sidebar h3 a {
+ font-weight: bold;
+}
+div#sidebar div ul {
+ border-bottom: none;
+}
+
+div#history {
+ width: 150px;
+ margin-left: 20px;
+ margin-bottom: 22px;
+}
+div#history table {
+ width: 150px;
+ border-collapse:collapse;
+ border-spacing:0;
+}
+div#history table * {
+ text-align: left;
+}
+div#history table tr {
+ border-bottom: 1px solid #ccc;
+}
+div#history table th {
+ font-size: 0.8em;
+ color: #666;
+ font-weight: normal;
+}
+div#history table td {
+ font-weight: bold;
+}
+div#history table th, div#history table td {
+ padding: 5px 0;
+}
+div#history table tr.last-child {
+ border-bottom: none;
+}
+#related {
+ clear: both;
+ border-top: 1em solid #fff;
+}
+#related ul {
+ font-size: 0.9em;
+ padding: 0 0 0 18px;
+}
+#related ul li {
+ margin: 0;
+}
+
+ol.screenshots {
+ clear: both;
+ list-style: none;
+ margin: 0 !important;
+ padding: 0;
+}
+ol.screenshots li {
+ padding-bottom: 35px;
+}
+ol.screenshots li img {
+ border: 1px solid #dadada;
+}
+ol.screenshots li p {
+ margin: 0 !important;
+ padding: 0;
+ font: italic 0.85em/1.4em "Lucida Sans", "Lucida Grande", Verdana, sans-serif !important;
+}
+
+#pagebody ul.translation-details {
+ margin-left: 0;
+}
+
+ .translation-details-row {
+ background-color: #f4f4f4;
+ list-style: none outside none;
+ padding: 15px 20px 12px 20px;
+ }
+
+ .translation-details-row-alternate {
+ background-color: inherit;
+ }
+
+/* Get Hosted */
+
+div#get-hosted {
+ clear: both;
+ background-color: #EDEDFF;
+ border-top: 1.5em solid #fff;
+}
+
+div#get-hosted h3.head {
+ border-top: 1px solid #CACAD9;
+ background-color: #E1E1F2;
+}
+
+/* Change site-wide stuff */
+
+form .alt { background: #eee }
+
+#thread li.alt {
+ border-top: 1px solid #ccc;
+ border-bottom: 1px solid #ccc;
+}
+
+#thread { background-color: #fff; }
+
+#thread li { padding: 1em .8em }
+
+.threadauthor{
+ position: static;
+ width: auto;
+ overflow: visible;
+}
+
+
+/* About */
+
+#about h3 {
+ font-size: 22px;
+}
+
+#about code { background-color: transparent; color: #000; }
+
+#about th[scope=row] { text-align: left; }
+
+.prompt { color: green; }
+.comment { color: maroon; }
+.stdout { color: #222; }
+
+dl dt { color: #000; }
+dl dd { margin-bottom: 1em; }
+
+
+#admin {
+ background-color: #FFEBFE;
+ border-top: 1px solid #D9C8D8;
+}
+
+#admin h3.head {
+ background-color: #F2DFF1;
+}
+
+#admin-forums {
+ border-collapse: collapse;
+}
+
+#admin-forums .alt {
+ background-color: transparent;
+}
+
+#admin-forums .num {
+ text-align: right;
+}
+
+#admin-forums th, #admin-forums td {
+ padding: 0 12px;
+}
+
+div.has-plugins {
+ background-color: #FFC0CB;
+}
+
+div.alt.has-plugins {
+ background-color: #FFB6C1;
+}
+
+div.emailed-author {
+ background-color: #FFCC99;
+}
+div.alt.emailed-author {
+ background-color: #FFCC66;
+}
+
+div.pending textarea {
+ width: 529px;
+ margin: 0 8px 8px;
+}
+
+.video {
+ margin: 0 0 22px;
+ text-align: center;
+}
+
+.tc-warning, .tc-required, .tc-fail {
+ color:red;
+}
+
+.tc-recommended, .tc-pass {
+ color: green;
+}
+
+.tc-info {
+ color: blue;
+}
+
+@media screen and (max-width:960px) {
+ #sidebar {
+ display:none;
+ }
+ .col-10, .col-10 .col-3 {
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ width: 100%;
+ margin: 5px 0;
+ padding: 0 15px;
+ }
+ .col-7 {
+ width: 100%;
+ }
+ .plugin-head-with-banner {
+ background-color: #eee;
+ }
+ #plugin-title.with-banner {
+ margin: 0 auto;
+ width: 100%;
+ max-width: 772px;
+ background-size: 100%;
+ height: 0;
+ padding-bottom: 32%;
+ font-size: 20px;
+ }
+ #plugin-title.with-banner h2 {
+ font-size: 20px;
+ line-height: 1em;
+ bottom: 4%;
+ left: 3%;
+ }
+ #pagebody .col-2 > .submenu:nth-of-type(2) {
+ overflow: hidden;
+ }
+ #pagebody .col-2 .submenu:nth-of-type(2) li {
+ display: block;
+ width: 50%;
+ float: left;
+ }
+ .plugin-authors > div {
+ display: block;
+ float: left;
+ width: 50%;
+ margin-bottom: 8px;
+ }
+ #plugin-info .head-big {
+ overflow: hidden;
+ width: 100%;
+ height: auto;
+ padding: 10px 0 0;
+ margin-bottom: 29px;
+ background: #eee;
+ -webkit-box-shadow: inset 0px -20px 32px 0px rgba( 100, 100, 100, 0.1 );
+ -moz-box-shadow: inset 0px -20px 32px 0px rgba( 100, 100, 100, 0.1 );
+ box-shadow: inset 0px -20px 32px 0px rgba( 100, 100, 100, 0.1 );
+ }
+
+ #plugin-description .shortdesc {
+ width: 100%;
+ }
+
+ body.trac #plugin-description p, #plugin-description p.button {
+ margin-top:0;
+ }
+}
+
+@media screen and (min-width:810px) and (max-width:960px) {
+ #plugin-title.with-banner {
+ height: 250px;
+ padding-bottom: 0;
+ }
+}
+
+@media screen and (max-width:620px) {
+ #plugin-title.with-banner {
+ margin-bottom: 2em;
+ }
+ #plugin-title.with-banner h2 {
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ min-height: 2em;
+ width: 100%;
+ font-size: 20px;
+ bottom: -2em;
+ left: 0;
+ margin: 0;
+ -webkit-border-radius: 0;
+ border-radius: 0;
+ }
+}
+
+@media screen and (max-width:530px) {
+ .video iframe {
+ width:100%;
+ }
+}
+
+@media screen and (max-width:460px) {
+ #headline .login {
+ width: 91.35%;
+ }
+ #headline .login label {
+ padding:0 0 10px;
+ }
+}
+
+@media screen and (max-width:400px) {
+ #headline .login label {
+ display:block;
+ }
+}
+
+/* New theme styles. */
+
+body.plugins-directory {
+ background: #f1f1f1;
+}
+body.plugins-directory.topic-page, body.plugins-directory.page, body.plugins-directory.forum-page {
+ background: #fff;
+}
+body.plugins-directory #pagebody {
+ margin-top: 0;
+}
+
+.col-12 {
+ width: 940px;
+ margin: 0 10px;
+}
+#pagebody p.intro {
+ font-family: inherit;
+ text-align: center;
+}
+#sidebar h4 {
+ margin-top: 20px;
+}
+#sidebar h4:first-child {
+ margin-top: 0;
+}
+/* Hide visually but not from screen readers */
+.screen-reader-text,
+.screen-reader-text span {
+ position: absolute;
+ margin: -1px;
+ padding: 0;
+ height: 1px;
+ width: 1px;
+ overflow: hidden;
+ clip: rect(0 0 0 0);
+ border: 0;
+}
+
+/* Plugin card table view */
+.plugin-pagination {
+ text-align: right;
+}
+.plugin-pagination .plugin-pagination-showing {
+ float: left;
+ font-weight: bold;
+}
+.plugin-group {
+ overflow: hidden; /* clearfix */
+ width: 100%;
+ margin-top: 1.5em;
+ display: table;
+}
+
+.plugin-group h3 {
+ margin-top: 0;
+}
+#pagebody .plugin-card p {
+ margin: 0 0 10px 0;
+}
+.plugin-card {
+ float: left;
+ margin: 0 8px 16px;
+ width: 48.5%;
+ width: -webkit-calc( 50% - 8px );
+ width: calc( 50% - 8px );
+ background-color: #fff;
+ border: 1px solid #dedede;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ display: table-row;
+}
+.plugin-card:nth-child(odd) {
+ clear: both;
+ margin-left: 0;
+}
+
+.plugin-card:nth-child(even) {
+ margin-right: 0;
+}
+
+@media screen and ( max-width: 976px ) {
+ .col-12.filter-bar {
+ width: 100%;
+ margin: 0;
+ }
+
+ .col-12.filter-bar .wp-filter {
+ border-left: 0;
+ border-right: 0;
+ padding-left: 0;
+ }
+
+ #pagebody p {
+ padding-left: 9px;
+ }
+}
+@media screen and ( max-width: 940px ) {
+ .col-12 {
+ width: 100%;
+ margin: 0;
+ }
+}
+@media screen and ( max-width: 782px ) {
+ .plugin-card {
+ margin-left: 0;
+ margin-right: 0;
+ width: 100%;
+ }
+}
+
+.plugin-card-top {
+ position: relative;
+ padding: 20px 20px 10px;
+ min-height: 135px;
+}
+
+.plugin-card h4 {
+ font-weight: 600;
+ border: 0;
+ margin: 0 0 12px;
+ font-size: 18px;
+ line-height: 1.3;
+}
+.plugin-card a {
+ border: 0;
+}
+.plugin-card .name,
+.plugin-card .desc {
+ margin-left: 148px; /* icon + margin */
+ margin-right: 120px; /* action links */
+ margin-right: inherit;
+ word-break: break-word;
+}
+
+.plugin-card-bottom {
+ clear: both;
+ padding: 12px 20px;
+ background-color: #fafafa;
+ border-top: 1px solid #dedede;
+ overflow: hidden;
+}
+
+.plugin-card-bottom .wporg-ratings {
+ display: inline;
+}
+
+.plugin-card .column-rating {
+ line-height: 23px;
+}
+
+.plugin-card .column-rating,
+.plugin-card .column-updated {
+ margin-bottom: 4px;
+}
+
+.plugin-card .column-rating,
+.plugin-card .column-installs {
+ float: left;
+ clear: left;
+ max-width: 160px;
+}
+
+.plugin-card .column-updated,
+.plugin-card .column-compatibility {
+ text-align: right;
+ float: right;
+ clear: right;
+ width: 65%;
+ width: -webkit-calc( 100% - 160px );
+ width: calc( 100% - 160px );
+}
+.plugin-card .column-compatibility span:before {
+ font: normal 20px/.5 'dashicons';
+ speak: none;
+ display: inline-block;
+ padding: 0;
+ top: 4px;
+ left: -2px;
+ position: relative;
+ vertical-align: top;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ text-decoration: none !important;
+ color: #444;
+}
+
+.plugin-card .compatibility-incompatible:before {
+ content: '\f158';
+}
+
+.plugin-card .compatibility-compatible:before {
+ content: '\f147';
+}
+
+.plugin-card .compatibility-untested strong {
+ font-weight: normal;
+}
+.plugin-icon {
+ position: absolute;
+ top: 20px;
+ left: 20px;
+ width: 128px;
+ height: 128px;
+ margin: 0 20px 20px 0;
+ top: 10px;
+ left: 10px;
+}
+
+.plugin-icon img {
+ width: 128px;
+ height: 128px;
+}
+
+.no-plugin-results {
+ color: #999;
+ font-size: 18px;
+ font-style: normal;
+ margin: 0;
+ padding: 30px 0 20px;
+ text-align: center;
+}
+@media screen and ( max-width: 1100px ) and ( min-width: 782px ), ( max-width: 480px ) {
+ .plugin-card .name,
+ .plugin-card .desc {
+ margin-right: 0;
+ }
+
+ .plugin-card .desc p:first-of-type {
+ margin-top: 0;
+ }
+}
+
+
+/* Filter bar */
+.wp-filter {
+ display: inline-block;
+ position: relative;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ margin: 12px 0 25px;
+ padding: 0 20px;
+ width: 100%;
+ -webkit-box-shadow: 0 1px 1px rgba(0,0,0,0.04);
+ box-shadow: 0 1px 1px rgba(0,0,0,0.04);
+ border: 1px solid #e5e5e5;
+ background: #fff;
+ color: #555;
+ font-size: 13px;
+}
+
+.wp-filter a {
+ text-decoration: none;
+}
+
+.wp-filter .plugin-install-beta {
+ padding-right: 15px;
+ border-right: 1px solid #e5e5e5;
+ margin-right: 15px;
+}
+body.search-page .wp-filter .plugin-install-beta,
+body.tag-page .wp-filter .plugin-install-beta {
+ padding-right: 10px;
+ margin-right: 10px;
+}
+
+.filter-count {
+ display: inline-block;
+ vertical-align: middle;
+ min-width: 4em;
+}
+
+.title-count,
+.filter-count .count {
+ display: inline-block;
+ position: relative;
+ top: -1px;
+ padding: 4px 10px;
+ -webkit-border-radius: 30px;
+ border-radius: 30px;
+ background: #777;
+ color: #fff;
+ font-size: 14px;
+ font-weight: 600;
+}
+
+/* not a part of filter bar, but derived from it, so here for now */
+.title-count {
+ display: inline;
+ top: -3px;
+ margin-left: 5px;
+ margin-right: 20px;
+}
+
+#pagebody ul.filter-links {
+ display: inline-block;
+ margin: 0;
+}
+
+.filter-links li {
+ display: inline-block;
+ margin: 0;
+}
+
+.filter-links li > a {
+ display: inline-block;
+ margin: 0 10px;
+ padding: 15px 0;
+ border-bottom: 4px solid #fff;
+ color: #666;
+ cursor: pointer;
+}
+
+.filter-links .current {
+ -webkit-box-shadow: none;
+ box-shadow: none;
+ border-bottom: 4px solid #666;
+ color: #222;
+}
+
+.filter-links li > a:hover,
+.filter-links li > a:focus,
+.show-filters .filter-links a.current:hover,
+.show-filters .filter-links a.current:focus {
+ color: #2ea2cc;
+}
+
+.wp-filter .search-form {
+ float: right;
+ margin: 12px 0 11px;
+}
+
+.wp-filter .search-form input[type="search"] {
+ margin: 0;
+ padding: 3px 5px;
+ width: 280px;
+ font-size: 16px;
+ font-weight: 300;
+ line-height: 1.5;
+}
+body.search-page .wp-filter .search-form input[type="search"],
+body.tag-page .wp-filter .search-form input[type="search"] {
+ width: 240px;
+}
+
+.wp-filter .search-form select {
+ height: 33px;
+ vertical-align: top;
+
+ padding: 2px;
+ line-height: 28px;
+ font-size: 14px;
+ border-radius: 0;
+ border: 1px solid #ddd;
+ background-color: #fff;
+ color: #333;
+ outline: 0;
+ -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,.07);
+ box-shadow: inset 0 1px 2px rgba(0,0,0,.07);
+ transition: .05s border-color ease-in-out;
+}
+
+.wp-filter .drawer-toggle {
+ display: inline-block;
+ margin: 0 10px;
+ padding: 4px 6px;
+ color: #666;
+ cursor: pointer;
+}
+
+.wp-filter .drawer-toggle:before {
+ display: inline-block;
+ vertical-align: top;
+ content: "\f111";
+ margin: 0 5px 0 0;
+ width: 16px;
+ height: 16px;
+ color: #777;
+ -webkit-transition: color .1s ease-in 0;
+ transition: color .1s ease-in 0;
+ font-family: "dashicons";
+ font-size: 16px;
+ line-height: 1;
+ text-align: center;
+ text-decoration: inherit;
+ font-weight: normal;
+ font-style: normal;
+ -webkit-font-smoothing: antialiased;
+}
+
+.wp-filter .drawer-toggle:hover,
+.wp-filter .drawer-toggle:hover:before {
+ color: #2ea2cc;
+}
+
+.wp-filter .drawer-toggle.current:before {
+ color: #fff;
+}
+
+.filter-drawer {
+ display: none;
+ margin: 0 -20px;
+ padding: 20px;
+ border-top: 1px solid #eee;
+ background: #fafafa;
+}
+
+.show-filters .filter-drawer {
+ display: block;
+ overflow: hidden;
+}
+
+.show-filters .wp-filter .drawer-toggle:hover,
+.show-filters .wp-filter .drawer-toggle:focus {
+ background: rgb(46, 162, 204);
+}
+
+.show-filters .filter-links a.current {
+ border-bottom: none;
+}
+
+.show-filters .wp-filter .drawer-toggle {
+ -webkit-border-radius: 2px;
+ border-radius: 2px;
+ border: none;
+ background: #777;
+ color: #fff;
+}
+
+.show-filters .wp-filter .drawer-toggle:before {
+ color: #fff;
+}
+
+.filter-group {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ float: left;
+ margin: 0 1% 0 0;
+ padding: 10px;
+ width: 19%;
+ background: #fff;
+ border: 1px solid #e5e5e5;
+ -webkit-box-shadow: 0 1px 1px rgba(0,0,0,0.04);
+ box-shadow: 0 1px 1px rgba(0,0,0,0.04);
+}
+
+.filter-group.wide {
+ width: 38%;
+}
+
+.filter-group h4 {
+ position: relative;
+ margin: 0;
+}
+
+.filter-drawer ol {
+ margin: 20px 0 0;
+ list-style-type: none;
+ font-size: 12px;
+}
+
+.filter-drawer li {
+ display: inline-block;
+ vertical-align: top;
+ margin: 5px 0;
+ padding-right: 25px;
+ width: 160px;
+ list-style-type: none;
+}
+
+.filter-drawer .buttons {
+ margin-bottom: 20px;
+}
+
+.filter-drawer .buttons .button span {
+ display: inline-block;
+ opacity: 0.8;
+ font-size: 12px;
+ text-indent: 10px;
+}
+
+.wp-filter .button.clear-filters {
+ display: none;
+ margin: 0 0 20px 10px;
+}
+
+.filtered-by {
+ display: none;
+ margin: 0;
+}
+
+.filtered-by > span {
+ font-weight: 600;
+}
+
+.filtered-by a {
+ margin-left: 10px;
+}
+
+.filtered-by .tags {
+ display: inline;
+}
+
+.filtered-by .tag {
+ margin: 0 5px;
+ padding: 4px 8px;
+ border: 1px solid #e5e5e5;
+ -webkit-box-shadow: 0 1px 1px rgba(0,0,0,0.04);
+ box-shadow: 0 1px 1px rgba(0,0,0,0.04);
+ background: #fff;
+ font-size: 11px;
+}
+
+.filters-applied .filter-group,
+.filters-applied .filter-drawer .buttons,
+.filters-applied .filter-drawer br {
+ display: none !important;
+}
+
+.filters-applied .filtered-by {
+ display: block;
+}
+
+.filters-applied .filter-drawer {
+ padding: 20px;
+}
+
+.show-filters .content-filterable,
+.show-filters.filters-applied.loading-content .content-filterable,
+.loading-content .content-filterable,
+.error .content-filterable {
+ display: none;
+}
+
+.show-filters.filters-applied .content-filterable {
+ display: block;
+}
+
+
+/* ------- */
+.wp-filter .actions {
+ display: inline-block;
+ vertical-align: middle;
+}
+.wp-filter .view-switch {
+ display: inline-block;
+ vertical-align: middle;
+ padding: 14px 0;
+ margin: 0 20px 0 0;
+}
+
+input[type=search] {
+ border: 1px solid #ddd;
+ -webkit-box-shadow: inset 0 1px 2px rgba(0,0,0,.07);
+ box-shadow: inset 0 1px 2px rgba(0,0,0,.07);
+ background-color: #fff;
+ color: #333;
+ outline: 0;
+ -webkit-transition: .05s border-color ease-in-out;
+ transition: .05s border-color ease-in-out;
+ -webkit-appearance: textfield;
+}
+
+.nav.top {
+ text-align: right;
+}
+.nav.bottom {
+ margin: 10px 0 22px;
+ text-align: right;
+}
+
+.dots, .next, .prev {
+ background-color: inherit;
+}
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/style.css
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgpluginstemplatetagsphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/template-tags.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/template-tags.php (rev 0)
+++ sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/template-tags.php 2016-02-13 03:38:51 UTC (rev 2499)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,73 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+
+// Various Template tags
+
+// Returns an absolute url to the current url, no matter what that actually is.
+function wporg_plugins_self_link() {
+ $site_path = preg_replace( '!^' . preg_quote( parse_url( home_url(), PHP_URL_PATH ), '!' ) . '!', '', $_SERVER['REQUEST_URI'] );
+ return home_url( $site_path );
+}
+
+function wporg_plugins_template_last_updated() {
+ return '<span title="' . get_the_time('Y-m-d') . '">' . sprintf( _x( '%s ago', 'wporg-plugins' ), human_time_diff( get_the_time( 'U' ), current_time( 'timestamp' ) ) ) . '</span>';
+}
+
+function wporg_plugins_template_compatible_up_to() {
+ $tested = get_post_meta( get_the_id(), 'tested', true ) ;
+ if ( ! $tested ) {
+ $tested = _x( 'unknown', 'unknown version', 'wporg-plugins' );
+ }
+ return esc_html( $tested );
+}
+
+function wporg_plugins_template_requires() {
+ return esc_html( get_post_meta( get_the_id(), 'requires', true ) );
+}
+
+function wporg_plugins_the_version() {
+ return esc_html( get_post_meta( get_the_id(), 'version', true ) );
+}
+
+function wporg_plugins_download_link() {
+ $filename = sprintf( "%s.%s.zip", get_post()->post_name, wporg_plugins_the_version() );
+ return esc_url( "https://downloads.wordpress.org/plugin/{$filename}" );
+}
+
+function worg_plugins_template_active_installs( $full = true ) {
+ $count = Plugin_Directory_Template_Helpers::get_active_installs_count( get_post()->post_name );
+
+ if ( ! $count ) {
+ $text = __( 'Less than 10', 'wporg-plugins' );
+ } elseif ( $count >= 1000000 ) {
+ $text = __( '1+ million', 'wporg-plugins' );
+ } else {
+ $text = number_format_i18n( $count ) . '+';
+ }
+ return $full ? sprintf( __( '%s active installs', 'wporg-plugins' ), $text ) : $text;
+}
+
+function wporg_plugins_template_authors() {
+ $authors = get_post_meta( get_the_id(), 'contributors', true );
+
+ $author_links = array();
+ $and_more = false;
+ foreach ( $authors as $author ) {
+ $user = get_user_by( 'login', $author );
+ if ( ! $user ) {
+ continue;
+ }
+ $author_links[] = sprintf( '<a href="%s">%s</a>', 'https://profiles.wordpress.org/' . $user->user_nicename . '/', $user->display_name );
+ if ( count( $author_links ) > 5 ) {
+ $and_more = true;
+ break;
+ }
+ }
+
+ if ( $and_more ) {
+ return sprintf( '<cite> By: %s, and others.</cite>', implode(', ', $author_links ) );
+ } else {
+ return sprintf( '<cite> By: %s</cite>', implode(', ', $author_links ) );
+ }
+}
+
+
</ins><span class="cx" style="display: block; padding: 0 10px">Property changes on: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/template-tags.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span><a id="sitestrunkwordpressorgpublic_htmlwpcontentthemespubwporgpluginsviewintrophp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/view-intro.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/view-intro.php (rev 0)
+++ sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/view-intro.php 2016-02-13 03:38:51 UTC (rev 2499)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,19 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+
+if ( is_front_page() && ( ! get_query_var( 'browse' ) || 'featured' == get_query_var( 'browse' ) ) ) {
+ printf(
+ /* translators: 1: Plugins count 2: Download count */
+ '<p class="intro">' . __( 'Plugins extend and expand the functionality of WordPress. %1$s plugins with %2$s total downloads are at your fingertips.', 'wporg-plugins' ) . '</p>',
+ '<strong>' . number_format_i18n( wp_count_posts( 'plugin' )->publish ) . '</strong>',
+ '<strong>' . number_format_i18n( Plugin_Directory_Template_Helpers::get_total_downloads() ) . '</strong>'
+ );
+}
+
+if ( 'beta' == get_query_var( 'browse' ) ) {
+ echo '<p class="intro">' . __( 'The plugins listed here are proposed for a future version of WordPress. They are under active development.<br />You can try them out, provide feedback, or join one of the development teams.', 'wporg-plugins' ) . '</p>';
+} elseif ( 'favorites' == get_query_var( 'browse' ) ) {
+ echo '<p class="intro">' . sprintf(
+ __( 'Your favorite plugins are listed here. They also appear on <a href="%s">your profile</a>.', 'wporg-plugins' ),
+ 'https://profiles.wordpress.org/' . wp_get_current_user()->user_nicename
+ ) . '</p>';
+}
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of file
</span><span class="cx" style="display: block; padding: 0 10px">Property changes on: sites/trunk/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins/view-intro.php
</span><span class="cx" style="display: block; padding: 0 10px">___________________________________________________________________
</span></span></pre></div>
<a id="svneolstyle"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: svn:eol-style</h4></div>
<ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+native
</ins><span class="cx" style="display: block; padding: 0 10px">\ No newline at end of property
</span></div>
</body>
</html>