├── .distignore
├── phpunit.xml.dist
├── .editorconfig
├── includes
├── feed-jf2-comments.php
├── feed-mf2-comments.php
├── feed-jf2.php
├── feed-mf2.php
└── class-mf2-feed-entry.php
├── tests
└── bootstrap.php
├── docker-compose.yml
├── package.json
├── phpcs.xml
├── languages
└── mf2-feed.pot
├── LICENSE
├── composer.json
├── Gruntfile.js
├── bin
└── install-wp-tests.sh
├── readme.md
└── mf2-feed.php
/.distignore:
--------------------------------------------------------------------------------
1 | /.wordpress-org
2 | /.git
3 | /.github
4 | /node_modules
5 | /bin
6 | /vendor
7 | /tests
8 | package.json
9 | composer.json
10 | composer.lock
11 | Gruntfile.js
12 | push.sh
13 | phpunit.xml
14 | phpcs.xml
15 | readme.txt
16 | .travis.yml
17 | .distignore
18 | .gitignore
19 | .gitattributes
20 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 | ./tests/
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # This file is for unifying the coding style for different editors and IDEs
2 | # editorconfig.org
3 |
4 | # WordPress Coding Standards
5 | # https://make.wordpress.org/core/handbook/coding-standards/
6 |
7 | root = true
8 |
9 | [*]
10 | charset = utf-8
11 | end_of_line = lf
12 | insert_final_newline = true
13 | trim_trailing_whitespace = true
14 | indent_style = tab
15 | indent_size = 4
16 |
17 | [{.jshintrc,*.json,*.yml}]
18 | indent_style = space
19 | indent_size = 2
20 |
21 | [{*.txt,wp-config-sample.php}]
22 | end_of_line = crlf
23 |
--------------------------------------------------------------------------------
/includes/feed-jf2-comments.php:
--------------------------------------------------------------------------------
1 | to_jf2();
16 | }
17 |
18 | // filter output
19 | $items = apply_filters( 'jf2_feed_array', $items );
20 | echo Mf2Feed::encode_json( $items );
21 |
--------------------------------------------------------------------------------
/includes/feed-mf2-comments.php:
--------------------------------------------------------------------------------
1 | to_mf2();
16 | }
17 |
18 | // filter output
19 | $items = apply_filters( 'mf2_feed_array', $items );
20 | echo Mf2Feed::encode_json( $items );
21 |
--------------------------------------------------------------------------------
/tests/bootstrap.php:
--------------------------------------------------------------------------------
1 | 'feed',
13 | 'name' => get_bloginfo( 'name' ),
14 | 'summary' => get_bloginfo( 'description' ),
15 | 'url' => get_self_link(),
16 | );
17 | if ( ! empty( $featured ) ) {
18 | $items['featured'] = $featured;
19 | }
20 |
21 | while ( have_posts() ) {
22 | the_post();
23 | $item = new Mf2_Feed_Entry( get_the_ID() );
24 | $items['children'][] = $item->to_jf2();
25 | }
26 |
27 | // filter output
28 | $items = apply_filters( 'jf2_feed_array', $items );
29 | echo Mf2Feed::encode_json( $items );
30 |
--------------------------------------------------------------------------------
/phpcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | WordPress MF2 Feed Standards
4 |
5 | ./mf2-feed.php
6 | ./includes/
7 | */includes/*\.(inc|css|js|svg)
8 | */vendor/*
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/includes/feed-mf2.php:
--------------------------------------------------------------------------------
1 | array(
13 | array(
14 | 'type' => array( 'h-feed' ),
15 | 'properties' => array(
16 | 'name' => array( get_bloginfo( 'name' ) ),
17 | 'summary' => array( get_bloginfo( 'description' ) ),
18 | 'url' => array( get_self_link() ),
19 | ),
20 | ),
21 | ),
22 | );
23 |
24 | $featured = get_site_icon_url();
25 | if ( ! empty( $featured ) ) {
26 | $items['items'][0]['properties']['featured'] = array( $featured );
27 | }
28 |
29 | while ( have_posts() ) {
30 | the_post();
31 | $item = new Mf2_Feed_Entry( get_the_ID() );
32 | $items['items'][0]['children'][] = current( $item->to_mf2() );
33 | }
34 |
35 | // filter output
36 | $items = apply_filters( 'mf2_feed_array', $items );
37 | echo Mf2Feed::encode_json( $items );
38 |
--------------------------------------------------------------------------------
/languages/mf2-feed.pot:
--------------------------------------------------------------------------------
1 | # Copyright (C) 2022 IndieWeb WordPress Outreach Club
2 | # This file is distributed under the MIT.
3 | msgid ""
4 | msgstr ""
5 | "Project-Id-Version: MF2 Feed 3.1.1\n"
6 | "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/mf2-feed\n"
7 | "POT-Creation-Date: 2022-05-25 07:47:35+00:00\n"
8 | "MIME-Version: 1.0\n"
9 | "Content-Type: text/plain; charset=utf-8\n"
10 | "Content-Transfer-Encoding: 8bit\n"
11 | "PO-Revision-Date: 2022-MO-DA HO:MI+ZONE\n"
12 | "Last-Translator: FULL NAME \n"
13 | "Language-Team: LANGUAGE \n"
14 | "X-Generator: grunt-wp-i18n1.0.2\n"
15 |
16 | #. Plugin Name of the plugin/theme
17 | msgid "MF2 Feed"
18 | msgstr ""
19 |
20 | #. Plugin URI of the plugin/theme
21 | msgid "http://github.com/indieweb/wordpress-mf2-feed/"
22 | msgstr ""
23 |
24 | #. Description of the plugin/theme
25 | msgid "Adds a Microformats2 JSON feed for every entry"
26 | msgstr ""
27 |
28 | #. Author of the plugin/theme
29 | msgid "IndieWeb WordPress Outreach Club"
30 | msgstr ""
31 |
32 | #. Author URI of the plugin/theme
33 | msgid "https://indieweb.org/WordPress_Outreach_Club"
34 | msgstr ""
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Matthias Pfefferle
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "indieweb/wordpress-mf2-feed",
3 | "description": "provides a Microformats2 JSON Feed for every WordPress URL.",
4 | "type": "wordpress-plugin",
5 | "license": "MIT",
6 | "authors": [
7 | {
8 | "name": "Matthias Pfefferle",
9 | "homepage": "http://notiz.blog"
10 | }
11 | ],
12 | "require": {
13 | "php": ">=5.3.0",
14 | "composer/installers": "~1.0"
15 | },
16 | "extra": {
17 | "installer-name": "mf2-feed"
18 | },
19 | "require-dev": {
20 | "phpunit/phpunit": "5.7.*",
21 | "squizlabs/php_codesniffer": "^2.2 || ^3.0.2",
22 | "phpcompatibility/php-compatibility": "*",
23 | "wp-coding-standards/wpcs": "*",
24 | "dealerdirect/phpcodesniffer-composer-installer": "^0.4.3",
25 | "phpcompatibility/phpcompatibility-wp": "^1.0"
26 | },
27 | "scripts": {
28 | "install-codestandards": [
29 | "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin::run"
30 | ],
31 | "test": [
32 | "composer update",
33 | "bin/install-wp-tests.sh wordpress wordpress wordpress",
34 | "vendor/bin/phpunit"
35 | ]
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function(grunt) {
2 | // Project configuration.
3 | grunt.initConfig({
4 | checktextdomain: {
5 | options:{
6 | text_domain: 'mf2-feed',
7 | keywords: [
8 | '__:1,2d',
9 | '_e:1,2d',
10 | '_x:1,2c,3d',
11 | 'esc_html__:1,2d',
12 | 'esc_html_e:1,2d',
13 | 'esc_html_x:1,2c,3d',
14 | 'esc_attr__:1,2d',
15 | 'esc_attr_e:1,2d',
16 | 'esc_attr_x:1,2c,3d',
17 | '_ex:1,2c,3d',
18 | '_n:1,2,4d',
19 | '_nx:1,2,4c,5d',
20 | '_n_noop:1,2,3d',
21 | '_nx_noop:1,2,3c,4d'
22 | ]
23 | },
24 | files: {
25 | src: [
26 | '**/*.php', // Include all files
27 | 'includes/*.php', // Include includes
28 | '!sass/**', // Exclude sass/
29 | '!node_modules/**', // Exclude node_modules/
30 | '!tests/**', // Exclude tests/
31 | '!vendor/**', // Exclude vendor/
32 | '!build/**', // Exclude build/
33 | '!static/**', // Exclude static resources
34 | ],
35 | expand: true
36 | }
37 | },
38 |
39 | wp_readme_to_markdown: {
40 | target: {
41 | files: {
42 | 'readme.md': 'readme.txt'
43 | },
44 | },
45 | },
46 | makepot: {
47 | target: {
48 | options: {
49 | mainFile: 'mf2-feed.php',
50 | domainPath: '/languages',
51 | exclude: ['bin/.*', '.git/.*', 'vendor/.*'],
52 | potFilename: 'mf2-feed.pot',
53 | type: 'wp-plugin',
54 | updateTimestamp: true
55 | }
56 | }
57 | }
58 | });
59 |
60 | grunt.loadNpmTasks('grunt-wp-readme-to-markdown');
61 | grunt.loadNpmTasks('grunt-wp-i18n');
62 | grunt.loadNpmTasks('grunt-checktextdomain');
63 |
64 | // Default task(s).
65 | grunt.registerTask('default', ['wp_readme_to_markdown', 'makepot', 'checktextdomain']);
66 | };
67 |
--------------------------------------------------------------------------------
/bin/install-wp-tests.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | if [ $# -lt 3 ]; then
4 | echo "usage: $0 [db-host] [wp-version]"
5 | exit 1
6 | fi
7 |
8 | DB_NAME=$1
9 | DB_USER=$2
10 | DB_PASS=$3
11 | DB_HOST=${4-localhost}
12 | WP_VERSION=${5-latest}
13 |
14 | WP_TESTS_DIR=${WP_TESTS_DIR-/tmp/wordpress-tests-lib}
15 | WP_CORE_DIR=${WP_CORE_DIR-/tmp/wordpress/}
16 |
17 | download() {
18 | if [ `which curl` ]; then
19 | curl -s "$1" > "$2";
20 | elif [ `which wget` ]; then
21 | wget -nv -O "$2" "$1"
22 | fi
23 | }
24 |
25 | if [[ $WP_VERSION =~ [0-9]+\.[0-9]+(\.[0-9]+)? ]]; then
26 | WP_TESTS_TAG="tags/$WP_VERSION"
27 | elif [[ $WP_VERSION == 'nightly' || $WP_VERSION == 'trunk' ]]; then
28 | WP_TESTS_TAG="trunk"
29 | else
30 | # http serves a single offer, whereas https serves multiple. we only want one
31 | download http://api.wordpress.org/core/version-check/1.7/ /tmp/wp-latest.json
32 | grep '[0-9]+\.[0-9]+(\.[0-9]+)?' /tmp/wp-latest.json
33 | LATEST_VERSION=$(grep -o '"version":"[^"]*' /tmp/wp-latest.json | sed 's/"version":"//')
34 | if [[ -z "$LATEST_VERSION" ]]; then
35 | echo "Latest WordPress version could not be found"
36 | exit 1
37 | fi
38 | WP_TESTS_TAG="tags/$LATEST_VERSION"
39 | fi
40 |
41 | set -ex
42 |
43 | install_wp() {
44 |
45 | if [ -d $WP_CORE_DIR ]; then
46 | return;
47 | fi
48 |
49 | mkdir -p $WP_CORE_DIR
50 |
51 | if [[ $WP_VERSION == 'nightly' || $WP_VERSION == 'trunk' ]]; then
52 | mkdir -p /tmp/wordpress-nightly
53 | download https://wordpress.org/nightly-builds/wordpress-latest.zip /tmp/wordpress-nightly/wordpress-nightly.zip
54 | unzip -q /tmp/wordpress-nightly/wordpress-nightly.zip -d /tmp/wordpress-nightly/
55 | mv /tmp/wordpress-nightly/wordpress/* $WP_CORE_DIR
56 | else
57 | if [ $WP_VERSION == 'latest' ]; then
58 | local ARCHIVE_NAME='latest'
59 | else
60 | local ARCHIVE_NAME="wordpress-$WP_VERSION"
61 | fi
62 | download https://wordpress.org/${ARCHIVE_NAME}.tar.gz /tmp/wordpress.tar.gz
63 | tar --strip-components=1 -zxmf /tmp/wordpress.tar.gz -C $WP_CORE_DIR
64 | fi
65 |
66 | download https://raw.github.com/markoheijnen/wp-mysqli/master/db.php $WP_CORE_DIR/wp-content/db.php
67 | }
68 |
69 | install_test_suite() {
70 | # portable in-place argument for both GNU sed and Mac OSX sed
71 | if [[ $(uname -s) == 'Darwin' ]]; then
72 | local ioption='-i .bak'
73 | else
74 | local ioption='-i'
75 | fi
76 |
77 | # set up testing suite if it doesn't yet exist
78 | if [ ! -d $WP_TESTS_DIR ]; then
79 | # set up testing suite
80 | mkdir -p $WP_TESTS_DIR
81 | svn co --quiet https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/includes/ $WP_TESTS_DIR/includes
82 | fi
83 |
84 | cd $WP_TESTS_DIR
85 |
86 | if [ ! -f wp-tests-config.php ]; then
87 | download https://develop.svn.wordpress.org/${WP_TESTS_TAG}/wp-tests-config-sample.php "$WP_TESTS_DIR"/wp-tests-config.php
88 | sed $ioption "s:dirname( __FILE__ ) . '/src/':'$WP_CORE_DIR':" "$WP_TESTS_DIR"/wp-tests-config.php
89 | sed $ioption "s/youremptytestdbnamehere/$DB_NAME/" "$WP_TESTS_DIR"/wp-tests-config.php
90 | sed $ioption "s/yourusernamehere/$DB_USER/" "$WP_TESTS_DIR"/wp-tests-config.php
91 | sed $ioption "s/yourpasswordhere/$DB_PASS/" "$WP_TESTS_DIR"/wp-tests-config.php
92 | sed $ioption "s|localhost|${DB_HOST}|" "$WP_TESTS_DIR"/wp-tests-config.php
93 | fi
94 |
95 | }
96 |
97 | install_db() {
98 | # parse DB_HOST for port or socket references
99 | local PARTS=(${DB_HOST//\:/ })
100 | local DB_HOSTNAME=${PARTS[0]};
101 | local DB_SOCK_OR_PORT=${PARTS[1]};
102 | local EXTRA=""
103 |
104 | if ! [ -z $DB_HOSTNAME ] ; then
105 | if [ $(echo $DB_SOCK_OR_PORT | grep -e '^[0-9]\{1,\}$') ]; then
106 | EXTRA=" --host=$DB_HOSTNAME --port=$DB_SOCK_OR_PORT --protocol=tcp"
107 | elif ! [ -z $DB_SOCK_OR_PORT ] ; then
108 | EXTRA=" --socket=$DB_SOCK_OR_PORT"
109 | elif ! [ -z $DB_HOSTNAME ] ; then
110 | EXTRA=" --host=$DB_HOSTNAME --protocol=tcp"
111 | fi
112 | fi
113 |
114 | # create database
115 | mysqladmin create $DB_NAME --user="$DB_USER" --password="$DB_PASS"$EXTRA
116 | }
117 |
118 | install_wp
119 | install_test_suite
120 | install_db
121 |
--------------------------------------------------------------------------------
/includes/class-mf2-feed-entry.php:
--------------------------------------------------------------------------------
1 | _id = $post->ID;
31 | $this->type = 'entry';
32 | $this->name = get_the_title( $post );
33 | // Eliminate IDs as names
34 | if ( $this->name = $this->_id ) {
35 | $this->name = null;
36 | }
37 | $this->published = get_post_time( DATE_W3C, false, $post );
38 | $this->updated = get_post_modified_time( DATE_W3C, false, $post );
39 | $content = get_the_content( null, false, $post );
40 | if ( ! empty( $content ) ) {
41 | $this->content['html'] = get_the_content( null, false, $post );
42 | $this->content['value'] = wp_strip_all_tags( $this->content['html'] );
43 | }
44 | $this->summary = get_the_excerpt( $post );
45 | $this->url = get_permalink( $post );
46 | $this->uid = get_permalink( $post );
47 |
48 | // Get a list of categories and extract their names
49 | $post_categories = get_the_terms( $post->ID, 'category' );
50 | if ( ! empty( $post_categories ) && ! is_wp_error( $post_categories ) ) {
51 | $this->category = wp_list_pluck( $post_categories, 'name' );
52 | }
53 |
54 | // Get a list of tags and extract their names
55 | $post_tags = get_the_terms( $post->ID, 'post_tag' );
56 | if ( ! empty( $post_tags ) && ! is_wp_error( $post_tags ) ) {
57 | $this->category = array_merge( $this->category, wp_list_pluck( $post_tags, 'name' ) );
58 | }
59 |
60 | if ( has_post_thumbnail( $post ) ) {
61 | $this->featured = wp_get_attachment_url( get_post_thumbnail_id( $post ), 'full' );
62 | }
63 |
64 | $this->author['type'] = 'card';
65 | $this->author['name'] = get_the_author_meta( 'display_name', $post->post_author );
66 | $this->author['value'] = get_the_author_meta( 'display_name', $post->post_author );
67 | $this->author['url'] = get_the_author_meta( 'user_url', $post->post_author ) ? get_the_author_meta( 'user_url', $post->post_author ) : get_author_posts_url( $post->post_author );
68 | $this->author['photo'] = get_avatar_url( $post->post_author );
69 |
70 | // add comments
71 | if ( $with_comments ) {
72 | foreach ( get_comments( array( 'post_id' => $post->ID ) ) as $post_comment ) {
73 | $comment = array();
74 | $comment['type'] = 'cite';
75 | $comment['content']['html'] = get_comment_text( $post_comment );
76 | $comment['content']['value'] = wp_strip_all_tags( $comment['content']['html'] );
77 | $comment['published'] = get_comment_date( DATE_W3C, $post_comment );
78 | $comment['author']['type'] = 'card';
79 | $comment['author']['name'] = get_comment_author( $post_comment );
80 | $comment['author']['value'] = $comment['author']['name'];
81 |
82 | if ( $post_comment->comment_author_url ) {
83 | $comment['author']['url'] = get_comment_author_url( $post_comment );
84 | }
85 |
86 | $this->comment[] = $comment;
87 | }
88 | }
89 | }
90 |
91 | public function to_mf2() {
92 | $entry = apply_filters( 'jf2_entry_array', get_object_vars( $this ), $this->_id );
93 | $entry = array_filter( $entry );
94 | $entry = apply_filters( 'mf2_entry_array', $this->jf2_to_mf2( $entry ), $this->_id );
95 | return $entry;
96 | }
97 |
98 | public function to_jf2() {
99 | $entry = apply_filters( 'jf2_entry_array', get_object_vars( $this ), $this->_id );
100 | return array_filter( $entry );
101 | }
102 |
103 | public function jf2_to_mf2( $entry ) {
104 | if ( ! $entry || ! is_array( $entry ) | isset( $entry['properties'] ) ) {
105 | return $entry;
106 | }
107 |
108 | $return = array();
109 | $return['type'] = array( 'h-' . $entry['type'] );
110 | $return['properties'] = array();
111 |
112 | if ( ! empty( $entry['value'] ) ) {
113 | $return['type'] = $entry['value'];
114 | }
115 |
116 | unset( $entry['type'] );
117 | unset( $entry['value'] );
118 |
119 | foreach ( $entry as $key => $value ) {
120 | if ( empty( $value ) ) {
121 | continue;
122 | }
123 | if ( ! wp_is_numeric_array( $value ) && is_array( $value ) && array_key_exists( 'type', $value ) ) {
124 | $value = $this->jf2_to_mf2( $value );
125 | } elseif ( wp_is_numeric_array( $value ) && is_array( $value[0] ) && array_key_exists( 'type', $value[0] ) ) {
126 | foreach ( $value as $item ) {
127 | $items[] = $this->jf2_to_mf2( $item );
128 | }
129 | $value = $items;
130 | } elseif ( wp_is_numeric_array( $value ) && ! is_array( $value[0] ) ) {
131 | $value = $value;
132 | } elseif ( ! wp_is_numeric_array( $value ) ) {
133 | $value = array( $value );
134 | } else {
135 | continue;
136 | }
137 |
138 | $return['properties'][ $key ] = $value;
139 | }
140 |
141 | return array_filter( array( $return ) );
142 | }
143 | }
144 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # MF2 Feeds
2 | - Contributors: pfefferle, dshanske, indieweb
3 | - Donate link: https://opencollective.com/indieweb
4 | - Tags: microformats, mf2, jf2, rel-alternate, indieweb
5 | - Requires at least: 5.2
6 | - Tested up to: 6.9
7 | - Stable tag: 3.1.1
8 | - Requires PHP: 7.2
9 | - License: MIT
10 | - License URI: http://opensource.org/licenses/MIT
11 |
12 | Add Microformats2 Feeds for WordPress
13 |
14 | ## Description
15 |
16 | Provides a [Microformats2 JSON](http://microformats.org/wiki/microformats2-parsing) "Feed" for every WordPress URL, and helps to allow other sites to get pre-parsed [Microformats-JSON](https://indieweb.org/jf2) even if the theme
17 | does not support Microformats2.
18 |
19 | [Microformats2](https://indieweb.org/microformats) are a key [building-block](https://indieweb.org/Category:building-blocks) of the IndieWeb, but it is very hard (if not impossible) to get Microformats2 as a core feature for all WordPress themes. There are several themes that are supporting Microformats2, but everyone should choose his prefered theme and should not be limited to use one of the [few community themes](https://indieweb.org/WordPress/Themes). After [a lot of discussions](https://github.com/indieweb/wordpress-uf2/issues/30) and some different plugin approaches, we are trying to provide an alternate ([`rel=altenate`](https://indieweb.org/rel-alternate)) representation of the microformatted HTML.
20 |
21 | The plugin is inspired by the URL design of [p3k](https://github.com/aaronpk/p3k) of [@aaronpk](https://github.com/aaronpk).
22 |
23 | p3k Example:
24 |
25 | * Original:
26 | * Microformats2 JSON:
27 | * JF2:
28 |
29 | WordPress Example:
30 |
31 | * Original:
32 | * Microformats2 JSON:
33 | * JF2:
34 |
35 | ## FAQ
36 |
37 | ### What are Microformats 2?
38 |
39 | Microformats are a simple way to markup structured information in HTML using classes. WordPress incorporates some classic Microformats. Microformats 2 supersedes classic microformats.
40 |
41 | ## Installation
42 |
43 | Follow the normal instructions for [installing WordPress plugins](https://codex.wordpress.org/Managing_Plugins#Installing_Plugins).
44 |
45 | ### Automatic Plugin Installation
46 |
47 | To add a WordPress Plugin using the [built-in plugin installer](https://codex.wordpress.org/Administration_Screens#Add_New_Plugins):
48 |
49 | 1. Go to [Plugins](https://codex.wordpress.org/Administration_Screens#Plugins) > [Add New](https://codex.wordpress.org/Plugins_Add_New_Screen).
50 | 1. Type "`mf2-feed`" into the **Search Plugins** box.
51 | 1. Find the WordPress Plugin you wish to install.
52 | 1. Click **Details** for more information about the Plugin and instructions you may wish to print or save to help setup the Plugin.
53 | 1. Click **Install Now** to install the WordPress Plugin.
54 | 1. The resulting installation screen will list the installation as successful or note any problems during the install.
55 | 1. If successful, click **Activate Plugin** to activate it, or **Return to Plugin Installer** for further actions.
56 |
57 | ### Manual Plugin Installation
58 |
59 | There are a few cases when manually installing a WordPress Plugin is appropriate.
60 |
61 | * If you wish to control the placement and the process of installing a WordPress Plugin.
62 | * If your server does not permit automatic installation of a WordPress Plugin.
63 | * If you want to try the [latest development version](https://github.com/indieweb/wordpress-mf2-feed).
64 |
65 | Installation of a WordPress Plugin manually requires FTP familiarity and the awareness that you may put your site at risk if you install a WordPress Plugin incompatible with the current version or from an unreliable source.
66 |
67 | Backup your site completely before proceeding.
68 |
69 | To install a WordPress Plugin manually:
70 |
71 | * Download your WordPress Plugin to your desktop.
72 | * Download from [the WordPress directory](https://wordpress.org/plugins/mf2-feed/)
73 | * Download from [GitHub](https://github.com/indieweb/wordpress-mf2-feed/releases)
74 | * If downloaded as a zip archive, extract the Plugin folder to your desktop.
75 | * With your FTP program, upload the Plugin folder to the `wp-content/plugins` folder in your WordPress directory online.
76 | * Go to [Plugins screen](https://codex.wordpress.org/Administration_Screens#Plugins) and find the newly uploaded Plugin in the list.
77 | * Click **Activate** to activate it.
78 |
79 | ## Changelog
80 |
81 | Project actively developed on Github at [indieweb/wordpress-mf2-feed](https://github.com/indieweb/wordpress-mf2-feed). Please file support issues there.
82 |
83 | ### 3.1.1
84 |
85 | * Small tweaks and dependency updates
86 |
87 | ### 3.1.0
88 |
89 | * Support Content Negotiation
90 |
91 | ### 3.0.0
92 |
93 | * Refactored to match the configuration of feeds built into WordPress
94 | * Bumped PHP Version requirement to PHP5.6 to match WordPress 5.3
95 | * Bumped minimum WordPress version to 5.2 as this allows for the version of get_content that includes a $post parameter
96 | * Fixed incorrect PHPCS configuration
97 | * Enabled JSON Pretty Print by default as originally disabled due a PHP5.4 requirement
98 | * Changed Post Item Generation Class to use WordPress functions instead of directly accessing the data where applicable
99 | * Adjusted jf2 feed to comply with jf2feed spec (https://jf2.spec.indieweb.org/#jf2feed)
100 |
101 | ### 2.1.0
102 |
103 | * Fixed JSON output
104 | * Fixed "flush rewrite rules" again
105 |
106 | ### 2.0.1
107 |
108 | * Fixed "flush rewrite rules"
109 | * Added filter to extend the mf2/jf2 data
110 |
111 | ### 2.0.0
112 |
113 | * Complete re-write to match the latest ideas of rel-alternate: https://github.com/indieweb/wordpress-uf2/issues/38
114 |
115 | ### 1.0.0
116 |
117 | * Initial plugin
118 |
--------------------------------------------------------------------------------
/mf2-feed.php:
--------------------------------------------------------------------------------
1 |
173 |
174 |
175 |
178 |
179 |
180 |