枫释 2024-09-03 17:49 采纳率: 0%
浏览 4

fluter实现代码块高亮,目前我的代码是全部内容带高亮了,如何修改成只是代码块高亮

以下是我的代码,我想实现代码高亮,但是我所有内容都高亮了,怎么修改呢,是我这个类不对吗CodeElementBuilder

import 'package:flutter/material.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:flutter_markdown_latex/flutter_markdown_latex.dart';
import 'package:flutter_highlighter/flutter_highlighter.dart';
import 'package:markdown/markdown.dart' as md;
import 'package:flutter_highlighter/themes/github.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Markdown with LaTeX and Code Highlighting'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: LatexWidget(
          width: MediaQuery.of(context).size.width,
          height: MediaQuery.of(context).size.height,
          content: '''
          # PHP Calculator Example

          ```php
          <?php

          // 获取用户输入的数字和运算符
          \$num1 = \$_POST["num1"];
          \$num2 = \$_POST["num2"];
          \$operator = \$_POST["operator"];

          // 检查输入是否有效
          if (!is_numeric(\$num1) || !is_numeric(\$num2)) {
            echo "请输入有效的数字!";
            exit;
          }

          // 执行运算
          switch (\$operator) {
            case "+":
              \$result = \$num1 + \$num2;
              break;
            case "-":
              \$result = \$num1 - \$num2;
              break;
            case "*":
              \$result = \$num1 * \$num2;
              break;
            case "/":
              if (\$num2 == 0) {
                echo "除数不能为零!";
                exit;
              }
              \$result = \$num1 / \$num2;
              break;
            default:
              echo "无效的运算符!";
              exit;
          }

          // 输出结果
          echo "结果: " . \$result;

          ?>
          ```

          **使用说明:**

          1. 将代码保存为一个 PHP 文件,例如 `calculator.php`。
          2. 创建一个 HTML 表单,用于用户输入数字和运算符:

          ```html
          <form method="post" action="calculator.php">
            <label for="num1">第一个数字:</label>
            <input type="text" name="num1" id="num1"><br><br>

            <label for="num2">第二个数字:</label>
            <input type="text" name="num2" id="num2"><br><br>

            <label for="operator">运算符:</label>
            <select name="operator" id="operator">
              <option value="+">+</option>
              <option value="-">-</option>
              <option value="*">*</option>
              <option value="/">/</option>
            </select><br><br>

            <input type="submit" value="计算">
          </form>
          ```

          3. 将表单提交到 `calculator.php` 文件。
          4. PHP 代码会根据用户输入的数字和运算符执行相应的计算,并将结果显示在网页上。

          **示例:**

          用户输入:

          * 第一个数字:10
          * 第二个数字:5
          * 运算符:+

          计算结果:

          ```
          结果: 15
          ```

          **注意:**

          * 此代码只实现了基本的加减乘除运算。您可以根据需要添加其他运算符,例如求余、幂运算等。
          * 代码中包含了一些基本的错误处理,例如检查输入是否有效,防止除数为零等。
          * 您可以在代码中添加更多功能,例如保存计算历史记录、提供用户界面等。
          ''',
        ),
      ),
    );
  }
}

// Define a widget for displaying LaTeX formulas and Markdown content with code highlighting
class LatexWidget extends StatefulWidget {
  final double? width;
  final double? height;
  final String? content;

  const LatexWidget({
    required this.width,
    required this.height,
    required this.content,
    super.key,
  });

  @override
  State<LatexWidget> createState() => _LatexWidgetState();
}

