Skip to content

䷂ Verify the existence—and assess the quality—of README files on GitHub (Enterprise) repositories.

License

Notifications You must be signed in to change notification settings

commonality/readme-inspector

Repository files navigation

readme-inspector NPM version GitHub release

markdown Inspect GitHub (Enterprise) repositories for the presence and quality of READMEs.

The MIT License FOSSA Status NSP Status Known Vulnerabilities
Dependency Status Development Dependency Status
MacOS and Ubuntu build statuses Windows build status Coverage percentage Codacy code quality Maintenance
NPMS score NPM downloads per month

Table of contents

1. Installation

readme-inspector is written in JavaScript (CommonJS) for Node.js External link versions 7.6.0 or higher (for async/await support).

$ npm install --save readme-inspector

2. Configuration

The commonality/readme-inspector module combines the mediator, proxy, and factory design patterns to simplify:

  • README detection with the readmeInfo object, and
  • Quality assessment with the readmeInfo.appraisal object.

2.1. Setting environment variables

readme-inspector invokes Web services to return information. These services use .env variables that require configuration:

# ENV VARS defaults for readme-inspector:

# ReadmeAppraisal REST API
# 💼 Modify this if you are using a company hosted installation.
API_ENDPOINT_README_SCORE="http://readme-score-api.herokuapp.com/score.json?url=&human_breakdown=false&force=false"

# Bitbucket REST API v1.0 and v2.0 base url.
# 💼 Modify this if you're using on-premise,
#    company-hosted Bitbucket servers.
BITBUCKET_API_BASE_URL="https://api.bitbucket.org"

## Google Analytics trackingCode
GA_README_INSPECTOR="UA-117338111-1"

# GitHub REST API v3 baseUrl.
# 💼 Modify this if you're using GitHub Enterprise, e.g.,
# GITHUB_API_BASE_URL="https://evilcorp.github.com/v3
GITHUB_API_BASE_URL="https://api.github.com"

# readme-score-api base url.
# 💼 Modify this if you've installed it behind a company firewall.
README_SCORE_API_BASE_URL="http://readme-score-api.herokuapp.com"

light-bulb To avoid rate-limiting, you should create a personal access token External link and save your personal access token in an environment variable called GH_TOKEN.


Click here for detailed .env variable initialization instructions.

info View dotenv-extended's README External link for detailed .env variable set up instructions.

file .env.schema

Defines a schema of what variables should be defined in the combination of .env and .env.defaults.

# .env.schema, committed to repo

## See https://github.com/keithmorris/node-dotenv-extended/#readme
## ⛔️
## 🚫  DO NOT COMMIT YOUR ACTUAL .env file to version control.
## 🚫  It should only include environment-specific values such
## 🚫  as database passwords or API keys.
## 🚫  Your production database should have a different password
## 🚫  than your development database.

# ENV VARS required for readme-inspector
## Add values to these ENV VARs and save to
## {your-project-root-directory}/.env, e.g.,
## if your root project directory is
##
## $ more-bort-license-plates/
##
## then save your .env file to
##
## $ more-bort-license-plates/.env

# 🔹 OPTIONAL env vars (set in .env.defaults):
API_ENDPOINT_README_SCORE=
BITBUCKET_API_BASE_URL=
GA_README_INSPECTOR=
GITHUB_API_BASE_URL=
README_SCORE_API_BASE_URL=

# 🔸 RECOMMENDED vars (to extend API rate limits)
BITBUCKET_ACCESS_TOKEN=
BITBUCKET_AUTH_PASSWORD=
BITBUCKET_AUTH_USERNAME=
GH_TOKEN=
GITHUB_ACCESS_TOKEN=

file .env.defaults

.env.defaults provides common configuration defaults across all environments (commited to source control). This contains overall app configuration values that would be common across environments. The .env.defaults file is loaded first; then the .env file is loaded and will overwrite any values from the .env.defaults file.

# .env.defaults, committed to repo

