├── .editorconfig ├── .github └── workflows │ ├── bb.yml │ └── main.yml ├── .gitignore ├── .npmrc ├── .prettierignore ├── .remarkignore ├── index.js ├── lib ├── get-repo-from-package.default.js ├── get-repo-from-package.node.js └── index.js ├── license ├── package.json ├── readme.md ├── test ├── fixtures │ ├── issue-gh-reloaded │ │ ├── input.md │ │ └── output.md │ ├── issue-hash-reloaded │ │ ├── input.md │ │ └── output.md │ ├── issue-project │ │ ├── input.md │ │ └── output.md │ ├── issue-user │ │ ├── input.md │ │ └── output.md │ ├── issue │ │ ├── input.md │ │ └── output.md │ ├── links │ │ ├── input.md │ │ └── output.md │ ├── mention-team-reloaded │ │ ├── input.md │ │ └── output.md │ ├── mention-user-reloaded │ │ ├── input.md │ │ └── output.md │ ├── mention │ │ ├── input.md │ │ └── output.md │ ├── reference-advanced │ │ ├── input.md │ │ └── output.md │ ├── sha-project │ │ ├── input.md │ │ └── output.md │ ├── sha-range │ │ ├── input.md │ │ └── output.md │ ├── sha-reloaded │ │ ├── input.md │ │ └── output.md │ ├── sha-user-reloaded │ │ ├── input.md │ │ └── output.md │ ├── sha-user │ │ ├── input.md │ │ └── output.md │ └── sha │ │ ├── input.md │ │ └── output.md ├── index.js └── package.json └── tsconfig.json /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | -------------------------------------------------------------------------------- /.github/workflows/bb.yml: -------------------------------------------------------------------------------- 1 | name: bb 2 | on: 3 | issues: 4 | types: [opened, reopened, edited, closed, labeled, unlabeled] 5 | pull_request_target: 6 | types: [opened, reopened, edited, closed, labeled, unlabeled] 7 | jobs: 8 | main: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: unifiedjs/beep-boop-beta@main 12 | with: 13 | repo-token: ${{secrets.GITHUB_TOKEN}} 14 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: main 2 | on: 3 | - pull_request 4 | - push 5 | jobs: 6 | main: 7 | name: ${{matrix.node}} 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v3 11 | - uses: actions/setup-node@v3 12 | with: 13 | node-version: ${{matrix.node}} 14 | - run: npm install 15 | - run: npm test 16 | - uses: codecov/codecov-action@v3 17 | strategy: 18 | matrix: 19 | node: 20 | - lts/gallium 21 | - node 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | node_modules/ 3 | .DS_Store 4 | *.d.ts 5 | *.log 6 | yarn.lock 7 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | ignore-scripts=true 2 | package-lock=false 3 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | *.md 3 | -------------------------------------------------------------------------------- /.remarkignore: -------------------------------------------------------------------------------- 1 | /test/fixtures/ 2 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @typedef {import('./lib/index.js').BuildUrl} BuildUrl 3 | * @typedef {import('./lib/index.js').BuildUrlCommitValues} BuildUrlCommitValues 4 | * @typedef {import('./lib/index.js').BuildUrlCompareValues} BuildUrlCompareValues 5 | * @typedef {import('./lib/index.js').BuildUrlIssueValues} BuildUrlIssueValues 6 | * @typedef {import('./lib/index.js').BuildUrlMentionValues} BuildUrlMentionValues 7 | * @typedef {import('./lib/index.js').BuildUrlValues} BuildUrlValues 8 | * @typedef {import('./lib/index.js').Options} Options 9 | */ 10 | 11 | export {default, defaultBuildUrl} from './lib/index.js' 12 | -------------------------------------------------------------------------------- /lib/get-repo-from-package.default.js: -------------------------------------------------------------------------------- 1 | export function getRepoFromPackage() {} 2 | -------------------------------------------------------------------------------- /lib/get-repo-from-package.node.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @typedef {import('type-fest').PackageJson} PackageJson 3 | */ 4 | 5 | import fs from 'node:fs' 6 | import path from 'node:path' 7 | 8 | /** 9 | * Get the repository from `package.json`. 10 | * 11 | * @param {string} cwd 12 | * CWD. 13 | * @returns {string | undefined} 14 | * Repository. 15 | */ 16 | export function getRepoFromPackage(cwd) { 17 | /** @type {PackageJson | undefined} */ 18 | let pkg 19 | 20 | try { 21 | pkg = JSON.parse(String(fs.readFileSync(path.join(cwd, 'package.json')))) 22 | } catch {} 23 | 24 | const repository = 25 | pkg && pkg.repository 26 | ? // Object form. 27 | /* c8 ignore next 2 */ 28 | typeof pkg.repository === 'object' 29 | ? pkg.repository.url 30 | : pkg.repository 31 | : '' 32 | 33 | return repository 34 | } 35 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @typedef {import('mdast').PhrasingContent} PhrasingContent 3 | * @typedef {import('mdast').Root} Root 4 | * @typedef {import('mdast-util-find-and-replace').ReplaceFunction} ReplaceFunction 5 | * @typedef {import('mdast-util-find-and-replace').RegExpMatchObject} RegExpMatchObject 6 | * @typedef {import('vfile').VFile} VFile 7 | */ 8 | 9 | /** 10 | * @callback BuildUrl 11 | * Create a URL. 12 | * @param {Readonly} values 13 | * Info on the link to build. 14 | * @returns {string | false} 15 | * URL to use or `false` to not link. 16 | * 17 | * @typedef BuildUrlCommitValues 18 | * Info for commit hash. 19 | * @property {string} hash 20 | * Commit hash value. 21 | * @property {string} project 22 | * Project name. 23 | * @property {'commit'} type 24 | * Kind. 25 | * @property {string} user 26 | * Owner of repo. 27 | * 28 | * @typedef BuildUrlCompareValues 29 | * Info for commit hash ranges. 30 | * @property {string} base 31 | * SHA of the range start. 32 | * @property {string} compare 33 | * SHA of the range end. 34 | * @property {string} project 35 | * Project name. 36 | * @property {'compare'} type 37 | * Kind. 38 | * @property {string} user 39 | * Owner of repo. 40 | * 41 | * @typedef BuildUrlIssueValues 42 | * Info for issues. 43 | * @property {string} no 44 | * Issue number. 45 | * @property {string} project 46 | * Project name. 47 | * @property {'issue'} type 48 | * Kind. 49 | * @property {string} user 50 | * Owner of repo. 51 | * 52 | * @typedef BuildUrlMentionValues 53 | * Info for mentions. 54 | * @property {'mention'} type 55 | * Kind. 56 | * @property {string} user 57 | * User name. 58 | * 59 | * @typedef {BuildUrlCommitValues | BuildUrlCompareValues | BuildUrlIssueValues | BuildUrlMentionValues} BuildUrlValues 60 | * Info. 61 | * 62 | * @typedef Options 63 | * Configuration. 64 | * @property {BuildUrl | null | undefined} [buildUrl] 65 | * Change how things are linked (optional). 66 | * @property {boolean | null | undefined} [mentionStrong=true] 67 | * Wrap mentions in `strong` (default: `true`); 68 | * this makes them render more like how GitHub styles them, but GH itself 69 | * uses CSS instead of `strong`. 70 | * @property {string | null | undefined} [repository] 71 | * Repository to link against (default: `repository` from `packag.json` in CWD in Node); 72 | * should point to a GitHub repository (such as `'user/project'`) 73 | * 74 | * @typedef RepositoryInfo 75 | * Owner and project of repo. 76 | * @property {string} project 77 | * Project name. 78 | * @property {string} user 79 | * User/organization name. 80 | * 81 | * @typedef UrlInfo 82 | * Info. 83 | * @property {boolean} comment 84 | * Whether the link is to a comment. 85 | * @property {string} page 86 | * Page type. 87 | * @property {string} project 88 | * Project name. 89 | * @property {string} reference 90 | * Reference. 91 | * @property {string} user 92 | * User/organization name. 93 | */ 94 | 95 | import {findAndReplace} from 'mdast-util-find-and-replace' 96 | import {toString} from 'mdast-util-to-string' 97 | import {visit} from 'unist-util-visit' 98 | import {getRepoFromPackage} from '#get-repo-from-package' 99 | 100 | /** @type {Readonly} */ 101 | const emptyOptions = {} 102 | 103 | // Previously, GitHub linked `@mention` and `@mentions` to their blog post about 104 | // mentions (). 105 | // Since June 2019, and possibly earlier, they stopped linking those references. 106 | const denyMention = new Set(['mention', 'mentions']) 107 | 108 | // Denylist of SHAs that are also valid words. 109 | // 110 | // GitHub allows abbreviating SHAs up to 7 characters. 111 | // These cases are ignored in text because they might just be ment as normal 112 | // words. 113 | // If you’d like these to link to their SHAs, use more than 7 characters. 114 | // 115 | // Generated by: 116 | // 117 | // ```sh 118 | // egrep -i "^[a-f0-9]{7,}$" /usr/share/dict/words 119 | // ``` 120 | // 121 | // Added a couple forms of 6 character words in GH-20: 122 | // . 123 | const denyHash = new Set([ 124 | 'acceded', 125 | 'deedeed', 126 | 'defaced', 127 | 'effaced', 128 | 'fabaceae' 129 | ]) 130 | 131 | // Constants. 132 | const minShaLength = 7 133 | 134 | // Username may only contain alphanumeric characters or single hyphens, and 135 | // cannot begin or end with a hyphen*. 136 | // 137 | // \* That is: until . 138 | const userGroup = '[\\da-z][-\\da-z]{0,38}' 139 | const projectGroup = '(?:\\.git[\\w-]|\\.(?!git)|[\\w-])+' 140 | const repoGroup = '(' + userGroup + ')\\/(' + projectGroup + ')' 141 | 142 | const linkRegex = new RegExp( 143 | '^https?:\\/\\/github\\.com\\/' + 144 | repoGroup + 145 | '\\/(commit|compare|issues|pull)\\/([a-f\\d]+(?:\\.{3}[a-f\\d]+)?\\/?(?=[#?]|$))', 146 | 'i' 147 | ) 148 | 149 | const repoRegex = new RegExp( 150 | '(?:^|/(?:repos/)?)' + repoGroup + '(?=\\.git|[\\/#@]|$)', 151 | 'i' 152 | ) 153 | 154 | const referenceRegex = new RegExp( 155 | '(' + 156 | userGroup + 157 | ')(?:\\/(' + 158 | projectGroup + 159 | '))?(?:#([1-9]\\d*)|@([a-f\\d]{7,40}))', 160 | 'gi' 161 | ) 162 | 163 | const mentionRegex = new RegExp( 164 | '@(' + userGroup + '(?:\\/' + userGroup + ')?)', 165 | 'gi' 166 | ) 167 | 168 | /** 169 | * Create a URL to GH. 170 | * 171 | * @satisfies {BuildUrl} 172 | * @param {Readonly} values 173 | * Info on the link to build. 174 | * @returns {string} 175 | * URL to use. 176 | */ 177 | export function defaultBuildUrl(values) { 178 | const base = 'https://github.com' 179 | 180 | if (values.type === 'mention') { 181 | return [base, values.user].join('/') 182 | } 183 | 184 | const {project, user} = values 185 | 186 | if (values.type === 'commit') { 187 | return [base, user, project, 'commit', values.hash].join('/') 188 | } 189 | 190 | if (values.type === 'issue') { 191 | return [base, user, project, 'issues', values.no].join('/') 192 | } 193 | 194 | // `values.type` is `'compare'` 195 | return [ 196 | base, 197 | user, 198 | project, 199 | 'compare', 200 | values.base + '...' + values.compare 201 | ].join('/') 202 | } 203 | 204 | /** 205 | * Link references to users, commits, and issues, in the same way that GitHub 206 | * does in comments, issues, PRs, and releases. 207 | * 208 | * @param {Readonly | null | undefined} [options] 209 | * Configuration (optional). 210 | * @returns 211 | * Transform. 212 | */ 213 | export default function remarkGithub(options) { 214 | const settings = options || emptyOptions 215 | const buildUrl = settings.buildUrl || defaultBuildUrl 216 | 217 | /** 218 | * Transform. 219 | * 220 | * @param {Root} tree 221 | * Tree. 222 | * @param {VFile} file 223 | * File. 224 | * @returns {undefined} 225 | * Nothing. 226 | */ 227 | return function (tree, file) { 228 | // To do: when async/await in React is easier, we can do `getRepoFromPackage` async. 229 | // Then it should throw errors when the repo is incorrect / files are broken / etc. 230 | const repository = settings.repository || getRepoFromPackage(file.cwd) 231 | 232 | if (!repository) { 233 | throw new Error('Unexpected missing `repository` in `options`') 234 | } 235 | 236 | // Parse the URL: See the tests for all possible kinds. 237 | const repositoryMatch = repoRegex.exec(repository) 238 | 239 | if (!repositoryMatch) { 240 | throw new Error( 241 | 'Unexpected invalid `repository`, expected for example `user/project`' 242 | ) 243 | } 244 | 245 | /** @type {Readonly} */ 246 | const repositoryInfo = { 247 | project: repositoryMatch[2], 248 | user: repositoryMatch[1] 249 | } 250 | 251 | findAndReplace( 252 | tree, 253 | [ 254 | [referenceRegex, replaceReference], 255 | [mentionRegex, replaceMention], 256 | [/(?:#|\bgh-)([1-9]\d*)/gi, replaceIssue], 257 | [/\b([a-f\d]{7,40})\.{3}([a-f\d]{7,40})\b/gi, replaceHashRange], 258 | [/\b[a-f\d]{7,40}\b/gi, replaceHash] 259 | ], 260 | {ignore: ['link', 'linkReference']} 261 | ) 262 | 263 | visit(tree, 'link', function (node) { 264 | /** @type {Readonly | undefined} */ 265 | const link = parse(node) 266 | 267 | if (!link) { 268 | return 269 | } 270 | 271 | const comment = link.comment ? ' (comment)' : '' 272 | /** @type {string} */ 273 | let base 274 | 275 | if ( 276 | link.project !== repositoryInfo.project || 277 | // Compare page uses full `user/project` for forks. 278 | (link.page === 'compare' && link.user !== repositoryInfo.user) 279 | ) { 280 | base = link.user + '/' + link.project 281 | } else if (link.user === repositoryInfo.user) { 282 | base = '' 283 | } else { 284 | base = link.user 285 | } 286 | 287 | /** @type {Array} */ 288 | const children = [] 289 | 290 | if (link.page === 'issues' || link.page === 'pull') { 291 | base += '#' 292 | children.push({ 293 | type: 'text', 294 | value: base + link.reference + comment 295 | }) 296 | } else { 297 | if (base) { 298 | children.push({type: 'text', value: base + '@'}) 299 | } 300 | 301 | children.push({type: 'inlineCode', value: link.reference}) 302 | 303 | if (link.comment) { 304 | children.push({type: 'text', value: comment}) 305 | } 306 | } 307 | 308 | node.children = children 309 | }) 310 | 311 | /** 312 | * @type {ReplaceFunction} 313 | * @param {string} value 314 | * @param {string} username 315 | * @param {RegExpMatchObject} match 316 | */ 317 | function replaceMention(value, username, match) { 318 | if ( 319 | /[\w`]/.test(match.input.charAt(match.index - 1)) || 320 | /[/\w`]/.test(match.input.charAt(match.index + value.length)) || 321 | denyMention.has(username) 322 | ) { 323 | return false 324 | } 325 | 326 | const url = buildUrl({type: 'mention', user: username}) 327 | 328 | if (!url) return false 329 | 330 | /** @type {PhrasingContent} */ 331 | let node = {type: 'text', value} 332 | 333 | if (settings.mentionStrong !== false) { 334 | node = {type: 'strong', children: [node]} 335 | } 336 | 337 | return {type: 'link', title: null, url, children: [node]} 338 | } 339 | 340 | /** 341 | * @type {ReplaceFunction} 342 | * @param {string} value 343 | * @param {string} no 344 | * @param {RegExpMatchObject} match 345 | */ 346 | function replaceIssue(value, no, match) { 347 | if ( 348 | /\w/.test(match.input.charAt(match.index - 1)) || 349 | /\w/.test(match.input.charAt(match.index + value.length)) 350 | ) { 351 | return false 352 | } 353 | 354 | const url = buildUrl({no, type: 'issue', ...repositoryInfo}) 355 | 356 | return url 357 | ? {type: 'link', title: null, url, children: [{type: 'text', value}]} 358 | : false 359 | } 360 | 361 | /** 362 | * @type {ReplaceFunction} 363 | * @param {string} value 364 | * @param {string} a 365 | * @param {string} b 366 | * @param {RegExpMatchObject} match 367 | */ 368 | function replaceHashRange(value, a, b, match) { 369 | if ( 370 | /[^\t\n\r (@[{]/.test(match.input.charAt(match.index - 1)) || 371 | /\w/.test(match.input.charAt(match.index + value.length)) || 372 | denyHash.has(value) 373 | ) { 374 | return false 375 | } 376 | 377 | const url = buildUrl({ 378 | base: a, 379 | compare: b, 380 | type: 'compare', 381 | ...repositoryInfo 382 | }) 383 | 384 | return url 385 | ? { 386 | type: 'link', 387 | title: null, 388 | url, 389 | children: [{type: 'inlineCode', value: abbr(a) + '...' + abbr(b)}] 390 | } 391 | : false 392 | } 393 | 394 | /** 395 | * @type {ReplaceFunction} 396 | * @param {string} value 397 | * @param {RegExpMatchObject} match 398 | */ 399 | function replaceHash(value, match) { 400 | if ( 401 | /[^\t\n\r (@[{.]/.test(match.input.charAt(match.index - 1)) || 402 | // For some weird reason GH does link two dots, but not one 🤷‍♂️ 403 | (match.input.charAt(match.index - 1) === '.' && 404 | match.input.charAt(match.index - 2) !== '.') || 405 | /\w/.test(match.input.charAt(match.index + value.length)) || 406 | denyHash.has(value) 407 | ) { 408 | return false 409 | } 410 | 411 | const url = buildUrl({hash: value, type: 'commit', ...repositoryInfo}) 412 | 413 | return url 414 | ? { 415 | type: 'link', 416 | title: null, 417 | url, 418 | children: [{type: 'inlineCode', value: abbr(value)}] 419 | } 420 | : false 421 | } 422 | 423 | /** 424 | * @type {ReplaceFunction} 425 | * @param {string} $0 426 | * @param {string} user 427 | * @param {string} specificProject 428 | * @param {string} no 429 | * @param {string} hash 430 | * @param {RegExpMatchObject} match 431 | */ 432 | // eslint-disable-next-line max-params 433 | function replaceReference($0, user, specificProject, no, hash, match) { 434 | if ( 435 | /[^\t\n\r (@[{]/.test(match.input.charAt(match.index - 1)) || 436 | /\w/.test(match.input.charAt(match.index + $0.length)) 437 | ) { 438 | return false 439 | } 440 | 441 | const project = specificProject || repositoryInfo.project 442 | /** @type {BuildUrlValues} */ 443 | const values = no 444 | ? {no, project, type: 'issue', user} 445 | : {hash, project, type: 'commit', user} 446 | const url = buildUrl(values) 447 | 448 | if (!url) return false 449 | 450 | /** @type {Array} */ 451 | const nodes = [] 452 | let value = '' 453 | 454 | if (project !== repositoryInfo.project) { 455 | value += user + '/' + project 456 | } else if (user !== repositoryInfo.user) { 457 | value += user 458 | } 459 | 460 | if (no) { 461 | value += '#' + no 462 | } else { 463 | value += '@' 464 | nodes.push({type: 'inlineCode', value: abbr(hash)}) 465 | } 466 | 467 | nodes.unshift({type: 'text', value}) 468 | 469 | return {type: 'link', title: null, url, children: nodes} 470 | } 471 | } 472 | } 473 | 474 | /** 475 | * Abbreviate a SHA. 476 | * 477 | * @param {string} sha 478 | * SHA. 479 | * @returns {string} 480 | * Abbreivated SHA. 481 | */ 482 | function abbr(sha) { 483 | return sha.slice(0, minShaLength) 484 | } 485 | 486 | /** 487 | * Parse a link and determine whether it links to GitHub. 488 | * 489 | * @param {import('mdast').Link} node 490 | * Link node. 491 | * @returns {UrlInfo | undefined} 492 | * Info. 493 | */ 494 | function parse(node) { 495 | const match = linkRegex.exec(node.url) 496 | 497 | if ( 498 | // Not a proper URL. 499 | !match || 500 | // Looks like formatting. 501 | node.children.length !== 1 || 502 | node.children[0].type !== 'text' || 503 | toString(node) !== node.url || 504 | // SHAs can be min 4, max 40 characters. 505 | (match[3] === 'commit' && (match[4].length < 4 || match[4].length > 40)) || 506 | // SHAs can be min 4, max 40 characters. 507 | (match[3] === 'compare' && 508 | !/^[a-f\d]{4,40}\.{3}[a-f\d]{4,40}$/.test(match[4])) || 509 | // Issues / PRs are decimal only. 510 | ((match[3] === 'issues' || match[3] === 'pull') && 511 | /[a-f]/i.test(match[4])) || 512 | // Projects can be at most 99 characters. 513 | match[2].length >= 100 514 | ) { 515 | return 516 | } 517 | 518 | let reference = match[4] 519 | 520 | if (match[3] === 'compare') { 521 | const [base, compare] = reference.split('...') 522 | reference = abbr(base) + '...' + abbr(compare) 523 | } else { 524 | reference = abbr(reference) 525 | } 526 | 527 | return { 528 | comment: 529 | node.url.charAt(match[0].length) === '#' && 530 | match[0].length + 1 < node.url.length, 531 | page: match[3], 532 | project: match[2], 533 | reference, 534 | user: match[1] 535 | } 536 | } 537 | -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2015 Titus Wormer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | 'Software'), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "remark-github", 3 | "version": "12.0.0", 4 | "description": "remark plugin to autolink references like in GitHub issues, PRs, and comments", 5 | "license": "MIT", 6 | "keywords": [ 7 | "github", 8 | "issue", 9 | "markdown", 10 | "mdast", 11 | "mention", 12 | "on", 13 | "plugin", 14 | "pull", 15 | "reference", 16 | "remark", 17 | "remark-plugin", 18 | "request", 19 | "sha", 20 | "unified", 21 | "user", 22 | "writing" 23 | ], 24 | "repository": "remarkjs/remark-github", 25 | "bugs": "https://github.com/remarkjs/remark-github/issues", 26 | "funding": { 27 | "type": "opencollective", 28 | "url": "https://opencollective.com/unified" 29 | }, 30 | "author": "Titus Wormer (https://wooorm.com)", 31 | "contributors": [ 32 | "Titus Wormer (https://wooorm.com)", 33 | "Anthony Maki <4cm4k1@gmail.com>", 34 | "Ev Haus " 35 | ], 36 | "sideEffects": false, 37 | "type": "module", 38 | "exports": "./index.js", 39 | "imports": { 40 | "#get-repo-from-package": { 41 | "node": "./lib/get-repo-from-package.node.js", 42 | "default": "./lib/get-repo-from-package.default.js" 43 | } 44 | }, 45 | "files": [ 46 | "lib/", 47 | "index.d.ts", 48 | "index.js" 49 | ], 50 | "dependencies": { 51 | "@types/mdast": "^4.0.0", 52 | "mdast-util-find-and-replace": "^3.0.0", 53 | "mdast-util-to-string": "^4.0.0", 54 | "to-vfile": "^8.0.0", 55 | "unist-util-visit": "^5.0.0", 56 | "vfile": "^6.0.0" 57 | }, 58 | "devDependencies": { 59 | "@types/node": "^20.0.0", 60 | "c8": "^8.0.0", 61 | "prettier": "^3.0.0", 62 | "remark": "^15.0.0", 63 | "remark-cli": "^11.0.0", 64 | "remark-gfm": "^4.0.0", 65 | "remark-preset-wooorm": "^9.0.0", 66 | "type-coverage": "^2.0.0", 67 | "type-fest": "^4.0.0", 68 | "typescript": "^5.0.0", 69 | "xo": "^0.56.0" 70 | }, 71 | "scripts": { 72 | "build": "tsc --build --clean && tsc --build && type-coverage", 73 | "format": "remark . --frail --output --quiet && prettier . --log-level warn --write && xo --fix", 74 | "prepack": "npm run build && npm run format", 75 | "test": "npm run build && npm run format && npm run test-coverage", 76 | "test-api": "node --conditions development test/index.js", 77 | "test-coverage": "c8 --100 --reporter lcov npm run test-api" 78 | }, 79 | "prettier": { 80 | "bracketSpacing": false, 81 | "singleQuote": true, 82 | "semi": false, 83 | "tabWidth": 2, 84 | "trailingComma": "none", 85 | "useTabs": false 86 | }, 87 | "remarkConfig": { 88 | "plugins": [ 89 | "remark-preset-wooorm" 90 | ] 91 | }, 92 | "typeCoverage": { 93 | "atLeast": 100, 94 | "detail": true, 95 | "ignoreCatch": true, 96 | "strict": true 97 | }, 98 | "xo": { 99 | "prettier": true 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # remark-github 2 | 3 | [![Build][build-badge]][build] 4 | [![Coverage][coverage-badge]][coverage] 5 | [![Downloads][downloads-badge]][downloads] 6 | [![Size][size-badge]][size] 7 | [![Sponsors][sponsors-badge]][collective] 8 | [![Backers][backers-badge]][collective] 9 | [![Chat][chat-badge]][chat] 10 | 11 | **[remark][]** plugin to link references to commits, issues, and users, in the 12 | same way that GitHub does in comments, issues, PRs, and releases (see [Writing 13 | on GitHub][github-writing]). 14 | 15 | ## Contents 16 | 17 | * [What is this?](#what-is-this) 18 | * [When should I use this?](#when-should-i-use-this) 19 | * [Install](#install) 20 | * [Use](#use) 21 | * [API](#api) 22 | * [`defaultBuildUrl(values)`](#defaultbuildurlvalues) 23 | * [`unified().use(remarkGithub[, options])`](#unifieduseremarkgithub-options) 24 | * [`BuildUrl`](#buildurl) 25 | * [`BuildUrlCommitValues`](#buildurlcommitvalues) 26 | * [`BuildUrlCompareValues`](#buildurlcomparevalues) 27 | * [`BuildUrlIssueValues`](#buildurlissuevalues) 28 | * [`BuildUrlMentionValues`](#buildurlmentionvalues) 29 | * [`BuildUrlValues`](#buildurlvalues) 30 | * [`Options`](#options) 31 | * [Examples](#examples) 32 | * [Example: `buildUrl`](#example-buildurl) 33 | * [Syntax](#syntax) 34 | * [Types](#types) 35 | * [Compatibility](#compatibility) 36 | * [Security](#security) 37 | * [Related](#related) 38 | * [Contribute](#contribute) 39 | * [License](#license) 40 | 41 | ## What is this? 42 | 43 | This package is a [unified][] ([remark][]) plugin to link references to commits, 44 | issues, and users: `@wooorm` -> `[**@wooorm**](https://github.com/wooorm)`. 45 | 46 | ## When should I use this? 47 | 48 | This project is useful if you want to emulate how markdown would work in GitHub 49 | comments, issues, PRs, or releases, but it’s actually displayed somewhere else 50 | (on a website, or in other places on GitHub which don’t link references, such as 51 | markdown in a repo or Gist). 52 | This plugin does not support other platforms such as GitLab or Bitbucket and 53 | their custom features. 54 | 55 | A different plugin, [`remark-gfm`][remark-gfm], adds support for GFM (GitHub 56 | Flavored Markdown). 57 | GFM is a set of extensions (autolink literals, footnotes, strikethrough, tables, 58 | and tasklists) to markdown that are supported everywhere on GitHub. 59 | 60 | Another plugin, [`remark-breaks`][remark-breaks], turns soft line endings 61 | (enters) into hard breaks (`
`s). 62 | GitHub does this in a few places (comments, issues, PRs, and releases), but it’s 63 | not semantic according to HTML and not compliant to markdown. 64 | 65 | Yet another plugin, [`remark-frontmatter`][remark-frontmatter], adds support 66 | for YAML frontmatter. 67 | GitHub supports frontmatter for files in Gists and repos. 68 | 69 | ## Install 70 | 71 | This package is [ESM only][esm]. 72 | In Node.js (version 16+), install with [npm][]: 73 | 74 | ```sh 75 | npm install remark-github 76 | ``` 77 | 78 | In Deno with [`esm.sh`][esmsh]: 79 | 80 | ```js 81 | import remarkGithub, {defaultBuildUrl} from 'https://esm.sh/remark-github@12' 82 | ``` 83 | 84 | In browsers with [`esm.sh`][esmsh]: 85 | 86 | ```html 87 | 90 | ``` 91 | 92 | ## Use 93 | 94 | Say we have the following file `example.md`: 95 | 96 | ```markdown 97 | Some references: 98 | 99 | * Commit: f8083175fe890cbf14f41d0a06e7aa35d4989587 100 | * Commit (fork): foo@f8083175fe890cbf14f41d0a06e7aa35d4989587 101 | * Commit (repo): remarkjs/remark@e1aa9f6c02de18b9459b7d269712bcb50183ce89 102 | * Issue or PR (`#`): #1 103 | * Issue or PR (`GH-`): GH-1 104 | * Issue or PR (fork): foo#1 105 | * Issue or PR (project): remarkjs/remark#1 106 | * Mention: @wooorm 107 | 108 | Some links: 109 | 110 | * Commit: 111 | * Commit comment: 112 | * Issue or PR: 113 | * Issue or PR comment: 114 | * Mention: 115 | ``` 116 | 117 | …and a module `example.js`: 118 | 119 | ```js 120 | import {remark} from 'remark' 121 | import remarkGfm from 'remark-gfm' 122 | import remarkGithub from 'remark-github' 123 | import {read} from 'to-vfile' 124 | 125 | const file = await remark() 126 | .use(remarkGfm) 127 | .use(remarkGithub) 128 | .process(await read('example.md')) 129 | 130 | console.log(String(file)) 131 | ``` 132 | 133 | …then running `node example.js` yields: 134 | 135 | ```markdown 136 | Some references: 137 | 138 | * Commit: [`f808317`](https://github.com/remarkjs/remark-github/commit/f8083175fe890cbf14f41d0a06e7aa35d4989587) 139 | * Commit (fork): [foo@`f808317`](https://github.com/foo/remark-github/commit/f8083175fe890cbf14f41d0a06e7aa35d4989587) 140 | * Commit (repo): [remarkjs/remark@`e1aa9f6`](https://github.com/remarkjs/remark/commit/e1aa9f6c02de18b9459b7d269712bcb50183ce89) 141 | * Issue or PR (`#`): [#1](https://github.com/remarkjs/remark-github/issues/1) 142 | * Issue or PR (`GH-`): [GH-1](https://github.com/remarkjs/remark-github/issues/1) 143 | * Issue or PR (fork): [foo#1](https://github.com/foo/remark-github/issues/1) 144 | * Issue or PR (project): [remarkjs/remark#1](https://github.com/remarkjs/remark/issues/1) 145 | * Mention: [**@wooorm**](https://github.com/wooorm) 146 | 147 | Some links: 148 | 149 | * Commit: [remarkjs/remark@`e1aa9f6`](https://github.com/remarkjs/remark/commit/e1aa9f6c02de18b9459b7d269712bcb50183ce89) 150 | * Commit comment: [remarkjs/remark@`ac63bc3` (comment)](https://github.com/remarkjs/remark/commit/ac63bc3abacf14cf08ca5e2d8f1f8e88a7b9015c#commitcomment-16372693) 151 | * Issue or PR: [remarkjs/remark#182](https://github.com/remarkjs/remark/issues/182) 152 | * Issue or PR comment: [#3 (comment)](https://github.com/remarkjs/remark-github/issues/3#issue-151160339) 153 | * Mention: 154 | ``` 155 | 156 | ## API 157 | 158 | This package exports the identifier [`defaultBuildUrl`][api-default-build-url]. 159 | The default export is [`remarkGithub`][api-remark-github]. 160 | 161 | ### `defaultBuildUrl(values)` 162 | 163 | Create a URL to GH. 164 | 165 | ###### Parameters 166 | 167 | * `values` ([`BuildUrlValues`][api-build-url-values]) 168 | — info on the link to build 169 | 170 | ###### Returns 171 | 172 | URL to use (`string`). 173 | 174 | ### `unified().use(remarkGithub[, options])` 175 | 176 | Link references to users, commits, and issues, in the same way that GitHub does 177 | in comments, issues, PRs, and releases. 178 | 179 | ###### Parameters 180 | 181 | * `options` ([`Options`][api-options], optional) 182 | — configuration 183 | 184 | ###### Returns 185 | 186 | Transform ([`Transformer`][unified-transformer]). 187 | 188 | ### `BuildUrl` 189 | 190 | Create a URL (TypeScript type). 191 | 192 | ###### Parameters 193 | 194 | * `values` ([`BuildUrlValues`][api-build-url-values]) 195 | — info on the link to build 196 | 197 | ###### Returns 198 | 199 | URL to use or `false` to not link (`string | false`). 200 | 201 | ### `BuildUrlCommitValues` 202 | 203 | Info for commit hash (TypeScript type). 204 | 205 | ###### Fields 206 | 207 | * `hash` (`string`) 208 | — commit hash value 209 | * `project` (`string`) 210 | — project name 211 | * `type` (`'commit'`) 212 | — kind 213 | * `user` (`string`) 214 | — owner of repo 215 | 216 | ### `BuildUrlCompareValues` 217 | 218 | Info for commit hash ranges (TypeScript type). 219 | 220 | ###### Fields 221 | 222 | * `base` (`string`) 223 | — SHA of the range start 224 | * `compare` (`string`) 225 | — SHA of the range end 226 | * `project` (`string`) 227 | — project name 228 | * `type` (`'compare'`) 229 | — kind 230 | * `user` (`string`) 231 | — owner of repo 232 | 233 | ### `BuildUrlIssueValues` 234 | 235 | Info for issues (TypeScript type). 236 | 237 | ###### Fields 238 | 239 | * `no` (`string`) 240 | — issue number 241 | * `project` (`string`) 242 | — project name 243 | * `type` (`'issue'`) 244 | — kind 245 | * `user` (`string`) 246 | — owner of repo 247 | 248 | ### `BuildUrlMentionValues` 249 | 250 | Info for mentions (TypeScript type). 251 | 252 | ###### Fields 253 | 254 | * `type` (`'mention'`) 255 | — kind 256 | * `user` (`string`) 257 | — user name 258 | 259 | ### `BuildUrlValues` 260 | 261 | Info (TypeScript type). 262 | 263 | ###### Type 264 | 265 | ```ts 266 | type BuildUrlValues = 267 | | BuildUrlCommitValues 268 | | BuildUrlCompareValues 269 | | BuildUrlIssueValues 270 | | BuildUrlMentionValues 271 | ``` 272 | 273 | ### `Options` 274 | 275 | Configuration (TypeScript type). 276 | 277 | ###### Fields 278 | 279 | * `buildUrl` ([`BuildUrl`][api-build-url], default: 280 | [`defaultBuildUrl`][api-default-build-url]) 281 | — change how things are linked 282 | * `mentionStrong` (`boolean`, default: `true`) 283 | — wrap mentions in `strong`; 284 | this makes them render more like how GitHub styles them, but GH itself 285 | uses CSS instead of `strong` 286 | * `repository` (`string`, default: `repository` from `packag.json` in CWD in 287 | Node, otherwise required) 288 | — repository to link against; 289 | should point to a GitHub repository (such as `'user/project'`) 290 | 291 | ## Examples 292 | 293 | ### Example: `buildUrl` 294 | 295 | A `buildUrl` can be passed to not link mentions. 296 | For example, by changing `example.js` from before like so: 297 | 298 | ```diff 299 | @@ -1,11 +1,15 @@ 300 | import {remark} from 'remark' 301 | import remarkGfm from 'remark-gfm' 302 | -import remarkGithub from 'remark-github' 303 | +import remarkGithub, {defaultBuildUrl} from 'remark-github' 304 | import {read} from 'to-vfile' 305 | 306 | const file = await remark() 307 | .use(remarkGfm) 308 | - .use(remarkGithub) 309 | + .use(remarkGithub, { 310 | + buildUrl(values) { 311 | + return values.type === 'mention' ? false : defaultBuildUrl(values) 312 | + } 313 | + }) 314 | .process(await read('example.md')) 315 | 316 | console.log(String(file)) 317 | ``` 318 | 319 | To instead point mentions to a different place, change `example.js` like so: 320 | 321 | ```diff 322 | @@ -1,11 +1,17 @@ 323 | import {remark} from 'remark' 324 | import remarkGfm from 'remark-gfm' 325 | -import remarkGithub from 'remark-github' 326 | +import remarkGithub, {defaultBuildUrl} from 'remark-github' 327 | import {read} from 'to-vfile' 328 | 329 | const file = await remark() 330 | .use(remarkGfm) 331 | - .use(remarkGithub) 332 | + .use(remarkGithub, { 333 | + buildUrl(values) { 334 | + return values.type === 'mention' 335 | + ? `https://yourwebsite.com/${values.user}/` 336 | + : defaultBuildUrl(values) 337 | + } 338 | + }) 339 | .process(await read('example.md')) 340 | 341 | console.log(String(file)) 342 | ``` 343 | 344 | ## Syntax 345 | 346 | The following references are supported: 347 | 348 | * Commits: 349 | `1f2a4fb` → 350 | [`1f2a4fb`][github-sha] 351 | * Commits across forks: 352 | `remarkjs@1f2a4fb` → 353 | [remarkjs@`1f2a4fb`][github-sha] 354 | * Commits across projects: 355 | `remarkjs/remark-github@1f2a4fb` → 356 | [remarkjs/remark-github@`1f2a4fb`][github-sha] 357 | * Compare ranges: 358 | `e2acebc...2aa9311` → 359 | [`e2acebc...2aa9311`][github-sha-range] 360 | * Compare ranges across forks: 361 | `remarkjs@e2acebc...2aa9311` → 362 | [remarkjs/remark-github@`e2acebc...2aa9311`][github-sha-range] 363 | * Compare ranges across projects: 364 | `remarkjs/remark-github@e2acebc...2aa9311` → 365 | [remarkjs/remark-github@`e2acebc...2aa9311`][github-sha-range] 366 | * Prefix issues: 367 | `GH-1` → 368 | [GH-1][github-issue] 369 | * Hash issues: 370 | `#1` → 371 | [#1][github-issue] 372 | * Issues across forks: 373 | `remarkjs#1` → 374 | [remarkjs#1][github-issue] 375 | * Issues across projects: 376 | `remarkjs/remark-github#1` → 377 | [remarkjs/remark-github#1][github-issue] 378 | * At-mentions: 379 | `@wooorm` → 380 | [**@wooorm**][github-mention] 381 | 382 | Autolinks to these references are also transformed: 383 | `https://github.com/wooorm` -> `[**@wooorm**](https://github.com/wooorm)` 384 | 385 | ## Types 386 | 387 | This package is fully typed with [TypeScript][]. 388 | It exports the additional types 389 | [`BuildUrl`][api-build-url], 390 | [`BuildUrlCommitValues`][api-build-url-commit-values], 391 | [`BuildUrlCompareValues`][api-build-url-compare-values], 392 | [`BuildUrlIssueValues`][api-build-url-issue-values], 393 | [`BuildUrlMentionValues`][api-build-url-mention-values], 394 | [`BuildUrlValues`][api-build-url-values], 395 | [`DefaultBuildUrl`][api-default-build-url], 396 | [`Options`][api-options]. 397 | 398 | ## Compatibility 399 | 400 | Projects maintained by the unified collective are compatible with maintained 401 | versions of Node.js. 402 | 403 | When we cut a new major release, we drop support for unmaintained versions of 404 | Node. 405 | This means we try to keep the current release line, `remark-github@^12`, 406 | compatible with Node.js 16. 407 | 408 | This plugin works with `unified` version 6+ and `remark` version 7+. 409 | 410 | ## Security 411 | 412 | Use of `remark-github` does not involve **[rehype][]** (**[hast][]**). 413 | It does inject links based on user content, but those links only go to GitHub. 414 | There are no openings for [cross-site scripting (XSS)][wiki-xss] attacks. 415 | 416 | ## Related 417 | 418 | * [`remark-gfm`][remark-gfm] 419 | — support GFM (autolink literals, footnotes, strikethrough, tables, 420 | tasklists) 421 | * [`remark-breaks`][remark-breaks] 422 | — support breaks without needing spaces or escapes (enters to `
`) 423 | * [`remark-frontmatter`][remark-frontmatter] 424 | — support frontmatter (YAML, TOML, and more) 425 | 426 | ## Contribute 427 | 428 | See [`contributing.md`][contributing] in [`remarkjs/.github`][health] for ways 429 | to get started. 430 | See [`support.md`][support] for ways to get help. 431 | 432 | This project has a [code of conduct][coc]. 433 | By interacting with this repository, organization, or community you agree to 434 | abide by its terms. 435 | 436 | ## License 437 | 438 | [MIT][license] © [Titus Wormer][author] 439 | 440 | 441 | 442 | [build-badge]: https://github.com/remarkjs/remark-github/workflows/main/badge.svg 443 | 444 | [build]: https://github.com/remarkjs/remark-github/actions 445 | 446 | [coverage-badge]: https://img.shields.io/codecov/c/github/remarkjs/remark-github.svg 447 | 448 | [coverage]: https://codecov.io/github/remarkjs/remark-github 449 | 450 | [downloads-badge]: https://img.shields.io/npm/dm/remark-github.svg 451 | 452 | [downloads]: https://www.npmjs.com/package/remark-github 453 | 454 | [size-badge]: https://img.shields.io/bundlejs/size/remark-github 455 | 456 | [size]: https://bundlejs.com/?q=remark-github 457 | 458 | [sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg 459 | 460 | [backers-badge]: https://opencollective.com/unified/backers/badge.svg 461 | 462 | [collective]: https://opencollective.com/unified 463 | 464 | [chat-badge]: https://img.shields.io/badge/chat-discussions-success.svg 465 | 466 | [chat]: https://github.com/remarkjs/remark/discussions 467 | 468 | [npm]: https://docs.npmjs.com/cli/install 469 | 470 | [esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c 471 | 472 | [esmsh]: https://esm.sh 473 | 474 | [health]: https://github.com/remarkjs/.github 475 | 476 | [contributing]: https://github.com/remarkjs/.github/blob/main/contributing.md 477 | 478 | [support]: https://github.com/remarkjs/.github/blob/main/support.md 479 | 480 | [coc]: https://github.com/remarkjs/.github/blob/main/code-of-conduct.md 481 | 482 | [license]: license 483 | 484 | [author]: https://wooorm.com 485 | 486 | [github-issue]: https://github.com/remarkjs/remark-github/issues/1 487 | 488 | [github-mention]: https://github.com/wooorm 489 | 490 | [github-sha]: https://github.com/remarkjs/remark-github/commit/1f2a4fb8f88a0a98ea9d0c0522cd538a9898f921 491 | 492 | [github-sha-range]: https://github.com/wooorm/remark/compare/e2acebc...2aa9311 493 | 494 | [github-writing]: https://docs.github.com/en/github/writing-on-github#references 495 | 496 | [hast]: https://github.com/syntax-tree/hast 497 | 498 | [rehype]: https://github.com/rehypejs/rehype 499 | 500 | [remark]: https://github.com/remarkjs/remark 501 | 502 | [remark-gfm]: https://github.com/remarkjs/remark-gfm 503 | 504 | [remark-breaks]: https://github.com/remarkjs/remark-breaks 505 | 506 | [remark-frontmatter]: https://github.com/remarkjs/remark-frontmatter 507 | 508 | [typescript]: https://www.typescriptlang.org 509 | 510 | [unified]: https://github.com/unifiedjs/unified 511 | 512 | [unified-transformer]: https://github.com/unifiedjs/unified#transformer 513 | 514 | [wiki-xss]: https://en.wikipedia.org/wiki/Cross-site_scripting 515 | 516 | [api-options]: #options 517 | 518 | [api-remark-github]: #unifieduseremarkgithub-options 519 | 520 | [api-build-url]: #buildurl 521 | 522 | [api-build-url-commit-values]: #buildurlcommitvalues 523 | 524 | [api-build-url-compare-values]: #buildurlcomparevalues 525 | 526 | [api-build-url-issue-values]: #buildurlissuevalues 527 | 528 | [api-build-url-mention-values]: #buildurlmentionvalues 529 | 530 | [api-build-url-values]: #buildurlvalues 531 | 532 | [api-default-build-url]: # 533 | -------------------------------------------------------------------------------- /test/fixtures/issue-gh-reloaded/input.md: -------------------------------------------------------------------------------- 1 | # Issue w/ `GH-` prefix 2 | 3 | ## After 4 | 5 | After a space GH-1. 6 | 7 | After an exclamation !GH-1. 8 | 9 | After a quote "GH-1. 10 | 11 | After a number sign #GH-1. 12 | 13 | After a dollar sign $GH-1. 14 | 15 | After a percentage sign %GH-1. 16 | 17 | After an ampersand &GH-1. 18 | 19 | After an apostrophe 'GH-1. 20 | 21 | After a left paren (GH-1. 22 | 23 | After a right paren )GH-1. 24 | 25 | After an asterisk *GH-1. 26 | 27 | After a plus sign +GH-1. 28 | 29 | After a comma ,GH-1. 30 | 31 | After a dash -GH-1. 32 | 33 | After a dot .GH-1. 34 | 35 | After a slash /GH-1. 36 | 37 | After a digit 0GH-1. 38 | 39 | After a colon :GH-1. 40 | 41 | After a semicolon ;GH-1. 42 | 43 | After a less than GH-1. 48 | 49 | After a question mark ?GH-1. 50 | 51 | After an at sign @GH-1. 52 | 53 | After an upper case AGH-1. 54 | 55 | After a left square bracket [GH-1. 56 | 57 | After a backslash \GH-1. 58 | 59 | After a right square bracket ]GH-1. 60 | 61 | After a caret ^GH-1. 62 | 63 | After an underscore _GH-1. 64 | 65 | After a grave accent `GH-1. 66 | 67 | After a lower case aGH-1. 68 | 69 | After a left curly brace {GH-1. 70 | 71 | After a pipe |GH-1. 72 | 73 | After a right curly bracket }GH-1. 74 | 75 | After a tilde ~GH-1. 76 | 77 | ## Before 78 | 79 | Before a space GH-1 . 80 | 81 | Before an exclamation GH-1! 82 | 83 | Before a quote GH-1" 84 | 85 | Before a number sign GH-1# 86 | 87 | Before a dollar sign GH-1$ 88 | 89 | Before a percentage sign GH-1% 90 | 91 | Before an ampersand GH-1& 92 | 93 | Before an apostrophe GH-1' 94 | 95 | Before a left paren GH-1( 96 | 97 | Before a right paren GH-1) 98 | 99 | Before an asterisk GH-1* 100 | 101 | Before a plus sign GH-1+ 102 | 103 | Before a comma GH-1, 104 | 105 | Before a dash GH-1- 106 | 107 | Before a dot GH-1. 108 | 109 | Before a slash GH-1/ 110 | 111 | Before a digit GH-10 112 | 113 | Before a colon GH-1: 114 | 115 | Before a semicolon GH-1; 116 | 117 | Before a less than GH-1< 118 | 119 | Before an equals to GH-1= 120 | 121 | Before a greater than GH-1> 122 | 123 | Before a question mark GH-1? 124 | 125 | Before an at sign GH-1@ 126 | 127 | Before an upper case GH-1A 128 | 129 | Before a left square bracket GH-1[ 130 | 131 | Before a backslash GH-1\ 132 | 133 | Before a right square bracket GH-1] 134 | 135 | Before a caret GH-1^ 136 | 137 | Before an underscore GH-1_ 138 | 139 | Before a grave accent GH-1` 140 | 141 | Before a lower case GH-1a 142 | 143 | Before a left curly brace GH-1{ 144 | 145 | Before a pipe GH-1| 146 | 147 | Before a right curly bracket GH-1} 148 | 149 | Before a tilde GH-1~ 150 | -------------------------------------------------------------------------------- /test/fixtures/issue-gh-reloaded/output.md: -------------------------------------------------------------------------------- 1 | # Issue w/ `GH-` prefix 2 | 3 | ## After 4 | 5 | After a space [GH-1](https://github.com/wooorm/remark/issues/1). 6 | 7 | After an exclamation \![GH-1](https://github.com/wooorm/remark/issues/1). 8 | 9 | After a quote "[GH-1](https://github.com/wooorm/remark/issues/1). 10 | 11 | After a number sign #[GH-1](https://github.com/wooorm/remark/issues/1). 12 | 13 | After a dollar sign $[GH-1](https://github.com/wooorm/remark/issues/1). 14 | 15 | After a percentage sign %[GH-1](https://github.com/wooorm/remark/issues/1). 16 | 17 | After an ampersand &[GH-1](https://github.com/wooorm/remark/issues/1). 18 | 19 | After an apostrophe '[GH-1](https://github.com/wooorm/remark/issues/1). 20 | 21 | After a left paren ([GH-1](https://github.com/wooorm/remark/issues/1). 22 | 23 | After a right paren )[GH-1](https://github.com/wooorm/remark/issues/1). 24 | 25 | After an asterisk \*[GH-1](https://github.com/wooorm/remark/issues/1). 26 | 27 | After a plus sign +[GH-1](https://github.com/wooorm/remark/issues/1). 28 | 29 | After a comma ,[GH-1](https://github.com/wooorm/remark/issues/1). 30 | 31 | After a dash -[GH-1](https://github.com/wooorm/remark/issues/1). 32 | 33 | After a dot .[GH-1](https://github.com/wooorm/remark/issues/1). 34 | 35 | After a slash /[GH-1](https://github.com/wooorm/remark/issues/1). 36 | 37 | After a digit 0GH-1. 38 | 39 | After a colon :[GH-1](https://github.com/wooorm/remark/issues/1). 40 | 41 | After a semicolon ;[GH-1](https://github.com/wooorm/remark/issues/1). 42 | 43 | After a less than <[GH-1](https://github.com/wooorm/remark/issues/1). 44 | 45 | After an equals to =[GH-1](https://github.com/wooorm/remark/issues/1). 46 | 47 | After a greater than >[GH-1](https://github.com/wooorm/remark/issues/1). 48 | 49 | After a question mark ?[GH-1](https://github.com/wooorm/remark/issues/1). 50 | 51 | After an at sign [**@GH-1**](https://github.com/GH-1). 52 | 53 | After an upper case AGH-1. 54 | 55 | After a left square bracket \[[GH-1](https://github.com/wooorm/remark/issues/1). 56 | 57 | After a backslash \\[GH-1](https://github.com/wooorm/remark/issues/1). 58 | 59 | After a right square bracket ][GH-1](https://github.com/wooorm/remark/issues/1). 60 | 61 | After a caret ^[GH-1](https://github.com/wooorm/remark/issues/1). 62 | 63 | After an underscore \_GH-1. 64 | 65 | After a grave accent \`[GH-1](https://github.com/wooorm/remark/issues/1). 66 | 67 | After a lower case aGH-1. 68 | 69 | After a left curly brace {[GH-1](https://github.com/wooorm/remark/issues/1). 70 | 71 | After a pipe |[GH-1](https://github.com/wooorm/remark/issues/1). 72 | 73 | After a right curly bracket }[GH-1](https://github.com/wooorm/remark/issues/1). 74 | 75 | After a tilde \~[GH-1](https://github.com/wooorm/remark/issues/1). 76 | 77 | ## Before 78 | 79 | Before a space [GH-1](https://github.com/wooorm/remark/issues/1) . 80 | 81 | Before an exclamation [GH-1](https://github.com/wooorm/remark/issues/1)! 82 | 83 | Before a quote [GH-1](https://github.com/wooorm/remark/issues/1)" 84 | 85 | Before a number sign [GH-1](https://github.com/wooorm/remark/issues/1)# 86 | 87 | Before a dollar sign [GH-1](https://github.com/wooorm/remark/issues/1)$ 88 | 89 | Before a percentage sign [GH-1](https://github.com/wooorm/remark/issues/1)% 90 | 91 | Before an ampersand [GH-1](https://github.com/wooorm/remark/issues/1)& 92 | 93 | Before an apostrophe [GH-1](https://github.com/wooorm/remark/issues/1)' 94 | 95 | Before a left paren [GH-1](https://github.com/wooorm/remark/issues/1)( 96 | 97 | Before a right paren [GH-1](https://github.com/wooorm/remark/issues/1)) 98 | 99 | Before an asterisk [GH-1](https://github.com/wooorm/remark/issues/1)\* 100 | 101 | Before a plus sign [GH-1](https://github.com/wooorm/remark/issues/1)+ 102 | 103 | Before a comma [GH-1](https://github.com/wooorm/remark/issues/1), 104 | 105 | Before a dash [GH-1](https://github.com/wooorm/remark/issues/1)- 106 | 107 | Before a dot [GH-1](https://github.com/wooorm/remark/issues/1). 108 | 109 | Before a slash [GH-1](https://github.com/wooorm/remark/issues/1)/ 110 | 111 | Before a digit [GH-10](https://github.com/wooorm/remark/issues/10) 112 | 113 | Before a colon [GH-1](https://github.com/wooorm/remark/issues/1): 114 | 115 | Before a semicolon [GH-1](https://github.com/wooorm/remark/issues/1); 116 | 117 | Before a less than [GH-1](https://github.com/wooorm/remark/issues/1)< 118 | 119 | Before an equals to [GH-1](https://github.com/wooorm/remark/issues/1)= 120 | 121 | Before a greater than [GH-1](https://github.com/wooorm/remark/issues/1)> 122 | 123 | Before a question mark [GH-1](https://github.com/wooorm/remark/issues/1)? 124 | 125 | Before an at sign [GH-1](https://github.com/wooorm/remark/issues/1)@ 126 | 127 | Before an upper case GH-1A 128 | 129 | Before a left square bracket [GH-1](https://github.com/wooorm/remark/issues/1)\[ 130 | 131 | Before a backslash [GH-1](https://github.com/wooorm/remark/issues/1)\\ 132 | 133 | Before a right square bracket [GH-1](https://github.com/wooorm/remark/issues/1)] 134 | 135 | Before a caret [GH-1](https://github.com/wooorm/remark/issues/1)^ 136 | 137 | Before an underscore GH-1\_ 138 | 139 | Before a grave accent [GH-1](https://github.com/wooorm/remark/issues/1)\` 140 | 141 | Before a lower case GH-1a 142 | 143 | Before a left curly brace [GH-1](https://github.com/wooorm/remark/issues/1){ 144 | 145 | Before a pipe [GH-1](https://github.com/wooorm/remark/issues/1)| 146 | 147 | Before a right curly bracket [GH-1](https://github.com/wooorm/remark/issues/1)} 148 | 149 | Before a tilde [GH-1](https://github.com/wooorm/remark/issues/1)\~ 150 | -------------------------------------------------------------------------------- /test/fixtures/issue-hash-reloaded/input.md: -------------------------------------------------------------------------------- 1 | # Issue w/ hash 2 | 3 | ## After 4 | 5 | After a space #1. 6 | 7 | After an exclamation !#1. 8 | 9 | After a quote "#1. 10 | 11 | After a number sign ##1. 12 | 13 | After a dollar sign $#1. 14 | 15 | After a percentage sign %#1. 16 | 17 | After an ampersand . 18 | 19 | After an apostrophe '#1. 20 | 21 | After a left paren (#1. 22 | 23 | After a right paren )#1. 24 | 25 | After an asterisk *#1. 26 | 27 | After a plus sign +#1. 28 | 29 | After a comma ,#1. 30 | 31 | After a dash -#1. 32 | 33 | After a dot .#1. 34 | 35 | After a slash /#1. 36 | 37 | After a digit 0#1. 38 | 39 | After a colon :#1. 40 | 41 | After a semicolon ;#1. 42 | 43 | After a less than <#1. 44 | 45 | After an equals to =#1. 46 | 47 | After a greater than >#1. 48 | 49 | After a question mark ?#1. 50 | 51 | After an at sign @#1. 52 | 53 | After an upper case A#1. 54 | 55 | After a left square bracket [#1. 56 | 57 | After a backslash \#1. 58 | 59 | After a right square bracket ]#1. 60 | 61 | After a caret ^#1. 62 | 63 | After an underscore _#1. 64 | 65 | After a grave accent `#1. 66 | 67 | After a lower case a#1. 68 | 69 | After a left curly brace {#1. 70 | 71 | After a pipe |#1. 72 | 73 | After a right curly bracket }#1. 74 | 75 | After a tilde ~#1. 76 | 77 | ## Before 78 | 79 | Before a space #1 . 80 | 81 | Before an exclamation #1! 82 | 83 | Before a quote #1" 84 | 85 | Before a number sign #1# 86 | 87 | Before a dollar sign #1$ 88 | 89 | Before a percentage sign #1% 90 | 91 | Before an ampersand #1& 92 | 93 | Before an apostrophe #1' 94 | 95 | Before a left paren #1( 96 | 97 | Before a right paren #1) 98 | 99 | Before an asterisk #1* 100 | 101 | Before a plus sign #1+ 102 | 103 | Before a comma #1, 104 | 105 | Before a dash #1- 106 | 107 | Before a dot #1. 108 | 109 | Before a slash #1/ 110 | 111 | Before a digit #10 112 | 113 | Before a colon #1: 114 | 115 | Before a semicolon #1; 116 | 117 | Before a less than #1< 118 | 119 | Before an equals to #1= 120 | 121 | Before a greater than #1> 122 | 123 | Before a question mark #1? 124 | 125 | Before an at sign #1@ 126 | 127 | Before an upper case #1A 128 | 129 | Before a left square bracket #1[ 130 | 131 | Before a backslash #1\ 132 | 133 | Before a right square bracket #1] 134 | 135 | Before a caret #1^ 136 | 137 | Before an underscore #1_ 138 | 139 | Before a grave accent #1` 140 | 141 | Before a lower case #1a 142 | 143 | Before a left curly brace #1{ 144 | 145 | Before a pipe #1| 146 | 147 | Before a right curly bracket #1} 148 | 149 | Before a tilde #1~ 150 | -------------------------------------------------------------------------------- /test/fixtures/issue-hash-reloaded/output.md: -------------------------------------------------------------------------------- 1 | # Issue w/ hash 2 | 3 | ## After 4 | 5 | After a space [#1](https://github.com/wooorm/remark/issues/1). 6 | 7 | After an exclamation \![#1](https://github.com/wooorm/remark/issues/1). 8 | 9 | After a quote "[#1](https://github.com/wooorm/remark/issues/1). 10 | 11 | After a number sign #[#1](https://github.com/wooorm/remark/issues/1). 12 | 13 | After a dollar sign $[#1](https://github.com/wooorm/remark/issues/1). 14 | 15 | After a percentage sign %[#1](https://github.com/wooorm/remark/issues/1). 16 | 17 | After an ampersand &[#1](https://github.com/wooorm/remark/issues/1). 18 | 19 | After an apostrophe '[#1](https://github.com/wooorm/remark/issues/1). 20 | 21 | After a left paren ([#1](https://github.com/wooorm/remark/issues/1). 22 | 23 | After a right paren )[#1](https://github.com/wooorm/remark/issues/1). 24 | 25 | After an asterisk \*[#1](https://github.com/wooorm/remark/issues/1). 26 | 27 | After a plus sign +[#1](https://github.com/wooorm/remark/issues/1). 28 | 29 | After a comma ,[#1](https://github.com/wooorm/remark/issues/1). 30 | 31 | After a dash -[#1](https://github.com/wooorm/remark/issues/1). 32 | 33 | After a dot .[#1](https://github.com/wooorm/remark/issues/1). 34 | 35 | After a slash /[#1](https://github.com/wooorm/remark/issues/1). 36 | 37 | After a digit [0#1](https://github.com/0/remark/issues/1). 38 | 39 | After a colon :[#1](https://github.com/wooorm/remark/issues/1). 40 | 41 | After a semicolon ;[#1](https://github.com/wooorm/remark/issues/1). 42 | 43 | After a less than <[#1](https://github.com/wooorm/remark/issues/1). 44 | 45 | After an equals to =[#1](https://github.com/wooorm/remark/issues/1). 46 | 47 | After a greater than >[#1](https://github.com/wooorm/remark/issues/1). 48 | 49 | After a question mark ?[#1](https://github.com/wooorm/remark/issues/1). 50 | 51 | After an at sign @[#1](https://github.com/wooorm/remark/issues/1). 52 | 53 | After an upper case [A#1](https://github.com/A/remark/issues/1). 54 | 55 | After a left square bracket \[[#1](https://github.com/wooorm/remark/issues/1). 56 | 57 | After a backslash [#1](https://github.com/wooorm/remark/issues/1). 58 | 59 | After a right square bracket ][#1](https://github.com/wooorm/remark/issues/1). 60 | 61 | After a caret ^[#1](https://github.com/wooorm/remark/issues/1). 62 | 63 | After an underscore \_#1. 64 | 65 | After a grave accent \`[#1](https://github.com/wooorm/remark/issues/1). 66 | 67 | After a lower case [a#1](https://github.com/a/remark/issues/1). 68 | 69 | After a left curly brace {[#1](https://github.com/wooorm/remark/issues/1). 70 | 71 | After a pipe |[#1](https://github.com/wooorm/remark/issues/1). 72 | 73 | After a right curly bracket }[#1](https://github.com/wooorm/remark/issues/1). 74 | 75 | After a tilde \~[#1](https://github.com/wooorm/remark/issues/1). 76 | 77 | ## Before 78 | 79 | Before a space [#1](https://github.com/wooorm/remark/issues/1) . 80 | 81 | Before an exclamation [#1](https://github.com/wooorm/remark/issues/1)! 82 | 83 | Before a quote [#1](https://github.com/wooorm/remark/issues/1)" 84 | 85 | Before a number sign [#1](https://github.com/wooorm/remark/issues/1)# 86 | 87 | Before a dollar sign [#1](https://github.com/wooorm/remark/issues/1)$ 88 | 89 | Before a percentage sign [#1](https://github.com/wooorm/remark/issues/1)% 90 | 91 | Before an ampersand [#1](https://github.com/wooorm/remark/issues/1)& 92 | 93 | Before an apostrophe [#1](https://github.com/wooorm/remark/issues/1)' 94 | 95 | Before a left paren [#1](https://github.com/wooorm/remark/issues/1)( 96 | 97 | Before a right paren [#1](https://github.com/wooorm/remark/issues/1)) 98 | 99 | Before an asterisk [#1](https://github.com/wooorm/remark/issues/1)\* 100 | 101 | Before a plus sign [#1](https://github.com/wooorm/remark/issues/1)+ 102 | 103 | Before a comma [#1](https://github.com/wooorm/remark/issues/1), 104 | 105 | Before a dash [#1](https://github.com/wooorm/remark/issues/1)- 106 | 107 | Before a dot [#1](https://github.com/wooorm/remark/issues/1). 108 | 109 | Before a slash [#1](https://github.com/wooorm/remark/issues/1)/ 110 | 111 | Before a digit [#10](https://github.com/wooorm/remark/issues/10) 112 | 113 | Before a colon [#1](https://github.com/wooorm/remark/issues/1): 114 | 115 | Before a semicolon [#1](https://github.com/wooorm/remark/issues/1); 116 | 117 | Before a less than [#1](https://github.com/wooorm/remark/issues/1)< 118 | 119 | Before an equals to [#1](https://github.com/wooorm/remark/issues/1)= 120 | 121 | Before a greater than [#1](https://github.com/wooorm/remark/issues/1)> 122 | 123 | Before a question mark [#1](https://github.com/wooorm/remark/issues/1)? 124 | 125 | Before an at sign [#1](https://github.com/wooorm/remark/issues/1)@ 126 | 127 | Before an upper case #1A 128 | 129 | Before a left square bracket [#1](https://github.com/wooorm/remark/issues/1)\[ 130 | 131 | Before a backslash [#1](https://github.com/wooorm/remark/issues/1)\\ 132 | 133 | Before a right square bracket [#1](https://github.com/wooorm/remark/issues/1)] 134 | 135 | Before a caret [#1](https://github.com/wooorm/remark/issues/1)^ 136 | 137 | Before an underscore #1\_ 138 | 139 | Before a grave accent [#1](https://github.com/wooorm/remark/issues/1)\` 140 | 141 | Before a lower case #1a 142 | 143 | Before a left curly brace [#1](https://github.com/wooorm/remark/issues/1){ 144 | 145 | Before a pipe [#1](https://github.com/wooorm/remark/issues/1)| 146 | 147 | Before a right curly bracket [#1](https://github.com/wooorm/remark/issues/1)} 148 | 149 | Before a tilde [#1](https://github.com/wooorm/remark/issues/1)\~ 150 | -------------------------------------------------------------------------------- /test/fixtures/issue-project/input.md: -------------------------------------------------------------------------------- 1 | # User@Project 2 | 3 | A project-SHA is not relative to the current project. 4 | 5 | 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). 6 | 7 | * This is a valid issue: foo/bar#1; 8 | * So is this: foo/bar#123456789. 9 | 10 | They work here 11 | foo/bar#1 12 | 13 | and here 14 | foo/bar#1 15 | 16 | Usernames: this is not a valid, -foo/bar#1; but this is w-w/bar#1, and so is w/bar#1 and ww/bar#1. 17 | 18 | Note that this is no longer valid, but used to be: w-/bar#1. 19 | 20 | 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. 21 | 22 | This is too long: wooormwooormwooormwooormwooormwooormwooo/c#1 (40 character username). 23 | -------------------------------------------------------------------------------- /test/fixtures/issue-project/output.md: -------------------------------------------------------------------------------- 1 | # User\@Project 2 | 3 | A project-SHA is not relative to the current project. 4 | 5 | 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). 6 | 7 | * This is a valid issue: [foo/bar#1](https://github.com/foo/bar/issues/1); 8 | * So is this: [foo/bar#123456789](https://github.com/foo/bar/issues/123456789). 9 | 10 | They work here 11 | [foo/bar#1](https://github.com/foo/bar/issues/1) 12 | 13 | and here 14 | [foo/bar#1](https://github.com/foo/bar/issues/1) 15 | 16 | Usernames: this is not a valid, -foo/bar#1; but this is [w-w/bar#1](https://github.com/w-w/bar/issues/1), and so is [w/bar#1](https://github.com/w/bar/issues/1) and [ww/bar#1](https://github.com/ww/bar/issues/1). 17 | 18 | Note that this is no longer valid, but used to be: [w-/bar#1](https://github.com/w-/bar/issues/1). 19 | 20 | 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). 21 | 22 | This is too long: wooormwooormwooormwooormwooormwooormwooo/c#1 (40 character username). 23 | -------------------------------------------------------------------------------- /test/fixtures/issue-user/input.md: -------------------------------------------------------------------------------- 1 | # User@Issue 2 | 3 | A user-issue is relative to the project, but relative to the user’s fork. 4 | 5 | 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). 6 | 7 | * This is a valid issue: username#1; 8 | * So is this: username#123456789. 9 | 10 | They work here 11 | username#1 12 | 13 | and here 14 | username#1 15 | 16 | This is not a valid, -username#1; but this is w-w#1, and so is w#1 and ww#1, and w-#1 used to be valid. 17 | 18 | This is too long: wooormwooormwooormwooormwooormwooormwooo#1 (40 character username). 19 | -------------------------------------------------------------------------------- /test/fixtures/issue-user/output.md: -------------------------------------------------------------------------------- 1 | # User\@Issue 2 | 3 | A user-issue is relative to the project, but relative to the user’s fork. 4 | 5 | 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). 6 | 7 | * This is a valid issue: [username#1](https://github.com/username/remark/issues/1); 8 | * So is this: [username#123456789](https://github.com/username/remark/issues/123456789). 9 | 10 | They work here 11 | [username#1](https://github.com/username/remark/issues/1) 12 | 13 | and here 14 | [username#1](https://github.com/username/remark/issues/1) 15 | 16 | This is not a valid, -username#1; but this is [w-w#1](https://github.com/w-w/remark/issues/1), and so is [w#1](https://github.com/w/remark/issues/1) and [ww#1](https://github.com/ww/remark/issues/1), and [w-#1](https://github.com/w-/remark/issues/1) used to be valid. 17 | 18 | This is too long: wooormwooormwooormwooormwooormwooormwooo#1 (40 character username). 19 | -------------------------------------------------------------------------------- /test/fixtures/issue/input.md: -------------------------------------------------------------------------------- 1 | # Issue 2 | 3 | * This is a valid issue: #1, and so is this: GH-1; 4 | * So are these: #123456789, and: GH-123456789; 5 | * And these: gH-1, Gh-1, and gh-1. 6 | 7 | These will always be a header in pedantic mode (remark requires initial spaces for ATX-headings) 8 | #1 9 | 10 | Or here 11 | 12 | #1 13 | 14 | But these will always work: 15 | GH-1 16 | 17 | Or here 18 | GH-1 19 | -------------------------------------------------------------------------------- /test/fixtures/issue/output.md: -------------------------------------------------------------------------------- 1 | # Issue 2 | 3 | * This is a valid issue: [#1](https://github.com/wooorm/remark/issues/1), and so is this: [GH-1](https://github.com/wooorm/remark/issues/1); 4 | * So are these: [#123456789](https://github.com/wooorm/remark/issues/123456789), and: [GH-123456789](https://github.com/wooorm/remark/issues/123456789); 5 | * And these: [gH-1](https://github.com/wooorm/remark/issues/1), [Gh-1](https://github.com/wooorm/remark/issues/1), and [gh-1](https://github.com/wooorm/remark/issues/1). 6 | 7 | These will always be a header in pedantic mode (remark requires initial spaces for ATX-headings) 8 | [#1](https://github.com/wooorm/remark/issues/1) 9 | 10 | Or here 11 | 12 | ``` 13 | #1 14 | ``` 15 | 16 | But these will always work: 17 | [GH-1](https://github.com/wooorm/remark/issues/1) 18 | 19 | Or here 20 | [GH-1](https://github.com/wooorm/remark/issues/1) 21 | -------------------------------------------------------------------------------- /test/fixtures/links/input.md: -------------------------------------------------------------------------------- 1 | # GitHub Links 2 | 3 | This document tests transformation of links into references. 4 | The behaviour used on GitHub is very lacking. E.g., commit comments 5 | are not actually rendered “properly”, the hash of the URL is literally 6 | shown next to the reference. Another by GitHub unsupported feature is 7 | references for issues, pull requests, or commits on different projects. 8 | 9 | remark-github does support all these systems and makes things look 10 | pretty. 11 | 12 | ## Non-references 13 | 14 | An empty link: [this and that](). 15 | 16 | A link to GH: 17 | 18 | 19 | A link to a user: 20 | 21 | 22 | A link to a project: 23 | 24 | 25 | A link to a graphs: 26 | 27 | 28 | A link to a traffic: 29 | 30 | 31 | ## Commit 32 | 33 | Commits (should not render): 34 | 35 | 36 | A too long commit (should not render): 37 | 38 | 39 | A valid commit: 40 | 41 | 42 | A valid abbreviated commit: 43 | 44 | 45 | A too short commit (should not render): 46 | 47 | 48 | Across users: 49 | 50 | 51 | Across repositories: 52 | 53 | 54 | Same user, different repository: 55 | 56 | 57 | With dots (GH-14) 58 | 59 | 60 | Too long repo 61 | 62 | 63 | ## Commit comments 64 | 65 | A commit comment: 66 | 67 | 68 | Not a comment (should not render comment part): 69 | 70 | 71 | Across users: 72 | 73 | 74 | Across repositories: 75 | 76 | 77 | Same user, different repository: 78 | 79 | 80 | ## Issues 81 | 82 | Issues (should not render): 83 | 84 | 85 | Pulls (should not render): 86 | 87 | 88 | An issue: 89 | 90 | 91 | Not an issue, no HTTPS (should not render): 92 | 93 | 94 | A pull: 95 | 96 | 97 | Not a pull, no HTTPS (should not render): 98 | 99 | 100 | Issues across users: 101 | 102 | 103 | Issues across repositories: 104 | 105 | 106 | Issues on same user, different repository: 107 | 108 | 109 | Pulls across users: 110 | 111 | 112 | Pulls across repositories: 113 | 114 | 115 | Pull on same user, different repository: 116 | 117 | 118 | Issue with non-digit: 119 | 120 | 121 | Pull with non-digit: 122 | 123 | 124 | ## Issue comments 125 | 126 | Not a comment, no HTTPS (should not render): 127 | 128 | 129 | A commit comment: 130 | 131 | 132 | Not a comment (should not render comment part): 133 | 134 | 135 | Issues comment across users: 136 | 137 | 138 | Issues comment across repositories: 139 | 140 | 141 | Issues comment on same user, different repository: 142 | 143 | 144 | Pull comment across users: 145 | 146 | 147 | Pull comment across repositories: 148 | 149 | 150 | Pull comment on same user, different repository: 151 | 152 | 153 | ## Users 154 | 155 | Users (should not render): 156 | 157 | -------------------------------------------------------------------------------- /test/fixtures/links/output.md: -------------------------------------------------------------------------------- 1 | # GitHub Links 2 | 3 | This document tests transformation of links into references. 4 | The behaviour used on GitHub is very lacking. E.g., commit comments 5 | are not actually rendered “properly”, the hash of the URL is literally 6 | shown next to the reference. Another by GitHub unsupported feature is 7 | references for issues, pull requests, or commits on different projects. 8 | 9 | remark-github does support all these systems and makes things look 10 | pretty. 11 | 12 | ## Non-references 13 | 14 | An empty link: [this and that](). 15 | 16 | A link to GH: 17 | 18 | 19 | A link to a user: 20 | 21 | 22 | A link to a project: 23 | 24 | 25 | A link to a graphs: 26 | 27 | 28 | A link to a traffic: 29 | 30 | 31 | ## Commit 32 | 33 | Commits (should not render): 34 | 35 | 36 | A too long commit (should not render): 37 | 38 | 39 | A valid commit: 40 | [`1f2a4fb`](https://github.com/wooorm/remark/commit/1f2a4fb8f88a0a98ea9d0c0522cd538a9898f921) 41 | 42 | A valid abbreviated commit: 43 | [`1f2a`](https://github.com/wooorm/remark/commit/1f2a) 44 | 45 | A too short commit (should not render): 46 | 47 | 48 | Across users: 49 | [foo@`1f2a`](https://github.com/foo/remark/commit/1f2a) 50 | 51 | Across repositories: 52 | [foo/bar@`1f2a`](https://github.com/foo/bar/commit/1f2a) 53 | 54 | Same user, different repository: 55 | [wooorm/bar@`1f2a`](https://github.com/wooorm/bar/commit/1f2a) 56 | 57 | With dots ([GH-14](https://github.com/wooorm/remark/issues/14)) 58 | [wooorm/wooorm.github.io@`e5bd`](https://github.com/wooorm/wooorm.github.io/commit/e5bd) 59 | 60 | Too long repo 61 | 62 | 63 | ## Commit comments 64 | 65 | A commit comment: 66 | [`1f2a` (comment)](https://github.com/wooorm/remark/commit/1f2a#commitcomment-12312312) 67 | 68 | Not a comment (should not render comment part): 69 | [`1f2a`](https://github.com/wooorm/remark/commit/1f2a#) 70 | 71 | Across users: 72 | [foo@`1f2a` (comment)](https://github.com/foo/remark/commit/1f2a#commitcomment-12312312) 73 | 74 | Across repositories: 75 | [foo/bar@`1f2a` (comment)](https://github.com/foo/bar/commit/1f2a#commitcomment-12312312) 76 | 77 | Same user, different repository: 78 | [wooorm/bar@`1f2a` (comment)](https://github.com/wooorm/bar/commit/1f2a#commitcomment-12312312) 79 | 80 | ## Issues 81 | 82 | Issues (should not render): 83 | 84 | 85 | Pulls (should not render): 86 | 87 | 88 | An issue: 89 | [#2](https://github.com/wooorm/remark/issues/2) 90 | 91 | Not an issue, no HTTPS (should not render): 92 | [#2](http://github.com/wooorm/remark/issues/2) 93 | 94 | A pull: 95 | [#2](https://github.com/wooorm/remark/pull/2) 96 | 97 | Not a pull, no HTTPS (should not render): 98 | [#2](http://github.com/wooorm/remark/pull/2) 99 | 100 | Issues across users: 101 | [foo#2](https://github.com/foo/remark/issues/2) 102 | 103 | Issues across repositories: 104 | [foo/bar#2](https://github.com/foo/bar/issues/2) 105 | 106 | Issues on same user, different repository: 107 | [wooorm/bar#2](https://github.com/wooorm/bar/issues/2) 108 | 109 | Pulls across users: 110 | [foo#2](https://github.com/foo/remark/pull/2) 111 | 112 | Pulls across repositories: 113 | [foo/bar#2](https://github.com/foo/bar/pull/2) 114 | 115 | Pull on same user, different repository: 116 | [wooorm/bar#2](https://github.com/wooorm/bar/pull/2) 117 | 118 | Issue with non-digit: 119 | 120 | 121 | Pull with non-digit: 122 | 123 | 124 | ## Issue comments 125 | 126 | Not a comment, no HTTPS (should not render): 127 | [#2 (comment)](http://github.com/wooorm/remark/issues/2#issuecomment-123123) 128 | 129 | A commit comment: 130 | [#2 (comment)](https://github.com/wooorm/remark/issues/2#issuecomment-123123) 131 | 132 | Not a comment (should not render comment part): 133 | [#2](https://github.com/wooorm/remark/issues/2#) 134 | 135 | Issues comment across users: 136 | [foo#2 (comment)](https://github.com/foo/remark/issues/2#issuecomment-123123) 137 | 138 | Issues comment across repositories: 139 | [foo/bar#2 (comment)](https://github.com/foo/bar/issues/2#issuecomment-123123) 140 | 141 | Issues comment on same user, different repository: 142 | [wooorm/bar#2 (comment)](https://github.com/wooorm/bar/issues/2#issuecomment-123123) 143 | 144 | Pull comment across users: 145 | [foo#2 (comment)](https://github.com/foo/remark/pull/2#issuecomment-123123) 146 | 147 | Pull comment across repositories: 148 | [foo/bar#2 (comment)](https://github.com/foo/bar/pull/2#issuecomment-123123) 149 | 150 | Pull comment on same user, different repository: 151 | [wooorm/bar#2 (comment)](https://github.com/wooorm/bar/issues/2#issuecomment-123123) 152 | 153 | ## Users 154 | 155 | Users (should not render): 156 | 157 | -------------------------------------------------------------------------------- /test/fixtures/mention-team-reloaded/input.md: -------------------------------------------------------------------------------- 1 | # Team mention 2 | 3 | ## After 4 | 5 | After a space @username/team. 6 | 7 | After an exclamation !@username/team. 8 | 9 | After a quote "@username/team. 10 | 11 | After a number sign #@username/team. 12 | 13 | After a dollar sign $@username/team. 14 | 15 | After a percentage sign %@username/team. 16 | 17 | After an ampersand &@username/team. 18 | 19 | After an apostrophe '@username/team. 20 | 21 | After a left paren (@username/team. 22 | 23 | After a right paren )@username/team. 24 | 25 | After an asterisk *@username/team. 26 | 27 | After a plus sign +@username/team. 28 | 29 | After a comma ,@username/team. 30 | 31 | After a dash -@username/team. 32 | 33 | After a dot .@username/team. 34 | 35 | After a slash /@username/team. 36 | 37 | After a digit 0@username/team. 38 | 39 | After a colon :@username/team. 40 | 41 | After a semicolon ;@username/team. 42 | 43 | After a less than <@username/team. 44 | 45 | After an equals to =@username/team. 46 | 47 | After a greater than >@username/team. 48 | 49 | After a question mark ?@username/team. 50 | 51 | After an at sign @@username/team. 52 | 53 | After an upper case A@username/team. 54 | 55 | After a left square bracket [@username/team. 56 | 57 | After a backslash \@username/team. 58 | 59 | After a right square bracket ]@username/team. 60 | 61 | After a caret ^@username/team. 62 | 63 | After an underscore _@username/team. 64 | 65 | After a grave accent `@username/team. 66 | 67 | After a lower case a@username/team. 68 | 69 | After a left curly brace {@username/team. 70 | 71 | After a pipe |@username/team. 72 | 73 | After a right curly bracket }@username/team. 74 | 75 | After a tilde ~@username/team. 76 | 77 | ## Before 78 | 79 | Before a space @username/team . 80 | 81 | Before an exclamation @username/team! 82 | 83 | Before a quote @username/team" 84 | 85 | Before a number sign @username/team# 86 | 87 | Before a dollar sign @username/team$ 88 | 89 | Before a percentage sign @username/team% 90 | 91 | Before an ampersand @username/team& 92 | 93 | Before an apostrophe @username/team' 94 | 95 | Before a left paren @username/team( 96 | 97 | Before a right paren @username/team) 98 | 99 | Before an asterisk @username/team* 100 | 101 | Before a plus sign @username/team+ 102 | 103 | Before a comma @username/team, 104 | 105 | Before a dash @username/team- 106 | 107 | Before a dot @username/team. 108 | 109 | Before a slash @username/team/ 110 | 111 | Before a digit @username/team0 112 | 113 | Before a colon @username/team: 114 | 115 | Before a semicolon @username/team; 116 | 117 | Before a less than @username/team< 118 | 119 | Before an equals to @username/team= 120 | 121 | Before a greater than @username/team> 122 | 123 | Before a question mark @username/team? 124 | 125 | Before an at sign @username/team@ 126 | 127 | Before an upper case @username/teamA 128 | 129 | Before a left square bracket @username/team[ 130 | 131 | Before a backslash @username/team\ 132 | 133 | Before a right square bracket @username/team] 134 | 135 | Before a caret @username/team^ 136 | 137 | Before an underscore @username/team_ 138 | 139 | Before a grave accent @username/team` 140 | 141 | Before a lower case @username/teama 142 | 143 | Before a left curly brace @username/team{ 144 | 145 | Before a pipe @username/team| 146 | 147 | Before a right curly bracket @username/team} 148 | 149 | Before a tilde @username/team~ 150 | -------------------------------------------------------------------------------- /test/fixtures/mention-team-reloaded/output.md: -------------------------------------------------------------------------------- 1 | # Team mention 2 | 3 | ## After 4 | 5 | After a space [**@username/team**](https://github.com/username/team). 6 | 7 | After an exclamation \![**@username/team**](https://github.com/username/team). 8 | 9 | After a quote "[**@username/team**](https://github.com/username/team). 10 | 11 | After a number sign #[**@username/team**](https://github.com/username/team). 12 | 13 | After a dollar sign $[**@username/team**](https://github.com/username/team). 14 | 15 | After a percentage sign %[**@username/team**](https://github.com/username/team). 16 | 17 | After an ampersand &[**@username/team**](https://github.com/username/team). 18 | 19 | After an apostrophe '[**@username/team**](https://github.com/username/team). 20 | 21 | After a left paren ([**@username/team**](https://github.com/username/team). 22 | 23 | After a right paren )[**@username/team**](https://github.com/username/team). 24 | 25 | After an asterisk \*[**@username/team**](https://github.com/username/team). 26 | 27 | After a plus sign +[**@username/team**](https://github.com/username/team). 28 | 29 | After a comma ,[**@username/team**](https://github.com/username/team). 30 | 31 | After a dash -[**@username/team**](https://github.com/username/team). 32 | 33 | After a dot .[**@username/team**](https://github.com/username/team). 34 | 35 | After a slash /[**@username/team**](https://github.com/username/team). 36 | 37 | After a digit 0\@username/team. 38 | 39 | After a colon :[**@username/team**](https://github.com/username/team). 40 | 41 | After a semicolon ;[**@username/team**](https://github.com/username/team). 42 | 43 | After a less than <[**@username/team**](https://github.com/username/team). 44 | 45 | After an equals to =[**@username/team**](https://github.com/username/team). 46 | 47 | After a greater than >[**@username/team**](https://github.com/username/team). 48 | 49 | After a question mark ?[**@username/team**](https://github.com/username/team). 50 | 51 | After an at sign @[**@username/team**](https://github.com/username/team). 52 | 53 | After an upper case A\@username/team. 54 | 55 | After a left square bracket \[[**@username/team**](https://github.com/username/team). 56 | 57 | After a backslash [**@username/team**](https://github.com/username/team). 58 | 59 | After a right square bracket ][**@username/team**](https://github.com/username/team). 60 | 61 | After a caret ^[**@username/team**](https://github.com/username/team). 62 | 63 | After an underscore \_@username/team. 64 | 65 | After a grave accent \`@username/team. 66 | 67 | After a lower case a\@username/team. 68 | 69 | After a left curly brace {[**@username/team**](https://github.com/username/team). 70 | 71 | After a pipe |[**@username/team**](https://github.com/username/team). 72 | 73 | After a right curly bracket }[**@username/team**](https://github.com/username/team). 74 | 75 | After a tilde \~[**@username/team**](https://github.com/username/team). 76 | 77 | ## Before 78 | 79 | Before a space [**@username/team**](https://github.com/username/team) . 80 | 81 | Before an exclamation [**@username/team**](https://github.com/username/team)! 82 | 83 | Before a quote [**@username/team**](https://github.com/username/team)" 84 | 85 | Before a number sign [**@username/team**](https://github.com/username/team)# 86 | 87 | Before a dollar sign [**@username/team**](https://github.com/username/team)$ 88 | 89 | Before a percentage sign [**@username/team**](https://github.com/username/team)% 90 | 91 | Before an ampersand [**@username/team**](https://github.com/username/team)& 92 | 93 | Before an apostrophe [**@username/team**](https://github.com/username/team)' 94 | 95 | Before a left paren [**@username/team**](https://github.com/username/team)( 96 | 97 | Before a right paren [**@username/team**](https://github.com/username/team)) 98 | 99 | Before an asterisk [**@username/team**](https://github.com/username/team)\* 100 | 101 | Before a plus sign [**@username/team**](https://github.com/username/team)+ 102 | 103 | Before a comma [**@username/team**](https://github.com/username/team), 104 | 105 | Before a dash [**@username/team-**](https://github.com/username/team-) 106 | 107 | Before a dot [**@username/team**](https://github.com/username/team). 108 | 109 | Before a slash @username/team/ 110 | 111 | Before a digit [**@username/team0**](https://github.com/username/team0) 112 | 113 | Before a colon [**@username/team**](https://github.com/username/team): 114 | 115 | Before a semicolon [**@username/team**](https://github.com/username/team); 116 | 117 | Before a less than [**@username/team**](https://github.com/username/team)< 118 | 119 | Before an equals to [**@username/team**](https://github.com/username/team)= 120 | 121 | Before a greater than [**@username/team**](https://github.com/username/team)> 122 | 123 | Before a question mark [**@username/team**](https://github.com/username/team)? 124 | 125 | Before an at sign [**@username/team**](https://github.com/username/team)@ 126 | 127 | Before an upper case [**@username/teamA**](https://github.com/username/teamA) 128 | 129 | Before a left square bracket [**@username/team**](https://github.com/username/team)\[ 130 | 131 | Before a backslash [**@username/team**](https://github.com/username/team)\\ 132 | 133 | Before a right square bracket [**@username/team**](https://github.com/username/team)] 134 | 135 | Before a caret [**@username/team**](https://github.com/username/team)^ 136 | 137 | Before an underscore @username/team\_ 138 | 139 | Before a grave accent @username/team\` 140 | 141 | Before a lower case [**@username/teama**](https://github.com/username/teama) 142 | 143 | Before a left curly brace [**@username/team**](https://github.com/username/team){ 144 | 145 | Before a pipe [**@username/team**](https://github.com/username/team)| 146 | 147 | Before a right curly bracket [**@username/team**](https://github.com/username/team)} 148 | 149 | Before a tilde [**@username/team**](https://github.com/username/team)\~ 150 | -------------------------------------------------------------------------------- /test/fixtures/mention-user-reloaded/input.md: -------------------------------------------------------------------------------- 1 | # Mention. 2 | 3 | ## After 4 | 5 | After a space @username. 6 | 7 | After an exclamation !@username. 8 | 9 | After a quote "@username. 10 | 11 | After a number sign #@username. 12 | 13 | After a dollar sign $@username. 14 | 15 | After a percentage sign %@username. 16 | 17 | After an ampersand &@username. 18 | 19 | After an apostrophe '@username. 20 | 21 | After a left paren (@username. 22 | 23 | After a right paren )@username. 24 | 25 | After an asterisk *@username. 26 | 27 | After a plus sign +@username. 28 | 29 | After a comma ,@username. 30 | 31 | After a dash -@username. 32 | 33 | After a dot .@username. 34 | 35 | After a slash /@username. 36 | 37 | After a digit 0@username. 38 | 39 | After a colon :@username. 40 | 41 | After a semicolon ;@username. 42 | 43 | After a less than <@username. 44 | 45 | After an equals to =@username. 46 | 47 | After a greater than >@username. 48 | 49 | After a question mark ?@username. 50 | 51 | After an at sign @@username. 52 | 53 | After an upper case A@username. 54 | 55 | After a left square bracket [@username. 56 | 57 | After a backslash \@username. 58 | 59 | After a right square bracket ]@username. 60 | 61 | After a caret ^@username. 62 | 63 | After an underscore _@username. 64 | 65 | After a grave accent `@username. 66 | 67 | After a lower case a@username. 68 | 69 | After a left curly brace {@username. 70 | 71 | After a pipe |@username. 72 | 73 | After a right curly bracket }@username. 74 | 75 | After a tilde ~@username. 76 | 77 | ## Before 78 | 79 | Before a space @username . 80 | 81 | Before an exclamation @username! 82 | 83 | Before a quote @username" 84 | 85 | Before a number sign @username# 86 | 87 | Before a dollar sign @username$ 88 | 89 | Before a percentage sign @username% 90 | 91 | Before an ampersand @username& 92 | 93 | Before an apostrophe @username' 94 | 95 | Before a left paren @username( 96 | 97 | Before a right paren @username) 98 | 99 | Before an asterisk @username* 100 | 101 | Before a plus sign @username+ 102 | 103 | Before a comma @username, 104 | 105 | Before a dash @username- 106 | 107 | Before a dot @username. 108 | 109 | Before a slash @username/ 110 | 111 | Before a digit @username0 112 | 113 | Before a colon @username: 114 | 115 | Before a semicolon @username; 116 | 117 | Before a less than @username< 118 | 119 | Before an equals to @username= 120 | 121 | Before a greater than @username> 122 | 123 | Before a question mark @username? 124 | 125 | Before an at sign @username@ 126 | 127 | Before an upper case @usernameA 128 | 129 | Before a left square bracket @username[ 130 | 131 | Before a backslash @username\ 132 | 133 | Before a right square bracket @username] 134 | 135 | Before a caret @username^ 136 | 137 | Before an underscore @username_ 138 | 139 | Before a grave accent @username` 140 | 141 | Before a lower case @usernamea 142 | 143 | Before a left curly brace @username{ 144 | 145 | Before a pipe @username| 146 | 147 | Before a right curly bracket @username} 148 | 149 | Before a tilde @username~ 150 | -------------------------------------------------------------------------------- /test/fixtures/mention-user-reloaded/output.md: -------------------------------------------------------------------------------- 1 | # Mention. 2 | 3 | ## After 4 | 5 | After a space [**@username**](https://github.com/username). 6 | 7 | After an exclamation \![**@username**](https://github.com/username). 8 | 9 | After a quote "[**@username**](https://github.com/username). 10 | 11 | After a number sign #[**@username**](https://github.com/username). 12 | 13 | After a dollar sign $[**@username**](https://github.com/username). 14 | 15 | After a percentage sign %[**@username**](https://github.com/username). 16 | 17 | After an ampersand &[**@username**](https://github.com/username). 18 | 19 | After an apostrophe '[**@username**](https://github.com/username). 20 | 21 | After a left paren ([**@username**](https://github.com/username). 22 | 23 | After a right paren )[**@username**](https://github.com/username). 24 | 25 | After an asterisk \*[**@username**](https://github.com/username). 26 | 27 | After a plus sign +[**@username**](https://github.com/username). 28 | 29 | After a comma ,[**@username**](https://github.com/username). 30 | 31 | After a dash -[**@username**](https://github.com/username). 32 | 33 | After a dot .[**@username**](https://github.com/username). 34 | 35 | After a slash /[**@username**](https://github.com/username). 36 | 37 | After a digit 0\@username. 38 | 39 | After a colon :[**@username**](https://github.com/username). 40 | 41 | After a semicolon ;[**@username**](https://github.com/username). 42 | 43 | After a less than <[**@username**](https://github.com/username). 44 | 45 | After an equals to =[**@username**](https://github.com/username). 46 | 47 | After a greater than >[**@username**](https://github.com/username). 48 | 49 | After a question mark ?[**@username**](https://github.com/username). 50 | 51 | After an at sign @[**@username**](https://github.com/username). 52 | 53 | After an upper case A\@username. 54 | 55 | After a left square bracket \[[**@username**](https://github.com/username). 56 | 57 | After a backslash [**@username**](https://github.com/username). 58 | 59 | After a right square bracket ][**@username**](https://github.com/username). 60 | 61 | After a caret ^[**@username**](https://github.com/username). 62 | 63 | After an underscore \_@username. 64 | 65 | After a grave accent \`@username. 66 | 67 | After a lower case a\@username. 68 | 69 | After a left curly brace {[**@username**](https://github.com/username). 70 | 71 | After a pipe |[**@username**](https://github.com/username). 72 | 73 | After a right curly bracket }[**@username**](https://github.com/username). 74 | 75 | After a tilde \~[**@username**](https://github.com/username). 76 | 77 | ## Before 78 | 79 | Before a space [**@username**](https://github.com/username) . 80 | 81 | Before an exclamation [**@username**](https://github.com/username)! 82 | 83 | Before a quote [**@username**](https://github.com/username)" 84 | 85 | Before a number sign [**@username**](https://github.com/username)# 86 | 87 | Before a dollar sign [**@username**](https://github.com/username)$ 88 | 89 | Before a percentage sign [**@username**](https://github.com/username)% 90 | 91 | Before an ampersand [**@username**](https://github.com/username)& 92 | 93 | Before an apostrophe [**@username**](https://github.com/username)' 94 | 95 | Before a left paren [**@username**](https://github.com/username)( 96 | 97 | Before a right paren [**@username**](https://github.com/username)) 98 | 99 | Before an asterisk [**@username**](https://github.com/username)\* 100 | 101 | Before a plus sign [**@username**](https://github.com/username)+ 102 | 103 | Before a comma [**@username**](https://github.com/username), 104 | 105 | Before a dash [**@username-**](https://github.com/username-) 106 | 107 | Before a dot [**@username**](https://github.com/username). 108 | 109 | Before a slash @username/ 110 | 111 | Before a digit [**@username0**](https://github.com/username0) 112 | 113 | Before a colon [**@username**](https://github.com/username): 114 | 115 | Before a semicolon [**@username**](https://github.com/username); 116 | 117 | Before a less than [**@username**](https://github.com/username)< 118 | 119 | Before an equals to [**@username**](https://github.com/username)= 120 | 121 | Before a greater than [**@username**](https://github.com/username)> 122 | 123 | Before a question mark [**@username**](https://github.com/username)? 124 | 125 | Before an at sign [**@username**](https://github.com/username)@ 126 | 127 | Before an upper case [**@usernameA**](https://github.com/usernameA) 128 | 129 | Before a left square bracket [**@username**](https://github.com/username)\[ 130 | 131 | Before a backslash [**@username**](https://github.com/username)\\ 132 | 133 | Before a right square bracket [**@username**](https://github.com/username)] 134 | 135 | Before a caret [**@username**](https://github.com/username)^ 136 | 137 | Before an underscore @username\_ 138 | 139 | Before a grave accent @username\` 140 | 141 | Before a lower case [**@usernamea**](https://github.com/usernamea) 142 | 143 | Before a left curly brace [**@username**](https://github.com/username){ 144 | 145 | Before a pipe [**@username**](https://github.com/username)| 146 | 147 | Before a right curly bracket [**@username**](https://github.com/username)} 148 | 149 | Before a tilde [**@username**](https://github.com/username)\~ 150 | -------------------------------------------------------------------------------- /test/fixtures/mention/input.md: -------------------------------------------------------------------------------- 1 | # Mention 2 | 3 | A mention links to a user, organisation, or team. 4 | 5 | For example, @user, @organization, or @organization/team-name. 6 | 7 | GitHub ignores @mention and @mentions. 8 | 9 | Some valid real world examples: @a, @github, @github/security, @dependabot[bot]. 10 | 11 | But this is invalid: @-w. 12 | 13 | This is valid: @w-w. 14 | 15 | This used to be valid: @w- 16 | -------------------------------------------------------------------------------- /test/fixtures/mention/output.md: -------------------------------------------------------------------------------- 1 | # Mention 2 | 3 | A mention links to a user, organisation, or team. 4 | 5 | For example, [**@user**](https://github.com/user), [**@organization**](https://github.com/organization), or [**@organization/team-name**](https://github.com/organization/team-name). 6 | 7 | GitHub ignores @mention and @mentions. 8 | 9 | Some valid real world examples: [**@a**](https://github.com/a), [**@github**](https://github.com/github), [**@github/security**](https://github.com/github/security), [**@dependabot**](https://github.com/dependabot)\[bot]. 10 | 11 | But this is invalid: @-w. 12 | 13 | This is valid: [**@w-w**](https://github.com/w-w). 14 | 15 | This used to be valid: [**@w-**](https://github.com/w-) 16 | -------------------------------------------------------------------------------- /test/fixtures/reference-advanced/input.md: -------------------------------------------------------------------------------- 1 | # User@SHA 2 | 3 | Multiple slashes: foo/bar/baz@0000000, foo/bar/baz#1, @foo/bar/baz. 4 | 5 | Dashes around slashes: foobar-/baz@0000000, foobar-/baz#1. 6 | 7 | Upper-case projects: foobar/bAz@0000000, foobar/Baz#1. 8 | 9 | @foo-/bar, @foo/-bar. 10 | 11 | f/b#1. f/b#0. f/b@0000000. 12 | 13 | .#1. .@0000000. foo#. bar@. 14 | -------------------------------------------------------------------------------- /test/fixtures/reference-advanced/output.md: -------------------------------------------------------------------------------- 1 | # User\@SHA 2 | 3 | Multiple slashes: foo/bar/baz@[`0000000`](https://github.com/wooorm/remark/commit/0000000), foo/bar/baz#1, @foo/bar/baz. 4 | 5 | Dashes around slashes: [foobar-/baz@`0000000`](https://github.com/foobar-/baz/commit/0000000), [foobar-/baz#1](https://github.com/foobar-/baz/issues/1). 6 | 7 | Upper-case projects: [foobar/bAz@`0000000`](https://github.com/foobar/bAz/commit/0000000), [foobar/Baz#1](https://github.com/foobar/Baz/issues/1). 8 | 9 | [**@foo-/bar**](https://github.com/foo-/bar), @foo/-bar. 10 | 11 | [f/b#1](https://github.com/f/b/issues/1). f/b#0. [f/b@`0000000`](https://github.com/f/b/commit/0000000). 12 | 13 | .[#1](https://github.com/wooorm/remark/issues/1). .[**@0000000**](https://github.com/0000000). foo#. bar\@. 14 | -------------------------------------------------------------------------------- /test/fixtures/sha-project/input.md: -------------------------------------------------------------------------------- 1 | # Project@SHA 2 | 3 | A project-SHA is not relative to the current project. 4 | 5 | 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). 6 | 7 | * foo/bar@000000; 8 | * foo/bar@0000000; 9 | * foo/bar@00000000; 10 | * foo/bar@000000000; 11 | * foo/bar@0000000000; 12 | * foo/bar@00000000000; 13 | * foo/bar@000000000000; 14 | * foo/bar@0000000000000; 15 | * foo/bar@00000000000000; 16 | * foo/bar@000000000000000; 17 | * foo/bar@0000000000000000; 18 | * foo/bar@00000000000000000; 19 | * foo/bar@000000000000000000; 20 | * foo/bar@0000000000000000000; 21 | * foo/bar@00000000000000000000; 22 | * foo/bar@000000000000000000000; 23 | * foo/bar@0000000000000000000000; 24 | * foo/bar@00000000000000000000000; 25 | * foo/bar@000000000000000000000000; 26 | * foo/bar@0000000000000000000000000; 27 | * foo/bar@00000000000000000000000000; 28 | * foo/bar@000000000000000000000000000; 29 | * foo/bar@0000000000000000000000000000; 30 | * foo/bar@00000000000000000000000000000; 31 | * foo/bar@000000000000000000000000000000; 32 | * foo/bar@0000000000000000000000000000000; 33 | * foo/bar@00000000000000000000000000000000; 34 | * foo/bar@000000000000000000000000000000000; 35 | * foo/bar@0000000000000000000000000000000000; 36 | * foo/bar@00000000000000000000000000000000000; 37 | * foo/bar@00000000000000000000000000000000000; 38 | * foo/bar@000000000000000000000000000000000000; 39 | * foo/bar@0000000000000000000000000000000000000; 40 | * foo/bar@00000000000000000000000000000000000000; 41 | * foo/bar@000000000000000000000000000000000000000; 42 | * foo/bar@0000000000000000000000000000000000000000; 43 | * foo/bar@00000000000000000000000000000000000000000. 44 | 45 | And: 46 | 47 | * Prefix foo/bar@0000000 suffix; 48 | * Prefix foo/bar@0000000!; 49 | * a foo/bar@0000000!; 50 | 51 | And what about here 52 | foo/bar@0000000 53 | 54 | Or here 55 | foo/bar@0000000 56 | 57 | And these SHAs which could also be words? foo/bar@deedeed, and foo/bar@fabaceae. 58 | 59 | Usernames: this is not a valid, -foo/bar@0000000; but this is w-w/bar@0000000, and so is w/bar@0000000 and ww/bar@0000000. 60 | 61 | This used to be valid: foo-/bar@0000000. 62 | 63 | Project names: this is not a valid, foo/c.git@0000000; but this is foo/c@0000000, so is w/w@0000000, and ww/.gitconfig@0000000. 64 | -------------------------------------------------------------------------------- /test/fixtures/sha-project/output.md: -------------------------------------------------------------------------------- 1 | # Project\@SHA 2 | 3 | A project-SHA is not relative to the current project. 4 | 5 | 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). 6 | 7 | * foo/bar\@000000; 8 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/0000000); 9 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/00000000); 10 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/000000000); 11 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/0000000000); 12 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/00000000000); 13 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/000000000000); 14 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/0000000000000); 15 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/00000000000000); 16 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/000000000000000); 17 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/0000000000000000); 18 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/00000000000000000); 19 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/000000000000000000); 20 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/0000000000000000000); 21 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/00000000000000000000); 22 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/000000000000000000000); 23 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/0000000000000000000000); 24 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/00000000000000000000000); 25 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/000000000000000000000000); 26 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/0000000000000000000000000); 27 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/00000000000000000000000000); 28 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/000000000000000000000000000); 29 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/0000000000000000000000000000); 30 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/00000000000000000000000000000); 31 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/000000000000000000000000000000); 32 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/0000000000000000000000000000000); 33 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/00000000000000000000000000000000); 34 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/000000000000000000000000000000000); 35 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/0000000000000000000000000000000000); 36 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/00000000000000000000000000000000000); 37 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/00000000000000000000000000000000000); 38 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/000000000000000000000000000000000000); 39 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/0000000000000000000000000000000000000); 40 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/00000000000000000000000000000000000000); 41 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/000000000000000000000000000000000000000); 42 | * [foo/bar@`0000000`](https://github.com/foo/bar/commit/0000000000000000000000000000000000000000); 43 | * foo/bar\@00000000000000000000000000000000000000000. 44 | 45 | And: 46 | 47 | * Prefix [foo/bar@`0000000`](https://github.com/foo/bar/commit/0000000) suffix; 48 | * Prefix [foo/bar@`0000000`](https://github.com/foo/bar/commit/0000000)!; 49 | * a [foo/bar@`0000000`](https://github.com/foo/bar/commit/0000000)!; 50 | 51 | And what about here 52 | [foo/bar@`0000000`](https://github.com/foo/bar/commit/0000000) 53 | 54 | Or here 55 | [foo/bar@`0000000`](https://github.com/foo/bar/commit/0000000) 56 | 57 | And these SHAs which could also be words? [foo/bar@`deedeed`](https://github.com/foo/bar/commit/deedeed), and [foo/bar@`fabacea`](https://github.com/foo/bar/commit/fabaceae). 58 | 59 | Usernames: this is not a valid, -foo/bar@[`0000000`](https://github.com/wooorm/remark/commit/0000000); but this is [w-w/bar@`0000000`](https://github.com/w-w/bar/commit/0000000), and so is [w/bar@`0000000`](https://github.com/w/bar/commit/0000000) and [ww/bar@`0000000`](https://github.com/ww/bar/commit/0000000). 60 | 61 | This used to be valid: [foo-/bar@`0000000`](https://github.com/foo-/bar/commit/0000000). 62 | 63 | Project names: this is not a valid, foo/c.git@[`0000000`](https://github.com/wooorm/remark/commit/0000000); but this is [foo/c@`0000000`](https://github.com/foo/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). 64 | -------------------------------------------------------------------------------- /test/fixtures/sha-range/input.md: -------------------------------------------------------------------------------- 1 | range comparison: e2acebc...2aa9311 2 | 3 | actual unicode ellipsis: e2acebc…2aa9311 4 | 5 | punctuation before: -e2acebc...2aa9311 6 | 7 | e2acebc...2aa9311.punctuation after 8 | 9 | two: e2acebc..2aa9311 10 | 11 | one: e2acebc.2aa9311 12 | 13 | fork? other@e2acebc...2aa9311 14 | 15 | repo: name/project@e2acebc...2aa9311 16 | 17 | 5/5: e2ace...2aa93 18 | 19 | 7/5: e2acebc...2aa93 20 | 21 | 5/7: e2ace...2aa9311 22 | 23 | lonely a e2acebc... 24 | 25 | lonely b ...2aa9311 26 | 27 | Full links: 28 | 29 | Other project: https://github.com/wooorm/remark-toc/compare/e2ac...2aa9 30 | 31 | Fork: https://github.com/other/remark/compare/e2ac...2aa9 32 | 33 | 4/4: https://github.com/wooorm/remark/compare/e2ac...2aa9 34 | 35 | 4/40: https://github.com/wooorm/remark/compare/e2ac...2aa931154d6e0f6317aff644924163999cb61894 36 | 37 | 40/4: https://github.com/wooorm/remark/compare/e2acebcb40ae1bbe5b3ed87488f294faa45b2b85...2aa9 38 | 39 | 40/40: https://github.com/wooorm/remark/compare/e2acebcb40ae1bbe5b3ed87488f294faa45b2b85...2aa931154d6e0f6317aff644924163999cb61894 40 | 41 | Dots 5: 42 | 43 | 2aa93 44 | 45 | .2aa93 46 | 47 | ..2aa93 48 | 49 | ...2aa93 50 | 51 | Dots 7: 52 | 53 | e2acebc 54 | 55 | .e2acebc 56 | 57 | ..e2acebc 58 | 59 | ...e2acebc 60 | -------------------------------------------------------------------------------- /test/fixtures/sha-range/output.md: -------------------------------------------------------------------------------- 1 | range comparison: [`e2acebc...2aa9311`](https://github.com/wooorm/remark/compare/e2acebc...2aa9311) 2 | 3 | actual unicode ellipsis: [`e2acebc`](https://github.com/wooorm/remark/commit/e2acebc)…2aa9311 4 | 5 | punctuation before: -e2acebc...[`2aa9311`](https://github.com/wooorm/remark/commit/2aa9311) 6 | 7 | [`e2acebc...2aa9311`](https://github.com/wooorm/remark/compare/e2acebc...2aa9311).punctuation after 8 | 9 | two: [`e2acebc`](https://github.com/wooorm/remark/commit/e2acebc)..[`2aa9311`](https://github.com/wooorm/remark/commit/2aa9311) 10 | 11 | one: [`e2acebc`](https://github.com/wooorm/remark/commit/e2acebc).2aa9311 12 | 13 | fork? [other@`e2acebc`](https://github.com/other/remark/commit/e2acebc)...[`2aa9311`](https://github.com/wooorm/remark/commit/2aa9311) 14 | 15 | repo: [name/project@`e2acebc`](https://github.com/name/project/commit/e2acebc)...[`2aa9311`](https://github.com/wooorm/remark/commit/2aa9311) 16 | 17 | 5/5: e2ace...2aa93 18 | 19 | 7/5: [`e2acebc`](https://github.com/wooorm/remark/commit/e2acebc)...2aa93 20 | 21 | 5/7: e2ace...[`2aa9311`](https://github.com/wooorm/remark/commit/2aa9311) 22 | 23 | lonely a [`e2acebc`](https://github.com/wooorm/remark/commit/e2acebc)... 24 | 25 | lonely b ...[`2aa9311`](https://github.com/wooorm/remark/commit/2aa9311) 26 | 27 | Full links: 28 | 29 | Other project: [wooorm/remark-toc@`e2ac...2aa9`](https://github.com/wooorm/remark-toc/compare/e2ac...2aa9) 30 | 31 | Fork: [other/remark@`e2ac...2aa9`](https://github.com/other/remark/compare/e2ac...2aa9) 32 | 33 | 4/4: [`e2ac...2aa9`](https://github.com/wooorm/remark/compare/e2ac...2aa9) 34 | 35 | 4/40: [`e2ac...2aa9311`](https://github.com/wooorm/remark/compare/e2ac...2aa931154d6e0f6317aff644924163999cb61894) 36 | 37 | 40/4: [`e2acebc...2aa9`](https://github.com/wooorm/remark/compare/e2acebcb40ae1bbe5b3ed87488f294faa45b2b85...2aa9) 38 | 39 | 40/40: [`e2acebc...2aa9311`](https://github.com/wooorm/remark/compare/e2acebcb40ae1bbe5b3ed87488f294faa45b2b85...2aa931154d6e0f6317aff644924163999cb61894) 40 | 41 | Dots 5: 42 | 43 | 2aa93 44 | 45 | .2aa93 46 | 47 | ..2aa93 48 | 49 | ...2aa93 50 | 51 | Dots 7: 52 | 53 | [`e2acebc`](https://github.com/wooorm/remark/commit/e2acebc) 54 | 55 | .e2acebc 56 | 57 | ..[`e2acebc`](https://github.com/wooorm/remark/commit/e2acebc) 58 | 59 | ...[`e2acebc`](https://github.com/wooorm/remark/commit/e2acebc) 60 | -------------------------------------------------------------------------------- /test/fixtures/sha-reloaded/input.md: -------------------------------------------------------------------------------- 1 | # SHA 2 | 3 | ## After 4 | 5 | After a space 0000000. 6 | 7 | After an exclamation !0000000. 8 | 9 | After a quote "0000000. 10 | 11 | After a number sign #0000000. 12 | 13 | After a dollar sign $0000000. 14 | 15 | After a percentage sign %0000000. 16 | 17 | After an ampersand &0000000. 18 | 19 | After an apostrophe '0000000. 20 | 21 | After a left paren (0000000. 22 | 23 | After a right paren )0000000. 24 | 25 | After an asterisk *0000000. 26 | 27 | After a plus sign +0000000. 28 | 29 | After a comma ,0000000. 30 | 31 | After a dash -0000000. 32 | 33 | After a dot .0000000. 34 | 35 | After a slash /0000000. 36 | 37 | After a digit 00000000. 38 | 39 | After a colon :0000000. 40 | 41 | After a semicolon ;0000000. 42 | 43 | After a less than <0000000. 44 | 45 | After an equals to =0000000. 46 | 47 | After a greater than >0000000. 48 | 49 | After a question mark ?0000000. 50 | 51 | After an at sign @0000000. 52 | 53 | After an upper case A0000000. 54 | 55 | After a left square bracket [0000000. 56 | 57 | After a backslash \0000000. 58 | 59 | After a right square bracket ]0000000. 60 | 61 | After a caret ^0000000. 62 | 63 | After an underscore _0000000. 64 | 65 | After a grave accent `0000000. 66 | 67 | After a lower case a0000000. 68 | 69 | After a left curly brace {0000000. 70 | 71 | After a pipe |0000000. 72 | 73 | After a right curly bracket }0000000. 74 | 75 | After a tilde ~0000000. 76 | 77 | ## Before 78 | 79 | Before a space 0000000 . 80 | 81 | Before an exclamation 0000000! 82 | 83 | Before a quote 0000000" 84 | 85 | Before a number sign 0000000# 86 | 87 | Before a dollar sign 0000000$ 88 | 89 | Before a percentage sign 0000000% 90 | 91 | Before an ampersand 0000000& 92 | 93 | Before an apostrophe 0000000' 94 | 95 | Before a left paren 0000000( 96 | 97 | Before a right paren 0000000) 98 | 99 | Before an asterisk 0000000* 100 | 101 | Before a plus sign 0000000+ 102 | 103 | Before a comma 0000000, 104 | 105 | Before a dash 0000000- 106 | 107 | Before a dot 0000000. 108 | 109 | Before a slash 0000000/ 110 | 111 | Before a digit 00000000 112 | 113 | Before a colon 0000000: 114 | 115 | Before a semicolon 0000000; 116 | 117 | Before a less than 0000000< 118 | 119 | Before an equals to 0000000= 120 | 121 | Before a greater than 0000000> 122 | 123 | Before a question mark 0000000? 124 | 125 | Before an at sign 0000000@ 126 | 127 | Before an upper case 0000000A 128 | 129 | Before a left square bracket 0000000[ 130 | 131 | Before a backslash 0000000\ 132 | 133 | Before a right square bracket 0000000] 134 | 135 | Before a caret 0000000^ 136 | 137 | Before an underscore 0000000_ 138 | 139 | Before a grave accent 0000000` 140 | 141 | Before a lower case 0000000a 142 | 143 | Before a left curly brace 0000000{ 144 | 145 | Before a pipe 0000000| 146 | 147 | Before a right curly bracket 0000000} 148 | 149 | Before a tilde 0000000~ 150 | -------------------------------------------------------------------------------- /test/fixtures/sha-reloaded/output.md: -------------------------------------------------------------------------------- 1 | # SHA 2 | 3 | ## After 4 | 5 | After a space [`0000000`](https://github.com/wooorm/remark/commit/0000000). 6 | 7 | After an exclamation !0000000. 8 | 9 | After a quote "0000000. 10 | 11 | After a number sign #0000000. 12 | 13 | After a dollar sign $0000000. 14 | 15 | After a percentage sign %0000000. 16 | 17 | After an ampersand &0000000. 18 | 19 | After an apostrophe '0000000. 20 | 21 | After a left paren ([`0000000`](https://github.com/wooorm/remark/commit/0000000). 22 | 23 | After a right paren )0000000. 24 | 25 | After an asterisk \*0000000. 26 | 27 | After a plus sign +0000000. 28 | 29 | After a comma ,0000000. 30 | 31 | After a dash -0000000. 32 | 33 | After a dot .0000000. 34 | 35 | After a slash /0000000. 36 | 37 | After a digit [`0000000`](https://github.com/wooorm/remark/commit/00000000). 38 | 39 | After a colon :0000000. 40 | 41 | After a semicolon ;0000000. 42 | 43 | After a less than <0000000. 44 | 45 | After an equals to =0000000. 46 | 47 | After a greater than >0000000. 48 | 49 | After a question mark ?0000000. 50 | 51 | After an at sign [**@0000000**](https://github.com/0000000). 52 | 53 | After an upper case [`A000000`](https://github.com/wooorm/remark/commit/A0000000). 54 | 55 | After a left square bracket \[[`0000000`](https://github.com/wooorm/remark/commit/0000000). 56 | 57 | After a backslash \0000000. 58 | 59 | After a right square bracket ]0000000. 60 | 61 | After a caret ^0000000. 62 | 63 | After an underscore \_0000000. 64 | 65 | After a grave accent \`0000000. 66 | 67 | After a lower case [`a000000`](https://github.com/wooorm/remark/commit/a0000000). 68 | 69 | After a left curly brace {[`0000000`](https://github.com/wooorm/remark/commit/0000000). 70 | 71 | After a pipe |0000000. 72 | 73 | After a right curly bracket }0000000. 74 | 75 | After a tilde \~0000000. 76 | 77 | ## Before 78 | 79 | Before a space [`0000000`](https://github.com/wooorm/remark/commit/0000000) . 80 | 81 | Before an exclamation [`0000000`](https://github.com/wooorm/remark/commit/0000000)! 82 | 83 | Before a quote [`0000000`](https://github.com/wooorm/remark/commit/0000000)" 84 | 85 | Before a number sign [`0000000`](https://github.com/wooorm/remark/commit/0000000)# 86 | 87 | Before a dollar sign [`0000000`](https://github.com/wooorm/remark/commit/0000000)$ 88 | 89 | Before a percentage sign [`0000000`](https://github.com/wooorm/remark/commit/0000000)% 90 | 91 | Before an ampersand [`0000000`](https://github.com/wooorm/remark/commit/0000000)& 92 | 93 | Before an apostrophe [`0000000`](https://github.com/wooorm/remark/commit/0000000)' 94 | 95 | Before a left paren [`0000000`](https://github.com/wooorm/remark/commit/0000000)( 96 | 97 | Before a right paren [`0000000`](https://github.com/wooorm/remark/commit/0000000)) 98 | 99 | Before an asterisk [`0000000`](https://github.com/wooorm/remark/commit/0000000)\* 100 | 101 | Before a plus sign [`0000000`](https://github.com/wooorm/remark/commit/0000000)+ 102 | 103 | Before a comma [`0000000`](https://github.com/wooorm/remark/commit/0000000), 104 | 105 | Before a dash [`0000000`](https://github.com/wooorm/remark/commit/0000000)- 106 | 107 | Before a dot [`0000000`](https://github.com/wooorm/remark/commit/0000000). 108 | 109 | Before a slash [`0000000`](https://github.com/wooorm/remark/commit/0000000)/ 110 | 111 | Before a digit [`0000000`](https://github.com/wooorm/remark/commit/00000000) 112 | 113 | Before a colon [`0000000`](https://github.com/wooorm/remark/commit/0000000): 114 | 115 | Before a semicolon [`0000000`](https://github.com/wooorm/remark/commit/0000000); 116 | 117 | Before a less than [`0000000`](https://github.com/wooorm/remark/commit/0000000)< 118 | 119 | Before an equals to [`0000000`](https://github.com/wooorm/remark/commit/0000000)= 120 | 121 | Before a greater than [`0000000`](https://github.com/wooorm/remark/commit/0000000)> 122 | 123 | Before a question mark [`0000000`](https://github.com/wooorm/remark/commit/0000000)? 124 | 125 | Before an at sign [`0000000`](https://github.com/wooorm/remark/commit/0000000)@ 126 | 127 | Before an upper case [`0000000`](https://github.com/wooorm/remark/commit/0000000A) 128 | 129 | Before a left square bracket [`0000000`](https://github.com/wooorm/remark/commit/0000000)\[ 130 | 131 | Before a backslash [`0000000`](https://github.com/wooorm/remark/commit/0000000)\\ 132 | 133 | Before a right square bracket [`0000000`](https://github.com/wooorm/remark/commit/0000000)] 134 | 135 | Before a caret [`0000000`](https://github.com/wooorm/remark/commit/0000000)^ 136 | 137 | Before an underscore 0000000\_ 138 | 139 | Before a grave accent [`0000000`](https://github.com/wooorm/remark/commit/0000000)\` 140 | 141 | Before a lower case [`0000000`](https://github.com/wooorm/remark/commit/0000000a) 142 | 143 | Before a left curly brace [`0000000`](https://github.com/wooorm/remark/commit/0000000){ 144 | 145 | Before a pipe [`0000000`](https://github.com/wooorm/remark/commit/0000000)| 146 | 147 | Before a right curly bracket [`0000000`](https://github.com/wooorm/remark/commit/0000000)} 148 | 149 | Before a tilde [`0000000`](https://github.com/wooorm/remark/commit/0000000)\~ 150 | -------------------------------------------------------------------------------- /test/fixtures/sha-user-reloaded/input.md: -------------------------------------------------------------------------------- 1 | # SHA user 2 | 3 | ## After 4 | 5 | After a space username@0000000. 6 | 7 | After an exclamation !username@0000000. 8 | 9 | After a quote "username@0000000. 10 | 11 | After a number sign #username@0000000. 12 | 13 | After a dollar sign $username@0000000. 14 | 15 | After a percentage sign %username@0000000. 16 | 17 | After an ampersand &username@0000000. 18 | 19 | After an apostrophe 'username@0000000. 20 | 21 | After a left paren (username@0000000. 22 | 23 | After a right paren )username@0000000. 24 | 25 | After an asterisk *username@0000000. 26 | 27 | After a plus sign +username@0000000. 28 | 29 | After a comma ,username@0000000. 30 | 31 | After a dash -username@0000000. 32 | 33 | After a dot .username@0000000. 34 | 35 | After a slash /username@0000000. 36 | 37 | After a digit 0username@0000000. 38 | 39 | After a colon :username@0000000. 40 | 41 | After a semicolon ;username@0000000. 42 | 43 | After a less than username@0000000. 48 | 49 | After a question mark ?username@0000000. 50 | 51 | After an at sign @username@0000000. 52 | 53 | After an upper case Ausername@0000000. 54 | 55 | After a left square bracket [username@0000000. 56 | 57 | After a backslash \username@0000000. 58 | 59 | After a right square bracket ]username@0000000. 60 | 61 | After a caret ^username@0000000. 62 | 63 | After an underscore _username@0000000. 64 | 65 | After a grave accent `username@0000000. 66 | 67 | After a lower case ausername@0000000. 68 | 69 | After a left curly brace {username@0000000. 70 | 71 | After a pipe |username@0000000. 72 | 73 | After a right curly bracket }username@0000000. 74 | 75 | After a tilde ~username@0000000. 76 | 77 | ## Before 78 | 79 | Before a space username@0000000 . 80 | 81 | Before an exclamation username@0000000! 82 | 83 | Before a quote username@0000000" 84 | 85 | Before a number sign username@0000000# 86 | 87 | Before a dollar sign username@0000000$ 88 | 89 | Before a percentage sign username@0000000% 90 | 91 | Before an ampersand username@0000000& 92 | 93 | Before an apostrophe username@0000000' 94 | 95 | Before a left paren username@0000000( 96 | 97 | Before a right paren username@0000000) 98 | 99 | Before an asterisk username@0000000* 100 | 101 | Before a plus sign username@0000000+ 102 | 103 | Before a comma username@0000000, 104 | 105 | Before a dash username@0000000- 106 | 107 | Before a dot username@0000000. 108 | 109 | Before a slash username@0000000/ 110 | 111 | Before a digit username@00000000 112 | 113 | Before a colon username@0000000: 114 | 115 | Before a semicolon username@0000000; 116 | 117 | Before a less than username@0000000< 118 | 119 | Before an equals to username@0000000= 120 | 121 | Before a greater than username@0000000> 122 | 123 | Before a question mark username@0000000? 124 | 125 | Before an at sign username@0000000@ 126 | 127 | Before an upper case username@0000000A 128 | 129 | Before a left square bracket username@0000000[ 130 | 131 | Before a backslash username@0000000\ 132 | 133 | Before a right square bracket username@0000000] 134 | 135 | Before a caret username@0000000^ 136 | 137 | Before an underscore username@0000000_ 138 | 139 | Before a grave accent username@0000000` 140 | 141 | Before a lower case username@0000000a 142 | 143 | Before a left curly brace username@0000000{ 144 | 145 | Before a pipe username@0000000| 146 | 147 | Before a right curly bracket username@0000000} 148 | 149 | Before a tilde username@0000000~ 150 | -------------------------------------------------------------------------------- /test/fixtures/sha-user-reloaded/output.md: -------------------------------------------------------------------------------- 1 | # SHA user 2 | 3 | ## After 4 | 5 | After a space [username@`0000000`](https://github.com/username/remark/commit/0000000). 6 | 7 | After an exclamation !username@[`0000000`](https://github.com/wooorm/remark/commit/0000000). 8 | 9 | After a quote "username@[`0000000`](https://github.com/wooorm/remark/commit/0000000). 10 | 11 | After a number sign #username@[`0000000`](https://github.com/wooorm/remark/commit/0000000). 12 | 13 | After a dollar sign $username@[`0000000`](https://github.com/wooorm/remark/commit/0000000). 14 | 15 | After a percentage sign %username@[`0000000`](https://github.com/wooorm/remark/commit/0000000). 16 | 17 | After an ampersand \&username@[`0000000`](https://github.com/wooorm/remark/commit/0000000). 18 | 19 | After an apostrophe 'username@[`0000000`](https://github.com/wooorm/remark/commit/0000000). 20 | 21 | After a left paren ([username@`0000000`](https://github.com/username/remark/commit/0000000). 22 | 23 | After a right paren )username@[`0000000`](https://github.com/wooorm/remark/commit/0000000). 24 | 25 | After an asterisk \*username@[`0000000`](https://github.com/wooorm/remark/commit/0000000). 26 | 27 | After a plus sign +username@[`0000000`](https://github.com/wooorm/remark/commit/0000000). 28 | 29 | After a comma ,username@[`0000000`](https://github.com/wooorm/remark/commit/0000000). 30 | 31 | After a dash -username@[`0000000`](https://github.com/wooorm/remark/commit/0000000). 32 | 33 | After a dot .username@[`0000000`](https://github.com/wooorm/remark/commit/0000000). 34 | 35 | After a slash /username@[`0000000`](https://github.com/wooorm/remark/commit/0000000). 36 | 37 | After a digit [0username@`0000000`](https://github.com/0username/remark/commit/0000000). 38 | 39 | After a colon :username@[`0000000`](https://github.com/wooorm/remark/commit/0000000). 40 | 41 | After a semicolon ;username@[`0000000`](https://github.com/wooorm/remark/commit/0000000). 42 | 43 | After a less than \username@[`0000000`](https://github.com/wooorm/remark/commit/0000000). 48 | 49 | After a question mark ?username@[`0000000`](https://github.com/wooorm/remark/commit/0000000). 50 | 51 | After an at sign @[username@`0000000`](https://github.com/username/remark/commit/0000000). 52 | 53 | After an upper case [Ausername@`0000000`](https://github.com/Ausername/remark/commit/0000000). 54 | 55 | After a left square bracket \[[username@`0000000`](https://github.com/username/remark/commit/0000000). 56 | 57 | After a backslash \username@[`0000000`](https://github.com/wooorm/remark/commit/0000000). 58 | 59 | After a right square bracket ]username@[`0000000`](https://github.com/wooorm/remark/commit/0000000). 60 | 61 | After a caret ^username@[`0000000`](https://github.com/wooorm/remark/commit/0000000). 62 | 63 | After an underscore \_username@[`0000000`](https://github.com/wooorm/remark/commit/0000000). 64 | 65 | After a grave accent \`username@[`0000000`](https://github.com/wooorm/remark/commit/0000000). 66 | 67 | After a lower case [ausername@`0000000`](https://github.com/ausername/remark/commit/0000000). 68 | 69 | After a left curly brace {[username@`0000000`](https://github.com/username/remark/commit/0000000). 70 | 71 | After a pipe |username@[`0000000`](https://github.com/wooorm/remark/commit/0000000). 72 | 73 | After a right curly bracket }username@[`0000000`](https://github.com/wooorm/remark/commit/0000000). 74 | 75 | After a tilde \~username@[`0000000`](https://github.com/wooorm/remark/commit/0000000). 76 | 77 | ## Before 78 | 79 | Before a space [username@`0000000`](https://github.com/username/remark/commit/0000000) . 80 | 81 | Before an exclamation [username@`0000000`](https://github.com/username/remark/commit/0000000)! 82 | 83 | Before a quote [username@`0000000`](https://github.com/username/remark/commit/0000000)" 84 | 85 | Before a number sign [username@`0000000`](https://github.com/username/remark/commit/0000000)# 86 | 87 | Before a dollar sign [username@`0000000`](https://github.com/username/remark/commit/0000000)$ 88 | 89 | Before a percentage sign [username@`0000000`](https://github.com/username/remark/commit/0000000)% 90 | 91 | Before an ampersand [username@`0000000`](https://github.com/username/remark/commit/0000000)& 92 | 93 | Before an apostrophe [username@`0000000`](https://github.com/username/remark/commit/0000000)' 94 | 95 | Before a left paren [username@`0000000`](https://github.com/username/remark/commit/0000000)( 96 | 97 | Before a right paren [username@`0000000`](https://github.com/username/remark/commit/0000000)) 98 | 99 | Before an asterisk [username@`0000000`](https://github.com/username/remark/commit/0000000)\* 100 | 101 | Before a plus sign [username@`0000000`](https://github.com/username/remark/commit/0000000)+ 102 | 103 | Before a comma [username@`0000000`](https://github.com/username/remark/commit/0000000), 104 | 105 | Before a dash [username@`0000000`](https://github.com/username/remark/commit/0000000)- 106 | 107 | Before a dot [username@`0000000`](https://github.com/username/remark/commit/0000000). 108 | 109 | Before a slash [username@`0000000`](https://github.com/username/remark/commit/0000000)/ 110 | 111 | Before a digit [username@`0000000`](https://github.com/username/remark/commit/00000000) 112 | 113 | Before a colon [username@`0000000`](https://github.com/username/remark/commit/0000000): 114 | 115 | Before a semicolon [username@`0000000`](https://github.com/username/remark/commit/0000000); 116 | 117 | Before a less than [username@`0000000`](https://github.com/username/remark/commit/0000000)< 118 | 119 | Before an equals to [username@`0000000`](https://github.com/username/remark/commit/0000000)= 120 | 121 | Before a greater than [username@`0000000`](https://github.com/username/remark/commit/0000000)> 122 | 123 | Before a question mark [username@`0000000`](https://github.com/username/remark/commit/0000000)? 124 | 125 | Before an at sign [username@`0000000`](https://github.com/username/remark/commit/0000000)@ 126 | 127 | Before an upper case [username@`0000000`](https://github.com/username/remark/commit/0000000A) 128 | 129 | Before a left square bracket [username@`0000000`](https://github.com/username/remark/commit/0000000)\[ 130 | 131 | Before a backslash [username@`0000000`](https://github.com/username/remark/commit/0000000)\\ 132 | 133 | Before a right square bracket [username@`0000000`](https://github.com/username/remark/commit/0000000)] 134 | 135 | Before a caret [username@`0000000`](https://github.com/username/remark/commit/0000000)^ 136 | 137 | Before an underscore username\@0000000\_ 138 | 139 | Before a grave accent [username@`0000000`](https://github.com/username/remark/commit/0000000)\` 140 | 141 | Before a lower case [username@`0000000`](https://github.com/username/remark/commit/0000000a) 142 | 143 | Before a left curly brace [username@`0000000`](https://github.com/username/remark/commit/0000000){ 144 | 145 | Before a pipe [username@`0000000`](https://github.com/username/remark/commit/0000000)| 146 | 147 | Before a right curly bracket [username@`0000000`](https://github.com/username/remark/commit/0000000)} 148 | 149 | Before a tilde [username@`0000000`](https://github.com/username/remark/commit/0000000)\~ 150 | -------------------------------------------------------------------------------- /test/fixtures/sha-user/input.md: -------------------------------------------------------------------------------- 1 | # User@SHA 2 | 3 | A user-SHA is relative to the project, but relative to the user’s fork. 4 | 5 | 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). 6 | 7 | * username@000000; 8 | * username@0000000; 9 | * username@00000000; 10 | * username@000000000; 11 | * username@0000000000; 12 | * username@00000000000; 13 | * username@000000000000; 14 | * username@0000000000000; 15 | * username@00000000000000; 16 | * username@000000000000000; 17 | * username@0000000000000000; 18 | * username@00000000000000000; 19 | * username@000000000000000000; 20 | * username@0000000000000000000; 21 | * username@00000000000000000000; 22 | * username@000000000000000000000; 23 | * username@0000000000000000000000; 24 | * username@00000000000000000000000; 25 | * username@000000000000000000000000; 26 | * username@0000000000000000000000000; 27 | * username@00000000000000000000000000; 28 | * username@000000000000000000000000000; 29 | * username@0000000000000000000000000000; 30 | * username@00000000000000000000000000000; 31 | * username@000000000000000000000000000000; 32 | * username@0000000000000000000000000000000; 33 | * username@00000000000000000000000000000000; 34 | * username@000000000000000000000000000000000; 35 | * username@0000000000000000000000000000000000; 36 | * username@00000000000000000000000000000000000; 37 | * username@00000000000000000000000000000000000; 38 | * username@000000000000000000000000000000000000; 39 | * username@0000000000000000000000000000000000000; 40 | * username@00000000000000000000000000000000000000; 41 | * username@000000000000000000000000000000000000000; 42 | * username@0000000000000000000000000000000000000000; 43 | * username@00000000000000000000000000000000000000000. 44 | 45 | And: 46 | 47 | * Prefix username@0000000 suffix; 48 | * Prefix username@0000000!; 49 | * a username@0000000!; 50 | 51 | And what about here 52 | username@0000000 53 | 54 | Or here 55 | username@0000000 56 | 57 | And these SHAs which could also be words? username@deedeed, and username@fabaceae. 58 | 59 | This is not a valid, -username@0000000; but this is w-w@0000000, and so is w@0000000 and ww@0000000. 60 | 61 | This used to be valid: username-@0000000. 62 | 63 | And here’s an example of a disposable e-mail domain, which starts with 7 hexidecimal characters: username@deadaddress.com, which shouldn’t match, because there’s no word break after the SHA-like part. 64 | 65 | This is too long: wooormwooormwooormwooormwooormwooormwooo#0000000 (40 character username). 66 | -------------------------------------------------------------------------------- /test/fixtures/sha-user/output.md: -------------------------------------------------------------------------------- 1 | # User\@SHA 2 | 3 | A user-SHA is relative to the project, but relative to the user’s fork. 4 | 5 | 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). 6 | 7 | * username\@000000; 8 | * [username@`0000000`](https://github.com/username/remark/commit/0000000); 9 | * [username@`0000000`](https://github.com/username/remark/commit/00000000); 10 | * [username@`0000000`](https://github.com/username/remark/commit/000000000); 11 | * [username@`0000000`](https://github.com/username/remark/commit/0000000000); 12 | * [username@`0000000`](https://github.com/username/remark/commit/00000000000); 13 | * [username@`0000000`](https://github.com/username/remark/commit/000000000000); 14 | * [username@`0000000`](https://github.com/username/remark/commit/0000000000000); 15 | * [username@`0000000`](https://github.com/username/remark/commit/00000000000000); 16 | * [username@`0000000`](https://github.com/username/remark/commit/000000000000000); 17 | * [username@`0000000`](https://github.com/username/remark/commit/0000000000000000); 18 | * [username@`0000000`](https://github.com/username/remark/commit/00000000000000000); 19 | * [username@`0000000`](https://github.com/username/remark/commit/000000000000000000); 20 | * [username@`0000000`](https://github.com/username/remark/commit/0000000000000000000); 21 | * [username@`0000000`](https://github.com/username/remark/commit/00000000000000000000); 22 | * [username@`0000000`](https://github.com/username/remark/commit/000000000000000000000); 23 | * [username@`0000000`](https://github.com/username/remark/commit/0000000000000000000000); 24 | * [username@`0000000`](https://github.com/username/remark/commit/00000000000000000000000); 25 | * [username@`0000000`](https://github.com/username/remark/commit/000000000000000000000000); 26 | * [username@`0000000`](https://github.com/username/remark/commit/0000000000000000000000000); 27 | * [username@`0000000`](https://github.com/username/remark/commit/00000000000000000000000000); 28 | * [username@`0000000`](https://github.com/username/remark/commit/000000000000000000000000000); 29 | * [username@`0000000`](https://github.com/username/remark/commit/0000000000000000000000000000); 30 | * [username@`0000000`](https://github.com/username/remark/commit/00000000000000000000000000000); 31 | * [username@`0000000`](https://github.com/username/remark/commit/000000000000000000000000000000); 32 | * [username@`0000000`](https://github.com/username/remark/commit/0000000000000000000000000000000); 33 | * [username@`0000000`](https://github.com/username/remark/commit/00000000000000000000000000000000); 34 | * [username@`0000000`](https://github.com/username/remark/commit/000000000000000000000000000000000); 35 | * [username@`0000000`](https://github.com/username/remark/commit/0000000000000000000000000000000000); 36 | * [username@`0000000`](https://github.com/username/remark/commit/00000000000000000000000000000000000); 37 | * [username@`0000000`](https://github.com/username/remark/commit/00000000000000000000000000000000000); 38 | * [username@`0000000`](https://github.com/username/remark/commit/000000000000000000000000000000000000); 39 | * [username@`0000000`](https://github.com/username/remark/commit/0000000000000000000000000000000000000); 40 | * [username@`0000000`](https://github.com/username/remark/commit/00000000000000000000000000000000000000); 41 | * [username@`0000000`](https://github.com/username/remark/commit/000000000000000000000000000000000000000); 42 | * [username@`0000000`](https://github.com/username/remark/commit/0000000000000000000000000000000000000000); 43 | * username\@00000000000000000000000000000000000000000. 44 | 45 | And: 46 | 47 | * Prefix [username@`0000000`](https://github.com/username/remark/commit/0000000) suffix; 48 | * Prefix [username@`0000000`](https://github.com/username/remark/commit/0000000)!; 49 | * a [username@`0000000`](https://github.com/username/remark/commit/0000000)!; 50 | 51 | And what about here 52 | [username@`0000000`](https://github.com/username/remark/commit/0000000) 53 | 54 | Or here 55 | [username@`0000000`](https://github.com/username/remark/commit/0000000) 56 | 57 | And these SHAs which could also be words? [username@`deedeed`](https://github.com/username/remark/commit/deedeed), and [username@`fabacea`](https://github.com/username/remark/commit/fabaceae). 58 | 59 | This is not a valid, -username@[`0000000`](https://github.com/wooorm/remark/commit/0000000); but this is [w-w@`0000000`](https://github.com/w-w/remark/commit/0000000), and so is [w@`0000000`](https://github.com/w/remark/commit/0000000) and [ww@`0000000`](https://github.com/ww/remark/commit/0000000). 60 | 61 | This used to be valid: [username-@`0000000`](https://github.com/username-/remark/commit/0000000). 62 | 63 | And here’s an example of a disposable e-mail domain, which starts with 7 hexidecimal characters: , which shouldn’t match, because there’s no word break after the SHA-like part. 64 | 65 | This is too long: wooormwooormwooormwooormwooormwooormwooo#0000000 (40 character username). 66 | -------------------------------------------------------------------------------- /test/fixtures/sha/input.md: -------------------------------------------------------------------------------- 1 | # SHA 2 | 3 | * 000000; 4 | * 0000000; 5 | * 00000000; 6 | * 000000000; 7 | * 0000000000; 8 | * 00000000000; 9 | * 000000000000; 10 | * 0000000000000; 11 | * 00000000000000; 12 | * 000000000000000; 13 | * 0000000000000000; 14 | * 00000000000000000; 15 | * 000000000000000000; 16 | * 0000000000000000000; 17 | * 00000000000000000000; 18 | * 000000000000000000000; 19 | * 0000000000000000000000; 20 | * 00000000000000000000000; 21 | * 000000000000000000000000; 22 | * 0000000000000000000000000; 23 | * 00000000000000000000000000; 24 | * 000000000000000000000000000; 25 | * 0000000000000000000000000000; 26 | * 00000000000000000000000000000; 27 | * 000000000000000000000000000000; 28 | * 0000000000000000000000000000000; 29 | * 00000000000000000000000000000000; 30 | * 000000000000000000000000000000000; 31 | * 0000000000000000000000000000000000; 32 | * 00000000000000000000000000000000000; 33 | * 00000000000000000000000000000000000; 34 | * 000000000000000000000000000000000000; 35 | * 0000000000000000000000000000000000000; 36 | * 00000000000000000000000000000000000000; 37 | * 000000000000000000000000000000000000000; 38 | * 0000000000000000000000000000000000000000; 39 | * 00000000000000000000000000000000000000000 40 | 41 | And: 42 | 43 | * Prefix 0000000 suffix; 44 | * Prefix 0000000!; 45 | * a 0000000!; 46 | 47 | And what about here 48 | 0000000 49 | 50 | Or here 51 | 0000000 52 | 53 | And these SHAs which could also be words? deedeed, and fabaceae. 54 | 55 | 0.00.0.0000000 56 | -------------------------------------------------------------------------------- /test/fixtures/sha/output.md: -------------------------------------------------------------------------------- 1 | # SHA 2 | 3 | * 000000; 4 | * [`0000000`](https://github.com/wooorm/remark/commit/0000000); 5 | * [`0000000`](https://github.com/wooorm/remark/commit/00000000); 6 | * [`0000000`](https://github.com/wooorm/remark/commit/000000000); 7 | * [`0000000`](https://github.com/wooorm/remark/commit/0000000000); 8 | * [`0000000`](https://github.com/wooorm/remark/commit/00000000000); 9 | * [`0000000`](https://github.com/wooorm/remark/commit/000000000000); 10 | * [`0000000`](https://github.com/wooorm/remark/commit/0000000000000); 11 | * [`0000000`](https://github.com/wooorm/remark/commit/00000000000000); 12 | * [`0000000`](https://github.com/wooorm/remark/commit/000000000000000); 13 | * [`0000000`](https://github.com/wooorm/remark/commit/0000000000000000); 14 | * [`0000000`](https://github.com/wooorm/remark/commit/00000000000000000); 15 | * [`0000000`](https://github.com/wooorm/remark/commit/000000000000000000); 16 | * [`0000000`](https://github.com/wooorm/remark/commit/0000000000000000000); 17 | * [`0000000`](https://github.com/wooorm/remark/commit/00000000000000000000); 18 | * [`0000000`](https://github.com/wooorm/remark/commit/000000000000000000000); 19 | * [`0000000`](https://github.com/wooorm/remark/commit/0000000000000000000000); 20 | * [`0000000`](https://github.com/wooorm/remark/commit/00000000000000000000000); 21 | * [`0000000`](https://github.com/wooorm/remark/commit/000000000000000000000000); 22 | * [`0000000`](https://github.com/wooorm/remark/commit/0000000000000000000000000); 23 | * [`0000000`](https://github.com/wooorm/remark/commit/00000000000000000000000000); 24 | * [`0000000`](https://github.com/wooorm/remark/commit/000000000000000000000000000); 25 | * [`0000000`](https://github.com/wooorm/remark/commit/0000000000000000000000000000); 26 | * [`0000000`](https://github.com/wooorm/remark/commit/00000000000000000000000000000); 27 | * [`0000000`](https://github.com/wooorm/remark/commit/000000000000000000000000000000); 28 | * [`0000000`](https://github.com/wooorm/remark/commit/0000000000000000000000000000000); 29 | * [`0000000`](https://github.com/wooorm/remark/commit/00000000000000000000000000000000); 30 | * [`0000000`](https://github.com/wooorm/remark/commit/000000000000000000000000000000000); 31 | * [`0000000`](https://github.com/wooorm/remark/commit/0000000000000000000000000000000000); 32 | * [`0000000`](https://github.com/wooorm/remark/commit/00000000000000000000000000000000000); 33 | * [`0000000`](https://github.com/wooorm/remark/commit/00000000000000000000000000000000000); 34 | * [`0000000`](https://github.com/wooorm/remark/commit/000000000000000000000000000000000000); 35 | * [`0000000`](https://github.com/wooorm/remark/commit/0000000000000000000000000000000000000); 36 | * [`0000000`](https://github.com/wooorm/remark/commit/00000000000000000000000000000000000000); 37 | * [`0000000`](https://github.com/wooorm/remark/commit/000000000000000000000000000000000000000); 38 | * [`0000000`](https://github.com/wooorm/remark/commit/0000000000000000000000000000000000000000); 39 | * 00000000000000000000000000000000000000000 40 | 41 | And: 42 | 43 | * Prefix [`0000000`](https://github.com/wooorm/remark/commit/0000000) suffix; 44 | * Prefix [`0000000`](https://github.com/wooorm/remark/commit/0000000)!; 45 | * a [`0000000`](https://github.com/wooorm/remark/commit/0000000)!; 46 | 47 | And what about here 48 | [`0000000`](https://github.com/wooorm/remark/commit/0000000) 49 | 50 | Or here 51 | [`0000000`](https://github.com/wooorm/remark/commit/0000000) 52 | 53 | And these SHAs which could also be words? deedeed, and fabaceae. 54 | 55 | 0.00.0.0000000 56 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | import assert from 'node:assert/strict' 2 | import fs from 'node:fs/promises' 3 | import process from 'node:process' 4 | import test from 'node:test' 5 | import {remark} from 'remark' 6 | import remarkGfm from 'remark-gfm' 7 | import {VFile} from 'vfile' 8 | import remarkGithub, {defaultBuildUrl} from '../index.js' 9 | 10 | test('remarkGithub', async function (t) { 11 | await t.test('should expose the public api', async function () { 12 | assert.deepEqual(Object.keys(await import('../index.js')).sort(), [ 13 | 'default', 14 | 'defaultBuildUrl' 15 | ]) 16 | }) 17 | 18 | await t.test('should not throw if not passed options', async function () { 19 | assert.doesNotThrow(function () { 20 | remark().use(remarkGithub).freeze() 21 | }) 22 | }) 23 | 24 | await t.test( 25 | 'should wrap mentions in `strong` by default', 26 | async function () { 27 | const file = await remark() 28 | .use(remarkGfm) 29 | .use(remarkGithub) 30 | .process('@wooorm') 31 | 32 | assert.equal(String(file), '[**@wooorm**](https://github.com/wooorm)\n') 33 | } 34 | ) 35 | 36 | await t.test('should support `mentionStrong: false`', async function () { 37 | const file = await remark() 38 | .use(remarkGfm) 39 | .use(remarkGithub, {mentionStrong: false}) 40 | .process('@wooorm') 41 | 42 | assert.equal(String(file), '[@wooorm](https://github.com/wooorm)\n') 43 | }) 44 | 45 | await t.test( 46 | 'should load a `package.json` when available', 47 | async function () { 48 | const file = await remark() 49 | .use(remarkGfm) 50 | .use(remarkGithub) 51 | .process( 52 | new VFile({ 53 | cwd: new URL('..', import.meta.url).pathname, 54 | value: 'test@12345678' 55 | }) 56 | ) 57 | 58 | assert.equal( 59 | String(file), 60 | '[test@`1234567`](https://github.com/' + 61 | 'test/remark-github/commit/12345678)\n' 62 | ) 63 | } 64 | ) 65 | 66 | await t.test( 67 | 'should accept a `repository.url` in a `package.json`', 68 | async function () { 69 | const file = await remark() 70 | .use(remarkGfm) 71 | .use(remarkGithub) 72 | .process( 73 | new VFile({ 74 | cwd: new URL('.', import.meta.url).pathname, 75 | value: '12345678' 76 | }) 77 | ) 78 | 79 | assert.equal( 80 | String(file), 81 | '[`1234567`](https://github.com/wooorm/remark/commit/12345678)\n' 82 | ) 83 | } 84 | ) 85 | 86 | await t.test('should throw without `repository`', async function () { 87 | try { 88 | await remark() 89 | .use(remarkGfm) 90 | .use(remarkGithub) 91 | .process( 92 | new VFile({ 93 | cwd: new URL('fixtures', import.meta.url).pathname, 94 | value: '12345678' 95 | }) 96 | ) 97 | assert.fail() 98 | } catch (error) { 99 | assert.match( 100 | String(error), 101 | /Unexpected missing `repository` in `options`/ 102 | ) 103 | } 104 | }) 105 | 106 | await t.test('should throw w/ incorrect `repository`', async function () { 107 | try { 108 | await remark() 109 | .use(remarkGfm) 110 | .use(remarkGithub, {repository: 'a'}) 111 | .process('@wooorm') 112 | assert.fail() 113 | } catch (error) { 114 | assert.match( 115 | String(error), 116 | /Unexpected invalid `repository`, expected for example `user\/project`/ 117 | ) 118 | } 119 | }) 120 | 121 | await t.test('should support `buildUrl` for mentions', async function () { 122 | const file = await remark() 123 | .use(remarkGfm) 124 | .use(remarkGithub, { 125 | buildUrl(values) { 126 | return values.type === 'mention' 127 | ? `https://github.yourcompany.com/${values.user}/` 128 | : defaultBuildUrl(values) 129 | } 130 | }) 131 | .process('@wooorm') 132 | 133 | assert.equal( 134 | String(file), 135 | '[**@wooorm**](https://github.yourcompany.com/wooorm/)\n' 136 | ) 137 | }) 138 | 139 | await t.test('should support `buildUrl` for issues', async function () { 140 | const file = await remark() 141 | .use(remarkGfm) 142 | .use(remarkGithub, { 143 | buildUrl(values) { 144 | return values.type === 'issue' 145 | ? `https://github.yourcompany.com/${values.user}/${values.project}/issues/${values.no}` 146 | : defaultBuildUrl(values) 147 | } 148 | }) 149 | .process('#123') 150 | 151 | assert.equal( 152 | String(file), 153 | '[#123](https://github.yourcompany.com/remarkjs/remark-github/issues/123)\n' 154 | ) 155 | }) 156 | 157 | await t.test('should support `buildUrl` for `GH-` issues', async function () { 158 | const file = await remark() 159 | .use(remarkGfm) 160 | .use(remarkGithub, { 161 | buildUrl(values) { 162 | return values.type === 'issue' 163 | ? `https://github.yourcompany.com/${values.user}/${values.project}/issues/${values.no}` 164 | : defaultBuildUrl(values) 165 | } 166 | }) 167 | .process('GH-1') 168 | 169 | assert.equal( 170 | String(file), 171 | '[GH-1](https://github.yourcompany.com/remarkjs/remark-github/issues/1)\n' 172 | ) 173 | }) 174 | 175 | await t.test( 176 | 'should support `buildUrl` for compare ranges', 177 | async function () { 178 | const file = await remark() 179 | .use(remarkGfm) 180 | .use(remarkGithub, { 181 | buildUrl(values) { 182 | return values.type === 'compare' 183 | ? `https://github.yourcompany.com/${values.user}/${values.project}/compare/${values.base}...${values.compare}` 184 | : defaultBuildUrl(values) 185 | } 186 | }) 187 | .process('e2acebc...2aa9311') 188 | 189 | assert.equal( 190 | String(file), 191 | '[`e2acebc...2aa9311`](https://github.yourcompany.com/remarkjs/remark-github/compare/e2acebc...2aa9311)\n' 192 | ) 193 | } 194 | ) 195 | 196 | await t.test('should support `buildUrl` for commits', async function () { 197 | const file = await remark() 198 | .use(remarkGfm) 199 | .use(remarkGithub, { 200 | buildUrl(values) { 201 | return values.type === 'commit' 202 | ? `https://github.yourcompany.com/${values.user}/${values.project}/commit/${values.hash}` 203 | : defaultBuildUrl(values) 204 | } 205 | }) 206 | .process('1f2a4fb') 207 | 208 | assert.equal( 209 | String(file), 210 | '[`1f2a4fb`](https://github.yourcompany.com/remarkjs/remark-github/commit/1f2a4fb)\n' 211 | ) 212 | }) 213 | 214 | await t.test( 215 | 'should support `buildUrl` for cross-repo issues', 216 | async function () { 217 | const file = await remark() 218 | .use(remarkGfm) 219 | .use(remarkGithub, { 220 | buildUrl(values) { 221 | return values.type === 'issue' 222 | ? `https://github.yourcompany.com/${values.user}/${values.project}/issues/${values.no}` 223 | : defaultBuildUrl(values) 224 | } 225 | }) 226 | .process('remarkjs/remark-github#1') 227 | 228 | assert.equal( 229 | String(file), 230 | '[#1](https://github.yourcompany.com/remarkjs/remark-github/issues/1)\n' 231 | ) 232 | } 233 | ) 234 | 235 | await t.test( 236 | 'should support `buildUrl` for cross-repo commits', 237 | async function () { 238 | const file = await remark() 239 | .use(remarkGfm) 240 | .use(remarkGithub, { 241 | buildUrl(values) { 242 | return values.type === 'commit' 243 | ? `https://github.yourcompany.com/${values.user}/${values.project}/commit/${values.hash}` 244 | : defaultBuildUrl(values) 245 | } 246 | }) 247 | .process('remarkjs/remark-github@1f2a4fb') 248 | 249 | assert.equal( 250 | String(file), 251 | '[@`1f2a4fb`](https://github.yourcompany.com/remarkjs/remark-github/commit/1f2a4fb)\n' 252 | ) 253 | } 254 | ) 255 | 256 | await t.test( 257 | 'should support `buildUrl` returning `false` to not link something', 258 | async function () { 259 | const file = await remark() 260 | .use(remarkGfm) 261 | .use(remarkGithub, { 262 | buildUrl() { 263 | return false 264 | } 265 | }) 266 | .process( 267 | '@user, #1, 1f2a4fb, e2acebc...2aa9311, remarkjs/remark-github#1, remarkjs/remark-github@1f2a4fb' 268 | ) 269 | 270 | assert.equal( 271 | String(file), 272 | '@user, #1, 1f2a4fb, e2acebc...2aa9311, remarkjs/remark-github#1, remarkjs/remark-github\\@1f2a4fb\n' 273 | ) 274 | } 275 | ) 276 | }) 277 | 278 | test('repositories', async function (t) { 279 | // List of repo references possible in `package.json`s. 280 | // From `repo-utils/parse-github-repo-url`, with some tiny additions. 281 | /** @type {ReadonlyArray<[string, string, string]>} */ 282 | const repositories = [ 283 | ['component/emitter', 'component', 'emitter'], 284 | ['https://github.com/component/emitter', 'component', 'emitter'], 285 | ['git://github.com/component/emitter.git', 'component', 'emitter'], 286 | [ 287 | 'https://github.com/repos/component/emitter/tarball', 288 | 'component', 289 | 'emitter' 290 | ], 291 | [ 292 | 'https://github.com/repos/component/emitter/zipball', 293 | 'component', 294 | 'emitter' 295 | ], 296 | [ 297 | 'https://codeload.github.com/component/emitter/legacy.zip', 298 | 'component', 299 | 'emitter' 300 | ], 301 | [ 302 | 'https://codeload.github.com/component/emitter/legacy.tar.gz', 303 | 'component', 304 | 'emitter' 305 | ], 306 | ['component/emitter#1', 'component', 'emitter'], 307 | ['component/emitter@1', 'component', 'emitter'], 308 | ['component/emitter#"1"', 'component', 'emitter'], 309 | ['component/emitter@"1"', 'component', 'emitter'], 310 | ['git://github.com/component/emitter.git#1', 'component', 'emitter'], 311 | [ 312 | 'https://github.com/repos/component/emitter/tarball/1', 313 | 'component', 314 | 'emitter' 315 | ], 316 | [ 317 | 'https://github.com/repos/component/emitter/zipball/1', 318 | 'component', 319 | 'emitter' 320 | ], 321 | [ 322 | 'https://codeload.github.com/component/emitter/legacy.zip/1', 323 | 'component', 324 | 'emitter' 325 | ], 326 | [ 327 | 'https://codeload.github.com/component/emitter/legacy.tar.gz/1', 328 | 'component', 329 | 'emitter' 330 | ], 331 | [ 332 | 'https://github.com/component/emitter/archive/1.tar.gz', 333 | 'component', 334 | 'emitter' 335 | ], 336 | ['mame/_', 'mame', '_'], 337 | ['github/.gitignore', 'github', '.gitignore'], 338 | ['github/.gitc', 'github', '.gitc'], 339 | ['Qix-/color-convert', 'Qix-', 'color-convert'], 340 | ['example/example.github.io', 'example', 'example.github.io'] 341 | ] 342 | let index = -1 343 | 344 | while (++index < repositories.length) { 345 | const repo = repositories[index] 346 | const value = repo[0] 347 | const user = repo[1] 348 | const project = repo[2] 349 | 350 | await t.test('should work on `' + value + '`', async function () { 351 | const file = await remark() 352 | .use(remarkGfm) 353 | .use(remarkGithub, {repository: value}) 354 | .process( 355 | [ 356 | '* SHA: a5c3785ed8d6a35868bc169f07e40e889087fd2e', 357 | '* User@SHA: wooorm@a5c3785ed8d6a35868bc169f07e40e889087fd2e', 358 | '* # Num: #26', 359 | '* GH-Num: GH-26', 360 | '* User#Num: wooorm#26', 361 | '' 362 | ].join('\n') 363 | ) 364 | 365 | assert.equal( 366 | String(file), 367 | [ 368 | '* SHA: [`a5c3785`](https://github.com/' + 369 | user + 370 | '/' + 371 | project + 372 | '/commit/a5c3785ed8d6a35868bc169f07e40e' + 373 | '889087fd2e)', 374 | '* User\\@SHA: [wooorm@`a5c3785`](https://github.com/wooorm/' + 375 | project + 376 | '/commit/a5c3785ed8d6a35868bc169f07e40e' + 377 | '889087fd2e)', 378 | '* # Num: [#26](https://github.com/' + 379 | user + 380 | '/' + 381 | project + 382 | '/issues/26)', 383 | '* GH-Num: [GH-26](https://github.com/' + 384 | user + 385 | '/' + 386 | project + 387 | '/issues/26)', 388 | '* User#Num: [wooorm#26](https://github.com/wooorm/' + 389 | project + 390 | '/issues/26)', 391 | '' 392 | ].join('\n') 393 | ) 394 | }) 395 | } 396 | }) 397 | 398 | test('fixtures', async function (t) { 399 | const base = new URL('fixtures/', import.meta.url) 400 | const folders = await fs.readdir(base) 401 | 402 | let index = -1 403 | 404 | while (++index < folders.length) { 405 | const folder = folders[index] 406 | 407 | if (folder.startsWith('.')) continue 408 | 409 | await t.test(folder, async function () { 410 | const folderUrl = new URL(folder + '/', base) 411 | const inputUrl = new URL('input.md', folderUrl) 412 | const outputUrl = new URL('output.md', folderUrl) 413 | 414 | const input = String(await fs.readFile(inputUrl)) 415 | 416 | /** @type {string} */ 417 | let output 418 | 419 | const proc = remark() 420 | .use(remarkGfm) 421 | .use(remarkGithub, {repository: 'wooorm/remark'}) 422 | 423 | const actual = String(await proc.process(input)) 424 | 425 | try { 426 | if ('UPDATE' in process.env) { 427 | throw new Error('Updating…') 428 | } 429 | 430 | output = String(await fs.readFile(outputUrl)) 431 | } catch { 432 | output = actual 433 | await fs.writeFile(outputUrl, actual) 434 | } 435 | 436 | assert.equal(actual, String(output)) 437 | }) 438 | } 439 | }) 440 | -------------------------------------------------------------------------------- /test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "module", 3 | "repository": "wooorm/remark", 4 | "xo": { 5 | "prettier": true, 6 | "rules": { 7 | "no-await-in-loop": "off" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "checkJs": true, 4 | "customConditions": ["development"], 5 | "declaration": true, 6 | "emitDeclarationOnly": true, 7 | "exactOptionalPropertyTypes": true, 8 | "lib": ["es2022"], 9 | "module": "node16", 10 | "strict": true, 11 | "target": "es2022" 12 | }, 13 | "exclude": ["coverage/", "node_modules/"], 14 | "include": ["**/*.js"] 15 | } 16 | --------------------------------------------------------------------------------