-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
| 📖 [PR App][pr] | 🎫 Resolve CX-1135, RM-11085 | | :-------------: | :-----------------: | ## 🧰 Changes Fixes incompatable emphasis during the migration. I [fixed this](#988) in `@readme/mdx`, but I think it'll be nicer to keep the migration specific stuff in the main app. ## 💁 Customer Impact <!-- PLEASE DESCRIBE IF THIS CHANGE AFFECTS CUSTOMERS AND HOW --> <!-- This is extremely useful for Tony and Marc writing the changelog! --> ## 🧬 QA & Testing - [ ] insert the string `*the recommended initial action is to**initiate a[reversal operation (rollback)](https://docs.jupico.com/reference/ccrollback)**. *` into a page - [ ] note the bold and italics - [ ] migrate the project - [ ] confirm that the bold and italics render the same in the dash and hub <!-- --> - [Broken on next][next]. - [Working in this PR][pr]! [next]: https://next.readme.ninja [pr]: https://readme-pr-12963.readme.ninja [ui]: https://readme-pr-12963.readme.ninja/ui <!-- Uncomment and unescape this if you don't want a PR app! --> <!-- \[skip preview\] -->
- Loading branch information
0 parents
commit ea55754
Showing
2 changed files
with
162 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import type { $TSFixMe } from '@readme/iso'; | ||
import type { Emphasis, Parent, Root, Strong, Text } from 'mdast'; | ||
|
||
import visit from 'unist-util-visit'; | ||
|
||
const strongTest = (node: any): node is Emphasis | Strong => ['emphasis', 'strong'].includes(node.type); | ||
|
||
const addSpaceBefore = (index: number, parent: Parent) => { | ||
if (!(index > 0 && parent.children[index - 1])) return; | ||
|
||
const prev = parent.children[index - 1]; | ||
// @ts-ignore - I think this is also a dependency versioning issue | ||
if (!('value' in prev) || prev.value.endsWith(' ') || prev.type === 'escape') return; | ||
|
||
parent.children.splice(index, 0, { type: 'text', value: ' ' }); | ||
}; | ||
|
||
const addSpaceAfter = (index: number, parent: Parent) => { | ||
if (!(index < parent.children.length - 1 && parent.children[index + 1])) return; | ||
|
||
const nextChild = parent.children[index + 1]; | ||
if (!('value' in nextChild) || nextChild.value.startsWith(' ')) return; | ||
|
||
parent.children.splice(index + 1, 0, { type: 'text', value: ' ' }); | ||
}; | ||
|
||
const trimEmphasis = (node: Emphasis | Strong, index: number, parent: Parent) => { | ||
let trimmed = false; | ||
|
||
// @ts-expect-error: the current version of visit is before the package | ||
// types/mdast was created | ||
visit(node, 'text', (child: Text) => { | ||
const newValue = child.value.trim(); | ||
|
||
if (newValue !== child.value) { | ||
trimmed = true; | ||
child.value = newValue; | ||
} | ||
}); | ||
|
||
if (trimmed) { | ||
addSpaceBefore(index, parent); | ||
addSpaceAfter(index, parent); | ||
} | ||
}; | ||
|
||
const emphasisTransfomer = () => (tree: Root) => { | ||
// @ts-expect-error: the current version of visit is before the package | ||
// types/mdast was created | ||
visit(tree, strongTest, trimEmphasis as $TSFixMe); | ||
|
||
return tree; | ||
}; | ||
|
||
export default emphasisTransfomer; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
import type { $TSFixMe } from '@readme/iso'; | ||
import type { Code, InlineCode, Root, Table, TableCell, TableRow } from 'mdast'; | ||
import type { VFile } from 'vfile'; | ||
|
||
import * as rdmd from '@readme/markdown'; | ||
import visit, { SKIP } from 'unist-util-visit'; | ||
|
||
import emphasisTransfomer from './emphasis'; | ||
|
||
const magicIndex = (i: number, j: number) => `${i === 0 ? 'h' : `${i - 1}`}-${j}`; | ||
|
||
// @note: This regex is detect malformed lists that were created by the | ||
// markdown editor. Consider the following markdown: | ||
// | ||
// ``` | ||
// * item 1 | ||
// * item 2 | ||
// * item 3 | ||
// ``` | ||
// | ||
// This is a perfectly valid list. But when you put that text into a table | ||
// cell, the editor does **bad** things. After a save and load cycle, it gets | ||
// converted to this: | ||
// | ||
// ``` | ||
// \_ item 1 | ||
// \_ item 2 | ||
// \* item 3 | ||
// ``` | ||
// | ||
// The following regex attempts to detect this pattern, and we'll convert it to | ||
// something more standard. | ||
const psuedoListRegex = /^(?<ws>[ \t]*)\\?[*_]\s*(?<item>.*)$/gm; | ||
|
||
const migrateTableCells = (vfile: VFile) => (table: Table) => { | ||
let json; | ||
try { | ||
const { position } = table; | ||
|
||
if (position) { | ||
json = JSON.parse( | ||
vfile | ||
.toString() | ||
.slice(position.start.offset, position.end.offset) | ||
.replace(/.*\[block:parameters\](.*)\[\/block\].*/s, '$1'), | ||
); | ||
} | ||
} catch (err) { | ||
/** | ||
* This failure case is already handled by the following logic. Plus, | ||
* because it's being handled internally, there's no way for our | ||
* migration script to catch the error or keep track of it, and it just | ||
* ends up blowing up the output logs. | ||
*/ | ||
// console.error(err); | ||
} | ||
|
||
// @ts-expect-error: the current version of visit is before the package | ||
// types/mdast was created | ||
visit(table, 'tableRow', (row: TableRow, i: number) => { | ||
// @ts-expect-error: the current version of visit is before the package | ||
// types/mdast was created | ||
visit(row, 'tableCell', (cell: TableCell, j: number) => { | ||
let children = cell.children; | ||
|
||
if (json && json.data[magicIndex(i, j)]) { | ||
const string = json.data[magicIndex(i, j)].replace(psuedoListRegex, '$1- $2'); | ||
|
||
children = rdmd.mdast(string).children; | ||
} | ||
|
||
// eslint-disable-next-line no-param-reassign | ||
cell.children = children.length > 1 ? children : ([{ type: 'paragraph', children }] as $TSFixMe); | ||
|
||
return SKIP; | ||
}); | ||
|
||
return SKIP; | ||
}); | ||
|
||
// @ts-expect-error: the current version of visit is before the package | ||
// types/mdast was created | ||
visit(table, 'inlineCode', (code: Code | InlineCode) => { | ||
if (code.value.includes('\n')) { | ||
// eslint-disable-next-line no-param-reassign | ||
code.type = 'code'; | ||
} | ||
}); | ||
}; | ||
|
||
const compatability = | ||
() => | ||
(tree: Root, vfile: VFile): Root => { | ||
// @ts-expect-error: the current version of visit is before the package | ||
// types/mdast was created | ||
visit(tree, 'table', migrateTableCells(vfile)); | ||
|
||
return tree; | ||
}; | ||
|
||
export const compatParser = (doc: string): Root => { | ||
const proc = rdmd.processor().use(compatability).use(emphasisTransfomer); | ||
const tree = proc.parse(doc); | ||
proc.runSync(tree, doc); | ||
|
||
return tree; | ||
}; |