Skip to content

Commit

Permalink
Fix to resolve package.jsons from file, not process
Browse files Browse the repository at this point in the history
Closes GH-39.
Closes GH-41.

Reviewed-by: Titus Wormer <[email protected]>
Reviewed-by: Christian Murphy <[email protected]>
  • Loading branch information
remcohaszing authored Jul 13, 2022
1 parent b512f0b commit 792ad9c
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 168 deletions.
8 changes: 3 additions & 5 deletions lib/get-repo-from-package.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,20 @@
*/

import fs from 'fs'
import process from 'process'
import path from 'path'

/**
* Get the repository from `package.json`.
*
* @param {string} cwd
* @returns {string|undefined}
*/
export function getRepoFromPackage() {
export function getRepoFromPackage(cwd) {
/** @type {PackageJson|undefined} */
let pkg

try {
pkg = JSON.parse(
String(fs.readFileSync(path.join(process.cwd(), 'package.json')))
)
pkg = JSON.parse(String(fs.readFileSync(path.join(cwd, 'package.json'))))
} catch {}

const repository =
Expand Down
303 changes: 153 additions & 150 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,19 +139,22 @@ const mentionRegex = new RegExp(
* @type {import('unified').Plugin<[Options?]|void[], Root>}
*/
export default function remarkGithub(options = {}) {
const repository = options.repository || getRepoFromPackage()
return (tree, vfile) => {
const repository = options.repository || getRepoFromPackage(vfile.cwd)

// Parse the URL: See the tests for all possible kinds.
const repositoryMatch = repoRegex.exec(repository || '')
// Parse the URL: See the tests for all possible kinds.
const repositoryMatch = repoRegex.exec(repository || '')

if (!repositoryMatch) {
throw new Error('Missing or invalid `repository` field in `options`')
}
if (!repositoryMatch) {
throw new Error('Missing or invalid `repository` field in `options`')
}

/** @type {RepositoryInfo} */
const repositoryInfo = {user: repositoryMatch[1], project: repositoryMatch[2]}
/** @type {RepositoryInfo} */
const repositoryInfo = {
user: repositoryMatch[1],
project: repositoryMatch[2]
}

return (tree) => {
findAndReplace(
tree,
[
Expand Down Expand Up @@ -210,174 +213,174 @@ export default function remarkGithub(options = {}) {

node.children = children
})
}

/**
* @param {BuildUrlValues} values
* @returns {string|false}
*/
function buildUrl(values) {
if (options.buildUrl) return options.buildUrl(values, defaultBuildUrl)
return defaultBuildUrl(values)
}

/**
* @type {ReplaceFunction}
* @param {string} value
* @param {string} username
* @param {Match} match
*/
function replaceMention(value, username, match) {
if (
/[\w`]/.test(match.input.charAt(match.index - 1)) ||
/[/\w`]/.test(match.input.charAt(match.index + value.length)) ||
denyMention.has(username)
) {
return false
/**
* @param {BuildUrlValues} values
* @returns {string|false}
*/
function buildUrl(values) {
if (options.buildUrl) return options.buildUrl(values, defaultBuildUrl)
return defaultBuildUrl(values)
}

const url = buildUrl({type: 'mention', user: username})
/**
* @type {ReplaceFunction}
* @param {string} value
* @param {string} username
* @param {Match} match
*/
function replaceMention(value, username, match) {
if (
/[\w`]/.test(match.input.charAt(match.index - 1)) ||
/[/\w`]/.test(match.input.charAt(match.index + value.length)) ||
denyMention.has(username)
) {
return false
}

if (!url) return false
const url = buildUrl({type: 'mention', user: username})

/** @type {StaticPhrasingContent} */
let node = {type: 'text', value}
if (!url) return false

if (options.mentionStrong !== false) {
node = {type: 'strong', children: [node]}
}
/** @type {StaticPhrasingContent} */
let node = {type: 'text', value}

return {type: 'link', title: null, url, children: [node]}
}
if (options.mentionStrong !== false) {
node = {type: 'strong', children: [node]}
}

/**
* @type {ReplaceFunction}
* @param {string} value
* @param {string} no
* @param {Match} match
*/
function replaceIssue(value, no, match) {
if (
/\w/.test(match.input.charAt(match.index - 1)) ||
/\w/.test(match.input.charAt(match.index + value.length))
) {
return false
return {type: 'link', title: null, url, children: [node]}
}

const url = buildUrl({type: 'issue', ...repositoryInfo, no})
/**
* @type {ReplaceFunction}
* @param {string} value
* @param {string} no
* @param {Match} match
*/
function replaceIssue(value, no, match) {
if (
/\w/.test(match.input.charAt(match.index - 1)) ||
/\w/.test(match.input.charAt(match.index + value.length))
) {
return false
}

return url
? {type: 'link', title: null, url, children: [{type: 'text', value}]}
: false
}
const url = buildUrl({type: 'issue', ...repositoryInfo, no})

/**
* @type {ReplaceFunction}
* @param {string} value
* @param {string} a
* @param {string} b
* @param {Match} match
*/
function replaceHashRange(value, a, b, match) {
if (
/[^\t\n\r (@[{]/.test(match.input.charAt(match.index - 1)) ||
/\w/.test(match.input.charAt(match.index + value.length)) ||
denyHash.has(value)
) {
return false
return url
? {type: 'link', title: null, url, children: [{type: 'text', value}]}
: false
}

const url = buildUrl({
type: 'compare',
...repositoryInfo,
base: a,
compare: b
})

return url
? {
type: 'link',
title: null,
url,
children: [{type: 'inlineCode', value: abbr(a) + '...' + abbr(b)}]
}
: false
}
/**
* @type {ReplaceFunction}
* @param {string} value
* @param {string} a
* @param {string} b
* @param {Match} match
*/
function replaceHashRange(value, a, b, match) {
if (
/[^\t\n\r (@[{]/.test(match.input.charAt(match.index - 1)) ||
/\w/.test(match.input.charAt(match.index + value.length)) ||
denyHash.has(value)
) {
return false
}

/**
* @type {ReplaceFunction}
* @param {string} value
* @param {Match} match
*/
function replaceHash(value, match) {
if (
/[^\t\n\r (@[{.]/.test(match.input.charAt(match.index - 1)) ||
// For some weird reason GH does link two dots, but not one 🤷‍♂️
(match.input.charAt(match.index - 1) === '.' &&
match.input.charAt(match.index - 2) !== '.') ||
/\w/.test(match.input.charAt(match.index + value.length)) ||
denyHash.has(value)
) {
return false
const url = buildUrl({
type: 'compare',
...repositoryInfo,
base: a,
compare: b
})

return url
? {
type: 'link',
title: null,
url,
children: [{type: 'inlineCode', value: abbr(a) + '...' + abbr(b)}]
}
: false
}

const url = buildUrl({type: 'commit', ...repositoryInfo, hash: value})
/**
* @type {ReplaceFunction}
* @param {string} value
* @param {Match} match
*/
function replaceHash(value, match) {
if (
/[^\t\n\r (@[{.]/.test(match.input.charAt(match.index - 1)) ||
// For some weird reason GH does link two dots, but not one 🤷‍♂️
(match.input.charAt(match.index - 1) === '.' &&
match.input.charAt(match.index - 2) !== '.') ||
/\w/.test(match.input.charAt(match.index + value.length)) ||
denyHash.has(value)
) {
return false
}

return url
? {
type: 'link',
title: null,
url,
children: [{type: 'inlineCode', value: abbr(value)}]
}
: false
}
const url = buildUrl({type: 'commit', ...repositoryInfo, hash: value})

/**
* @type {ReplaceFunction}
* @param {string} $0
* @param {string} user
* @param {string} specificProject
* @param {string} no
* @param {string} hash
* @param {Match} match
*/
// eslint-disable-next-line max-params
function replaceReference($0, user, specificProject, no, hash, match) {
if (
/[^\t\n\r (@[{]/.test(match.input.charAt(match.index - 1)) ||
/\w/.test(match.input.charAt(match.index + $0.length))
) {
return false
return url
? {
type: 'link',
title: null,
url,
children: [{type: 'inlineCode', value: abbr(value)}]
}
: false
}

const project = specificProject || repositoryInfo.project
const url = no
? buildUrl({type: 'issue', user, project, no})
: buildUrl({type: 'commit', user, project, hash})
/**
* @type {ReplaceFunction}
* @param {string} $0
* @param {string} user
* @param {string} specificProject
* @param {string} no
* @param {string} hash
* @param {Match} match
*/
// eslint-disable-next-line max-params
function replaceReference($0, user, specificProject, no, hash, match) {
if (
/[^\t\n\r (@[{]/.test(match.input.charAt(match.index - 1)) ||
/\w/.test(match.input.charAt(match.index + $0.length))
) {
return false
}

if (!url) return false
const project = specificProject || repositoryInfo.project
const url = no
? buildUrl({type: 'issue', user, project, no})
: buildUrl({type: 'commit', user, project, hash})

/** @type {StaticPhrasingContent[]} */
const nodes = []
let value = ''
if (!url) return false

if (project !== repositoryInfo.project) {
value += user + '/' + project
} else if (user !== repositoryInfo.user) {
value += user
}
/** @type {StaticPhrasingContent[]} */
const nodes = []
let value = ''

if (no) {
value += '#' + no
} else {
value += '@'
nodes.push({type: 'inlineCode', value: abbr(hash)})
}
if (project !== repositoryInfo.project) {
value += user + '/' + project
} else if (user !== repositoryInfo.user) {
value += user
}

nodes.unshift({type: 'text', value})
if (no) {
value += '#' + no
} else {
value += '@'
nodes.push({type: 'inlineCode', value: abbr(hash)})
}

return {type: 'link', title: null, url, children: nodes}
nodes.unshift({type: 'text', value})

return {type: 'link', title: null, url, children: nodes}
}
}
}

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
"type-coverage": "^2.0.0",
"type-fest": "^2.0.0",
"typescript": "^4.0.0",
"vfile": "^5.0.0",
"xo": "^0.50.0"
},
"scripts": {
Expand Down
Loading

0 comments on commit 792ad9c

Please sign in to comment.