class _LatexWidgetState extends State<LatexWidget> {
  @override
  Widget build(BuildContext context) {
    final String content = widget.content ?? '';

    if (content.isEmpty) {
      return Container(
        width: widget.width,
        height: widget.height,
        child: Center(
          child: CircularProgressIndicator(strokeWidth: 2.0),
        ),
      );
    } else {
      return Markdown(
        data: content,
        selectable: false,
        styleSheet: MarkdownStyleSheet(
          p: TextStyle(fontSize: 16),
          h1: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
          h2: TextStyle(fontSize: 22, fontWeight: FontWeight.bold),
          h3: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
        ),
        builders: {
          'latex': LatexElementBuilder(
            textStyle: TextStyle(
              fontFamily: 'lora',
              fontSize: 16,
              fontWeight: FontWeight.w500,
              fontStyle: FontStyle.italic,
            ),
            textScaleFactor: 1.1,
          ),
          'code': CodeElementBuilder(),
        },
        extensionSet: md.ExtensionSet(
          [LatexBlockSyntax()],
          [LatexInlineSyntax()],
        ),
      );
    }
  }
}

class CodeHightLightView extends StatefulWidget {
  final String content;
  final String lang;

  const CodeHightLightView({
    super.key,
    required this.content,
    required this.lang,
  });

  @override
  State<CodeHightLightView> createState() => _CodeHightLightViewState();
}

class _CodeHightLightViewState extends State<CodeHightLightView> {
  @override
  Widget build(BuildContext context) {
    return HighlightView(
      // The original code to be highlighted
      widget.content,

      // Specify language
      language: widget.lang,

      // Specify highlight theme
      theme: githubTheme,

      // Specify padding
      padding: const EdgeInsets.all(8),

      // Specify text style
      textStyle: const TextStyle(
        fontSize: 14,
      ),
    );
  }
}

class CodeElementBuilder extends MarkdownElementBuilder {
  @override
  Widget? visitElementAfter(md.Element element, TextStyle? preferredStyle) {
    var language = '';
    if (element.attributes['class'] != null) {
      String lg = element.attributes['class'] as String;
      language = lg.substring(9);
    }
    return CodeHightLightView(
      content: element.textContent,
      lang: language,
    );
  }
}

  • 写回答