## See https://github.com/keithmorris/node-dotenv-extended/#readme
## ⛔️
## 🚫  DO NOT COMMIT YOUR ACTUAL .env file to version control.
## 🚫  It should only include environment-specific values such
## 🚫  as database passwords or API keys.
## 🚫  Your production database should have a different password
## 🚫  than your development database.

# ENV VARS defaults for readme-inspector:

# ReadmeAppraisal REST API
# 💼 Modify this if you are using a company hosted installation.
API_ENDPOINT_README_SCORE="http://readme-score-api.herokuapp.com/score.json?url=&human_breakdown=false&force=false"

# Bitbucket REST API v1.0 and v2.0 base url.
# 💼 Modify this if you're using on-premise, company-hosted Bitbucket servers.
BITBUCKET_API_BASE_URL="https://api.bitbucket.org"

## Google Analytics trackingCode
GA_README_INSPECTOR="UA-117338111-1"

# GitHub REST API v3 baseUrl.
# 💼 Modify this if you're using GitHub Enterprise.
GITHUB_API_BASE_URL="https://api.github.com"

# readme-score-api base url.
# 💼 Modify this if you've installed it behind a company firewall.
README_SCORE_API_BASE_URL="http://readme-score-api.herokuapp.com"

file .env

The environment-specific file (not committed to source control). This file will have sensitive information such as usernames, passwords, api keys, etc. These would be specific to each environment and should not be committed to source control.

# BITBUCKET_ACCESS_TOKEN=
# BITBUCKET_API_BASE_URL=
# BITBUCKET_AUTH_PASSWORD=
# BITBUCKET_AUTH_USERNAME=
# GA_README_INSPECTOR="UA-117338111-1"
# GITHUB_API_BASE_URL=
# README_SCORE_API_BASE_URL=
API_ENDPOINT_README_SCORE="http://readme-score-api.herokuapp.com/score.json?url=&human_breakdown=false&force=false"
GH_TOKEN=$(echo $GH_TOKEN)
GITHUB_ACCESS_TOKEN=$(echo $GH_TOKEN)


2. Usage

beaker Test readme-inspector in your Web browser link-external.

// Load all .env variables before anything else.

const dotenvExtended = require('dotenv-extended')
const envConfig = dotenvExtended.config()

// Import readme-inspector.

const readmeInspector = require('readme-inspector')

// Recommended: authenticate to avoid rate limts.

readmeInspector.authenticate({
  token: envConfig.GH_TOKEN,
  type: 'oauth'
})

// Verify that the repository with the slug
// gregswindle/github-resource-converter
// 1. Has a README, and
// 2. Score the README for quality.

const info = await readmeInspector.check({
  owner: 'gregswindle',
  repo:  'github-resource-converter'
})

// Display the resulting readmeInfo as a
// JSON string.

const WHITESPACE = 2
console.log(JSON.stringify(results, null, WHITESPACE))
// =>
/*
{
  "appraisal": {
    "breakdown": {
      "cumulativeCodeBlockLength": 0,
      "hasLists": 0,
      "lowCodeBlockPenalty": 0,
      "numberOfCodeBlocks": 0,
      "numberOfGifs": 0,
      "numberOfImages": 0,
      "numberOfNonCodeSections": 0
    },
    "error": null,
    "score": 0,
    "url": null
  },
  "error": null,
  "isPresent": true,
  "value": {
    "name": "README.md",
    "path": "README.md",
    "sha": "4769744aad57ff3e9aac2df603795c4d10fcdc31",
    "size": 36877,
    "url": "https://api.github.com/repos/commonality/readme-inspector/contents/README.md?ref=master",
    "html_url": "https://github.com/commonality/readme-inspector/blob/master/README.md",
    "git_url": "https://api.github.com/repos/commonality/readme-inspector/git/blobs/4769744aad57ff3e9aac2df603795c4d10fcdc31",
    "download_url": "https://raw.githubusercontent.com/commonality/readme-inspector/master/README.md",
    "type": "file",
    "content": "{base64-encoding-of-readme-markdown}",
    "encoding": "base64",
    "_links": {
      "self": "https://api.github.com/repos/commonality/readme-inspector/contents/README.md?ref=master",
      "git": "https://api.github.com/repos/commonality/readme-inspector/git/blobs/4769744aad57ff3e9aac2df603795c4d10fcdc31",
      "html": "https://github.com/commonality/readme-inspector/blob/master/README.md"
    }
  }
}
*/

