Markdown の表形式を作るのが面倒くさいので補助ツール作った

マークダウンの表を書くのが面倒くさかったので、WPF で作ってみました。

ただ、今回は、比較差異を出したかったので、比較処理がからまっています。ただつなげるだけだったら、sb.AppendLine($"| {lefts[i]} | {rights[i]} |") でいけるはずです。

動作イメージ

f:id:sutefu7:20190830135752p:plain

NuGet

  • AvalonEdit
  • Markdig

画面

<Window x:Class="WpfApp2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp2"
        xmlns:edit="http://icsharpcode.net/sharpdevelop/avalonedit"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <edit:TextEditor x:Name="textbox1" Grid.Column="0" ShowLineNumbers="True" FontSize="16" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Auto" />
        <edit:TextEditor x:Name="textbox2" Grid.Column="1" ShowLineNumbers="True" FontSize="16" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Auto" />
        <Grid Grid.Column="2">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition />
                <RowDefinition />
            </Grid.RowDefinitions>
            <Button x:Name="button1" Grid.Row="0" Content="merge" Height="50" />
            <edit:TextEditor x:Name="textbox3" Grid.Row="1" ShowLineNumbers="True" FontSize="16" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" />
            <WebBrowser x:Name="webBrowser1" Grid.Row="2" />
        </Grid>
    </Grid>
</Window>

コードビハインド

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Markdig;

namespace WpfApp2
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            this.button1.Click += Button1_Click;
        }

        private void Button1_Click(object sender, RoutedEventArgs e)
        {
            var sb = new StringBuilder();
            var lefts = this.textbox1.Text.Split(new String[] { "\r\n" }, StringSplitOptions.None).ToList();
            var rights = this.textbox2.Text.Split(new String[] { "\r\n" }, StringSplitOptions.None).ToList();

            // 処理を簡単にするため、仕様を設ける。左も右も同じ行数であること
            if (lefts.Count != rights.Count)
            {
                MessageBox.Show("左と右が同じ行数ではありません。空行を入れるなどして調整してください。", "エラー", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }

            var foundItems = new List<string>();

            for (var i = 0; i < lefts.Count; i++)
            {
                // 左から見た「両方ある、左にある、右にある」、右から見た「両方ある、左にある、右にある」
                // 左ベース
                if (!string.IsNullOrWhiteSpace(lefts[i]))
                {
                    var target = lefts[i];
                    var isRightFound = rights.Contains(target);

                    if (isRightFound && !foundItems.Contains(target))
                    {
                        sb.AppendLine($"| {target} | {target} |");
                        foundItems.Add(target);
                    }

                    if (!isRightFound)
                        sb.AppendLine($"| {target} |   |");
                }

                // 右ベース
                if (!string.IsNullOrWhiteSpace(rights[i]))
                {
                    var target = rights[i];
                    var isLeftFound = lefts.Contains(target);

                    if (isLeftFound && !foundItems.Contains(target))
                    {
                        sb.AppendLine($"| {target} | {target} |");
                        foundItems.Add(target);
                    }

                    if (!isLeftFound)
                        sb.AppendLine($"|   | {target} |");
                }
            }

            this.textbox3.Text = sb.ToString();

            // 生成した表(markdown)をプレビュー表示
            sb.Insert(0, "| key | value |\r\n|--|--|\r\n");

            var pipeline = new MarkdownPipelineBuilder().UseAdvancedExtensions().Build();
            var html = Markdown.ToHtml(sb.ToString(), pipeline);
            webBrowser1.NavigateToString(html);


        }
    }
}

html の変換部分が、<table> タグのみなので、ちゃんと<html> タグから書いて、CSS も適用してあげれば見た目もよくなるはずです。またブラウザを CefSharp(Chromium)に変えるのもいいですね~。