-
Notifications
You must be signed in to change notification settings - Fork 172
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow handing in pre-parsed AST #79
Comments
So we could do two things I think
The problem with 2 is, What do you think? |
The output of I am currently using this code and it works great but has a performance hit due to double parsing: const links = useMemo(() => {
const markdown = MarkdownIt({
html: false,
typographer: false,
})
const ast = tokensToAST(stringToTokens(children, markdown))
const collectLinks = (result: FinePrintLink[], node: ASTNode): FinePrintLink[] => {
if (node.type === "link") {
result.push({
uri: node.attributes.href,
text: node.children?.map(({ content }) => content).join(" "),
})
}
return node.children.reduce(collectLinks, result)
}
return ast.reduce(collectLinks, [])
}, [children]) I would not introduce a new prop, but rather define So my call to Markdown could look like this: const ast = tokensToAST(stringToTokens(children, markdown))
<Markdown onLinkPress={onPress} style={style}>{ast}</Markdown> Could also be possible const tokens = stringToTokens(children, markdown)
// same as
const tokens = MarkdownIt().parse(children)
<Markdown onLinkPress={onPress} style={style}>{tokens}</Markdown> What do you think? |
Hey Sorry about the delay here - can you take a look at https://github.com/iamacup/react-native-markdown-display/releases/tag/6.2.x and let me know if this is what you were thinking? Supports this syntax:
|
released this in 6.1.5 - re-open if we need to change how it works :) Readme is updated to reflect the above |
Thanks, I'll test it on Monday and report back here! |
@iamacup works like a charm! Thanks for fulfilling this feature request! |
Two problems in
p.s. |
@helsonxiao thanks for reporting back. to 1st: Could you provide a source snippet how you use the AST within the FlatList? The markdown component also uses just memoization internally so maybe your AST is re-calculated over and over again because of unstable dependencies? to 2nd: You mean images are not displayed that way? That shouldn't make any difference. Maybe a test case could be made for that. |
just opening to keep track of this in case it turns out to be library related - thanks for handling @pke !! |
const input = "![背包四讲.png](https://media-test.jiuzhang.com/media/markdown/images/7/16/72644746-c710-11ea-8f89-0242ac1c0003.jpg)\n\n```\n[[java]]\nasfafagagag233\n[[golang]]\nasfgsagag\n```\n\n![背包四讲.png](https://media-test.jiuzhang.com/media/markdown/images/7/16/72644746-c710-11ea-8f89-0242ac1c0003.jpg)" // turn on astPreprocessor then images disappear
return (
<Markdown /* astPreprocessor={astPreprocessor} */ rules={rules}>
{input}
</Markdown>
);
// here I just return the ast, nothing changed.
// I will use this method to pick up important nodes.
const astPreprocessor = (ast: ASTNode[]) => {
return ast;
};
const Markdown: React.FC<MarkdownProps> = props => {
const _props = {
rules,
style: MarkdownStyles,
...props,
};
if (props.astPreprocessor) {
const ast = tokensToAST(stringToTokens(props.children, markdownItInstance));
return <_Markdown {..._props}>{props.astPreprocessor(ast)}</_Markdown>;
}
return <_Markdown {..._props}>{props.children}</_Markdown>;
}; |
About the speed difference: const {
children,
astPreprocessor,
} = props
const content= useMemo(() => {
astPreprocessor ? astPreprocessor(tokenToAST(stringToTokens(children, markdownItInstance)) : children
}, [children, astPreprocessor])
return <_Markdown markdownIt={markdownItInstance} {...props}>{content}</_Markdown> Make sure you are also re-using the markdownItInstance you globally defined, or the Markdown component will create its own. About the images I'd have to check this out in a free minute, but without knowing your styles for images and what the preprocessor actually does with the AST, its hard to predict. |
I think the markdown input is not entirely settled. I copied them into my project then it works fine 😄. It could be nicer if you export them or refine the |
+1 to cleaning up the necessary imports for a custom However I wouldn't be in favour of consolidating the current functions into import {
MarkdownIt,
stringToTokens,
tokensToAST,
} from 'react-native-markdown-display';
import { cleanupTokens } from 'react-native-markdown-display/src/lib/util/cleanupTokens';
import groupTextTokens from 'react-native-markdown-display/src/lib/util/groupTextTokens';
const markdownIt = MarkdownIt({
typographer: true,
});
export default function toAST(markdownContent) {
// Process into an AST, to support the changing of links into blocklinks.
let tokens = stringToTokens(markdownContent, markdownIt);
tokens = cleanupTokens(tokens);
// It's important to blockify the links before grouping the text tokens,
// as this will exclude the links from being grouped, which would otherwise cause issues on Android.
tokens = blockifyLinks(tokens);
tokens = groupTextTokens(tokens);
return tokensToAST(tokens);
}
// We need links to be treated as 'blocklinks' so that styling works correctly.
function blockifyLinks(tokens) {
tokens.forEach((token) => {
if (token.type === 'link') {
token.block = true;
}
});
return tokens;
} |
For my component I'd like to extract all the text links from the markdown to build an action sheet out of the links.
So I would like to pre-parse the markdown using markdown-it for all links and then hand in that AST to the component instead of a markdown-it prop.
I want to prevent thet parsing of the markdown twice, once in my component and second in yours.
Do you think that would be a possible addition?
The text was updated successfully, but these errors were encountered: