markdown-magic 2.6.1 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +47 -37
- package/cli.js +5 -82
- package/lib/block-parser-js.test.js +171 -0
- package/lib/block-parser.js +382 -0
- package/lib/block-parser.test.js +479 -0
- package/lib/cli.js +245 -0
- package/lib/cli.test.js +409 -0
- package/lib/defaults.js +12 -0
- package/lib/globals.d.ts +66 -0
- package/lib/index.js +353 -184
- package/lib/index.test.js +11 -0
- package/lib/process-contents.js +371 -0
- package/lib/process-file.js +37 -0
- package/lib/transforms/code.js +67 -28
- package/lib/transforms/file.js +17 -17
- package/lib/transforms/index.js +0 -114
- package/lib/transforms/remote.js +8 -6
- package/lib/transforms/sectionToc.js +18 -0
- package/lib/transforms/toc.js +12 -265
- package/lib/transforms/wordCount.js +5 -0
- package/lib/types.js +11 -0
- package/lib/utils/fs.js +342 -0
- package/lib/utils/fs.test.js +267 -0
- package/lib/utils/index.js +19 -0
- package/{cli-utils.js → lib/utils/load-config.js} +2 -6
- package/lib/utils/logs.js +94 -0
- package/lib/utils/md/filters.js +20 -0
- package/lib/utils/md/find-code-blocks.js +88 -0
- package/lib/utils/md/find-date.js +32 -0
- package/lib/utils/md/find-frontmatter.js +92 -0
- package/lib/utils/md/find-frontmatter.test.js +17 -0
- package/lib/utils/md/find-html-tags.js +105 -0
- package/lib/utils/md/find-images-md.js +27 -0
- package/lib/utils/md/find-images.js +107 -0
- package/lib/utils/md/find-links.js +220 -0
- package/lib/utils/md/find-unmatched-html-tags.js +32 -0
- package/lib/utils/md/fixtures/2022-01-22-date-in-filename.md +14 -0
- package/lib/utils/md/fixtures/file-with-frontmatter.md +32 -0
- package/lib/utils/md/fixtures/file-with-links.md +153 -0
- package/lib/utils/md/md.test.js +105 -0
- package/lib/utils/md/parse.js +146 -0
- package/lib/utils/md/utils.js +19 -0
- package/lib/utils/regex-timeout.js +84 -0
- package/lib/utils/regex.js +40 -6
- package/lib/utils/remoteRequest.js +55 -0
- package/lib/utils/syntax.js +82 -0
- package/lib/utils/text.js +328 -0
- package/lib/utils/text.test.js +305 -0
- package/lib/utils/toc.js +315 -0
- package/package.json +30 -26
- package/index.js +0 -46
- package/lib/processFile.js +0 -154
- package/lib/updateContents.js +0 -125
- package/lib/utils/_md.test.js +0 -63
- package/lib/utils/new-parser.js +0 -412
- package/lib/utils/new-parser.test.js +0 -324
- package/lib/utils/weird-parse.js +0 -230
- package/lib/utils/weird-parse.test.js +0 -217
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
|
|
2
|
+
// Might need ([\s\S]*?) instead of '*' in between tags
|
|
3
|
+
const HTML_TAG = /<([a-zA-Z1-6]+)([^<]+)*(?:>(.*)<\/\1>|\s+\/>)/gim
|
|
4
|
+
|
|
5
|
+
const MATCH_HTML_TAGS_REGEX = /<([a-zA-Z1-6]+)\b([^>]*)>*(?:>([\s\S]*?)<\/\1>|\s?\/?>)/gm
|
|
6
|
+
// old forces closes / - /<([a-zA-Z1-6]+)\b([^>]*)>*(?:>([\s\S]*?)<\/\1>|\s?\/>)/gm
|
|
7
|
+
|
|
8
|
+
function findHtmlTags(mdContents) {
|
|
9
|
+
const parents = mdContents
|
|
10
|
+
/* Fix non terminating <tags> */
|
|
11
|
+
.replace(/(['"`]<(.*)>['"`])/gm, '_$2_')
|
|
12
|
+
.match(MATCH_HTML_TAGS_REGEX)
|
|
13
|
+
// console.log('parents', parents)
|
|
14
|
+
|
|
15
|
+
if (parents) {
|
|
16
|
+
// const children = parents.filter(Boolean).map((p) => {
|
|
17
|
+
// return p.match(HTML_TAG)
|
|
18
|
+
// })
|
|
19
|
+
// console.log('children', children)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const htmlTags = mdContents
|
|
23
|
+
/* Fix non terminating <tags> */
|
|
24
|
+
.replace(/(['"`]<(.*)>['"`])/gm, '_$2_')
|
|
25
|
+
.match(MATCH_HTML_TAGS_REGEX)
|
|
26
|
+
// console.log('htmlTags', htmlTags)
|
|
27
|
+
|
|
28
|
+
let tags = []
|
|
29
|
+
if (htmlTags) {
|
|
30
|
+
let propsValues = {}
|
|
31
|
+
// var regexSingleTag = /<([a-zA-Z1-6]+)([^<]+)*(?:>(.*)<\/\1>|\s+\/>)/
|
|
32
|
+
// var regexSingleTag = /<([a-zA-Z1-6]+)([^<]+)*(?:>([\s\S]*?)<\/\1>|\s*\/>)/
|
|
33
|
+
var regexSingleTag = /<([a-zA-Z1-6]+)\b([^>]*)>*(?:>([\s\S]*?)<\/\1>|\s?\/?>)/
|
|
34
|
+
for (var i = 0; i < htmlTags.length; i++) {
|
|
35
|
+
// console.log('htmlTags[i]', htmlTags[i])
|
|
36
|
+
var tagMatches = regexSingleTag.exec(htmlTags[i]) || []
|
|
37
|
+
// console.log('tagMatches', tagMatches)
|
|
38
|
+
var [ match, tag, props ] = tagMatches
|
|
39
|
+
// console.log(`Tag #${i} ${tag}`)
|
|
40
|
+
if (props) {
|
|
41
|
+
const cleanProps = props
|
|
42
|
+
// Remove new lines and tabs
|
|
43
|
+
.replace(/\n\t/g, '')
|
|
44
|
+
// Remove extra spaces
|
|
45
|
+
.replace(/\s\s+/g, ' ')
|
|
46
|
+
.trim()
|
|
47
|
+
|
|
48
|
+
propsValues = cleanProps.split(" ").reduce((acc, curr) => {
|
|
49
|
+
const hasQuotes = curr.match(/=['"]/)
|
|
50
|
+
// Check key="value" | key='value' | key={value}
|
|
51
|
+
const propWithValue = /([A-Za-z-_$]+)=['{"](.*)['}"]/g.exec(curr)
|
|
52
|
+
if (propWithValue && propWithValue[1]) {
|
|
53
|
+
return {
|
|
54
|
+
...acc,
|
|
55
|
+
[`${propWithValue[1]}`]: (hasQuotes) ? propWithValue[2] : convert(propWithValue[2])
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Check isLoading boolean props
|
|
59
|
+
const booleanProp = curr.match(/([A-Za-z]*)/)
|
|
60
|
+
if (booleanProp && booleanProp[1]) {
|
|
61
|
+
return {
|
|
62
|
+
...acc,
|
|
63
|
+
[`${booleanProp[1]}`]: true
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return acc
|
|
67
|
+
}, {})
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
tags.push({
|
|
71
|
+
tag: tag,
|
|
72
|
+
props: propsValues,
|
|
73
|
+
raw: match
|
|
74
|
+
})
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return tags
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function convert(value) {
|
|
81
|
+
if (value === 'false') {
|
|
82
|
+
return false
|
|
83
|
+
}
|
|
84
|
+
if (value === 'true') {
|
|
85
|
+
return true
|
|
86
|
+
}
|
|
87
|
+
const isNumber = Number(value)
|
|
88
|
+
if (typeof isNumber === 'number' && !isNaN(isNumber)) {
|
|
89
|
+
return isNumber
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
try {
|
|
93
|
+
const val = JSON.parse(value)
|
|
94
|
+
return val
|
|
95
|
+
} catch (err) {
|
|
96
|
+
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return value
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
module.exports = {
|
|
103
|
+
findHtmlTags,
|
|
104
|
+
MATCH_HTML_TAGS_REGEX
|
|
105
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const { onlyUnique } = require('./filters')
|
|
2
|
+
|
|
3
|
+
// https://regex101.com/r/u2DwY2/2/
|
|
4
|
+
const MARKDOWN_IMAGE_REGEX = /!\[[^\]]*\]\((.*?)\s*("(?:.*[^"])")?\s*\)/g
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Get markdown style images from text
|
|
8
|
+
* @param {string} text
|
|
9
|
+
* @returns {string[]}
|
|
10
|
+
*/
|
|
11
|
+
function findMarkdownImages(text) {
|
|
12
|
+
let matches
|
|
13
|
+
let imageLinks = []
|
|
14
|
+
while ((matches = MARKDOWN_IMAGE_REGEX.exec(text)) !== null) {
|
|
15
|
+
if (matches.index === MARKDOWN_IMAGE_REGEX.lastIndex) {
|
|
16
|
+
MARKDOWN_IMAGE_REGEX.lastIndex++ // avoid infinite loops with zero-width matches
|
|
17
|
+
}
|
|
18
|
+
const [ match, image, altText ] = matches
|
|
19
|
+
imageLinks.push(image)
|
|
20
|
+
}
|
|
21
|
+
return imageLinks.filter(onlyUnique)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
module.exports = {
|
|
25
|
+
findMarkdownImages,
|
|
26
|
+
MARKDOWN_IMAGE_REGEX
|
|
27
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
const { onlyUnique, isImage, isRelative } = require('./filters')
|
|
2
|
+
const { findLinks, findAbsoluteLinks } = require('./find-links')
|
|
3
|
+
const { findMarkdownImages, MARKDOWN_IMAGE_REGEX } = require('./find-images-md')
|
|
4
|
+
|
|
5
|
+
// https://regex101.com/r/Uxgu3P/1
|
|
6
|
+
const RELATIVE_IMAGES_REGEX = /(<img.*?src=['"])(?!(?:(?:https?|ftp):\/\/|data:))(\.?\/)?(.*?)(['"].*?\/?>)/gim
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {object} findImagesOpts
|
|
10
|
+
* @property {string[]} [links] - optional links to use to avoid re-parse
|
|
11
|
+
* @property {boolean} [unique=true] - ensure links unique
|
|
12
|
+
* @property {Record<string,any>} [frontmatter] - Frontmatter data
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @typedef {object} findImagesResult
|
|
17
|
+
* @property {string[]} all - All links
|
|
18
|
+
* @property {string[]} absolute - All absolute links
|
|
19
|
+
* @property {string[]} relative - All relative links
|
|
20
|
+
* @property {string[]} md - All md style links
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Get image links from content
|
|
25
|
+
* @param {string} content
|
|
26
|
+
* @param {findImagesOpts} [opts] - optional links to use to avoid re-parse
|
|
27
|
+
* @returns {findImagesResult}
|
|
28
|
+
*/
|
|
29
|
+
function findImages(content = '', opts = {}) {
|
|
30
|
+
const { links, unique = true, frontmatter } = opts
|
|
31
|
+
let foundLinks = []
|
|
32
|
+
if (links && Array.isArray(links)) {
|
|
33
|
+
foundLinks = links
|
|
34
|
+
} else {
|
|
35
|
+
const results = findLinks(content, { frontmatter })
|
|
36
|
+
foundLinks = results.links.concat(results.images)
|
|
37
|
+
}
|
|
38
|
+
const imageLinks = foundLinks.filter(isImage)
|
|
39
|
+
const markdownLinks = findMarkdownImages(content)
|
|
40
|
+
const allImageLinks = imageLinks.concat(markdownLinks)
|
|
41
|
+
const all = (!unique) ? allImageLinks : allImageLinks.filter(onlyUnique)
|
|
42
|
+
return {
|
|
43
|
+
all,
|
|
44
|
+
absolute: all.filter((link) => !isRelative(link)),
|
|
45
|
+
relative: all.filter((link) => isRelative(link)),
|
|
46
|
+
md: markdownLinks
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Get absolute url image links
|
|
52
|
+
* @param {string} content
|
|
53
|
+
* @param {array} [links] - optional links to use to avoid re-parse
|
|
54
|
+
* @returns {array}
|
|
55
|
+
*/
|
|
56
|
+
function findAbsoluteImages(content = '', links) {
|
|
57
|
+
const foundLinks = (links && Array.isArray(links)) ? links : findAbsoluteLinks(content)
|
|
58
|
+
const imageLinks = foundLinks.filter(isImage)
|
|
59
|
+
const markdownLinks = findMarkdownImages(content)
|
|
60
|
+
const allImageLinks = imageLinks.concat(markdownLinks)
|
|
61
|
+
|
|
62
|
+
return allImageLinks
|
|
63
|
+
.filter(onlyUnique)
|
|
64
|
+
.filter((link) => !isRelative(link))
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Get relative image links from content
|
|
69
|
+
* @param {string} text
|
|
70
|
+
* @returns {array}
|
|
71
|
+
*/
|
|
72
|
+
function findRelativeImages(text) {
|
|
73
|
+
const imgTags = findRelativeImgTags(text) || []
|
|
74
|
+
const mdTags = findMarkdownImages(text).filter(isRelative)
|
|
75
|
+
return imgTags.concat(mdTags)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/*
|
|
79
|
+
// https://regex101.com/r/SvMfme/1
|
|
80
|
+
<img src="img/deploy/button.svg" />
|
|
81
|
+
<img src="/img/deploy/button.svg" />
|
|
82
|
+
<img src='/img/deploy/button.svg' />
|
|
83
|
+
<img src='./img/deploy/button.svg' />
|
|
84
|
+
<img src='../img/deploy/button.svg' />
|
|
85
|
+
<img src='../../img/deploy/button.svg' />
|
|
86
|
+
*/
|
|
87
|
+
function findRelativeImgTags(block) {
|
|
88
|
+
let matches
|
|
89
|
+
let relLinks = []
|
|
90
|
+
while ((matches = RELATIVE_IMAGES_REGEX.exec(block)) !== null) {
|
|
91
|
+
if (matches.index === RELATIVE_IMAGES_REGEX.lastIndex) {
|
|
92
|
+
RELATIVE_IMAGES_REGEX.lastIndex++ // avoid infinite loops with zero-width matches
|
|
93
|
+
}
|
|
94
|
+
const [ match, _, start, link ] = matches
|
|
95
|
+
relLinks.push(`${start || ''}${link}`)
|
|
96
|
+
}
|
|
97
|
+
return relLinks.filter(onlyUnique)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
module.exports = {
|
|
101
|
+
findImages,
|
|
102
|
+
findAbsoluteImages,
|
|
103
|
+
findRelativeImages,
|
|
104
|
+
findMarkdownImages,
|
|
105
|
+
MARKDOWN_IMAGE_REGEX,
|
|
106
|
+
RELATIVE_IMAGES_REGEX
|
|
107
|
+
}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
const { onlyUnique, isImage, isRelative } = require('./filters')
|
|
2
|
+
const { findMarkdownImages } = require('./find-images-md')
|
|
3
|
+
// Alt https://github.com/MikeKovarik/link-extract
|
|
4
|
+
|
|
5
|
+
// https://regex101.com/r/In5HtG/3
|
|
6
|
+
// const LIVE_LINKS_REGEX = /(?:['"(])((?:https?:\/\/)[\w\d\-_,./?=#%:+&]{3,})/gmi
|
|
7
|
+
// https://regex101.com/r/In5HtG/4
|
|
8
|
+
const LIVE_LINKS_REGEX = /['"(]((?:https?:\/\/)[\w\d\-_,./?=#%:+&]{3,})|<(\S*:\/\/\S*)>/gmi
|
|
9
|
+
// https://regex101.com/r/Nywerx/3
|
|
10
|
+
const RELATIVE_LINKS_REGEX = /(src|href|\()=?(['"/])(?!(?:(?:https?|ftp):\/\/|data:))(\.?\/)?([\w\d-_./,?=#%:+&]+)(?:['")])?/gim
|
|
11
|
+
// https://regex101.com/r/u2DwY2/2/
|
|
12
|
+
const MARKDOWN_IMAGE_REGEX = /!\[[^\]]*\]\((.*?)\s*("(?:.*[^"])")?\s*\)/g
|
|
13
|
+
// https://regex101.com/r/UeQ049/2 <https://www.markdownguide.org>
|
|
14
|
+
const ANGLE_LINKS = /(<)(\S*[@:]\S*)(>)/
|
|
15
|
+
|
|
16
|
+
const LINK_PATTERN = /^https?:\/\//
|
|
17
|
+
|
|
18
|
+
function isLocal(link) {
|
|
19
|
+
return isRelative(link)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function isRemote(link) {
|
|
23
|
+
return !isRelative(link)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @typedef {object} findLinksOpts
|
|
28
|
+
* @property {Record<string,any>} [frontmatter] - Frontmatter data
|
|
29
|
+
* @property {boolean} [unique=true] - ensure links unique
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @typedef {object} findLinksResult
|
|
34
|
+
* @property {string[]} links - All images
|
|
35
|
+
* @property {string[]} images - All live image links
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Finds all links in text relative or otherwise
|
|
40
|
+
* @param {string} text
|
|
41
|
+
* @param {findLinksOpts} opts
|
|
42
|
+
* @returns {findLinksResult}
|
|
43
|
+
*/
|
|
44
|
+
function findLinks(text, opts = {}) {
|
|
45
|
+
const { unique = true, frontmatter } = opts
|
|
46
|
+
|
|
47
|
+
const absoluteLinks = findAbsoluteLinks(text)
|
|
48
|
+
// console.log('absoluteLinks', absoluteLinks)
|
|
49
|
+
const relativeLinks = findRelativeLinks(text)
|
|
50
|
+
// console.log('relativeLinks', relativeLinks)
|
|
51
|
+
const frontmatterLinks = (frontmatter) ? findLinksInFrontMatter(frontmatter) : []
|
|
52
|
+
// console.log('frontmatterLinks', frontmatterLinks)
|
|
53
|
+
const markdownImages = findMarkdownImages(text)
|
|
54
|
+
// console.log('markdownImages', markdownImages)
|
|
55
|
+
const foundLinks = frontmatterLinks
|
|
56
|
+
.concat(absoluteLinks)
|
|
57
|
+
.concat(relativeLinks)
|
|
58
|
+
.concat(markdownImages)
|
|
59
|
+
|
|
60
|
+
const allLinks = (!unique) ? foundLinks : foundLinks.filter(onlyUnique)
|
|
61
|
+
|
|
62
|
+
let _images = markdownImages
|
|
63
|
+
let _links = []
|
|
64
|
+
for (let i = 0; i < allLinks.length; i++) {
|
|
65
|
+
if (isImage(allLinks[i])) {
|
|
66
|
+
_images.push(allLinks[i])
|
|
67
|
+
} else {
|
|
68
|
+
_links.push(allLinks[i])
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// const allImages = normalLinks.filter((link) => isImage(link)).concat(mdLinks)
|
|
72
|
+
// const links = normalLinks.filter((link) => !isImage(link))
|
|
73
|
+
const images = _images.filter(onlyUnique)
|
|
74
|
+
const links = _links.filter(onlyUnique).filter(function(el) {
|
|
75
|
+
return images.indexOf(el) < 0
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
links,
|
|
80
|
+
images
|
|
81
|
+
}
|
|
82
|
+
/*
|
|
83
|
+
// Old return https://github.com/DavidWells/markdown-magic/blob/b148b4ad3876c4ea07371451d230a5e9cec57ce5/lib/utils/md/find-links.js#L32-L44
|
|
84
|
+
return {
|
|
85
|
+
// all,
|
|
86
|
+
// live,
|
|
87
|
+
// relative,
|
|
88
|
+
// frontmatter: frontmatterLinks,
|
|
89
|
+
links: {
|
|
90
|
+
all: allLink,
|
|
91
|
+
relative: allLink.filter(isLocal),
|
|
92
|
+
live: allLink.filter(isRemote)
|
|
93
|
+
},
|
|
94
|
+
images: {
|
|
95
|
+
all: allImg,
|
|
96
|
+
relative: allImg.filter(isLocal),
|
|
97
|
+
live: allImg.filter(isRemote)
|
|
98
|
+
},
|
|
99
|
+
}
|
|
100
|
+
*/
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function findMarkdownImageLinks(text) {
|
|
104
|
+
let matches
|
|
105
|
+
let imageLinks = []
|
|
106
|
+
while ((matches = MARKDOWN_IMAGE_REGEX.exec(text)) !== null) {
|
|
107
|
+
if (matches.index === MARKDOWN_IMAGE_REGEX.lastIndex) {
|
|
108
|
+
MARKDOWN_IMAGE_REGEX.lastIndex++ // avoid infinite loops with zero-width matches
|
|
109
|
+
}
|
|
110
|
+
const [ match, image, altText ] = matches
|
|
111
|
+
imageLinks.push(image)
|
|
112
|
+
}
|
|
113
|
+
return imageLinks.filter(onlyUnique)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Finds all links in markdown <a>, <img> and md link format []()
|
|
118
|
+
* @param {string} text
|
|
119
|
+
* @returns
|
|
120
|
+
*/
|
|
121
|
+
function findAbsoluteLinks(text) {
|
|
122
|
+
let matches
|
|
123
|
+
let links = []
|
|
124
|
+
while ((matches = LIVE_LINKS_REGEX.exec(text)) !== null) {
|
|
125
|
+
if (matches.index === LIVE_LINKS_REGEX.lastIndex) {
|
|
126
|
+
LIVE_LINKS_REGEX.lastIndex++ // avoid infinite loops with zero-width matches
|
|
127
|
+
}
|
|
128
|
+
const [ match, url, bracketLink ] = matches
|
|
129
|
+
links.push(url || bracketLink)
|
|
130
|
+
}
|
|
131
|
+
return links.filter(onlyUnique)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/*
|
|
135
|
+
Match relative links
|
|
136
|
+
<h1 jdjdjjdjd=lksjskljfsdlk="jdjdj">Netlify + FaunaDB
|
|
137
|
+
<a href="https://app.netlify.com/start/deploy?repository=https://github.com/netlify/netlify-faunadb-example&stack=fauna">
|
|
138
|
+
<img src="../../../../img/deploy/lol.svg">
|
|
139
|
+
</a>
|
|
140
|
+
</h1>
|
|
141
|
+
[link](/my-great-page)
|
|
142
|
+
<a href="img/deploy/one.svg">cool</a>
|
|
143
|
+
<img src="img/deploy/duplicate.svg" />
|
|
144
|
+
<img src="img/deploy/duplicate.svg" >
|
|
145
|
+
<img src="/img/deploy/three.svg" />
|
|
146
|
+
<img src='/img/deploy/four.svg' />
|
|
147
|
+
<img src='./img/deploy/five.svg' />
|
|
148
|
+
<img src='../img/deploy/button.svg' />
|
|
149
|
+
<img src='../../img/deploy/button.svg' />
|
|
150
|
+
<img src="https://www.netlify.com/img/deploy/button.svg" />
|
|
151
|
+
<img src="https://www.netlify.com/img/deploy/button.svg" />
|
|
152
|
+

|
|
153
|
+
*/
|
|
154
|
+
|
|
155
|
+
function findRelativeLinks(text) {
|
|
156
|
+
let matches
|
|
157
|
+
let relLinks = []
|
|
158
|
+
while ((matches = RELATIVE_LINKS_REGEX.exec(text)) !== null) {
|
|
159
|
+
if (matches.index === RELATIVE_LINKS_REGEX.lastIndex) {
|
|
160
|
+
RELATIVE_LINKS_REGEX.lastIndex++ // avoid infinite loops with zero-width matches
|
|
161
|
+
}
|
|
162
|
+
// console.log(matches)
|
|
163
|
+
const [ match, _, start, link, x ] = matches
|
|
164
|
+
const one = (start === '/') ? start : ''
|
|
165
|
+
const two = (link === '/') ? link : ''
|
|
166
|
+
relLinks.push(`${one}${two}${x}`)
|
|
167
|
+
}
|
|
168
|
+
return relLinks.filter(onlyUnique)
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function findLinksInFrontMatter(data) {
|
|
172
|
+
const yamlStrings = traverse(data)
|
|
173
|
+
// console.log('yamlStrings', yamlStrings)
|
|
174
|
+
const linksInYml = yamlStrings.map((string) => {
|
|
175
|
+
if (LINK_PATTERN.test(string)) {
|
|
176
|
+
return [string]
|
|
177
|
+
}
|
|
178
|
+
// console.log('string', string)
|
|
179
|
+
const results = findLinks(string)
|
|
180
|
+
return results.links.concat(results.images)
|
|
181
|
+
})
|
|
182
|
+
.filter((x) => {
|
|
183
|
+
if (x && x.length) {
|
|
184
|
+
return x.length
|
|
185
|
+
}
|
|
186
|
+
return false
|
|
187
|
+
})
|
|
188
|
+
.flat()
|
|
189
|
+
// console.log('linksInYml', linksInYml)
|
|
190
|
+
return linksInYml
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function traverse(x, arr = []) {
|
|
194
|
+
if (typeof x === 'string') {
|
|
195
|
+
arr.push(x)
|
|
196
|
+
} else if (Array.isArray(x)) {
|
|
197
|
+
traverseArray(x, arr)
|
|
198
|
+
} else if ((typeof x === 'object') && (x !== null)) {
|
|
199
|
+
traverseObject(x, arr)
|
|
200
|
+
}
|
|
201
|
+
return arr
|
|
202
|
+
}
|
|
203
|
+
function traverseArray(arr, acc) {
|
|
204
|
+
for (let i = 0; i < arr.length; i++) {
|
|
205
|
+
traverse(arr[i], acc)
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
function traverseObject(obj, acc) {
|
|
209
|
+
for (var key in obj) {
|
|
210
|
+
if (obj.hasOwnProperty(key)) {
|
|
211
|
+
traverse(obj[key], acc)
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
module.exports = {
|
|
217
|
+
findLinks,
|
|
218
|
+
findAbsoluteLinks,
|
|
219
|
+
findRelativeLinks
|
|
220
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const { getLineNumberFromMatch } = require('./utils')
|
|
2
|
+
|
|
3
|
+
// https://regex101.com/r/he9l06/2
|
|
4
|
+
// http://xahlee.info/js/html5_non-closing_tag.html
|
|
5
|
+
// voidTags
|
|
6
|
+
const CLOSE_TAG_REGEX = /<(br|hr|img|embed|col|link|meta)(([^>]*)([^/])(>)|>)/g
|
|
7
|
+
|
|
8
|
+
function findUnmatchedHtmlTags(block, filePath) {
|
|
9
|
+
let matches
|
|
10
|
+
let errors = []
|
|
11
|
+
const msg = (filePath) ? ` in ${filePath}` : ''
|
|
12
|
+
while ((matches = CLOSE_TAG_REGEX.exec(block)) !== null) {
|
|
13
|
+
if (matches.index === CLOSE_TAG_REGEX.lastIndex) {
|
|
14
|
+
CLOSE_TAG_REGEX.lastIndex++ // avoid infinite loops with zero-width matches
|
|
15
|
+
}
|
|
16
|
+
// console.log(matches)
|
|
17
|
+
const [ _, tag, insideOrEnd ] = matches
|
|
18
|
+
const lineNumber = getLineNumberFromMatch(block, matches)
|
|
19
|
+
const fixed = (insideOrEnd === '>') ? '/>' : `${insideOrEnd.substring(0, insideOrEnd.length - 1)}/>`
|
|
20
|
+
errors.push({
|
|
21
|
+
message: `Unclosing HTML tag on line ${lineNumber}${msg}.\n Need closing tag "/>" on: \n${_}`,
|
|
22
|
+
brokenTag: _,
|
|
23
|
+
correctUsage: `<${tag}${fixed}`
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
return errors
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
module.exports = {
|
|
30
|
+
CLOSE_TAG_REGEX,
|
|
31
|
+
findUnmatchedHtmlTags,
|
|
32
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Welcome to ABC
|
|
3
|
+
description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'
|
|
4
|
+
thumbnail: https://dope-frontmatter.com/img/deploy/button.svg
|
|
5
|
+
categories:
|
|
6
|
+
- company
|
|
7
|
+
authors:
|
|
8
|
+
- Bob Bob
|
|
9
|
+
- Joe Smoe
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
**Welcome to ABC!** Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur [keynote presentation](https://youtu.be/A1bL4pHuivU).
|
|
13
|
+
|
|
14
|
+
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
draft: true
|
|
3
|
+
template: page
|
|
4
|
+
path: /foo/bar
|
|
5
|
+
title: Default title
|
|
6
|
+
components:
|
|
7
|
+
- type: PageHeading
|
|
8
|
+
heading: Nice
|
|
9
|
+
subHeading: Add it
|
|
10
|
+
- type: content
|
|
11
|
+
content: >-
|
|
12
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur
|
|
16
|
+
- type: content
|
|
17
|
+
content: |-
|
|
18
|
+
More content
|
|
19
|
+
|
|
20
|
+
<ComponentXyz />
|
|
21
|
+
|
|
22
|
+
stuff
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
- type: content
|
|
26
|
+
content: Even more content
|
|
27
|
+
seo:
|
|
28
|
+
title: xyz
|
|
29
|
+
description: seo description here
|
|
30
|
+
updatedBy: David Wells
|
|
31
|
+
updatedAt: 2022-11-10T01:52:37.383Z
|
|
32
|
+
---
|