Skip to content

Commit

Permalink
Merge pull request #62 from UmbrellaDocs/encoded-sections
Browse files Browse the repository at this point in the history
Handle encoded section IDs
  • Loading branch information
gaurav-nelson authored Jun 20, 2024
2 parents ecd4b77 + 7ef2686 commit d230eca
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 7 deletions.
38 changes: 37 additions & 1 deletion index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ test('linkspector should add back the removed duplicates when returning the resu
expect(results[3].status).toBe('error')
})

test(' linkspector should check hyperlinks in AsciiDoc files', async () => {
test('linkspector should check hyperlinks in AsciiDoc files', async () => {
let hasErrorLinks = false
let currentFile = '' // Variable to store the current file name
let results = [] // Array to store the results if json is true
Expand Down Expand Up @@ -184,3 +184,39 @@ test(' linkspector should check hyperlinks in AsciiDoc files', async () => {
expect(results[2].status).toBe('error')
expect(results[3].status).toBe('alive')
})

test('linkspector should check HTML encoded section links', async () => {
let hasErrorLinks = false
let currentFile = '' // Variable to store the current file name
let results = [] // Array to store the results if json is true

for await (const { file, result } of linkspector(
'./test/fixtures/markdown/decoded-sections/.decodedTest.yml',
cmd
)) {
currentFile = file
for (const linkStatusObj of result) {
if (cmd.json) {
results.push({
file: currentFile,
link: linkStatusObj.link,
status_code: linkStatusObj.status_code,
line_number: linkStatusObj.line_number,
position: linkStatusObj.position,
status: linkStatusObj.status,
error_message: linkStatusObj.error_message,
})
}
if (linkStatusObj.status === 'error') {
hasErrorLinks = true
}
}
}

expect(hasErrorLinks).toBe(false)
expect(results.length).toBe(4)
expect(results[0].status).toBe('alive')
expect(results[1].status).toBe('alive')
expect(results[2].status).toBe('alive')
expect(results[3].status).toBe('alive')
})
39 changes: 33 additions & 6 deletions lib/check-file-links.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@ import remarkGfm from 'remark-gfm'
import { visit } from 'unist-util-visit'
import GithubSlugger from 'github-slugger'

const fileCache = {}

/**
* Checks if a file and a section within the file exist.
*
* @param {Object} link - The link object.
* @param {string} file - The current file path.
* @returns {Object} An object containing the status code, status message, and error message (if any).
*/

function checkFileExistence(link, file) {
// Initialize status code, status message, and error message
let statusCode = '200'
Expand All @@ -27,7 +30,7 @@ function checkFileExistence(link, file) {
// Determine the file path
const filePath = urlWithoutSection.startsWith('/')
? path.join(process.cwd(), urlWithoutSection)
: urlWithoutSection === ''
: urlWithoutSection === '' || urlWithoutSection === path.basename(file)
? file
: path.resolve(path.dirname(file), urlWithoutSection)

Expand All @@ -39,23 +42,35 @@ function checkFileExistence(link, file) {
} else if (sectionId) {
// If the file exists and there's a section part in the URL, check if the section exists
const mdContent = fs.readFileSync(filePath, 'utf8')
const tree = unified().use(remarkParse).use(remarkGfm).parse(mdContent)

// Use the cache if the file has been parsed before
let tree = fileCache[filePath]
if (!tree) {
tree = unified().use(remarkParse).use(remarkGfm).parse(mdContent)
fileCache[filePath] = tree // Store the parsed file in the cache
}
// Collect all heading IDs in the file
// Use GitHub slugger to generate the heading slug for comparison
const headingNodes = new Set()
visit(tree, 'heading', (node) => {
const headingText = getText(node)

const headingId =
node.children[0].type === 'html'
? node.children[0].value.match(/name="(.+?)"/)?.[1]
: node.children[0].value.includes('{#')
: node.children[0] &&
node.children[0].value &&
node.children[0].value.includes('{#')
? node.children[0].value.match(/{#(.+?)}/)?.[1]
: slugger.slug(node.children[0].value)
: slugger.slug(headingText)

headingNodes.add(headingId)
})

// Decode the section ID from the URL
const decodedSectionId = decodeURIComponent(sectionId)

// Check if the section exists
if (!headingNodes.has(sectionId)) {
if (!headingNodes.has(decodedSectionId)) {
statusCode = '404'
status = 'error'
errorMessage = `Cannot find section: #${sectionId} in file: ${filePath}.`
Expand All @@ -69,4 +84,16 @@ function checkFileExistence(link, file) {
return { statusCode, status, errorMessage }
}

function getText(node) {
if (node.type === 'text') {
return node.value
}

if (Array.isArray(node.children)) {
return node.children.map(getText).join('')
}

return ''
}

export { checkFileExistence }
2 changes: 2 additions & 0 deletions test/fixtures/markdown/decoded-sections/.decodedTest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dirs:
- ./test/fixtures/markdown/decoded-sections
23 changes: 23 additions & 0 deletions test/fixtures/markdown/decoded-sections/decoded.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
A távolsági - lő- és hajítófegyverekkel - végzett harc során a védekező fél nem saját Védő Értékével vesz részt a harcban, ugyanolyan “céltárgynak” minősül, mint egy szalmabábú, vagy egy agyaggalamb. Ugyanakkor a célpont mozgásának jellege (lásd “Mozgás módosító" fejezetet) és a távolság erőteljesen befolyásolják a találat esélyeit. Lásd még: [Szándékos kitérés lövés elől](decoded.md#sz%C3%A1nd%C3%A9kos-kit%C3%A9r%C3%A9s-l%C3%B6v%C3%A9s-el%C5%91l) fejezetet. A támadó a távolsági harcban a **Célzó Értékét** használja, melynek megállapítása több tényezőtől függ.

[Bevezető](#0-bevezet%C5%91-jelz%C5%91k)

Also a link to check [the README Documentation Section](#-documentation)

## 📖 Documentation

This is the documentation section. It is a simple markdown file with some links and references to other sections.

### Szándékos kitérés lövés elől

Ha valaki látja és van ideje felkészülni a rá leadott lövésre/hajításra, valamint rendelkezik elegendő hellyel a kitérésre és bejelenti, hogy megpróbálja elkerülni végzetét, akkor Gyorsaságpróbát kell dobnia, melynek nehézsége függ a lövést leadó személy távolságától, valamint az általa használt fegyvertől.

| Gyorsaságpróba célszám | Dobófegyverek,<br />Mágikus lövedék I. | Íjak,<br />Mágikus lövedék II. | Nyílpuskák,<br />Mágikus lövedék III. |
| :--------------------: | -------------------------------------: | -----------------------------: | ------------------------------------: |
| 8 | 1m&nbsp;-&nbsp;3m | 0m - 5m | 0m - 10m |
| 7 | 4m - 6m | 6m&nbsp;-&nbsp;10m | 11m&nbsp;-&nbsp;20m |
| 6 | 7m&nbsp;-&nbsp;9m | 11m&nbsp;-&nbsp;15m | 21m&nbsp;-&nbsp;30m |
| 5 | 10m&nbsp;-&nbsp;12m | 16m&nbsp;-&nbsp;20m | 31m&nbsp;-&nbsp;40m |
| 4 | Testközelben | | |

### 0. [Bevezető, jelzők](decoded2.md)
1 change: 1 addition & 0 deletions test/fixtures/markdown/decoded-sections/decoded2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Decoded 2

0 comments on commit d230eca

Please sign in to comment.