├── .npmignore ├── .gitignore ├── CHANGELOG.md ├── .travis.yml ├── .editorconfig ├── test ├── basic.html ├── basic.url_object.expect.html ├── basic.expect.html └── basic.url.expect.html ├── index.js ├── package.json ├── LICENSE.md ├── CONTRIBUTING.md ├── test.js ├── README.md └── .eslintrc /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | npm-debug.log 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | npm-debug.log 3 | test/*.actual.html 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.0.0 (2015-12-14) 2 | 3 | - Added: Initial version 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - stable 5 | - "0.12" 6 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | indent_style = tab 7 | insert_final_newline = true 8 | trim_trailing_whitespace = true 9 | 10 | [*.md] 11 | trim_trailing_whitespace = false 12 | 13 | [*.{json,yml}] 14 | indent_size = 2 15 | indent_style = space 16 | -------------------------------------------------------------------------------- /test/basic.html: -------------------------------------------------------------------------------- 1 |
2 |

Avatar

3 | Director:
James Cameron (born August 16, 1954) 4 | Science fiction 5 | Trailer 6 |
7 | -------------------------------------------------------------------------------- /test/basic.url_object.expect.html: -------------------------------------------------------------------------------- 1 |
2 |

Avatar

3 | Director:
James Cameron
(born August 16, 1954) 4 | Science fiction 5 | Trailer 6 |
7 | -------------------------------------------------------------------------------- /test/basic.expect.html: -------------------------------------------------------------------------------- 1 |
2 |

Avatar

3 | Director:
James Cameron
(born August 16, 1954) 4 | Science fiction 5 | Trailer 6 |
7 | -------------------------------------------------------------------------------- /test/basic.url.expect.html: -------------------------------------------------------------------------------- 1 |
2 |

Avatar

3 | Director:
James Cameron
(born August 16, 1954) 4 | Science fiction 5 | Trailer 6 |
7 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var posthtml = require('posthtml'); 2 | 3 | module.exports = function (options) { 4 | var url = options && options.url || 'http://schema.org/'; 5 | 6 | return function Schemas(tree) { 7 | tree.walk(function (node) { 8 | var itemtype = typeof node.attrs === 'object' && node.attrs.itemtype; 9 | 10 | if (itemtype) { 11 | if (!node.attrs.itemscope) { 12 | node.attrs.itemscope = ''; 13 | } 14 | 15 | var prefix = typeof url === 'string' ? url : url[itemtype] || ''; 16 | 17 | node.attrs.itemtype = itemtype.replace(/^\w+$/, prefix + '$&'); 18 | } 19 | 20 | return node; 21 | }); 22 | }; 23 | }; 24 | 25 | module.exports.process = function (contents, options) { 26 | return posthtml().use(module.exports(options)).process(contents); 27 | }; 28 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "posthtml-schemas", 3 | "version": "1.0.0", 4 | "description": "Add schema.org microdata to your markup super easy", 5 | "keywords": [ 6 | "posthtml", 7 | "html", 8 | "posthtml-plugin", 9 | "schema.org", 10 | "schemas", 11 | "markup", 12 | "patterns", 13 | "itemprops", 14 | "itemtypes" 15 | ], 16 | "author": "Jonathan Neal ", 17 | "license": "CC0-1.0", 18 | "repository": "jonathantneal/posthtml-schemas", 19 | "homepage": "https://github.com/jonathantneal/posthtml-schemas#readme", 20 | "bugs": "https://github.com/jonathantneal/posthtml-schemas/issues", 21 | "dependencies": { 22 | "posthtml": "^0.8.0" 23 | }, 24 | "devDependencies": { 25 | "eslint": "^1.10.3", 26 | "tap-spec": "^4.1.1", 27 | "tape": "^4.2.2" 28 | }, 29 | "scripts": { 30 | "lint": "eslint . --ignore-path .gitignore", 31 | "tape": "tape test.js | tap-spec", 32 | "test": "npm run lint && npm run tape" 33 | }, 34 | "engines": { 35 | "iojs": ">=2.0.0", 36 | "node": ">=0.12.0" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # CC0 1.0 Universal License 2 | 3 | Public Domain Dedication 4 | 5 | The person(s) who associated a work with this deed has dedicated the work to the public domain by waiving all of his or her rights to the work worldwide under copyright law, including all related and neighboring rights, to the extent allowed by law. 6 | 7 | You can copy, modify, distribute and perform the work, even for commercial purposes, all without asking permission. 8 | 9 | In no way are the patent or trademark rights of any person affected by CC0, nor are the rights that other persons may have in the work or in how the work is used, such as publicity or privacy rights. 10 | 11 | Unless expressly stated otherwise, the person(s) who associated a work with this deed makes no warranties about the work, and disclaims liability for all uses of the work, to the fullest extent permitted by applicable law. 12 | 13 | When using or citing the work, you should not imply endorsement by the author or the affirmer. 14 | 15 | This is a [human-readable summary of the Legal Code](https://creativecommons.org/publicdomain/zero/1.0/) ([read the full text](https://creativecommons.org/publicdomain/zero/1.0/legalcode)). 16 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | You want to help? You rock! Now, take a moment to be sure your contributions make sense to everyone else. 2 | 3 | ## Reporting Issues 4 | 5 | Found a problem? Want a new feature? 6 | 7 | - See if your issue or idea has [already been reported]. 8 | - Provide a [reduced test case] or a [live example]. 9 | 10 | Remember, a bug is a _demonstrable problem_ caused by _our_ code. 11 | 12 | ## Submitting Pull Requests 13 | 14 | Pull requests are the greatest contributions, so be sure they are focused in scope, and do avoid unrelated commits. 15 | 16 | 1. To begin, [fork this project], clone your fork, and add our upstream. 17 | ```bash 18 | # Clone your fork of the repo into the current directory 19 | git clone https://github.com//posthtml-schemas 20 | # Navigate to the newly cloned directory 21 | cd posthtml-schemas 22 | # Assign the original repo to a remote called "upstream" 23 | git remote add upstream https://github.com/jonathantneal/posthtml-schemas 24 | # Install the tools necessary for development 25 | npm install 26 | ``` 27 | 28 | 2. Create a branch for your feature or fix: 29 | ```bash 30 | # Move into a new branch for a feature 31 | git checkout -b feature/thing 32 | ``` 33 | ```bash 34 | # Move into a new branch for a fix 35 | git checkout -b fix/something 36 | ``` 37 | 38 | 3. Be sure your code follows our practices. 39 | ```bash 40 | # Test current code 41 | npm run test 42 | ``` 43 | 44 | 4. Push your branch up to your fork: 45 | ```bash 46 | # Push a feature branch 47 | git push origin feature/thing 48 | ``` 49 | ```bash 50 | # Push a fix branch 51 | git push origin fix/something 52 | ``` 53 | 54 | 5. Now [open a pull request] with a clear title and description. 55 | 56 | [already been reported]: issues 57 | [fork this project]: fork 58 | [live example]: http://codepen.io/pen 59 | [open a pull request]: https://help.github.com/articles/using-pull-requests/ 60 | [reduced test case]: https://css-tricks.com/reduced-test-cases/ 61 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | var tests = { 2 | 'posthtml-schemas': { 3 | 'basic': { 4 | message: 'supports basic usage', 5 | options: {} 6 | }, 7 | 'basic:url': { 8 | message: 'supports basic usage (with a custom url)', 9 | options: { 10 | url: 'http://example.com/' 11 | } 12 | }, 13 | 'basic:url_object': { 14 | message: 'supports basic usage (with a custom url object)', 15 | options: { 16 | url: { 17 | Movie: 'http://example.com/' 18 | } 19 | } 20 | } 21 | } 22 | }; 23 | 24 | var debug = true; 25 | var dir = './test/'; 26 | 27 | var fs = require('fs'); 28 | var path = require('path'); 29 | var plugin = require('./'); 30 | var test = require('tape'); 31 | 32 | Object.keys(tests).forEach(function (name) { 33 | var parts = tests[name]; 34 | 35 | test(name, function (t) { 36 | var fixtures = Object.keys(parts); 37 | 38 | t.plan(fixtures.length); 39 | 40 | fixtures.forEach(function (fixture) { 41 | var message = parts[fixture].message; 42 | var options = parts[fixture].options; 43 | 44 | var baseName = fixture.split(':')[0]; 45 | var testName = fixture.split(':').join('.'); 46 | 47 | var inputPath = path.resolve(dir + baseName + '.html'); 48 | var expectPath = path.resolve(dir + testName + '.expect.html'); 49 | var actualPath = path.resolve(dir + testName + '.actual.html'); 50 | 51 | var inputHTML = ''; 52 | var expectHTML = ''; 53 | 54 | try { 55 | inputHTML = fs.readFileSync(inputPath, 'utf8'); 56 | } catch (error) { 57 | fs.writeFileSync(inputPath, inputHTML); 58 | } 59 | 60 | try { 61 | expectHTML = fs.readFileSync(expectPath, 'utf8'); 62 | } catch (error) { 63 | fs.writeFileSync(expectPath, expectHTML); 64 | } 65 | 66 | plugin.process(inputHTML, options).then(function (result) { 67 | var actualHTML = result.html; 68 | 69 | if (debug) { 70 | fs.writeFileSync(actualPath, actualHTML); 71 | } 72 | 73 | t.equal(actualHTML, expectHTML, message); 74 | }); 75 | }); 76 | }); 77 | }); 78 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Schemas 2 | 3 | PostHTML Logo 4 | 5 | [![NPM Version][npm-img]][npm] [![Build Status][ci-img]][ci] 6 | 7 | [Schemas] makes it super easy to write [schema.org] microdata without extra cruft. Search engine operators like Google, Microsoft and Yahoo! will rely on this markup to improve search results. 8 | 9 | ```html 10 | 11 |
12 | ACME Executive Anvil 13 | 14 | 15 | 16 | Average rating: 4.4, based on 17 | 89 reviews 18 | 19 | 20 | 21 | from $119.99 to 22 | $199.99 23 | 24 | 25 |
26 | 27 | 28 |
29 | ACME Executive Anvil 30 | 31 | 32 | 33 | Average rating: 4.4, based on 34 | 89 reviews 35 | 36 | 37 | 38 | from $119.99 to 39 | $199.99 40 | 41 | 42 |
43 | ``` 44 | 45 | ## Features 46 | 47 | **Schemas** makes the `itemscope` property totally optional. This is because the [microdata spec] says `itemtype` must **not** be specified on elements that do not **also** have an `itemscope` attribute. 48 | 49 | **Schemas** makes the `http://schema.org/` prefix totally optional. This is because all major search engines now [recognize] this common data vocabulary. 50 | 51 | ## Usage 52 | 53 | Add [Schemas] to your build tool: 54 | 55 | ```bash 56 | npm install posthtml-schemas --save-dev 57 | ``` 58 | 59 | #### Node 60 | 61 | ```js 62 | require('posthtml-schemas').process(YOUR_HTML, { /* options */ }); 63 | ``` 64 | 65 | #### PostHTML 66 | 67 | Add [PostHTML] to your build tool: 68 | 69 | ```bash 70 | npm install posthtml --save-dev 71 | ``` 72 | 73 | Load [Schemas] as a PostHTML plugin: 74 | 75 | ```js 76 | posthtml([ 77 | require('posthtml-schemas')({ /* options */ }) 78 | ]).process(YOUR_HTML, /* options */); 79 | ``` 80 | 81 | #### Gulp 82 | 83 | Add [Gulp PostHTML] to your build tool: 84 | 85 | ```bash 86 | npm install gulp-posthtml --save-dev 87 | ``` 88 | 89 | Enable [Schemas] within your Gulpfile: 90 | 91 | ```js 92 | var posthtml = require('gulp-posthtml'); 93 | 94 | gulp.task('html', function () { 95 | return gulp.src('./src/*.html').pipe( 96 | posthtml([ 97 | require('posthtml-schemas')({ /* options */ }) 98 | ]) 99 | ).pipe( 100 | gulp.dest('.') 101 | ); 102 | }); 103 | ``` 104 | 105 | #### Grunt 106 | 107 | Add [Grunt PostHTML] to your build tool: 108 | 109 | ```bash 110 | npm install grunt-posthtml --save-dev 111 | ``` 112 | 113 | Enable [Schemas] within your Gruntfile: 114 | 115 | ```js 116 | grunt.loadNpmTasks('grunt-posthtml'); 117 | 118 | grunt.initConfig({ 119 | posthtml: { 120 | options: { 121 | use: [ 122 | require('posthtml-schemas')({ /* options */ }) 123 | ] 124 | }, 125 | dist: { 126 | src: '*.html' 127 | } 128 | } 129 | }); 130 | ``` 131 | 132 | ## Options 133 | 134 | #### `url` 135 | 136 | Type: `Object|String` 137 | Default: `"http://schema.org/"` 138 | 139 | Specifies the URL used to prefix your microdata vocabulary (`itemtype`). You may also pass in an object of individual URLs for each vocabulary. 140 | 141 | [ci]: https://travis-ci.org/jonathantneal/posthtml-schemas 142 | [ci-img]: https://img.shields.io/travis/jonathantneal/posthtml-schemas.svg 143 | [npm]: https://www.npmjs.com/package/posthtml-schemas 144 | [npm-img]: https://img.shields.io/npm/v/posthtml-schemas.svg 145 | 146 | [schema.org]: https://schema.org/ 147 | [microdata spec]: https://html.spec.whatwg.org/multipage/microdata.html#items 148 | [recognize]: http://schema.org/docs/schemas.html 149 | 150 | [Gulp PostHTML]: https://github.com/posthtml/gulp-posthtml 151 | [Grunt PostHTML]: https://github.com/TCotton/grunt-posthtml 152 | [PostHTML]: https://github.com/posthtml/posthtml 153 | 154 | [Schemas]: https://github.com/jonathantneal/posthtml-schemas 155 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "no-shadow-restricted-names": [2], 4 | "computed-property-spacing": [2], 5 | "no-empty-character-class": [2], 6 | "no-irregular-whitespace": [2], 7 | "no-unexpected-multiline": [2], 8 | "no-multiple-empty-lines": [2], 9 | "space-return-throw-case": [2], 10 | "no-constant-condition": [2], 11 | "no-extra-boolean-cast": [2], 12 | "no-inner-declarations": [2], 13 | "no-this-before-super": [2], 14 | "no-array-constructor": [2], 15 | "object-curly-spacing": [2, "always"], 16 | "no-floating-decimal": [2], 17 | "no-warning-comments": [2], 18 | "handle-callback-err": [2], 19 | "no-unneeded-ternary": [2], 20 | "operator-assignment": [2], 21 | "space-before-blocks": [2], 22 | "no-native-reassign": [2], 23 | "no-trailing-spaces": [2], 24 | "operator-linebreak": [2, "after"], 25 | "consistent-return": [2], 26 | "no-duplicate-case": [2], 27 | "no-invalid-regexp": [2], 28 | "no-negated-in-lhs": [2], 29 | "constructor-super": [2], 30 | "no-nested-ternary": [0], 31 | "no-extend-native": [2], 32 | "block-scoped-var": [2], 33 | "no-control-regex": [2], 34 | "no-sparse-arrays": [2], 35 | "no-throw-literal": [2], 36 | "no-return-assign": [2], 37 | "no-const-assign": [2], 38 | "no-class-assign": [2], 39 | "no-extra-parens": [2], 40 | "no-regex-spaces": [2], 41 | "no-implied-eval": [2], 42 | "no-useless-call": [2], 43 | "no-self-compare": [2], 44 | "no-octal-escape": [2], 45 | "no-new-wrappers": [2], 46 | "no-process-exit": [2], 47 | "no-catch-shadow": [2], 48 | "linebreak-style": [2], 49 | "space-infix-ops": [2], 50 | "space-unary-ops": [2], 51 | "no-func-assign": [2], 52 | "no-unreachable": [2], 53 | "accessor-pairs": [2], 54 | "no-empty-label": [2], 55 | "no-fallthrough": [2], 56 | "no-path-concat": [2], 57 | "no-new-require": [2], 58 | "no-spaced-func": [2], 59 | "no-unused-vars": [2], 60 | "spaced-comment": [2], 61 | "no-delete-var": [2], 62 | "comma-spacing": [2], 63 | "no-extra-semi": [2], 64 | "no-extra-bind": [2], 65 | "arrow-spacing": [2], 66 | "prefer-spread": [2], 67 | "no-new-object": [2], 68 | "no-multi-str": [2], 69 | "semi-spacing": [2], 70 | "no-lonely-if": [2], 71 | "dot-notation": [2], 72 | "dot-location": [2, "property"], 73 | "comma-dangle": [2, "never"], 74 | "no-dupe-args": [2], 75 | "no-dupe-keys": [2], 76 | "no-ex-assign": [2], 77 | "no-obj-calls": [2], 78 | "valid-typeof": [2], 79 | "default-case": [2], 80 | "no-redeclare": [2], 81 | "no-div-regex": [2], 82 | "no-sequences": [2], 83 | "no-label-var": [2], 84 | "comma-style": [2], 85 | "brace-style": [2], 86 | "no-debugger": [2], 87 | "quote-props": [0], 88 | "no-iterator": [2], 89 | "no-new-func": [2], 90 | "key-spacing": [2, { "align": "value" }], 91 | "complexity": [2], 92 | "new-parens": [2], 93 | "no-eq-null": [2], 94 | "no-bitwise": [0], 95 | "wrap-iife": [2], 96 | "no-caller": [2], 97 | "use-isnan": [2], 98 | "no-labels": [2], 99 | "no-shadow": [2], 100 | "camelcase": [2], 101 | "eol-last": [2], 102 | "no-octal": [2], 103 | "no-empty": [2], 104 | "no-alert": [2], 105 | "no-proto": [2], 106 | "no-undef": [2], 107 | "no-eval": [2], 108 | "no-with": [2], 109 | "no-void": [2], 110 | "new-cap": [2], 111 | "eqeqeq": [2], 112 | "no-new": [2], 113 | "quotes": [2, "single"], 114 | "indent": [2, "tab"], 115 | "semi": [2, "always"], 116 | "yoda": [2, "never"] 117 | }, 118 | "env": { 119 | "mocha": true, 120 | "node": true 121 | } 122 | } 123 | --------------------------------------------------------------------------------