asjqkkkk / markdown_widget

📖Rendering markdown by flutter!Welcome for pr and issue.
MIT License
312 stars 90 forks source link

How to resolve nested custom tags #136

Closed wzlsquall closed 10 months ago

wzlsquall commented 10 months ago

Now I define two custom tags :::plugin xxxxx ::: and :::collapse xxxxx ::: There is no problem when using tags separately, but can't parse text when nest them. for example::::plugin this is :::collapse test ::: document :::

my code:

class PluginNodeInlineSyntax extends m.InlineSyntax {
  PluginNodeInlineSyntax() : super(r'(:::plugin)((?:.|\n)*?)(:::)(?!(plugin|collapse))');

  @override
  bool onMatch(m.InlineParser parser, Match match) {
    xxx
    return true;
  }
}

class CollapseNodeInlineSyntax extends m.InlineSyntax {

  CollapseNodeInlineSyntax() : super(r'(:::collapse)((?:.|\n)*?)(:::)(?!(plugin|collapse))');

  @override
  bool onMatch(m.InlineParser parser, Match match) {
    xxx
    return true;
  }
}

Is there any solution? Thank you !

asjqkkkk commented 10 months ago

@wzlsquall 你好,这个应该是正则表达式的原因

对于这一块的正则表达式,我的熟练度并不是很高,可以尝试通过chatGPT来帮忙修正

wzlsquall commented 10 months ago

@wzlsquall 你好,这个应该是正则表达式的原因

对于这一块的正则表达式,我的熟练度并不是很高,可以尝试通过chatGPT来帮忙修正

@asjqkkkk 感谢回复,但是我觉得好像不是正则表达式的原因,我把标签简化后也不行,而且在自定义标签中嵌套的标准标签也不好用了。 不知道是不是该使用DelimiterSyntax来解析标签呢?

asjqkkkk commented 10 months ago

:::collapse xxxxx :::

你好,能否提供一下更加详细的使用例子,编写正则表达式应该能够完全覆盖这些使用场景才可以,不然就会有很奇怪的表现

具体也可以参考一下这个issue:https://github.com/asjqkkkk/markdown_widget/issues/79

wzlsquall commented 10 months ago

你好,能否提供一下更加详细的使用例子,编写正则表达式应该能够完全覆盖这些使用场景才可以,不然就会有很奇怪的表现 具体也可以参考一下这个issue:#79

:::{pluginName="atoc" displayName="插件名"}

请求方法:插件匹配
找到以下请求参数
* 文字描述: :readmore{content="这是一条测试数据"}
* 会话ID: :readmore{content="1"}
* 上传文件服务器的地址: :readmore{content="http://127.0.0.1:9527/sagera/module/upload"}
* 上传文件服务器的类型: :readmore{content="interface"}

|||{title="请求信息"}
请求方法:插件匹配
|||
:::

我的代码大概是这样子,其中:::xxx:::|||xxx|||都是自定义标签,现在的问题是如果想要实现嵌套,就需要使用DelimiterSyntax而不是InlineSyntax,但是如果使用DelimiterSyntax的话,结束标签前就不能有换行或者空格,否则无法解析。

import 'package:flutter/material.dart';
import 'package:markdown_widget/markdown_widget.dart';
import 'package:markdown/markdown.dart' as m;

const _pluginNode = "plugin";
const _collapseNode = "collapse";

class PluginNode extends ElementNode {
  final m.Element element;
  final MarkdownConfig config;

  @override
  TextStyle get style => parentStyle?.merge(TextStyle(color: Colors.lightBlueAccent)) ?? TextStyle(color: Colors.lightBlueAccent);

  PluginNode(this.element, this.config);
}

class CollapseNode extends ElementNode {
  final m.Element element;
  final MarkdownConfig config;

  @override
  TextStyle get style => parentStyle?.merge(TextStyle(color: Colors.orange)) ?? TextStyle(color: Colors.orange);

  CollapseNode(this.element, this.config);
}

class PluginNodeSyntax extends m.DelimiterSyntax {
  PluginNodeSyntax() : super(
    ':::',
    requiresDelimiterRun: true,
    tags: [m.DelimiterTag("plugin", 3)],
    startCharacter: 0x3A,
  );
}

class CollapseNodeSyntax extends m.DelimiterSyntax {
  CollapseNodeSyntax() : super(
    '|||',
    requiresDelimiterRun: true,
    tags: [m.DelimiterTag("collapse", 3)],
    startCharacter: 0x7C,
  );
}

SpanNodeGeneratorWithTag pluginGeneratorWithTag = SpanNodeGeneratorWithTag(
    tag: _pluginNode,
    generator: (e, config, visitor) => PluginNode(e, config));

SpanNodeGeneratorWithTag collapseGeneratorWithTag = SpanNodeGeneratorWithTag(
    tag: _collapseNode,
    generator: (e, config, visitor) => CollapseNode(e, config));
wzlsquall commented 10 months ago

具体也可以参考一下这个issue:#79

例子我试了,是不支持嵌套的,标准的md标签我也测试了,好像使用InlineSyntax进行解析的都不支持嵌套

asjqkkkk commented 10 months ago

@wzlsquall 请问是是要求筛选出如:::{pluginName="atoc" displayName="插件名"}|||{pluginName="atoc" displayName="插件名"}中花括号的内容吗?

同时,嵌套指的是?

目前理解到的规则就是筛选出:::{xxx}|||{xxx}xxx的内容,是否还有其他的规则?

wzlsquall commented 10 months ago

@asjqkkkk

请问是是要求筛选出如:::{pluginName="atoc" displayName="插件名"} 和 |||{pluginName="atoc" displayName="插件名"}中花括号的内容吗?

不是的,是要解析一对:::和一对|||中间的内容,同时可能会有:::abc|||def||ghi:::这种嵌套的情况。

这个问题我解决了,通过自定义InlineSyntax或者DelimiterSyntax是无法满足我的需求的,我通过重写MarkdownGenerator中的buildWidgets方法实现的,在final List<m.Node> nodes = document.parseLines(lines);之后,通过对nodes重新解析和构造自定义ElementNode实现的。

wzlsquall commented 10 months ago

@asjqkkkk 我的解决方案我给你发邮件了,有点麻烦,如果你有更好的建议一定告诉我一下