3. API

beaker Test readme-inspector in your Web browser link-external.

gear View the full API docs for details link-external.

The readmeInspector module detects whether or not a README document exists at the root of a GitHub or GitHub Enterprise repository. If a README exists, it can evaluate the README's quality and provide a numerical score from 0 to 100, where 0 is the lowest quality and 100 is the highest.

3.1. authenticate({token, type, key})

Info Most GitHub API calls don't require authentication. Rules of thumb:

  1. If you can see the information by visiting the site without being logged in, you don't have to be authenticated to retrieve the same information through the API.
  2. If you want to change data, you have to be authenticated.

Note: authenticate is synchronous because it only sets the credentials for the following requests.

octokit/rest.js. (2018). GitHub. Retrieved 21 March 2018, from https://github.com/octokit/rest.js#authentication link-external

3.1.1. Parameters

Name Type Description
key String type=oauth Client identifier
token String `type=[integration
type Enum. basic, oauth, token, or integration
username String type=basic Basic authentication username
password String type=basic Basic authentication password

3.1.2. Returns void

authenticate does not return a value.

3.1.3. Example

// Token (https://github.com/settings/tokens)
// Load your GH_TOKEN or GITHUB_ACCESS_TOKEN from
// environment variables:
const dotenvExtended = require('dotenv-extended')
const envConfig = dotenvExtended.config()

const readmeInspector = require('readme-inspector')

readmeInspector.authenticate({
  token: envConfig.GH_TOKEN,
  type: 'token'
})

3.2. check({ower, repo, ref})

A convenience method that

  • Attempts to GET a repository's root-level README, and, if found,
  • Scores the README.

GET

/repos/:owner/:repo/readme

If a README is found, then the readme-score-api is invoked:

GET

/score.json?url=:owner/:repo

3.2.1. Parameters

Field Type Description
owner String
repo String
ref optional String The name of the commit/branch/tag. Default: the repository’s default branch (usually master).

3.2.2. Returns Promise<ReadmeInfo>

ReadmeInfo's interface (as a NullObject):

{
  'err': null,
  'isPresent': null,
  'appraisal': {
    'breakdown': {
      'cumulativeCodeBlockLength': 0,
      'hasLists': 0,
      'lowCodeBlockPenalty': 0,
      'numberOfCodeBlocks': 0,
      'numberOfGifs': 0,
      'numberOfImages': 0,
      'numberOfNonCodeSections': 0
    },
    'err': null,
    'score': 0,
    'url': null
  },
  'value': null
}

3.2.3. Examples

  • async/await:

    const readmeInfo = await readmeInspector.check({
      owner: 'commonality',
      ref: 'GH-1-a-topic-branch',
      repo: 'readme-inspector'
    })
  • Promise:

    readmeInspector
      .check({
        owner: 'commonality',
        ref: 'GH-1-a-topic-branch',
        repo: 'readme-inspector'
      })
      .then(readmeInfo => {})
      .catch(err => {})

3.3. getInfo({owner, repo, ref})

Retrieves README information without any AppraisalData.

GET

/repos/:owner/:repo/readme

3.3.1. Parameters

Field Type Description
owner String
repo String
ref optional String The name of the commit/branch/tag. Default: the repository’s default branch (usually master).

3.3.2. Returns Promise<ReadmeInfo>

ReadmeInfo's interface (as a NullObject):

{
  'err': null,
  'isPresent': null,
  'appraisal': {
    'breakdown': {
      'cumulativeCodeBlockLength': 0,
      'hasLists': 0,
      'lowCodeBlockPenalty': 0,
      'numberOfCodeBlocks': 0,
      'numberOfGifs': 0,
      'numberOfImages': 0,
      'numberOfNonCodeSections': 0
    },
    'err': null,
    'score': 0,
    'url': null
  },
  'value': null
}

3.3.3. Examples

  • async/await:

    const readmeInfo = await readmeInspector.getInfo({
      owner: 'commonality',
      ref: 'GH-1-a-topic-branch',
      repo: 'readme-inspector'
    })
  • Promise:

    readmeInspector
      .getInfo({
        owner: 'commonality',
        ref: 'GH-1-a-topic-branch',
        repo: 'readme-inspector'
      })
      .then(readmeInfo => readmeInfo)
      .catch(err => {
        console.error(err)
      })

3.4. getAppraisal(url)

A convenience wrapper that calls the ReadmeAppraisal.prototype.for method.

3.5. ReadmeAppraisal

ReadmeAppraisal is an API proxy for @clayallsopp External link's readme-score-api External link.

quote ScoreMe gives you a numerical score from 0 to 100 for your Github-style README. The intention is to measure complexity, which is a generally correlated with quality.

It won't measure if one README is absolutely better than another, but it will give you a good idea if the README is high-quality, needs more work, or somewhere inbetween.

ScoreMe. (2018). Clayallsopp.github.io. Retrieved 10 April 2018, from http://clayallsopp.github.io/readme-score/

3.5.1. for(url): Promise<AppraisalData>

Evaluate the README at the root of a GitHub repository.

3.5.1.1. Parameters
Name Type Description
url String The URL, or slug of the repository to be evaluated for a README.
3.5.1.2. Returns Promise<AppraisalData>
  • AppraisalData as a NullObject (see lib/appraisal-data):

    {
      breakdown: {
        cumulativeCodeBlockLength: 0
        hasLists: 0
        lowCodeBlockPenalty: 0
        numberOfCodeBlocks: 0
        numberOfGifs: 0
        numberOfImages: 0
        numberOfNonCodeSections: 0
      },
      err: null,
      score: 0
      url: null
    }
3.5.1.3. Examples
  • URL:

    const { ReadmeAppraisal } = require('readme-inspector')
    const readmeAppraisal = new ReadmeAppraisal()
    const url = 'https://github.com/gregswindle/github-resource-converter'
    
    const appraisal = readmeAppraisal.for(url)
    /** =>
     * {
     *   breakdown: {
     *    cumulativeCodeBlockLength: 10
     *    hasLists: 10
     *    lowCodeBlockPenalty: 0
     *    numberOfCodeBlocks: 40
     *    numberOfGifs: 0
     *    numberOfImages: 15
     *    numberOfNonCodeSections: 30
     *  },
     *  err: null,
     *  score: 100
     *  url: 'https://github.com/gregswindle/github-resource-converter'
     * }
     */
  • Repository slug:

    const { ReadmeAppraisal } = require('readme-inspector')
    const readmeAppraisal = new ReadmeAppraisal()
    const url = 'gregswindle/github-resource-converter'
    
    const appraisal = readmeAppraisal.for(url)

4. Version

NPM version

View the Change Log and Releases for details.

5. Contributing

PRs Welcome External link We welcome contributions with GitHub issues and pull requests.


Request a feature Report a defect

Read the CONTRIBUTING guidelines


Before embarking on a significant change, please follow these guidelines:

  1. Create an issue—e.g., a defect ("bug") report or a feature request—to propose changes.

    Exceptions:

    If you're working on documentation and fixing something simple like a typo or an easy bug, go ahead and make a pull request.

  2. Follow the CONTRIBUTING guidelines.

    Why:

    Standards and guidelines make communication easier. If you're willing and able to program—or want to learn how— following the guidelines will increase the likelihood of having your changes added to readme-inspector.

  3. Read the Code of Conduct.

  4. Make a pull request when you're ready for other to review your changes (or you get stuck somewhere).

    Never created a pull request?

    No problem: this free online training External link covers most of the conventions in the CONTRIBUTING guidelines.)

6. License

MIT link-external © commonality link-external

FOSSA Status


Greenkeeper badge Readme ReadmeAppraisal