xref: /webtrees/app/CommonMark/CensusTableContinueParser.php (revision 1da5dadd02c9f21e0a345e21a19b2c63ae792ed3)
1<?php
2
3/**
4 * webtrees: online genealogy
5 * Copyright (C) 2023 webtrees development team
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18declare(strict_types=1);
19
20namespace Fisharebest\Webtrees\CommonMark;
21
22use League\CommonMark\Extension\Table\Table;
23use League\CommonMark\Extension\Table\TableCell;
24use League\CommonMark\Extension\Table\TableRow;
25use League\CommonMark\Extension\Table\TableSection;
26use League\CommonMark\Node\Block\AbstractBlock;
27use League\CommonMark\Node\Inline\Text;
28use League\CommonMark\Parser\Block\AbstractBlockContinueParser;
29use League\CommonMark\Parser\Block\BlockContinue;
30use League\CommonMark\Parser\Block\BlockContinueParserInterface;
31use League\CommonMark\Parser\Cursor;
32
33use function array_map;
34use function explode;
35use function str_starts_with;
36use function strlen;
37use function substr;
38
39/**
40 * Convert webtrees 1.x census-assistant markup into tables.
41 * Note that webtrees 2.0 generates markdown tables directly.
42 */
43class CensusTableContinueParser extends AbstractBlockContinueParser
44{
45    private Table $table;
46
47    private TableSection $thead;
48
49    private TableSection $tbody;
50
51    /**
52     * Constructor
53     */
54    public function __construct()
55    {
56        $this->table = new Table();
57        $this->thead = new TableSection(TableSection::TYPE_HEAD);
58        $this->tbody = new TableSection(TableSection::TYPE_BODY);
59        $this->table->appendChild($this->thead);
60        $this->table->appendChild($this->tbody);
61    }
62
63    /**
64     * @param Cursor                       $cursor
65     * @param BlockContinueParserInterface $activeBlockParser
66     *
67     * @return BlockContinue|null
68     */
69    public function tryContinue(Cursor $cursor, BlockContinueParserInterface $activeBlockParser): ?BlockContinue
70    {
71        $line = $cursor->getLine();
72
73        if ($line === CensusTableExtension::CA_SUFFIX) {
74            return BlockContinue::finished();
75        }
76
77        // Blank line before the suffix is an error.
78        if ($line === '') {
79            return BlockContinue::none();
80        }
81
82        $cells = explode('|', $line);
83
84        $callback = static function (string $text): string {
85            if (str_starts_with($text, CensusTableExtension::TH_PREFIX)) {
86                return substr($text, strlen(CensusTableExtension::TH_PREFIX));
87            }
88
89            return $text;
90        };
91
92        $tr = new TableRow();
93
94        if (empty($this->thead->children())) {
95            $cells = array_map($callback, $cells);
96
97            foreach ($cells as $cell) {
98                $table_cell = new TableCell(TableCell::TYPE_HEADER);
99                $table_cell->appendChild(new Text($cell));
100                $tr->appendChild($table_cell);
101            }
102
103            $this->thead->appendChild($tr);
104        } else {
105            foreach ($cells as $cell) {
106                $table_cell = new TableCell(TableCell::TYPE_DATA);
107                $table_cell->appendChild(new Text($cell));
108                $tr->appendChild($table_cell);
109            }
110
111            $this->tbody->appendChild($tr);
112        }
113
114        return BlockContinue::at($cursor);
115    }
116
117    /**
118     * @return Table
119     */
120    public function getBlock(): AbstractBlock
121    {
122        return $this->table;
123    }
124}
125