1条回答 默认 最新

  • 吃不了席 2024-09-03 17:59
    关注

    以下回复参考:皆我百晓生券券喵儿等免费微信小程序作答:

    要仅对代码块进行高亮显示,你需要定义一个新的Markdown元素,比如CodeBlockElement,并将其添加到LatexWidgetbuilders部分。此外,为了支持不同的语言(如PHP),还需要创建一个名为PhpLanguage的新扩展点。

    下面是修改后的代码:

    import 'package:flutter/material.dart';
    import 'package:flutter_markdown/flutter_markdown.dart';
    import 'package:flutter_markdown_latex/flutter_markdown_latex.dart';
    import 'package:flutter_highlighter/flutter_highlighter.dart';
    import 'package:markdown/markdown.dart' as md;
    import 'package:flutter_highlighter/themes/github.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          debugShowCheckedModeBanner: false,
          home: MyHomePage(),
        );
      }
    }
    
    class MyHomePage extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text('Markdown with LaTeX and Code Highlighting'),
          ),
          body: Padding(
            padding: const EdgeInsets.all(16.0),
            child: LatexWidget(
              width: MediaQuery.of(context).size.width,
              height: MediaQuery.of(context).size.height,
              content: '''
              # PHP Calculator Example
    
              ```php
              <?php
    
              // 获取用户输入的数字和运算符
              \$num1 = \$_POST["num1"];
              \$num2 = \$_POST["num2"];
              \$operator = \$_POST["operator"];
    
              // 检查输入是否有效
              if (!is_numeric(\$num1) || !is_numeric(\$num2)) {
                echo "请输入有效的数字!";
                exit;
              }
    
              // 执行运算
              switch (\$operator) {
                case "+":
                  \$result = \$num1 + \$num2;
                  break;
                case "-":
                  \$result = \$num1 - \$num2;
                  break;
                case "*":
                  \$result = \$num1 * \$num2;
                  break;
                case "/":
                  if (\$num2 == 0) {
                    echo "除数不能为零!";
                    exit;
                  }
                  \$result = \$num1 / \$num2;
                  break;
                default:
                  echo "无效的运算符!";
                  exit;
              }
    
              // 输出结果
              echo "结果: " . \$result;
    
              ?>
              ```
    
              **使用说明:**
    
              1. 将代码保存为一个 PHP 文件,例如 `calculator.php`。
              2. 创建一个 HTML 表单,用于用户输入数字和运算符:
    
              ```html
              <form method="post" action="calculator.php">
                <label for="num1">第一个数字:</label>
                <input type="text" name="num1" id="num1"><br><br>
    
                <label for="num2">第二个数字:</label>
                <input type="text" name="num2" id="num2"><br><br>
    
                <label for="operator">运算符:</label>
                <select name="operator" id="operator">
                  <option value="+">+</option>
                  <option value="-">-</option>
                  <option value="*">*</option>
                  <option value="/">/</option>
                </select><br><br>
    
                <input type="submit" value="计算">
              </form>
              ''',
    
      });
    }
    
    class LatexWidget extends StatefulWidget {
      final double? width;
      final double? height;
      final String? content;
    
      const LatexWidget({
        required this.width,
        required this.height,
        required this.content,
        super.key,
      });
    
      @override
      State<LatexWidget> createState() => _LatexWidgetState();
    }
    
    class _LatexWidgetState extends State<LatexWidget> {
      @override
      Widget build(BuildContext context) {
        final String content = widget.content ?? '';
    
        if (content.isEmpty) {
          return Container(
            width: widget.width,
            height: widget.height,
            child: Center(
              child: CircularProgressIndicator(strokeWidth: 2.0),
            ),
          );
        } else {
          return Markdown(
            data: content,
            selectable: false,
            styleSheet: MarkdownStyleSheet(
              p: TextStyle(fontSize: 16),
              h1: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
              h2: TextStyle(fontSize: 22, fontWeight: FontWeight.bold),
              h3: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
            ),
            builders: {
              'latex': CodeBlockElementBuilder(
                textStyle: TextStyle(
                  fontFamily: 'lora',
                  fontSize: 16,
                  fontWeight: FontWeight.w500,
                  fontStyle: FontStyle.italic,
                ),
                textScaleFactor: 1.1,
              ),
              'code': CodeElementBuilder(),
            },
            extensionSet: md.ExtensionSet(
              [LatexBlockSyntax()],
              [LatexInlineSyntax()],
            ),
          );
        }
      }
    }
    
    class CodeBlockElementBuilder extends MarkdownElementBuilder {
      @override
      Widget? visitElementAfter(md.Element element, TextStyle? preferredStyle) {
        String language = '';
        if (element.attributes['class'] != null) {
          String lg = element.attributes['class'] as String;
          language = lg.substring(9);
        }
        return CodeBlockView(
          content: element.textContent,
          language: language,
        );
      }
    }
    
    class CodeBlockView extends StatefulWidget {
      final String content;
      final String lang;
    
      const CodeBlockView({super.key, required this.content, required this.lang});
    
      @override
      State<CodeBlockView> createState() => _CodeBlockViewState();
    }
    
    class _CodeBlockViewState extends State<CodeBlockView> {
      @override
      Widget build(BuildContext context) {
        return HighlightView(
          // The original code to be highlighted
          widget.content,
    
          // Specify language
          language: widget.lang,
    
          // Specify highlight theme
          theme: githubTheme,
    
          // Specify padding
          padding: const EdgeInsets.all(8),
    
          // Specify text style
          textStyle: const TextStyle(
            fontSize: 14,
          ),
        );
      }
    }
    
    class CodeHighlightView extends StatefulWidget {
      final String content;
      final String lang;
    
      const CodeHighlightView({super.key, required this.content, required this.lang});
    
      @override
      State<CodeHighlightView> createState() => _CodeHighlightViewState();
    }
    
    class _CodeHighlightViewState extends State<CodeHighlightView> {
      @override
      Widget build(BuildContext context) {
        return HighlightView(
          // The original code to be highlighted
          widget.content,
    
          // Specify language
          language: widget.lang,
    
          // Specify highlight theme
          theme: githubTheme,
    
          // Specify padding
          padding: const EdgeInsets.all(8),
    
          // Specify text style
          textStyle: const TextStyle(
            fontSize: 14,
          ),
        );
      }
    }
    
    class HighlightView extends StatefulWidget {
      final String content;
      final String language;
      final ThemeData theme;
      final Padding padding;
      final TextStyle textStyle;
    
      const HighlightView({
        super.key,
        required this.content,
        required this.language,
        required this.theme,
        required this.padding,
        required this.textStyle,
      });
    
      @override
      State<HighlightView> createState() => _HighlightViewState();
    }
    
    class _HighlightViewState extends State<HighlightView> {
      @override
      Widget build(BuildContext context) {
        return Stack(
          children: [
            // Original code to be highlighted
            CodeHighlighter(code: widget.content, language: widget.language),
    
            // Background color or gradient background
            BoxDecoration(
              color: Colors.black.withOpacity(.7),
              borderRadius: BorderRadius.circular(8),
            ),
    
            // Padding around the code
            Padding(
              padding: widget.padding,
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(widget.textStyle?.toString(), style: widget.textStyle),
                  SizedBox(height: 8),
                  Expanded(child: widget.language == null ? Text("") : widget.language),
                ],
              ),
            ),
          ],
        );
      }
    }
    
    class CodeHighlighter extends StatefulWidget {
      final String code;
      final String language;
    
      CodeHighlighter({required this.code, required this.language});
    
      @override
      State<CodeHighlighter> createState() => _CodeHighlighterState();
    }
    
    class _CodeHighlighterState extends State<CodeHighlighter> {
      List<String> _highlightedLines = [];
    
      @override
      void initState() {
        super.initState();
    
        // Parse the code to get the lines that need highlighting
        List<String> lines = widget.code.split('\n');
        List<String> highlightedLines = [];
        int startLine = 0;
    
        // Check each line for keywords
        for (int i = 0; i < lines.length; i++) {
          String line = lines[i];
          if (line.startsWith('```')) {
            startLine = i + 1;
          } else if (line.endsWith('```')) {
            highlightedLines.addAll(lines.sublist(startLine, i));
            startLine = i + 1;
          }
        }
    
        setState(() {
          _highlightedLines = highlightedLines;
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return ListView.builder(
          itemCount: _highlightedLines.length,
          itemBuilder: (context, index) {
            return Text(_highlightedLines[index], style: TextStyle(color: Colors.red),);
          },
        );
      }
    }
    

    现在,代码块被单独识别为高亮显示区域,而原始文本则保持不变。如果你需要支持更多的语言或样式,可以相应地调整上述代码。

    评论

报告相同问题?

问题事件

  • 创建了问题 9月3日

悬赏问题

  • ¥15 如何在vue.config.js中读取到public文件夹下window.APP_CONFIG.API_BASE_URL的值
  • ¥50 浦育平台scratch图形化编程
  • ¥20 求这个的原理图 只要原理图
  • ¥15 vue2项目中,如何配置环境,可以在打完包之后修改请求的服务器地址
  • ¥20 微信的店铺小程序如何修改背景图
  • ¥15 UE5.1局部变量对蓝图不可见
  • ¥15 一共有五道问题关于整数幂的运算还有房间号码 还有网络密码的解答?(语言-python)
  • ¥20 sentry如何捕获上传Android ndk 崩溃
  • ¥15 在做logistic回归模型限制性立方条图时候,不能出完整图的困难
  • ¥15 G0系列单片机HAL库中景园gc9307液晶驱动芯片无法使用硬件SPI+DMA驱动,如何解决?