From 4a3eb62282d90697d11bc156f9d99f32b16cdfb6 Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Tue, 1 Aug 2017 16:36:11 -0400 Subject: [PATCH 1/2] Update remark, retext --- test/package.json | 53 +++++++++++++++++----- test/prose | 111 ++++++++++++++++++++++++++++++---------------- 2 files changed, 113 insertions(+), 51 deletions(-) diff --git a/test/package.json b/test/package.json index 63c9f969a83..29e2980d29f 100644 --- a/test/package.json +++ b/test/package.json @@ -10,23 +10,52 @@ "js-yaml": "^3.6.1", "kindlegen": "^1.1.0", "mkdirp": "^0.5.1", - "remark-lint": "^5.0.0", - "remark-parse": "^2.0.0", - "remark-retext": "^2.0.0", - "remark-stringify": "^2.0.0", - "retext-english": "^2.0.0", - "retext-equality": "^2.3.2", - "retext-quotes": "^1.0.0", - "retext-readability": "^3.0.0", + "remark-frontmatter": "^1.1.0", + "remark-lint": "^6.0.0", + "remark-lint-blockquote-indentation": "^1.0.0", + "remark-lint-emphasis-marker": "^1.0.0", + "remark-lint-final-newline": "^1.0.0", + "remark-lint-first-heading-level": "^1.1.0", + "remark-lint-hard-break-spaces": "^1.0.1", + "remark-lint-heading-increment": "^1.0.0", + "remark-lint-heading-style": "^1.0.0", + "remark-lint-list-item-bullet-indent": "^1.0.0", + "remark-lint-list-item-content-indent": "^1.0.0", + "remark-lint-list-item-indent": "^1.0.0", + "remark-lint-maximum-heading-length": "^1.0.0", + "remark-lint-no-auto-link-without-protocol": "^1.0.0", + "remark-lint-no-blockquote-without-marker": "^2.0.0", + "remark-lint-no-consecutive-blank-lines": "^1.0.0", + "remark-lint-no-duplicate-definitions": "^1.0.0", + "remark-lint-no-duplicate-headings": "^1.0.0", + "remark-lint-no-heading-content-indent": "^1.0.0", + "remark-lint-no-inline-padding": "^1.0.0", + "remark-lint-no-literal-urls": "^1.0.0", + "remark-lint-no-missing-blank-lines": "^1.0.0", + "remark-lint-no-multiple-toplevel-headings": "^1.0.0", + "remark-lint-no-shortcut-reference-image": "^1.0.0", + "remark-lint-no-shortcut-reference-link": "^1.0.1", + "remark-lint-no-undefined-references": "^1.0.0", + "remark-lint-no-unused-definitions": "^1.0.0", + "remark-lint-ordered-list-marker-style": "^1.0.0", + "remark-lint-strong-marker": "^1.0.0", + "remark-lint-unordered-list-marker-style": "^1.0.0", + "remark-parse": "^4.0.0", + "remark-retext": "^3.0.0", + "remark-stringify": "^4.0.0", + "retext-english": "^3.0.0", + "retext-equality": "^3.1.0", + "retext-quotes": "^2.0.0", + "retext-readability": "^4.1.0", "retext-repeated-words": "^1.0.0", - "retext-sentence-spacing": "^1.0.0", - "retext-simplify": "^3.0.0", + "retext-sentence-spacing": "^2.0.0", + "retext-simplify": "^4.1.0", "retext-words": "bkeepers/retext-words", "slug": "^0.9.1", "to-vfile": "^2.1.0", - "unified": "^5.0.0", + "unified": "^6.1.0", "unist-util-visit": "^1.1.1", - "vfile-reporter": "^3.0.0", + "vfile-reporter": "^4.0.0", "vfile-statistics": "^1.0.0" } } diff --git a/test/prose b/test/prose index ab1893fcca0..e531a1ed588 100755 --- a/test/prose +++ b/test/prose @@ -5,9 +5,38 @@ var unified = require('unified'); // Remark stuff (markdown) var parse = require('remark-parse'); -var lint = require('remark-lint'); var remark2retext = require('remark-retext'); var stringify = require('remark-stringify'); +var frontmatter = require('remark-frontmatter'); +var lint = require('remark-lint'); +var headingStyle = require('remark-lint-heading-style'); +var firstHeadingLevel = require('remark-lint-first-heading-level'); +var headingIncrement = require('remark-lint-heading-increment'); +var maximumHeadingLength = require('remark-lint-maximum-heading-length'); +var noDuplicateHeadings = require('remark-lint-no-duplicate-headings'); +var noMultipleToplevelHeadings = require('remark-lint-no-multiple-toplevel-headings'); +var listItemIndent = require('remark-lint-list-item-indent'); +var listItemBulletIndent = require('remark-lint-list-item-bullet-indent'); +var listItemContentIndent = require('remark-lint-list-item-content-indent'); +var unorderedListMarkerStyle = require('remark-lint-unordered-list-marker-style'); +var orderedListMarkerStyle = require('remark-lint-ordered-list-marker-style'); +var emphasisMarker = require('remark-lint-emphasis-marker'); +var strongMarker = require('remark-lint-strong-marker'); +var blockquoteIndentation = require('remark-lint-blockquote-indentation'); +var noMissingBlankLines = require('remark-lint-no-missing-blank-lines'); +var noConsecutiveBlankLines = require('remark-lint-no-consecutive-blank-lines'); +var finalNewline = require('remark-lint-final-newline'); +var noAutoLinkWithoutProtocol = require('remark-lint-no-auto-link-without-protocol'); +var noBlockquoteWithoutMarker = require('remark-lint-no-blockquote-without-marker'); +var noLiteralUrls = require('remark-lint-no-literal-urls'); +var hardBreakSpaces = require('remark-lint-hard-break-spaces'); +var noDuplicateDefinitions = require('remark-lint-no-duplicate-definitions'); +var noHeadingContentIndent = require('remark-lint-no-heading-content-indent'); +var noInlinePadding = require('remark-lint-no-inline-padding'); +var noShortcutReferenceImage = require('remark-lint-no-shortcut-reference-image'); +var noShortcutReferenceLink = require('remark-lint-no-shortcut-reference-link'); +var noUndefinedReferences = require('remark-lint-no-undefined-references'); +var noUnusedDefinitions = require('remark-lint-no-unused-definitions'); // Retext stuff (prose) var english = require('retext-english'); @@ -53,52 +82,56 @@ if(process.env.FULL_PROSE_CHECK) { // Markdown checking pipeline. var markdown = unified() - .use(parse) + .use(parse, {footnotes: true}) + .use(stringify) + .use(frontmatter, 'yaml') + // https://github.com/wooorm/remark-lint/blob/master/doc/rules.md - .use(lint, { - // Headings - headingStyle: 'atx', // ## Headings - firstHeadingLevel: 2, // Page title is h1, so start with h2 - headingIncrement: true, - maximumHeadingLength: 80, // FIXME: Eventually remove this - noDuplicateHeadings: true, - noMultipleToplevelHeadings: true, + .use(lint) - // Lists - listItemIndent: 'space', // As the gods intended. - listItemBulletIndent: true, - listItemContentIndent: true, - unorderedListMarkerStyle: '*', - orderedListMarkerStyle: '.', + // Headings + .use(headingStyle, 'atx') // ## Headings + .use(firstHeadingLevel, 2) // Page title is h1, so start with h2 + .use(headingIncrement) + .use(maximumHeadingLength, 80) // FIXME: Eventually remove this + .use(noDuplicateHeadings) + .use(noMultipleToplevelHeadings) - // Misc - emphasisMarker: '_', - strongMarker: '*', - blockquoteIndentation: 2, - noMissingBlankLines: {exceptTightLists: true}, - noConsecutiveBlankLines: true, - finalNewline: true, - noAutoLinkWithoutProtocol: true, - noBlockquoteWithoutCaret: true, - noLiteralUrls: true, + // Lists + .use(listItemIndent, 'space') // As the gods intended. + .use(listItemBulletIndent) + .use(listItemContentIndent) + .use(unorderedListMarkerStyle, '*') + .use(orderedListMarkerStyle, '.') - // Mistakes - hardBreakSpaces: true, - noDuplicateDefinitions: true, - noHeadingContentIndent: true, - noInlinePadding: true, - noShortcutReferenceImage: true, - noShortcutReferenceLink: true, - noUndefinedReferences: true, - noUnusedDefinitions: true, - }) - .use(remark2retext, prose) - .use(stringify); + // Misc + .use(emphasisMarker, '_') + .use(strongMarker, '*') + .use(blockquoteIndentation, 2) + .use(noMissingBlankLines, {exceptTightLists: true}) + .use(noConsecutiveBlankLines) + .use(finalNewline) + .use(noAutoLinkWithoutProtocol) + .use(noBlockquoteWithoutMarker) + .use(noLiteralUrls) + + // Mistakes + .use(hardBreakSpaces) + .use(noDuplicateDefinitions) + .use(noHeadingContentIndent) + .use(noInlinePadding) + .use(noShortcutReferenceImage) + .use(noShortcutReferenceLink) + .use(noUndefinedReferences) + .use(noUnusedDefinitions) + + // Prose + .use(remark2retext, prose); async.map(ignore.filter(glob.sync('_articles/**/*.md')), function(filePath, callback) { vfile.read(filePath, function(err, file) { if(err) return callback(err); - markdown.process(file, {footnotes: true}, callback); + markdown.process(file, callback); }); }, function (err, results) { console.log(report(results)); From 57d8576d79d85160fbcde28711b2809de1fa17dc Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Thu, 3 Aug 2017 13:17:46 -0400 Subject: [PATCH 2/2] Add spell checking for articles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit adds spell checking to all the other prose and markdown checks currently in place. As spell checking is a pretty pedantic issue, often marking jargon (like 501c3, BDFL, or grantmaking) and project and product names (like Homebrew, Kubernetes, or WordPress), a personal `dictionary.txt` is included in `test/` with exceptions for the articles. URLs, filepaths, @mentions, emoji, and text in block quotes (as those are used for quotes in the articles) are excluded from the spell checking. The spell checking highlighted some cases that I changed: * All alt text of images is now properly cases if they start the paragraph * Typo `sizeable` > `sizable` (former is GB English, latter is US English) * Casing of `reddit` > `Reddit` (latter seems to be used more) * Casing of `pypa` > `PyPA` (latter seems to be used more) * Casing of `eslint` > `ESLint` (latter is the official casing) * Casing of `READMES` > `READMEs` (plural `s` is now cased just like `PRs` and `APIs`) * Casing of `ok` > `OK` (latter is the propper spelling) * Spelling of `PostgreSQL` > `Postgres` (both were used throughout, the latter seems simpler and is just as well known) * Hyphen in `tradeoffs` > `trade-offs` (both could probably be used, but the latter is more often used) * Latin `de minimis` > `minimal` (this section is about law, so the Latin makes sense, but it’s also a phrase I had to look up, so I’m guessing other people would have to as well) * Space in `pageviews` > `page views` (former is more about the metrics in Google Analytics I believe, latter is just as good?) * Space in `datasets` > `data sets` (both work, but latter is more common?) --- _articles/best-practices.md | 2 +- _articles/building-community.md | 10 +-- _articles/finding-users.md | 8 +-- _articles/how-to-contribute.md | 10 +-- _articles/leadership-and-governance.md | 4 +- _articles/legal.md | 4 +- _articles/metrics.md | 10 +-- _articles/starting-a-project.md | 6 +- test/dictionary.txt | 87 ++++++++++++++++++++++++++ test/package.json | 5 ++ test/prose | 16 ++++- 11 files changed, 134 insertions(+), 28 deletions(-) create mode 100644 test/dictionary.txt diff --git a/_articles/best-practices.md b/_articles/best-practices.md index 428b6f803b3..cbfc5c7ff56 100644 --- a/_articles/best-practices.md +++ b/_articles/best-practices.md @@ -119,7 +119,7 @@ If you don't want to accept a contribution: You shouldn't need more than 1-2 sentences to respond. For example, when a user of [celery](https://github.com/celery/celery/) reported a Windows-related error, @berkerpeksag [responded with](https://github.com/celery/celery/issues/3383): -![celery screenshot](/assets/images/best-practices/celery.png) +![Celery screenshot](/assets/images/best-practices/celery.png) If the thought of saying no terrifies you, you're not alone. As @jessfraz [put it](https://blog.jessfraz.com/post/the-art-of-closing/): diff --git a/_articles/building-community.md b/_articles/building-community.md index edb4790a106..307a1cc6fb1 100644 --- a/_articles/building-community.md +++ b/_articles/building-community.md @@ -20,7 +20,7 @@ A welcoming community is an investment into your project's future and reputation One way to think about your project's community is through what @MikeMcQuaid calls the [contributor funnel](https://speakerdeck.com/mikemcquaid/the-open-source-contributor-funnel): -![contributor funnel](/assets/images/building-community/contributor_funnel_mikemcquaid.png) +![Contributor funnel](/assets/images/building-community/contributor_funnel_mikemcquaid.png) As you build your community, consider how someone at the top of the funnel (a potential user) might theoretically make their way to the bottom (an active maintainer). Your goal is to reduce friction at each stage of the contributor experience. When people have easy wins, they will feel incentivized to do more. @@ -80,7 +80,7 @@ Try to be responsive when someone files an issue, submits a pull request, or ask Even if you can't review the request immediately, acknowledging it early helps increase engagement. Here's how @tdreyno responded to a pull request on [Middleman](https://github.com/middleman/middleman/pull/1466): -![middleman pull request](/assets/images/building-community/middleman_pr.png) +![Middleman pull request](/assets/images/building-community/middleman_pr.png) [A Mozilla study found that](https://docs.google.com/presentation/d/1hsJLv1ieSqtXBzd5YZusY-mB8e1VJzaeOmh8Q4VeMio/edit#slide=id.g43d857af8_0177) contributors who received code reviews within 48 hours had a much higher rate of return and repeat contribution. @@ -130,7 +130,7 @@ Good documentation only becomes more important as your community grows. Casual c In your CONTRIBUTING file, explicitly tell new contributors how to get started. You may even want to make a dedicated section for this purpose. [Django](https://github.com/django/django), for example, has a special landing page to welcome new contributors. -![django new contributors page](/assets/images/building-community/django_new_contributors.png) +![Django new contributors page](/assets/images/building-community/django_new_contributors.png) In your issue queue, label bugs that are suitable for different types of contributors: for example, [_"first timers only"_](https://medium.com/@kentcdodds/first-timers-only-78281ea47455#.g1k01jy05), _"good first bug"_, or _"documentation"_. [These labels](https://github.com/librariesio/libraries.io/blob/6afea1a3354aef4672d9b3a9fc4cc308d60020c8/app/models/github_issue.rb#L8-L14) make it easy for someone new to your project to quickly scan your issues and get started. @@ -158,11 +158,11 @@ See if you can find ways to share ownership with your community as much as possi * **Resist fixing easy (non-critical) bugs.** Instead, use them as opportunities to recruit new contributors, or mentor someone who'd like to contribute. It may seem unnatural at first, but your investment will pay off over time. For example, @michaeljoseph asked a contributor to submit a pull request on a [Cookiecutter](https://github.com/audreyr/cookiecutter) issue below, rather than fix it himself. -![cookiecutter issue](/assets/images/building-community/cookiecutter_submit_pr.png) +![Cookiecutter issue](/assets/images/building-community/cookiecutter_submit_pr.png) * **Start a CONTRIBUTORS or AUTHORS file in your project** that lists everyone who's contributed to your project, like [Sinatra](https://github.com/sinatra/sinatra/blob/master/AUTHORS.md) does. -* If you've got a sizeable community, **send out a newsletter or write a blog post** thanking contributors. Rust's [This Week in Rust](https://this-week-in-rust.org/) and Hoodie's [Shoutouts](http://hood.ie/blog/shoutouts-week-24.html) are two good examples. +* If you've got a sizable community, **send out a newsletter or write a blog post** thanking contributors. Rust's [This Week in Rust](https://this-week-in-rust.org/) and Hoodie's [Shoutouts](http://hood.ie/blog/shoutouts-week-24.html) are two good examples. * **Give every contributor commit access.** @felixge found that this made people [more excited to polish their patches](http://felixge.de/2013/03/11/the-pull-request-hack.html), and he even found new maintainers for projects that he hadn't worked on in awhile. diff --git a/_articles/finding-users.md b/_articles/finding-users.md index 63f51f986b5..200db3e1b55 100644 --- a/_articles/finding-users.md +++ b/_articles/finding-users.md @@ -27,7 +27,7 @@ Remember that people get involved as users, and eventually contributors, because For example, @robb uses code examples to clearly communicate why his project, [Cartography](https://github.com/robb/Cartography), is useful: -![cartography readme](/assets/images/finding-users/cartography.jpg) +![Cartography README](/assets/images/finding-users/cartography.jpg) For a deeper dive into messaging, check out Mozilla's ["Personas and Pathways"](http://mozillascience.github.io/working-open-workshop/personas_pathways/) exercise for developing user personas. @@ -60,7 +60,7 @@ If you don't wish to set up these channels for your project yet, promote your ow If your project is hosted on GitHub, you can use [GitHub Pages](https://pages.github.com/) to easily make a website. [Yeoman](http://yeoman.io/), [Vagrant](https://www.vagrantup.com/), and [Middleman](https://middlemanapp.com/) are [a few examples](https://github.com/showcases/github-pages-examples) of excellent, comprehensive websites. -![vagrant homepage](/assets/images/finding-users/vagrant_homepage.png) +![Vagrant homepage](/assets/images/finding-users/vagrant_homepage.png) Now that you have a message for your project, and an easy way for people to find your project, let's get out there and talk to your audience! @@ -68,7 +68,7 @@ Now that you have a message for your project, and an easy way for people to find Online outreach is a great way to share and spread the word quickly. Using online channels, you have the potential to reach a very wide audience. -Take advantage of existing online communities and platforms to reach your audience. If your open source project is a software project, you can probably find your audience on [Stack Overflow](http://stackoverflow.com/), [reddit](http://www.reddit.com), [Hacker News](https://news.ycombinator.com/), or [Quora](https://www.quora.com/). Find the channels where you think people will most benefit from or be excited about your work. +Take advantage of existing online communities and platforms to reach your audience. If your open source project is a software project, you can probably find your audience on [Stack Overflow](http://stackoverflow.com/), [Reddit](http://www.reddit.com), [Hacker News](https://news.ycombinator.com/), or [Quora](https://www.quora.com/). Find the channels where you think people will most benefit from or be excited about your work.