diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..7586723 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,9 @@ +{ + "env": { + "node": true, + "browser": true + }, + "rules": { + "quotes": [2, "single"] + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f41859a --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +.DS_Store +*.log +bower_components/ +build/ +components/ +coverage/ +node_modules/ +build.js diff --git a/.jscs.json b/.jscs.json new file mode 100644 index 0000000..7345bfb --- /dev/null +++ b/.jscs.json @@ -0,0 +1,143 @@ +{ + "plugins": [ + "jscs-jsdoc" + ], + "jsDoc": { + "checkAnnotations": "jsdoc3", + "checkParamNames": true, + "requireParamTypes": true, + "checkRedundantParams": true, + "checkReturnTypes": true, + "checkRedundantReturns": true, + "requireReturnTypes": true, + "checkTypes": "strictNativeCase", + "checkRedundantAccess": true, + "enforceExistence": true, + "requireHyphenBeforeDescription": true + }, + "requireCurlyBraces": [ + "if", + "else", + "for", + "while", + "do", + "try", + "catch" + ], + "requireSpaceAfterKeywords": [ + "if", + "else", + "for", + "while", + "do", + "switch", + "return", + "try", + "catch" + ], + "requireSpaceBeforeBlockStatements": true, + "requireParenthesesAroundIIFE": true, + "requireSpacesInConditionalExpression": true, + "requireSpacesInAnonymousFunctionExpression": { + "beforeOpeningRoundBrace": true, + "beforeOpeningCurlyBrace": true + }, + "requireSpacesInNamedFunctionExpression": { + "beforeOpeningRoundBrace": true, + "beforeOpeningCurlyBrace": true + }, + "requireSpacesInFunctionExpression": { + "beforeOpeningCurlyBrace": true + }, + "requireBlocksOnNewline": true, + "disallowPaddingNewlinesInBlocks": true, + "disallowEmptyBlocks": true, + "disallowSpacesInsideObjectBrackets": true, + "disallowSpacesInsideArrayBrackets": true, + "disallowSpacesInsideParentheses": true, + "requireSpacesInsideObjectBrackets": "all", + "disallowDanglingUnderscores": true, + "disallowSpaceAfterObjectKeys": true, + "requireCommaBeforeLineBreak": true, + "requireOperatorBeforeLineBreak": [ + "?", + "+", + "-", + "/", + "*", + "=", + "==", + "===", + "!=", + "!==", + ">", + ">=", + "<", + "<=" + ], + "requireSpaceBeforeBinaryOperators": [ + "+", + "-", + "/", + "*", + "=", + "==", + "===", + "!=", + "!==" + ], + "requireSpaceAfterBinaryOperators": [ + "+", + "-", + "/", + "*", + "=", + "==", + "===", + "!=", + "!==" + ], + "disallowSpaceAfterPrefixUnaryOperators": [ + "++", + "--", + "+", + "-", + "~", + "!" + ], + "disallowSpaceBeforePostfixUnaryOperators": [ + "++", + "--" + ], + "disallowImplicitTypeConversion": [ + "numeric", + "boolean", + "binary", + "string" + ], + "requireCamelCaseOrUpperCaseIdentifiers": true, + "disallowKeywords": [ + "with" + ], + "disallowMultipleLineStrings": true, + "disallowMultipleLineBreaks": true, + "validateLineBreaks": "LF", + "validateQuoteMarks": "'", + "disallowMixedSpacesAndTabs": true, + "disallowTrailingWhitespace": true, + "disallowTrailingComma": true, + "disallowKeywordsOnNewLine": [ + "else" + ], + "requireLineFeedAtFileEnd": true, + "maximumLineLength": 78, + "requireCapitalizedConstructors": true, + "safeContextKeyword": "self", + "requireDotNotation": true, + "disallowYodaConditions": true, + "validateJSDoc": { + "checkParamNames": true, + "checkRedundantParams": true, + "requireParamTypes": true + } +} diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..adbc59e --- /dev/null +++ b/.npmignore @@ -0,0 +1,15 @@ +.* +*.log +bower_components/ +build/ +components/ +coverage/ +node_modules/ +test/ +build.js +example.js +mdast-github.js +mdast-github.min.js +bower.json +component.json +History.md diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..b457dbd --- /dev/null +++ b/.travis.yml @@ -0,0 +1,16 @@ +language: node_js +script: npm run-script test-travis +node_js: +- '0.10' +- '0.11' +- '0.12' +- iojs +after_script: npm install coveralls@2.10.0 && cat ./coverage/lcov.info | coveralls +sudo: false +deploy: + provider: npm + email: tituswormer@gmail.com + api_key: + secure: eXE7Veb+DIeH1B39sjwn22+LlJVqELk07/Mx48vWd5OGUK38NYN781mH+1cB6JrtIM0lJlAu1RJahbZo8uEcINEpZIXKR7UiUwOng1EbrSeV+DgC2HL71lPxapeYmU6eGkCiu2usAM6o7Wn8XY9//HP8+weBVnWhDCVuCqQSCx8= + on: + repo: wooorm/mdast-github diff --git a/History.md b/History.md new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/History.md @@ -0,0 +1 @@ + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..32e7a3d --- /dev/null +++ b/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2015 Titus Wormer + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..dc4c05d --- /dev/null +++ b/Readme.md @@ -0,0 +1,152 @@ +# mdast-github [![Build Status](https://img.shields.io/travis/wooorm/mdast-github.svg?style=flat)](https://travis-ci.org/wooorm/mdast-github) [![Coverage Status](https://img.shields.io/coveralls/wooorm/mdast-github.svg?style=flat)](https://coveralls.io/r/wooorm/mdast-github?branch=master) + +Auto-link references to commits, issues, pull-requests, and users like GitHub: [Writing on GitHub](https://help.github.com/articles/writing-on-github/#references). + +## Installation + +[npm](https://docs.npmjs.com/cli/install) + +```bash +$ npm install mdast-github +``` + +[Component.js](https://github.com/componentjs/component) + +```bash +$ component install wooorm/mdast-github +``` + +[Bower](http://bower.io/#install-packages) + +```bash +$ bower install mdast-github +``` + +[Duo](http://duojs.org/#getting-started) + +```javascript +var github = require('wooorm/mdast-github'); +``` + +UMD: globals, AMD, and CommonJS ([uncompressed](mdast-github.js) and [compressed](mdast-github.min.js)): + +```html + + + +``` + +## Table of Contents + +- [Usage](#usage) +- [API](#api) + - [mdast.use(github)](#mdastusegithub) +- [CLI](#cli) +- [License](#license) + +## Usage + +Dependencies and input: + +```javascript +var github = require('mdast-github'); +var mdast = require('mdast').use(github); +var input = [ + '* SHA: a5c3785ed8d6a35868bc169f07e40e889087fd2e', + '* User@SHA: jlord@a5c3785ed8d6a35868bc169f07e40e889087fd2e', + '* User/Repository@SHA: jlord/sheetsee.js@a5c3785e', + '* #Num: #26', + '* GH-Num: GH-26', + '* User#Num: jlord#26', + '* User/Repository#Num: jlord/sheetsee.js#26', + '* @mention', + '* And @mentioning someone else', + '* And nothing.' +].join('\n'); +``` + +Stringify: + +```javascript +var doc = mdast.stringify(mdast.parse(input)); +``` + +Yields: + +```markdown +- SHA: [a5c3785](https://github.com/wooorm/mdast-github/commit/a5c3785ed8d6a35868bc169f07e40e889087fd2e) +- User@SHA: [jlord@a5c3785](https://github.com/jlord/mdast-github/commit/a5c3785ed8d6a35868bc169f07e40e889087fd2e) +- User/Repository@SHA: [jlord/sheetsee.js@a5c3785](https://github.com/jlord/sheetsee.js/commit/a5c3785e) +- # Num: [#26](https://github.com/wooorm/mdast-github/issues/26) +- GH-Num: [GH-26](https://github.com/wooorm/mdast-github/issues/26) +- User#Num: [jlord#26](https://github.com/jlord/mdast-github/issues/26) +- User/Repository#Num: [jlord/sheetsee.js#26](https://github.com/jlord/sheetsee.js/issues/26) +- [@mention](https://github.com/blog/821) +- And [@mentioning](https://github.com/mentioning) someone else +- And nothing. +``` + +## API + +### [mdast](https://github.com/wooorm/mdast#api).[use](https://github.com/wooorm/mdast#mdastuseplugin)(github) + +Adds references to commits, issues, pull-requests, and users similar to how [GitHub](https://help.github.com/articles/writing-on-github/#references) renders these in issues, comments, and pull request descriptions. + +- SHA commits references: `e2c1dc7690932b0cef900fa4e7355df093448341` — [e2c1dc7](https://github.com/wooorm/mdast-github/commit/e2c1dc7690932b0cef900fa4e7355df093448341) +- User@SHA: `wooorm@e2c1dc7690932b0cef900fa4e7355df093448341` — [wooorm@e2c1dc7](https://github.com/wooorm/mdast-github/commit/e2c1dc7690932b0cef900fa4e7355df093448341) +- User/Repository@SHA: `wooorm/mdast-github@e2c1dc7690932b0cef900fa4e7355df093448341` — [wooorm/mdast-github@e2c1dc7](https://github.com/wooorm/mdast-github/commit/e2c1dc7690932b0cef900fa4e7355df093448341) +- Hash-Num: `#1` — [#1](https://github.com/wooorm/mdast-github/issues/1) +- GH-Num: `GH-1` — [GH-1](https://github.com/wooorm/mdast-github/issues/1) +- User#Num: `wooorm#1` — [wooorm#1](https://github.com/wooorm/mdast-github/issues/1) +- User/Repository#Num: `wooorm/mdast-github#1` — [wooorm/mdast-github#1](https://github.com/wooorm/mdast-github/issues/1) +- At-mentions: `@mention` and `@wooorm` — [@mention](https://github.com/blog/821) and [@wooorm](https://github.com/wooorm) + +These links are generated relative to a project. In Node this is auto-detected by loading `package.json` and looking for a `repository` field. +In the browser, or when overwriting this, you can pass a `repository` to [`mdast.parse`](https://github.com/wooorm/mdast#mdastparsevalue-options) or [`mdast.run()`](https://github.com/wooorm/mdast#mdastrunast-options). + +## CLI + +A simple wrapper around `mdast --use mdast-github` + +Install: + +```bash +$ npm install --global mdast-github +``` + +Use: + +```text +Usage: mdast-github [mdast options] + +Auto-link references like in GitHub issues, PRs, and comments + +Options: + + -h, --help output usage information + -v, --version output version number + +A wrapper around `mdast --use mdast-github` + +Help for mdast: + + https://github.com/wooorm/mdast + +Usage: + +# Pass `Readme.md` through mdast-github +$ mdast-github Readme.md -o Readme.md + +# Pass stdin through mdast-github, with mdast options, and write to stdout +$ cat Docs.md | mdast-github --setting setext > Docs-new.md + +# Use other plugins +$ npm install mdast-usage +$ mdast-github --use mdast-usage Readme.md +``` + +## License + +[MIT](LICENSE) © [Titus Wormer](http://wooorm.com) diff --git a/bower.json b/bower.json new file mode 100644 index 0000000..dcfcb9c --- /dev/null +++ b/bower.json @@ -0,0 +1,42 @@ +{ + "name": "mdast-github", + "main": "mdast-github.js", + "description": "Auto-link references like in GitHub issues, PRs, and comments", + "license": "MIT", + "keywords": [ + "text", + "markdown", + "plain", + "text", + "table", + "of", + "contents", + "content", + "toc", + "generation", + "mdast" + ], + "repository": { + "type": "git", + "url": "https://github.com/wooorm/mdast-github.git" + }, + "authors": [ + "Titus Wormer " + ], + "ignore": [ + ".*", + "*.log", + "*.md", + "build/", + "components/", + "coverage/", + "node_modules/", + "test/", + "build.js", + "cli.js", + "example.js", + "index.js", + "component.json", + "package.json" + ] +} diff --git a/cli.js b/cli.js new file mode 100755 index 0000000..3c6612a --- /dev/null +++ b/cli.js @@ -0,0 +1,79 @@ +#!/usr/bin/env node +'use strict'; + +/* + * Dependencies. + */ + +var spawn = require('win-fork'); +var pack = require('./package.json'); + +/* + * Resolve. + */ + +var mdast = require.resolve('mdast/cli.js'); +var toc = require.resolve('./index.js'); + +/* + * Arguments. + */ + +var argv = process.argv.slice(2); + +/* + * Command. + */ + +var command = Object.keys(pack.bin)[0]; + +/* + * Program. + */ + +if (argv[0] === '--version' || argv[0] === '-v') { + console.log(pack.version); +} else if (argv[0] === '--help' || argv[0] === '-h') { + console.log([ + '', + 'Usage: ' + command + ' [mdast options]', + '', + pack.description, + '', + 'Options:', + '', + ' -h, --help output usage information', + ' -v, --version output version number', + '', + 'A wrapper around `mdast --use ' + command + '`', + '', + 'Help for mdast:', + '', + ' https://github.com/wooorm/mdast', + '', + 'Usage:', + '', + '# Pass `Readme.md` through ' + command, + '$ ' + command + ' Readme.md -o Readme.md', + '', + '# Pass stdin through ' + command + ', with mdast options, ' + + 'and write to stdout', + '$ cat Docs.md | ' + command + ' --setting setext > Docs-new.md', + '', + '# Use other plugins', + '$ npm install mdast-usage', + '$ ' + command + ' --use mdast-usage Readme.md' + ].join('\n ') + '\n'); +} else { + var proc = spawn(mdast, ['--use', toc].concat(argv), { + 'stdio': 'inherit' + }); + + /* + * Exit. + */ + + proc.on('exit', function (code) { + process.exit(code); + }); +} diff --git a/component.json b/component.json new file mode 100644 index 0000000..84be088 --- /dev/null +++ b/component.json @@ -0,0 +1,23 @@ +{ + "name": "mdast-github", + "version": "0.1.0", + "description": "Auto-link references like in GitHub issues, PRs, and comments", + "license": "MIT", + "keywords": [ + "text", + "markdown", + "plain", + "text", + "table", + "of", + "contents", + "content", + "toc", + "generation", + "mdast" + ], + "repository": "wooorm/mdast-github", + "scripts": [ + "index.js" + ] +} \ No newline at end of file diff --git a/example.js b/example.js new file mode 100644 index 0000000..cc978d1 --- /dev/null +++ b/example.js @@ -0,0 +1,22 @@ +// Dependencies and input: +var github = require('./index.js'); +var mdast = require('mdast').use(github); + +var input = [ + '* SHA: a5c3785ed8d6a35868bc169f07e40e889087fd2e', + '* User@SHA: jlord@a5c3785ed8d6a35868bc169f07e40e889087fd2e', + '* User/Repository@SHA: jlord/sheetsee.js@a5c3785e', + '* #Num: #26', + '* GH-Num: GH-26', + '* User#Num: jlord#26', + '* User/Repository#Num: jlord/sheetsee.js#26', + '* @mention', + '* And @mentioning someone else', + '* And nothing.' +].join('\n'); + +// Stringify: +var doc = mdast.stringify(mdast.parse(input)); + +// Yields: +console.log('markdown', doc); diff --git a/index.js b/index.js new file mode 100644 index 0000000..8feea5c --- /dev/null +++ b/index.js @@ -0,0 +1,519 @@ +'use strict'; + +/* + * Cached method. + */ + +var splice = Array.prototype.splice; +var has = Object.prototype.hasOwnProperty; + +/* + * Hide process use from browserify. + */ +var proc = typeof global !== 'undefined' && global.process; + +/** + * Return a URL to GitHub, relative to an optional + * `repo` object, or `user` and `project`. + * + * @param {Object|string?} repo + * @param {string?} project + * @return {string} + */ +function gh(repo, project) { + var base = 'https://github.com/'; + + if (project) { + repo = { + 'user': repo, + 'project': project + }; + } + + if (repo) { + base += repo.user + '/' + repo.project + '/'; + } + + return base; +} + +/* + * Username may only contain alphanumeric characters or + * single hyphens, and cannot begin or end with a hyphen. + * + * `PERSON` is either a user or a team, but also matches a team: + * https://github.com/blog/1121-introducing-team-mentions + */ + +var NAME = '(?:[a-z0-9]{1,2}|[a-z0-9][a-z0-9-]{1,37}[a-z0-9])'; +var USER = '(' + NAME + ')'; +var PERSON = '(' + NAME + '(?:\\/' + NAME + ')?)'; +var SHA = '([a-f0-9]{7,40})'; +var NUMBER = '([0-9]+)'; +var PROJECT = '((?:[a-z0-9-]|\\.git[a-z0-9-]|\\.(?!git))+)'; +var ISSUE = '(?:GH-|#)' + NUMBER; +var REPO = USER + '\\/' + PROJECT; + +var EXPRESSION_SHA = new RegExp( + '^' + SHA + '\\b', 'gi' +); + +var EXPRESSION_USER_SHA = new RegExp( + '^' + USER + '@' + SHA + '\\b', 'gi' +); + +var EXPRESSION_REPO_SHA = new RegExp( + '^' + REPO + '@' + SHA + '\\b', 'gi' +); + +var EXPRESSION_ISSUE = new RegExp( + '^' + ISSUE + '\\b', 'gi' +); + +var EXPRESSION_USER_ISSUE = new RegExp( + '^' + USER + '#' + NUMBER + '\\b', 'gi' +); + +var EXPRESSION_REPO_ISSUE = new RegExp( + '^' + REPO + '#' + NUMBER + '\\b', 'gi' +); + +var EXPRESSION_MENTION = new RegExp( + '^@' + PERSON + '\\b(?!-)', 'gi' +); + +var EXPRESSIONS_REPO = new RegExp( + '(?:^|/(?:repos/)?)' + REPO + '(?=\\.git|[\\/#@]|$)', 'i' +); + +var EXPRESSIONS_WHITE_SPACE = new RegExp('\\s'); + +/* + * Expressions to use. + */ + +var expressions = { + 'sha': EXPRESSION_SHA, + 'userSHA': EXPRESSION_USER_SHA, + 'repoSHA': EXPRESSION_REPO_SHA, + 'issue': EXPRESSION_ISSUE, + 'userIssue': EXPRESSION_USER_ISSUE, + 'repoIssue': EXPRESSION_REPO_ISSUE, + 'mention': EXPRESSION_MENTION +}; + +var order = [ + 'repoSHA', + 'userSHA', + 'sha', + 'repoIssue', + 'userIssue', + 'issue', + 'mention' +]; + +/* + * Blacklist of SHAs which are also valid words. + * + * GitHub allows abbreviating SHAs up to 7 characters. + * + * Generated by: + * + * egrep -i "^[a-f0-9]{7,}$" /usr/share/dict/words + */ + +var BLACKLIST = [ + 'deedeed', + 'fabaceae' +]; + +/** + * Check if a value is a SHA. + * + * @param {string} sha + * @return {boolean} + */ +function isSHA(sha) { + return BLACKLIST.indexOf(sha.toLowerCase()) === -1; +} + +/** + * Abbreviate a SHA. + * + * @param {string} sha + * @return {string} + */ +function abbr(sha) { + return sha.slice(0, 7); +} + +/** + * Check if a node is a text node. + * + * @param {Node} node + * @return {boolean} + */ +function isText(node) { + return node && node.type === 'text'; +} + +/** + * Render a link node. + * + * @param {Object} position + * @param {string} href + * @param {Array.} children + * @return {Node} + */ +function link(position, href, children) { + return { + 'type': 'link', + 'href': href, + 'title': null, + 'children': children, + 'position': position + }; +} + +/** + * Render a text node. + * + * @param {Object} position + * @param {string} value + * @return {Node} + */ +function text(position, value) { + return { + 'type': 'text', + 'value': value, + 'position': position + }; +} + +/** + * Find references in a text node, and return a list + * of replacement nodes. + * + * @param {Node} parent + * @param {Object} repo + * @return {Array.} + */ +function augment(parent, repo) { + var value = parent.value; + var valueLength = value.length; + var nodes = []; + var length = order.length; + var index = -1; + var offset = -1; + var node; + var name; + var match; + var subposition; + var start = 0; + var end = 0; + var position = parent.position ? parent.position.start : {}; + var line = position.line || 1; + var column = position.column || 1; + + /** + * Get the current position. + * + * @return {Object} + */ + function now() { + return { + 'line': line, + 'column': column + }; + } + + /** + * Location getter. + * + * @return {function(): Object} + */ + function location() { + var before = now(); + + /** + * Return a `position`. + * + * @return {Object} + */ + return function () { + return { + 'start': before, + 'end': now() + }; + }; + } + + position = location(); + + while (++offset < valueLength) { + index = -1; + + if ( + offset === 0 || + EXPRESSIONS_WHITE_SPACE.test(value.charAt(offset - 1)) + ) { + while (++index < length) { + name = order[index]; + + match = expressions[name].exec(value.slice(offset)); + + expressions[name].lastIndex = 0; + + if (match) { + subposition = location(); + + end = offset; + + offset += match[0].length; + + node = augment[name].apply( + null, [subposition(), repo].concat(match) + ); + + if (node) { + if (end !== start) { + nodes.push(text( + position(), value.slice(start, end) + )); + + position = location(); + } + + start = offset; + nodes.push(node); + } + } + } + } + + if (value.charAt(index) === '\n') { + line++; + column = 0; + } + + column++; + } + + if (start < valueLength) { + nodes.push(text(position(), value.slice(start, offset))); + } + + return nodes; +} + +/** + * Render a SHA relative to a repo. + * + * @param {Object} position + * @param {Object} repo + * @param {string} $0 - Whole content. + * @param {Object} $1 - Username. + * @param {Object} $2 - Project. + * @param {Object} $3 - SHA. + * @return {Node?} + */ +augment.repoSHA = function (position, repo, $0, $1, $2, $3) { + var href; + var value; + + if (isSHA($3)) { + href = gh($1, $2) + 'commit/' + $3; + value = $1 + '/' + $2 + '@' + abbr($3); + + return link(position, href, [text(position, value)]); + } +}; + +/** + * Render a SHA relative to a user. + * + * @param {Object} position + * @param {Object} repo + * @param {string} $0 - Whole content. + * @param {Object} $1 - Username. + * @param {Object} $2 - SHA. + * @return {Node?} + */ +augment.userSHA = function (position, repo, $0, $1, $2) { + var href; + var value; + + if (isSHA($2)) { + href = gh($1, repo.project) + 'commit/' + $2; + value = $1 + '@' + abbr($2); + + return link(position, href, [text(position, value)]); + } +}; + +/** + * Render a SHA. + * + * @param {Object} position + * @param {Object} repo + * @param {string} $0 - Whole content. + * @param {Object} $1 - SHA. + * @return {Node?} + */ +augment.sha = function (position, repo, $0, $1) { + var href; + + if (isSHA($1)) { + href = gh(repo) + 'commit/' + $1; + + return link(position, href, [text(position, abbr($0))]); + } +}; + +/** + * Render an issue relative to a repo. + * + * @param {Object} position + * @param {Object} repo + * @param {string} $0 - Whole content. + * @param {Object} $1 - Username. + * @param {Object} $2 - Project. + * @param {Object} $3 - Issue number. + * @return {Node} + */ +augment.repoIssue = function (position, repo, $0, $1, $2, $3) { + var href = gh($1, $2) + 'issues/' + $3; + + return link(position, href, [text(position, $0)]); +}; + +/** + * Render an issue relative to a user. + * + * @param {Object} position + * @param {Object} repo + * @param {string} $0 - Whole content. + * @param {Object} $1 - Username. + * @param {Object} $2 - Issue number. + * @return {Node} + */ +augment.userIssue = function (position, repo, $0, $1, $2) { + var href = gh($1, repo.project) + 'issues/' + $2; + + return link(position, href, [text(position, $0)]); +}; + +/** + * Render an issue. + * + * @param {Object} position + * @param {Object} repo + * @param {string} $0 - Whole content. + * @param {Object} $1 - Issue number. + * @return {Node} + */ +augment.issue = function (position, repo, $0, $1) { + var href = gh(repo) + 'issues/' + $1; + + return link(position, href, [text(position, $0)]); +}; + +var OVERWRITES = {}; + +OVERWRITES.mentions = OVERWRITES.mention = 'blog/821'; + +/** + * Render a mention. + * + * @param {Object} position + * @param {Object} repo + * @param {string} $0 - Whole content. + * @param {Object} $1 - Username. + * @return {Node} + */ +augment.mention = function (position, repo, $0, $1) { + var href = gh() + (has.call(OVERWRITES, $1) ? OVERWRITES[$1] : $1); + + return link(position, href, [text(position, $0)]); +}; + +/** + * Adds an example section based on a valid example + * JavaScript document to a `Usage` section. + * + * @param {Node} node + */ +function github(node, options) { + var repo = options.repository; + var pack; + + if (!repo) { + try { + pack = require(require('path').resolve( + proc.cwd(), 'package.json' + )); + } catch (exception) { + pack = {}; + } + + repo = pack.repository ? pack.repository.url || pack.repository : ''; + } + + repo = EXPRESSIONS_REPO.exec(repo); + + EXPRESSIONS_REPO.lastIndex = 0; + + if (!repo) { + throw new Error('Missing `repository` field in `options`'); + } + + repo = { + 'user': repo[1], + 'project': repo[2] + }; + + /** + * Replace a text node with results from `augment`. + * + * @param {Node} child + * @param {number} position + * @param {Array.} children + */ + function replace(child, position, children) { + splice.apply(children, [position, 1].concat(augment(child, repo))); + } + + var visit; + var visitAll; + + /** + * Visit `node`. Returns zero or more text blocks. + * + * @param {Node} child + */ + visit = function (child, position, children) { + if (isText(child)) { + replace(child, position, children); + } else if ('children' in child && child.type !== 'link') { + visitAll(child.children); + } + }; + + /** + * Visit all `children`. Returns a single nested + * array. + * + * @param {Array.} children + */ + visitAll = function (children) { + children.map(visit); + }; + + visit(node); +} + +/* + * Expose `github`. + */ + +module.exports = github; diff --git a/mdast-github.js b/mdast-github.js new file mode 100644 index 0000000..18ab250 --- /dev/null +++ b/mdast-github.js @@ -0,0 +1,525 @@ +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.mdastGitHub = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o} children + * @return {Node} + */ +function link(position, href, children) { + return { + 'type': 'link', + 'href': href, + 'title': null, + 'children': children, + 'position': position + }; +} + +/** + * Render a text node. + * + * @param {Object} position + * @param {string} value + * @return {Node} + */ +function text(position, value) { + return { + 'type': 'text', + 'value': value, + 'position': position + }; +} + +/** + * Find references in a text node, and return a list + * of replacement nodes. + * + * @param {Node} parent + * @param {Object} repo + * @return {Array.} + */ +function augment(parent, repo) { + var value = parent.value; + var valueLength = value.length; + var nodes = []; + var length = order.length; + var index = -1; + var offset = -1; + var node; + var name; + var match; + var subposition; + var start = 0; + var end = 0; + var position = parent.position ? parent.position.start : {}; + var line = position.line || 1; + var column = position.column || 1; + + /** + * Get the current position. + * + * @return {Object} + */ + function now() { + return { + 'line': line, + 'column': column + }; + } + + /** + * Location getter. + * + * @return {function(): Object} + */ + function location() { + var before = now(); + + /** + * Return a `position`. + * + * @return {Object} + */ + return function () { + return { + 'start': before, + 'end': now() + }; + }; + } + + position = location(); + + while (++offset < valueLength) { + index = -1; + + if ( + offset === 0 || + EXPRESSIONS_WHITE_SPACE.test(value.charAt(offset - 1)) + ) { + while (++index < length) { + name = order[index]; + + match = expressions[name].exec(value.slice(offset)); + + expressions[name].lastIndex = 0; + + if (match) { + subposition = location(); + + end = offset; + + offset += match[0].length; + + node = augment[name].apply( + null, [subposition(), repo].concat(match) + ); + + if (node) { + if (end !== start) { + nodes.push(text( + position(), value.slice(start, end) + )); + + position = location(); + } + + start = offset; + nodes.push(node); + } + } + } + } + + if (value.charAt(index) === '\n') { + line++; + column = 0; + } + + column++; + } + + if (start < valueLength) { + nodes.push(text(position(), value.slice(start, offset))); + } + + return nodes; +} + +/** + * Render a SHA relative to a repo. + * + * @param {Object} position + * @param {Object} repo + * @param {string} $0 - Whole content. + * @param {Object} $1 - Username. + * @param {Object} $2 - Project. + * @param {Object} $3 - SHA. + * @return {Node?} + */ +augment.repoSHA = function (position, repo, $0, $1, $2, $3) { + var href; + var value; + + if (isSHA($3)) { + href = gh($1, $2) + 'commit/' + $3; + value = $1 + '/' + $2 + '@' + abbr($3); + + return link(position, href, [text(position, value)]); + } +}; + +/** + * Render a SHA relative to a user. + * + * @param {Object} position + * @param {Object} repo + * @param {string} $0 - Whole content. + * @param {Object} $1 - Username. + * @param {Object} $2 - SHA. + * @return {Node?} + */ +augment.userSHA = function (position, repo, $0, $1, $2) { + var href; + var value; + + if (isSHA($2)) { + href = gh($1, repo.project) + 'commit/' + $2; + value = $1 + '@' + abbr($2); + + return link(position, href, [text(position, value)]); + } +}; + +/** + * Render a SHA. + * + * @param {Object} position + * @param {Object} repo + * @param {string} $0 - Whole content. + * @param {Object} $1 - SHA. + * @return {Node?} + */ +augment.sha = function (position, repo, $0, $1) { + var href; + + if (isSHA($1)) { + href = gh(repo) + 'commit/' + $1; + + return link(position, href, [text(position, abbr($0))]); + } +}; + +/** + * Render an issue relative to a repo. + * + * @param {Object} position + * @param {Object} repo + * @param {string} $0 - Whole content. + * @param {Object} $1 - Username. + * @param {Object} $2 - Project. + * @param {Object} $3 - Issue number. + * @return {Node} + */ +augment.repoIssue = function (position, repo, $0, $1, $2, $3) { + var href = gh($1, $2) + 'issues/' + $3; + + return link(position, href, [text(position, $0)]); +}; + +/** + * Render an issue relative to a user. + * + * @param {Object} position + * @param {Object} repo + * @param {string} $0 - Whole content. + * @param {Object} $1 - Username. + * @param {Object} $2 - Issue number. + * @return {Node} + */ +augment.userIssue = function (position, repo, $0, $1, $2) { + var href = gh($1, repo.project) + 'issues/' + $2; + + return link(position, href, [text(position, $0)]); +}; + +/** + * Render an issue. + * + * @param {Object} position + * @param {Object} repo + * @param {string} $0 - Whole content. + * @param {Object} $1 - Issue number. + * @return {Node} + */ +augment.issue = function (position, repo, $0, $1) { + var href = gh(repo) + 'issues/' + $1; + + return link(position, href, [text(position, $0)]); +}; + +var OVERWRITES = {}; + +OVERWRITES.mentions = OVERWRITES.mention = 'blog/821'; + +/** + * Render a mention. + * + * @param {Object} position + * @param {Object} repo + * @param {string} $0 - Whole content. + * @param {Object} $1 - Username. + * @return {Node} + */ +augment.mention = function (position, repo, $0, $1) { + var href = gh() + (has.call(OVERWRITES, $1) ? OVERWRITES[$1] : $1); + + return link(position, href, [text(position, $0)]); +}; + +/** + * Adds an example section based on a valid example + * JavaScript document to a `Usage` section. + * + * @param {Node} node + */ +function github(node, options) { + var repo = options.repository; + var pack; + + if (!repo) { + try { + pack = require(require('path').resolve( + proc.cwd(), 'package.json' + )); + } catch (exception) { + pack = {}; + } + + repo = pack.repository ? pack.repository.url || pack.repository : ''; + } + + repo = EXPRESSIONS_REPO.exec(repo); + + EXPRESSIONS_REPO.lastIndex = 0; + + if (!repo) { + throw new Error('Missing `repository` field in `options`'); + } + + repo = { + 'user': repo[1], + 'project': repo[2] + }; + + /** + * Replace a text node with results from `augment`. + * + * @param {Node} child + * @param {number} position + * @param {Array.} children + */ + function replace(child, position, children) { + splice.apply(children, [position, 1].concat(augment(child, repo))); + } + + var visit; + var visitAll; + + /** + * Visit `node`. Returns zero or more text blocks. + * + * @param {Node} child + */ + visit = function (child, position, children) { + if (isText(child)) { + replace(child, position, children); + } else if ('children' in child && child.type !== 'link') { + visitAll(child.children); + } + }; + + /** + * Visit all `children`. Returns a single nested + * array. + * + * @param {Array.} children + */ + visitAll = function (children) { + children.map(visit); + }; + + visit(node); +} + +/* + * Expose `github`. + */ + +module.exports = github; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"path":undefined}]},{},[1])(1) +}); \ No newline at end of file diff --git a/mdast-github.min.js b/mdast-github.min.js new file mode 100644 index 0000000..05ee230 --- /dev/null +++ b/mdast-github.min.js @@ -0,0 +1 @@ +!function(b,a){typeof exports==='object'&&typeof module!=='undefined'?module.exports=b():typeof define==='function'&&define.amd?define([],b):(typeof window!=='undefined'?a=window:typeof global!=='undefined'?a=global:typeof self!=='undefined'?a=self:a=this,a.mdastGitHub=b())}(function(){return function a(b,c,e){function f(d,k){if(!c[d]){if(!b[d]){var i=typeof require=='function'&&require;if(!k&&i)return i(d,!0);if(g)return g(d,!0);var j=new Error("Cannot find module '"+d+"'");throw j.code='MODULE_NOT_FOUND',j}var h=c[d]={exports:{}};b[d][0].call(h.exports,function(c){var a=b[d][1][c];return f(a?a:c)},h,h.exports,a,b,c,e)}return c[d].exports}var g=typeof require=='function'&&require;for(var d=0;d", + "bin": { + "mdast-github": "cli.js" + }, + "peerDependencies": { + "mdast": ">=0.11.0" + }, + "devDependencies": { + "browserify": "^9.0.0", + "chalk": "^1.0.0", + "diff": "^1.2.2", + "eslint": "^0.17.0", + "esmangle": "^1.0.0", + "istanbul": "^0.3.0", + "jscs": "^1.0.0", + "jscs-jsdoc": "^0.4.0", + "mdast": "^0.12.0", + "mdast-toc": "^0.1.1", + "mdast-usage": "^0.1.0", + "mocha": "^2.0.0" + }, + "scripts": { + "test-api": "mocha --check-leaks test/index.js", + "test-cli": "bash test/cli.sh", + "test-coveralls": "istanbul cover _mocha --report lcovonly -- --check-leaks test/index.js", + "test-coverage": "istanbul cover _mocha -- test/index.js", + "test-travis": "npm run test-coveralls && npm run test-cli", + "test": "npm run test-api && npm run test-cli", + "lint-api": "eslint index.js", + "lint-cli": "eslint --rule no-process-exit:false cli.js", + "lint-test": "eslint --env mocha test/index.js", + "lint-script": "eslint example.js", + "lint-style": "jscs --reporter inline index.js cli.js example.js test/index.js", + "lint": "npm run lint-api && npm run lint-cli && npm run lint-test && npm run lint-script && npm run lint-style", + "make": "npm run lint && npm run test-coverage", + "bundle": "browserify --no-builtins index.js -s mdastGitHub > mdast-github.js", + "postbundle": "esmangle mdast-github.js > mdast-github.min.js", + "build-readme": "mdast --use mdast-toc --use mdast-usage --use index.js -o Readme.md Readme.md", + "build-history": "mdast --use index.js -o History.md History.md", + "build": "npm run bundle && npm run build-readme && npm run build-history", + "prepublish": "npm run build" + } +} diff --git a/test/cli.sh b/test/cli.sh new file mode 100755 index 0000000..f3fc303 --- /dev/null +++ b/test/cli.sh @@ -0,0 +1,72 @@ +#!/bin/sh +#!/bin/bash + +typeset -i tests=0 + +function it { + let tests+=1; + description="$1"; +} + +function assert { + if [[ "$1" == "$2" ]]; then + printf "\033[32m.\033[0m"; + else + printf "\033[31m\nFAIL: $description\033[0m: '$1' != '$2'\n"; + exit 1 + fi +} + +it "Should accept a file" + code=0 + ./cli.js Readme.md > /dev/null 2>&1 || code=$? + assert $code 0 + +it "Should accept stdin" + code=0 + cat History.md | ./cli.js > /dev/null 2>&1 || code=$? + assert $code 0 + +it "Should fail without input" + code=0 + ./cli.js > /dev/null 2>&1 || code=$? + assert $code 1 + +it "Should fail on an invalid file" + code=0 + ./cli.js some-other-file.md > /dev/null 2>&1 || code=$? + assert $code 1 + +it "Should fail on multiple files" + code=0 + ./cli.js History.md Readme.md > /dev/null 2>&1 || code=$? + assert $code 1 + +it "Should fail on stdin and files" + code=0 + cat History.md | ./cli.js Readme.md > /dev/null 2>&1 || code=$? + assert $code 1 + +it "Should accept \`--help\`" + code=0 + ./cli.js --help > /dev/null 2>&1 || code=$? + assert $code 0 + +it "Should accept \`-h\`" + code=0 + ./cli.js -h > /dev/null 2>&1 || code=$? + assert $code 0 + +it "Should accept \`--version\`" + code=0 + ./cli.js --version > /dev/null 2>&1 || code=$? + assert $code 0 + +it "Should accept \`-v\`" + code=0 + ./cli.js -v > /dev/null 2>&1 || code=$? + assert $code 0 + +printf "\033[32m\n(✓) Passed $tests assertions without errors\033[0m\n"; + +exit 0 diff --git a/test/fixtures/issue-project/Input.md b/test/fixtures/issue-project/Input.md new file mode 100644 index 0000000..636db25 --- /dev/null +++ b/test/fixtures/issue-project/Input.md @@ -0,0 +1,20 @@ +# User@Project + +A project-SHA is not relative to the current project. + +GitHub’s project names can include alphabetical characters, dashes, and full-stops. They may end in a TLD (such as `.com`), but may not end in `.git` (for obvious reasons). + +- This is a valid issue: wooorm/mdast#1; +- So is this: wooorm/mdast#123456789. + +They work here +wooorm/mdast#1 + +and here + wooorm/mdast#1 + +Usernames: this is not a valid, -wooorm/mdast#1; nor is this wooorm-/mdast#1; but this is w-w/mdast#1, and so is w/mdast#1 and ww/mdast#1. + +Project names: this is not a valid, wooorm/c.git#1; but this is wooorm/c#1, so is w/w#1, and ww/.gitconfig#1. + +This is too long: wooormwooormwooormwooormwooormwooormwooo/c#1 (40 character username). diff --git a/test/fixtures/issue-project/Output.md b/test/fixtures/issue-project/Output.md new file mode 100644 index 0000000..b4a296a --- /dev/null +++ b/test/fixtures/issue-project/Output.md @@ -0,0 +1,20 @@ +# User@Project + +A project-SHA is not relative to the current project. + +GitHub’s project names can include alphabetical characters, dashes, and full-stops. They may end in a TLD (such as `.com`), but may not end in `.git` (for obvious reasons). + +- This is a valid issue: [wooorm/mdast#1](https://github.com/wooorm/mdast/issues/1); +- So is this: [wooorm/mdast#123456789](https://github.com/wooorm/mdast/issues/123456789). + +They work here +[wooorm/mdast#1](https://github.com/wooorm/mdast/issues/1) + +and here + [wooorm/mdast#1](https://github.com/wooorm/mdast/issues/1) + +Usernames: this is not a valid, -wooorm/mdast#1; nor is this wooorm-/mdast#1; but this is [w-w/mdast#1](https://github.com/w-w/mdast/issues/1), and so is [w/mdast#1](https://github.com/w/mdast/issues/1) and [ww/mdast#1](https://github.com/ww/mdast/issues/1). + +Project names: this is not a valid, wooorm/c.git#1; but this is [wooorm/c#1](https://github.com/wooorm/c/issues/1), so is [w/w#1](https://github.com/w/w/issues/1), and [ww/.gitconfig#1](https://github.com/ww/.gitconfig/issues/1). + +This is too long: wooormwooormwooormwooormwooormwooormwooo/c#1 (40 character username). diff --git a/test/fixtures/issue-user/Input.md b/test/fixtures/issue-user/Input.md new file mode 100644 index 0000000..8f58bda --- /dev/null +++ b/test/fixtures/issue-user/Input.md @@ -0,0 +1,18 @@ +# User@Issue + +A user-issue is relative to the project, but relative to the user’s fork. + +GitHub’s usernames can contain alphabetical characters and dashes, but can neither begin nor end with a dash. Additionally, the length of a username can be between 1 and 39 characters (both including). + +- This is a valid issue: wooorm#1; +- So is this: wooorm#123456789. + +They work here +wooorm#1 + +and here + wooorm#1 + +This is not a valid, -wooorm#1; nor is this wooorm-#1; but this is w-w#1, and so is w#1 and ww#1. + +This is too long: wooormwooormwooormwooormwooormwooormwooo#1 (40 character username). diff --git a/test/fixtures/issue-user/Output.md b/test/fixtures/issue-user/Output.md new file mode 100644 index 0000000..030e5e1 --- /dev/null +++ b/test/fixtures/issue-user/Output.md @@ -0,0 +1,18 @@ +# User@Issue + +A user-issue is relative to the project, but relative to the user’s fork. + +GitHub’s usernames can contain alphabetical characters and dashes, but can neither begin nor end with a dash. Additionally, the length of a username can be between 1 and 39 characters (both including). + +- This is a valid issue: [wooorm#1](https://github.com/wooorm/mdast/issues/1); +- So is this: [wooorm#123456789](https://github.com/wooorm/mdast/issues/123456789). + +They work here +[wooorm#1](https://github.com/wooorm/mdast/issues/1) + +and here + [wooorm#1](https://github.com/wooorm/mdast/issues/1) + +This is not a valid, -wooorm#1; nor is this wooorm-#1; but this is [w-w#1](https://github.com/w-w/mdast/issues/1), and so is [w#1](https://github.com/w/mdast/issues/1) and [ww#1](https://github.com/ww/mdast/issues/1). + +This is too long: wooormwooormwooormwooormwooormwooormwooo#1 (40 character username). diff --git a/test/fixtures/issue/Input.md b/test/fixtures/issue/Input.md new file mode 100644 index 0000000..b1c6818 --- /dev/null +++ b/test/fixtures/issue/Input.md @@ -0,0 +1,17 @@ +# Issue + +- This is a valid issue: #1, and so is this: GH-1; +- So are these: #123456789, and: GH-123456789; +- And these: gH-1, Gh-1, and gh-1. + +These will always be a header in non-commonmark mode (commonmark requires initial spaces for ATX-headings) +#1 + +Or here + #1 + +But these will always work: +GH-1 + +Or here + GH-1 diff --git a/test/fixtures/issue/Output.md b/test/fixtures/issue/Output.md new file mode 100644 index 0000000..cc29822 --- /dev/null +++ b/test/fixtures/issue/Output.md @@ -0,0 +1,19 @@ +# Issue + +- This is a valid issue: [#1](https://github.com/wooorm/mdast/issues/1), and so is this: [GH-1](https://github.com/wooorm/mdast/issues/1); +- So are these: [#123456789](https://github.com/wooorm/mdast/issues/123456789), and: [GH-123456789](https://github.com/wooorm/mdast/issues/123456789); +- And these: [gH-1](https://github.com/wooorm/mdast/issues/1), [Gh-1](https://github.com/wooorm/mdast/issues/1), and [gh-1](https://github.com/wooorm/mdast/issues/1). + +These will always be a header in non-commonmark mode (commonmark requires initial spaces for ATX-headings) + +# 1 + +Or here + + #1 + +But these will always work: +[GH-1](https://github.com/wooorm/mdast/issues/1) + +Or here + [GH-1](https://github.com/wooorm/mdast/issues/1) diff --git a/test/fixtures/mention/Input.md b/test/fixtures/mention/Input.md new file mode 100644 index 0000000..2ae98da --- /dev/null +++ b/test/fixtures/mention/Input.md @@ -0,0 +1,11 @@ +# Mention + +A mention links to a user, organisation, or team. + +For example, @user, @organization, or @organization/team-name. + +Additionally, GitHub does something funny with @mention’s and @mentions. + +Some valid real world examples: @a, @github, @github/security. + +But these names are invalid: @-w, @w-, but this is: @w-w. diff --git a/test/fixtures/mention/Output.md b/test/fixtures/mention/Output.md new file mode 100644 index 0000000..1657b8b --- /dev/null +++ b/test/fixtures/mention/Output.md @@ -0,0 +1,11 @@ +# Mention + +A mention links to a user, organisation, or team. + +For example, [@user](https://github.com/user), [@organization](https://github.com/organization), or [@organization/team-name](https://github.com/organization/team-name). + +Additionally, GitHub does something funny with [@mention](https://github.com/blog/821)’s and [@mentions](https://github.com/blog/821). + +Some valid real world examples: [@a](https://github.com/a), [@github](https://github.com/github), [@github/security](https://github.com/github/security). + +But these names are invalid: @-w, @w-, but this is: [@w-w](https://github.com/w-w). diff --git a/test/fixtures/sha-project/Input.md b/test/fixtures/sha-project/Input.md new file mode 100644 index 0000000..93404e7 --- /dev/null +++ b/test/fixtures/sha-project/Input.md @@ -0,0 +1,61 @@ +# Project@SHA + +A project-SHA is not relative to the current project. + +GitHub’s project names can include alphabetical characters, dashes, and full-stops. They may end in a TLD (such as `.com`), but may not end in `.git` (for obvious reasons). + +- wooorm/mdast@000000; +- wooorm/mdast@0000000; +- wooorm/mdast@00000000; +- wooorm/mdast@000000000; +- wooorm/mdast@0000000000; +- wooorm/mdast@00000000000; +- wooorm/mdast@000000000000; +- wooorm/mdast@0000000000000; +- wooorm/mdast@00000000000000; +- wooorm/mdast@000000000000000; +- wooorm/mdast@0000000000000000; +- wooorm/mdast@00000000000000000; +- wooorm/mdast@000000000000000000; +- wooorm/mdast@0000000000000000000; +- wooorm/mdast@00000000000000000000; +- wooorm/mdast@000000000000000000000; +- wooorm/mdast@0000000000000000000000; +- wooorm/mdast@00000000000000000000000; +- wooorm/mdast@000000000000000000000000; +- wooorm/mdast@0000000000000000000000000; +- wooorm/mdast@00000000000000000000000000; +- wooorm/mdast@000000000000000000000000000; +- wooorm/mdast@0000000000000000000000000000; +- wooorm/mdast@00000000000000000000000000000; +- wooorm/mdast@000000000000000000000000000000; +- wooorm/mdast@0000000000000000000000000000000; +- wooorm/mdast@00000000000000000000000000000000; +- wooorm/mdast@000000000000000000000000000000000; +- wooorm/mdast@0000000000000000000000000000000000; +- wooorm/mdast@00000000000000000000000000000000000; +- wooorm/mdast@00000000000000000000000000000000000; +- wooorm/mdast@000000000000000000000000000000000000; +- wooorm/mdast@0000000000000000000000000000000000000; +- wooorm/mdast@00000000000000000000000000000000000000; +- wooorm/mdast@000000000000000000000000000000000000000; +- wooorm/mdast@0000000000000000000000000000000000000000; +- wooorm/mdast@00000000000000000000000000000000000000000. + +And: + +- Prefix wooorm/mdast@0000000 suffix; +- Prefix wooorm/mdast@0000000!; +- a wooorm/mdast@0000000!; + +And what about here +wooorm/mdast@0000000 + +Or here + wooorm/mdast@0000000 + +And these SHAs which could also be words? wooorm/mdast@deedeed, and wooorm/mdast@fabaceae. + +Usernames: this is not a valid, -wooorm/mdast@0000000; nor is this wooorm-/mdast@0000000; but this is w-w/mdast@0000000, and so is w/mdast@0000000 and ww/mdast@0000000. + +Project names: this is not a valid, wooorm/c.git@0000000; but this is wooorm/c@0000000, so is w/w@0000000, and ww/.gitconfig@0000000. diff --git a/test/fixtures/sha-project/Output.md b/test/fixtures/sha-project/Output.md new file mode 100644 index 0000000..3bf19b5 --- /dev/null +++ b/test/fixtures/sha-project/Output.md @@ -0,0 +1,61 @@ +# Project@SHA + +A project-SHA is not relative to the current project. + +GitHub’s project names can include alphabetical characters, dashes, and full-stops. They may end in a TLD (such as `.com`), but may not end in `.git` (for obvious reasons). + +- wooorm/mdast@000000; +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/0000000); +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/00000000); +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/000000000); +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/0000000000); +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/00000000000); +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/000000000000); +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/0000000000000); +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/00000000000000); +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/000000000000000); +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/0000000000000000); +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/00000000000000000); +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/000000000000000000); +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/0000000000000000000); +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/00000000000000000000); +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/000000000000000000000); +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/0000000000000000000000); +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/00000000000000000000000); +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/000000000000000000000000); +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/0000000000000000000000000); +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/00000000000000000000000000); +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/000000000000000000000000000); +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/0000000000000000000000000000); +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/00000000000000000000000000000); +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/000000000000000000000000000000); +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/0000000000000000000000000000000); +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/00000000000000000000000000000000); +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/000000000000000000000000000000000); +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/0000000000000000000000000000000000); +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/00000000000000000000000000000000000); +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/00000000000000000000000000000000000); +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/000000000000000000000000000000000000); +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/0000000000000000000000000000000000000); +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/00000000000000000000000000000000000000); +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/000000000000000000000000000000000000000); +- [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/0000000000000000000000000000000000000000); +- wooorm/mdast@00000000000000000000000000000000000000000. + +And: + +- Prefix [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/0000000) suffix; +- Prefix [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/0000000)!; +- a [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/0000000)!; + +And what about here +[wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/0000000) + +Or here + [wooorm/mdast@0000000](https://github.com/wooorm/mdast/commit/0000000) + +And these SHAs which could also be words? wooorm/mdast@deedeed, and wooorm/mdast@fabaceae. + +Usernames: this is not a valid, -wooorm/mdast@0000000; nor is this wooorm-/mdast@0000000; but this is [w-w/mdast@0000000](https://github.com/w-w/mdast/commit/0000000), and so is [w/mdast@0000000](https://github.com/w/mdast/commit/0000000) and [ww/mdast@0000000](https://github.com/ww/mdast/commit/0000000). + +Project names: this is not a valid, wooorm/c.git@0000000; but this is [wooorm/c@0000000](https://github.com/wooorm/c/commit/0000000), so is [w/w@0000000](https://github.com/w/w/commit/0000000), and [ww/.gitconfig@0000000](https://github.com/ww/.gitconfig/commit/0000000). diff --git a/test/fixtures/sha-user/Input.md b/test/fixtures/sha-user/Input.md new file mode 100644 index 0000000..64dfff3 --- /dev/null +++ b/test/fixtures/sha-user/Input.md @@ -0,0 +1,63 @@ +# User@SHA + +A user-SHA is relative to the project, but relative to the user’s fork. + +GitHub’s usernames can contain alphabetical characters and dashes, but can neither begin nor end with a dash. Additionally, the length of a username can be between 1 and 39 characters (both including). + +- wooorm@000000; +- wooorm@0000000; +- wooorm@00000000; +- wooorm@000000000; +- wooorm@0000000000; +- wooorm@00000000000; +- wooorm@000000000000; +- wooorm@0000000000000; +- wooorm@00000000000000; +- wooorm@000000000000000; +- wooorm@0000000000000000; +- wooorm@00000000000000000; +- wooorm@000000000000000000; +- wooorm@0000000000000000000; +- wooorm@00000000000000000000; +- wooorm@000000000000000000000; +- wooorm@0000000000000000000000; +- wooorm@00000000000000000000000; +- wooorm@000000000000000000000000; +- wooorm@0000000000000000000000000; +- wooorm@00000000000000000000000000; +- wooorm@000000000000000000000000000; +- wooorm@0000000000000000000000000000; +- wooorm@00000000000000000000000000000; +- wooorm@000000000000000000000000000000; +- wooorm@0000000000000000000000000000000; +- wooorm@00000000000000000000000000000000; +- wooorm@000000000000000000000000000000000; +- wooorm@0000000000000000000000000000000000; +- wooorm@00000000000000000000000000000000000; +- wooorm@00000000000000000000000000000000000; +- wooorm@000000000000000000000000000000000000; +- wooorm@0000000000000000000000000000000000000; +- wooorm@00000000000000000000000000000000000000; +- wooorm@000000000000000000000000000000000000000; +- wooorm@0000000000000000000000000000000000000000; +- wooorm@00000000000000000000000000000000000000000. + +And: + +- Prefix wooorm@0000000 suffix; +- Prefix wooorm@0000000!; +- a wooorm@0000000!; + +And what about here +wooorm@0000000 + +Or here + wooorm@0000000 + +And these SHAs which could also be words? wooorm@deedeed, and wooorm@fabaceae. + +This is not a valid, -wooorm@0000000; nor is this wooorm-@0000000; but this is w-w@0000000, and so is w@0000000 and ww@0000000. + +And here’s an example of a disposable e-mail domain, which starts with 7 hexidecimal characters: wooorm@deadaddress.com, which shouldn’t match, because there’s no word break after the SHA-like part. + +This is too long: wooormwooormwooormwooormwooormwooormwooo#0000000 (40 character username). diff --git a/test/fixtures/sha-user/Output.md b/test/fixtures/sha-user/Output.md new file mode 100644 index 0000000..0b9105d --- /dev/null +++ b/test/fixtures/sha-user/Output.md @@ -0,0 +1,63 @@ +# User@SHA + +A user-SHA is relative to the project, but relative to the user’s fork. + +GitHub’s usernames can contain alphabetical characters and dashes, but can neither begin nor end with a dash. Additionally, the length of a username can be between 1 and 39 characters (both including). + +- wooorm@000000; +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/0000000); +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/00000000); +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/000000000); +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/0000000000); +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/00000000000); +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/000000000000); +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/0000000000000); +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/00000000000000); +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/000000000000000); +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/0000000000000000); +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/00000000000000000); +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/000000000000000000); +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/0000000000000000000); +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/00000000000000000000); +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/000000000000000000000); +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/0000000000000000000000); +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/00000000000000000000000); +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/000000000000000000000000); +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/0000000000000000000000000); +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/00000000000000000000000000); +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/000000000000000000000000000); +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/0000000000000000000000000000); +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/00000000000000000000000000000); +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/000000000000000000000000000000); +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/0000000000000000000000000000000); +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/00000000000000000000000000000000); +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/000000000000000000000000000000000); +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/0000000000000000000000000000000000); +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/00000000000000000000000000000000000); +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/00000000000000000000000000000000000); +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/000000000000000000000000000000000000); +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/0000000000000000000000000000000000000); +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/00000000000000000000000000000000000000); +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/000000000000000000000000000000000000000); +- [wooorm@0000000](https://github.com/wooorm/mdast/commit/0000000000000000000000000000000000000000); +- wooorm@00000000000000000000000000000000000000000. + +And: + +- Prefix [wooorm@0000000](https://github.com/wooorm/mdast/commit/0000000) suffix; +- Prefix [wooorm@0000000](https://github.com/wooorm/mdast/commit/0000000)!; +- a [wooorm@0000000](https://github.com/wooorm/mdast/commit/0000000)!; + +And what about here +[wooorm@0000000](https://github.com/wooorm/mdast/commit/0000000) + +Or here + [wooorm@0000000](https://github.com/wooorm/mdast/commit/0000000) + +And these SHAs which could also be words? wooorm@deedeed, and wooorm@fabaceae. + +This is not a valid, -wooorm@0000000; nor is this wooorm-@0000000; but this is [w-w@0000000](https://github.com/w-w/mdast/commit/0000000), and so is [w@0000000](https://github.com/w/mdast/commit/0000000) and [ww@0000000](https://github.com/ww/mdast/commit/0000000). + +And here’s an example of a disposable e-mail domain, which starts with 7 hexidecimal characters: wooorm@deadaddress.com, which shouldn’t match, because there’s no word break after the SHA-like part. + +This is too long: wooormwooormwooormwooormwooormwooormwooo#0000000 (40 character username). diff --git a/test/fixtures/sha/Input.md b/test/fixtures/sha/Input.md new file mode 100644 index 0000000..269d7ef --- /dev/null +++ b/test/fixtures/sha/Input.md @@ -0,0 +1,53 @@ +# SHA + +- 000000; +- 0000000; +- 00000000; +- 000000000; +- 0000000000; +- 00000000000; +- 000000000000; +- 0000000000000; +- 00000000000000; +- 000000000000000; +- 0000000000000000; +- 00000000000000000; +- 000000000000000000; +- 0000000000000000000; +- 00000000000000000000; +- 000000000000000000000; +- 0000000000000000000000; +- 00000000000000000000000; +- 000000000000000000000000; +- 0000000000000000000000000; +- 00000000000000000000000000; +- 000000000000000000000000000; +- 0000000000000000000000000000; +- 00000000000000000000000000000; +- 000000000000000000000000000000; +- 0000000000000000000000000000000; +- 00000000000000000000000000000000; +- 000000000000000000000000000000000; +- 0000000000000000000000000000000000; +- 00000000000000000000000000000000000; +- 00000000000000000000000000000000000; +- 000000000000000000000000000000000000; +- 0000000000000000000000000000000000000; +- 00000000000000000000000000000000000000; +- 000000000000000000000000000000000000000; +- 0000000000000000000000000000000000000000; +- 00000000000000000000000000000000000000000. + +And: + +- Prefix 0000000 suffix; +- Prefix 0000000!; +- a 0000000!; + +And what about here +0000000 + +Or here + 0000000 + +And these SHAs which could also be words? deedeed, and fabaceae. diff --git a/test/fixtures/sha/Output.md b/test/fixtures/sha/Output.md new file mode 100644 index 0000000..48374f0 --- /dev/null +++ b/test/fixtures/sha/Output.md @@ -0,0 +1,53 @@ +# SHA + +- 000000; +- [0000000](https://github.com/wooorm/mdast/commit/0000000); +- [0000000](https://github.com/wooorm/mdast/commit/00000000); +- [0000000](https://github.com/wooorm/mdast/commit/000000000); +- [0000000](https://github.com/wooorm/mdast/commit/0000000000); +- [0000000](https://github.com/wooorm/mdast/commit/00000000000); +- [0000000](https://github.com/wooorm/mdast/commit/000000000000); +- [0000000](https://github.com/wooorm/mdast/commit/0000000000000); +- [0000000](https://github.com/wooorm/mdast/commit/00000000000000); +- [0000000](https://github.com/wooorm/mdast/commit/000000000000000); +- [0000000](https://github.com/wooorm/mdast/commit/0000000000000000); +- [0000000](https://github.com/wooorm/mdast/commit/00000000000000000); +- [0000000](https://github.com/wooorm/mdast/commit/000000000000000000); +- [0000000](https://github.com/wooorm/mdast/commit/0000000000000000000); +- [0000000](https://github.com/wooorm/mdast/commit/00000000000000000000); +- [0000000](https://github.com/wooorm/mdast/commit/000000000000000000000); +- [0000000](https://github.com/wooorm/mdast/commit/0000000000000000000000); +- [0000000](https://github.com/wooorm/mdast/commit/00000000000000000000000); +- [0000000](https://github.com/wooorm/mdast/commit/000000000000000000000000); +- [0000000](https://github.com/wooorm/mdast/commit/0000000000000000000000000); +- [0000000](https://github.com/wooorm/mdast/commit/00000000000000000000000000); +- [0000000](https://github.com/wooorm/mdast/commit/000000000000000000000000000); +- [0000000](https://github.com/wooorm/mdast/commit/0000000000000000000000000000); +- [0000000](https://github.com/wooorm/mdast/commit/00000000000000000000000000000); +- [0000000](https://github.com/wooorm/mdast/commit/000000000000000000000000000000); +- [0000000](https://github.com/wooorm/mdast/commit/0000000000000000000000000000000); +- [0000000](https://github.com/wooorm/mdast/commit/00000000000000000000000000000000); +- [0000000](https://github.com/wooorm/mdast/commit/000000000000000000000000000000000); +- [0000000](https://github.com/wooorm/mdast/commit/0000000000000000000000000000000000); +- [0000000](https://github.com/wooorm/mdast/commit/00000000000000000000000000000000000); +- [0000000](https://github.com/wooorm/mdast/commit/00000000000000000000000000000000000); +- [0000000](https://github.com/wooorm/mdast/commit/000000000000000000000000000000000000); +- [0000000](https://github.com/wooorm/mdast/commit/0000000000000000000000000000000000000); +- [0000000](https://github.com/wooorm/mdast/commit/00000000000000000000000000000000000000); +- [0000000](https://github.com/wooorm/mdast/commit/000000000000000000000000000000000000000); +- [0000000](https://github.com/wooorm/mdast/commit/0000000000000000000000000000000000000000); +- 00000000000000000000000000000000000000000. + +And: + +- Prefix [0000000](https://github.com/wooorm/mdast/commit/0000000) suffix; +- Prefix [0000000](https://github.com/wooorm/mdast/commit/0000000)!; +- a [0000000](https://github.com/wooorm/mdast/commit/0000000)!; + +And what about here +[0000000](https://github.com/wooorm/mdast/commit/0000000) + +Or here + [0000000](https://github.com/wooorm/mdast/commit/0000000) + +And these SHAs which could also be words? deedeed, and fabaceae. diff --git a/test/index.js b/test/index.js new file mode 100644 index 0000000..8226319 --- /dev/null +++ b/test/index.js @@ -0,0 +1,349 @@ +'use strict'; + +/* + * Dependencies. + */ + +var mdastGitHub = require('..'); +var mdast = require('mdast').use(mdastGitHub); +var assert = require('assert'); +var fs = require('fs'); +var path = require('path'); +var diff = require('diff'); +var chalk = require('chalk'); + +/* + * Methods. + */ + +var read = fs.readFileSync; +var readdir = fs.readdirSync; + +/* + * Constants. + */ + +var ROOT = path.join(__dirname, 'fixtures'); + +/* + * Fixtures. + */ + +var fixtures = readdir(ROOT); + +/** + * Shortcut to process. + * + * @param {string} value + * @return {string} + */ +function github(value, repo) { + var options; + + if (typeof repo === 'string' || !repo) { + options = { + 'repository': repo || null + }; + } else { + options = repo; + } + + return mdast.stringify(mdast.parse(value, options)); +} + +/* + * Tests. + */ + +describe('mdast-github()', function () { + it('should be a function', function () { + assert(typeof mdastGitHub === 'function'); + }); + + it('should throw if not passed a node', function () { + assert.throws(function () { + mdastGitHub(true); + }); + }); +}); + +/** + * Diff text. + * + * @param {string} value + * @param {string} baseline + */ +function compare(value, baseline) { + var difference; + + try { + assert(value === baseline); + } catch (error) { + /* istanbul ignore next */ + difference = diff.diffLines(value, baseline); + + difference.forEach(function (change) { + var colour = change.added ? + 'green' : change.removed ? 'red' : 'dim'; + + process.stderr.write(chalk[colour](change.value)); + }); + + /* istanbul ignore next */ + throw error; + } +} + +/** + * Describe a fixtures. + * + * @param {string} fixture + */ +function describeFixture(fixture) { + it('should work on `' + fixture + '`', function () { + var filepath = ROOT + '/' + fixture; + var output = read(filepath + '/Output.md', 'utf-8'); + var input = read(filepath + '/Input.md', 'utf-8'); + var result = github(input, 'wooorm/mdast'); + + compare(result, output); + }); +} + +/** + * Describe a repo URL. + * + * @param {Array.} repo + */ +function describeRepository(repo) { + var user = repo[1]; + var project = repo[2]; + + repo = repo[0]; + + it('should work on `' + repo + '`', function () { + var input; + var output; + var result; + + input = [ + '- SHA: a5c3785ed8d6a35868bc169f07e40e889087fd2e', + '- User@SHA: wooorm@a5c3785ed8d6a35868bc169f07e40e889087fd2e', + '- #Num: #26', + '- GH-Num: GH-26', + '- User#Num: wooorm#26' + ].join('\n') + '\n'; + + output = [ + '- SHA: [a5c3785](https://github.com/' + user + '/' + project + + '/commit/a5c3785ed8d6a35868bc169f07e40e889087fd2e)', + '- User@SHA: [wooorm@a5c3785](https://github.com/wooorm/' + + project + '/commit/a5c3785ed8d6a35868bc169f07e40e889087fd2e)', + '- # Num: [#26](https://github.com/' + user + '/' + project + + '/issues/26)', + '- GH-Num: [GH-26](https://github.com/' + user + '/' + project + + '/issues/26)', + '- User#Num: [wooorm#26](https://github.com/wooorm/' + project + + '/issues/26)' + ].join('\n') + '\n'; + + result = github(input, repo); + + compare(result, output); + }); +} + +/* + * Gather fixtures. + */ + +fixtures = fixtures.filter(function (filepath) { + return filepath.indexOf('.') !== 0; +}); + +describe('Fixtures', function () { + fixtures.forEach(describeFixture); +}); + +/* + * List of repo references possible in `package.json`s. + * + * From repo-utils/parse-github-repo-url, with some + * tiny additions. + */ + +var repositories = [ + [ + 'component/emitter', + 'component', + 'emitter' + ], + [ + 'https://github.com/component/emitter', + 'component', + 'emitter' + ], + [ + 'git://github.com/component/emitter.git', + 'component', + 'emitter' + ], + [ + 'https://github.com/repos/component/emitter/tarball', + 'component', + 'emitter' + ], + [ + 'https://github.com/repos/component/emitter/zipball', + 'component', + 'emitter' + ], + [ + 'https://codeload.github.com/component/emitter/legacy.zip', + 'component', + 'emitter' + ], + [ + 'https://codeload.github.com/component/emitter/legacy.tar.gz', + 'component', + 'emitter' + ], + [ + 'component/emitter#1', + 'component', + 'emitter' + ], + [ + 'component/emitter@1', + 'component', + 'emitter' + ], + [ + 'component/emitter#"1"', + 'component', + 'emitter' + ], + [ + 'component/emitter@"1"', + 'component', + 'emitter' + ], + [ + 'git://github.com/component/emitter.git#1', + 'component', + 'emitter' + ], + [ + 'https://github.com/repos/component/emitter/tarball/1', + 'component', + 'emitter' + ], + [ + 'https://github.com/repos/component/emitter/zipball/1', + 'component', + 'emitter' + ], + [ + 'https://codeload.github.com/component/emitter/legacy.zip/1', + 'component', + 'emitter' + ], + [ + 'https://codeload.github.com/component/emitter/legacy.tar.gz/1', + 'component', + 'emitter' + ], + [ + 'https://github.com/component/emitter/archive/1.tar.gz', + 'component', + 'emitter' + ], + [ + 'github/.gitignore', + 'github', + '.gitignore' + ], + [ + 'github/.gitc', + 'github', + '.gitc' + ] +]; + +describe('Repositories', function () { + repositories.forEach(describeRepository); +}); + +describe('Miscellaneous', function () { + it('should load a `package.json` when available', function () { + assert( + github('test@12345678', null) === + '[test@1234567](https://github.com/' + + 'test/mdast-github/commit/12345678)\n' + ); + }); + + it('should accept a `repository.url` in a `package.json`', function () { + var cwd = process.cwd; + + /** + * Move cwd to a path without another + * `package.json`. + */ + function fakeCWD() { + return cwd() + '/test'; + } + + process.cwd = fakeCWD; + + compare( + github('12345678', null), + '[1234567](https://github.com/' + + 'wooorm/mdast/commit/12345678)\n' + ); + + process.cwd = cwd; + }); + + it('should not fail on ASTs without `position`', function () { + var ast = { + 'type': 'root', + 'children': [ + { + 'type': 'paragraph', + 'children': [ + { + 'type': 'text', + 'value': '12345678' + } + ] + } + ] + }; + + compare( + mdast.stringify(mdast.run(ast)), + '[1234567](https://github.com/' + + 'wooorm/mdast-github/commit/12345678)\n' + ); + }); + + it('should throw without `repository`', function () { + var cwd = process.cwd; + + /** + * Move cwd to a path without a `package.json`. + */ + function fakeCWD() { + return cwd() + '/test/fixtures'; + } + + process.cwd = fakeCWD; + + assert.throws(function () { + github('1234567', null); + }, /Missing `repository`/); + + process.cwd = cwd; + }); +}); diff --git a/test/package.json b/test/package.json new file mode 100644 index 0000000..5e3d9ba --- /dev/null +++ b/test/package.json @@ -0,0 +1,3 @@ +{ + "repository": "wooorm/mdast" +}