├── .gitignore ├── assets └── sample-screenshot.png ├── inclusive-language.js ├── test └── inclusive-language-test.js ├── LICENSE ├── package.json ├── README.md └── .eleventy.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package-lock.json -------------------------------------------------------------------------------- /assets/sample-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/11ty/eleventy-plugin-inclusive-language/master/assets/sample-screenshot.png -------------------------------------------------------------------------------- /inclusive-language.js: -------------------------------------------------------------------------------- 1 | const chalk = require("chalk"); 2 | 3 | module.exports = function(content, words) { 4 | let found = []; 5 | for( let word of words) { 6 | word = word.trim(); 7 | let regexp = new RegExp("\\b(" + word + ")\\b", "gi"); 8 | if(!!content.match(regexp)) { 9 | let split = content.split(regexp); 10 | for(let j = 0, k = split.length; j + 1 < k; j+=2) { 11 | found.push( split[j].substr(-30) + chalk.underline(split[j+1]) + split[j+2].substr(0, 30)); 12 | } 13 | } 14 | } 15 | 16 | return found; 17 | }; -------------------------------------------------------------------------------- /test/inclusive-language-test.js: -------------------------------------------------------------------------------- 1 | const test = require("ava"); 2 | const inclusiveLanguage = require("../inclusive-language"); 3 | 4 | test("Results not found", t => { 5 | t.is(inclusiveLanguage("", []).length, 0); 6 | t.is(inclusiveLanguage("hello, you are cool", []).length, 0); 7 | t.is(inclusiveLanguage("", ["basically", "just"]).length, 0); 8 | t.is(inclusiveLanguage("hello, you are cool", ["basically", "just"]).length, 0); 9 | }); 10 | 11 | test("Results found", t => { 12 | t.is(inclusiveLanguage("hello, just do this", ["just"]).length, 1); 13 | t.is(inclusiveLanguage("hello, basically just do this", ["basically", "just"]).length, 2); 14 | }); -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Eleventy 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 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@11ty/eleventy-plugin-inclusive-language", 3 | "version": "1.0.3", 4 | "description": "An Eleventy linter plugin to check for inclusive language in markdown files.", 5 | "publishConfig": { 6 | "access": "public" 7 | }, 8 | "main": ".eleventy.js", 9 | "scripts": { 10 | "test": "npx ava" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/11ty/eleventy-plugin-inclusive-language.git" 15 | }, 16 | "funding": { 17 | "type": "opencollective", 18 | "url": "https://opencollective.com/11ty" 19 | }, 20 | "keywords": [ 21 | "eleventy", 22 | "eleventy-plugin" 23 | ], 24 | "author": { 25 | "name": "Zach Leatherman", 26 | "email": "zachleatherman@gmail.com", 27 | "url": "https://zachleat.com/" 28 | }, 29 | "license": "MIT", 30 | "bugs": { 31 | "url": "https://github.com/11ty/eleventy-plugin-inclusive-language/issues" 32 | }, 33 | "homepage": "https://www.11ty.dev/docs/plugins/inclusive-language/", 34 | "11ty": { 35 | "compatibility": ">=0.6" 36 | }, 37 | "devDependencies": { 38 | "ava": "^3.15.0" 39 | }, 40 | "dependencies": { 41 | "chalk": "^4.1.0" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # eleventy-plugin-inclusive-language 2 | 3 | An [Eleventy](https://github.com/11ty/eleventy) linter plugin to check for inclusive language in markdown files. Inspired by [_CSS Tricks’ Words to Avoid in Educational Writing_](https://css-tricks.com/words-avoid-educational-writing/). No browser/client JavaScript here—everything is this plugin is done at build-time. 4 | 5 | ![Sample screenshot of eleventy-plugin-inclusive-language in action](./assets/sample-screenshot.png) 6 | 7 | ## Installation 8 | 9 | Available on [npm](https://www.npmjs.com/package/@11ty/eleventy-plugin-inclusive-language). 10 | 11 | ``` 12 | npm install @11ty/eleventy-plugin-inclusive-language --save-dev 13 | ``` 14 | 15 | Open up your Eleventy config file (probably `.eleventy.js`) and use `addPlugin`: 16 | 17 | ```js 18 | const inclusiveLangPlugin = require("@11ty/eleventy-plugin-inclusive-language"); 19 | 20 | module.exports = function(eleventyConfig) { 21 | eleventyConfig.addPlugin(inclusiveLangPlugin); 22 | }; 23 | ``` 24 | 25 | Read more about [Eleventy plugins.](https://www.11ty.io/docs/plugins/) 26 | 27 | ### Options 28 | 29 | Optionally pass in an options object as the second argument to `addPlugin` to further customize this plugin. 30 | 31 | ``` 32 | const inclusiveLangPlugin = require("@11ty/eleventy-plugin-inclusive-language"); 33 | 34 | module.exports = function(eleventyConfig) { 35 | eleventyConfig.addPlugin(inclusiveLangPlugin, { 36 | templateFormats: ["md"], // default, add more file extensions here 37 | 38 | // accepts an array or a comma-delimited string 39 | words: "simply,obviously,basically,of course,clearly,just,everyone knows,however,easy" 40 | }); 41 | }; 42 | 43 | ``` 44 | -------------------------------------------------------------------------------- /.eleventy.js: -------------------------------------------------------------------------------- 1 | const pkg = require("./package.json"); 2 | const chalk = require("chalk"); 3 | const inclusiveLanguage = require("./inclusive-language"); 4 | 5 | module.exports = { 6 | initArguments: {}, 7 | configFunction: function(eleventyConfig, options = {}) { 8 | try { 9 | eleventyConfig.versionCheck(pkg["11ty"].compatibility); 10 | } catch(e) { 11 | console.log( `WARN: Eleventy Plugin (${pkg.name}) Compatibility: ${e.message}` ); 12 | } 13 | 14 | // TODO move this into default argument when 0.5.5 or newer is released 15 | /* { 16 | words: "simply,obviously,basically,of course,clearly,just,everyone knows,however,easy", 17 | templateFormats: ["md"] 18 | } */ 19 | if(!options.words) { 20 | options.words = "simply,obviously,basically,of course,clearly,just,everyone knows,however,easy"; 21 | } 22 | if(!options.templateFormats) { 23 | options.templateFormats = ["md"]; 24 | } 25 | 26 | eleventyConfig.addLinter("inclusive-language", function(content, inputPath, outputPath) { 27 | let words; 28 | if(Array.isArray(options.words)) { 29 | words = options.words; 30 | } else if(typeof options.words === "string") { 31 | words = options.words.split(","); 32 | } else { 33 | throw new Error("Invalid type for options.words (needs string or array) in eleventy-plugin-inclusive-language"); 34 | } 35 | 36 | if(!Array.isArray(options.templateFormats)) { 37 | throw new Error("Invalid type for options.templateFormats (needs array) in eleventy-plugin-inclusive-language"); 38 | } 39 | 40 | let checkThisFile = false; 41 | for( let format of options.templateFormats ) { 42 | if( inputPath.endsWith("." + format) ) { 43 | checkThisFile = true; 44 | break; 45 | } 46 | } 47 | if( !checkThisFile ) { 48 | return; 49 | } 50 | 51 | let found = inclusiveLanguage(content, words); 52 | 53 | if(found.length) { 54 | console.warn(chalk.yellow(`Inclusive Language Linter (${inputPath}):`)); 55 | console.warn(" " + found.join("\n" + " ")); 56 | } 57 | }); 58 | } 59 | }; 60 | --------------------------------------------------------------------------------