$line) { // 静态文本数据 $sep = Utils::strContains($line, [':', ':']); if ($sep) { list($key, $value) = Utils::getKeyValue($sep, $line); $data = [ 'type' => 'pair', 'label' => $key, 'text' => $value, ]; $finalData[] = $data; $prevDataKey = count($finalData) - 1; continue; } // 动态文本数据 $sep = Utils::strContains($line, ['=']); if ($sep) { list($key, $value) = Utils::getKeyValue($sep, $line); if ($key === '') { // While text is '= key' $key = $value; } if (isset($dataMap[$value])) { $data = [ 'type' => 'pair', 'label' => $key, 'text' => $dataMap[$value], ]; } else { $data = [ 'type' => 'pair', 'label' => $key, 'text' => '#' . $value, ]; } $finalData[] = $data; $prevDataKey = count($finalData) - 1; continue; } // 多行数据,附加到上一行 /* 暂时仅支持
if (preg_match('/^[ \t]+/', $line) && $prevDataKey !== null) { $finalData[$prevDataKey]['text'] .= "\n\n" . trim($line); continue; } */ if ($lineNum === 0) { $title = trim($line); continue; } // 归类为分栏数据 $data = [ 'type' => 'banner', 'text' => trim($line) ]; $finalData[] = $data; $prevDataKey = count($finalData) - 1; } return [$finalData, $title]; } public static function parseMap($dataMap) { $finalData = []; foreach ($dataMap as $key => $value) { $finalData[] = [ 'type' => 'pair', 'label' => $key, 'text' => $value ]; } return $finalData; } public static function buildText(Parser $parser, PPFrame $frame, array $dataMap, $title, $picture, $float) { global $wgIsekaiWidgetInformationTextSeparator; $sep = $wgIsekaiWidgetInformationTextSeparator; $lines = []; foreach ($dataMap as $information) { if ($information['type'] === 'pair') { $lines[] = $information['label'] . $sep . $information['text']; } } $html = implode("\n\n", $lines); $html = str_replace("\n", "\r\n", $html); $html = $parser->recursiveTagParseFully($html, $frame); return [$html, 'markerType' => 'nowiki']; } public static function buildInfoBox(Parser $parser, PPFrame $frame, array $dataMap, $title, $picture, $float) { $parser->getOutput()->addModules(['ext.isekai.information.infobox']); $tableClasses = ['wikitable-container', 'infobox']; if ($float === 'right') { $tableClasses[] = 'infobox-float-right'; } else if ($float === 'left') { $tableClasses[] = 'infobox-float-left'; } $htmlBuilder = [ Html::openElement('div', [ 'class' => implode(' ', $tableClasses) ]) . Html::openElement('table', [ 'class' => 'wikitable' ]) ]; if (is_string($title) && $title !== '') { $htmlBuilder[] = Html::rawElement('thead', [], Html::rawElement('th', ['colspan' => 2, 'class' => 'infobox-title'], $parser->recursiveTagParse($title, $frame) ) ); } $htmlBuilder[] = Html::openElement('tbody'); if (is_string($picture) && $picture !== '') { $htmlBuilder[] = Html::rawElement('tr', [], Html::rawElement('td', ['colspan' => 2, 'class' => 'infobox-picture'], $parser->recursiveTagParse("[[$picture|frameless]]", $frame)) ); } foreach ($dataMap as $information) { switch ($information['type']) { case 'pair': $htmlBuilder[] = Html::rawElement('tr', [], Html::rawElement('td', [], $parser->recursiveTagParse($information['label'], $frame)) . Html::rawElement('td', ['style' => 'text-align:center'], $parser->recursiveTagParse($information['text'], $frame)) ); break; case 'banner': $htmlBuilder[] = Html::rawElement('tr', [], Html::rawElement('td', ['colspan' => 2, 'class' => 'infobox-banner'], $parser->recursiveTagParse($information['text'], $frame)) ); break; } } $htmlBuilder[] = Html::closeElement('tbody') . Html::closeElement('table') . Html::closeElement('div'); $html = implode('', $htmlBuilder); return [$html, 'markerType' => 'nowiki']; } /** * @param string $content * @param array $args * @param Parser $parser * @param PPFrame $frame * @return array|string */ public static function create(string $content, array $args, Parser $parser, PPFrame $frame) { $configKeys = ['type', 'float', 'title_key', 'picture']; $configArgs = []; $infoArgs = []; foreach ($args as $key => $value) { if (in_array($key, $configKeys)) { $configArgs[$key] = $value; } else { $infoArgs[$key] = $value; } } $type = strtolower($configArgs['type']) ?? 'text'; $picture = $configArgs['picture'] ?? null; $float = $configArgs['float'] ?? ''; $titleKey = $configArgs['title_key'] ?? null; $title = null; if ($type === 'text') { // 文本模式中,没有title $titleKey = null; } else if ($type === 'infobox') { // 信息框默认居右 if ($float === '') { $float = 'right'; } } $dataMap = []; foreach ($infoArgs as $key => $value) { if ((is_int($key) && !$titleKey) || ($titleKey && $key === $titleKey)) { $title = $value; unset($dataMap[$key]); } else { $dataMap[$key] = $value; } } if (trim($content) !== '') { list($dataMap, $title) = static::parseContent($content, $dataMap, $title); } else { $dataMap = static::parseMap($dataMap); if ($type === 'infobox') { array_unshift($dataMap, [ 'type' => 'banner', 'text' => wfMessage('isekai-information-title-base-information')->parse() ]); } } switch ($type) { case 'text': return static::buildText($parser, $frame, $dataMap, $title, $picture, $float); case 'infobox': return static::buildInfoBox($parser, $frame, $dataMap, $title, $picture, $float); default: return '' . wfMessage('isekai-information-error-invalid-type')->parse() . ''; } } }