Upgrade for MediaWiki 1.39

master
落雨楓 2 years ago
parent bd762712a6
commit 045ed26cb3

@ -3,5 +3,6 @@ $magicWords = [
'en' => [ 'en' => [
'htmldetails' => [0, 'htmldetails'], 'htmldetails' => [0, 'htmldetails'],
'htmlsummary' => [0, 'htmlsummary'], 'htmlsummary' => [0, 'htmlsummary'],
'information' => [0, 'information']
], ],
]; ];

@ -1,5 +1,5 @@
{ {
"name": "Isekai Discover Box", "name": "Isekai Widgets",
"namemsg": "isekai-widgets", "namemsg": "isekai-widgets",
"author": "Hyperzlib", "author": "Hyperzlib",
"version": "1.0.3", "version": "1.0.3",
@ -29,6 +29,10 @@
"ext.isekai.widgets.global": { "ext.isekai.widgets.global": {
"styles": [ "styles": [
"ext.isekai.widgets.global.less" "ext.isekai.widgets.global.less"
],
"targets": [
"desktop",
"mobile"
] ]
}, },
"ext.isekai.createPage": { "ext.isekai.createPage": {
@ -56,42 +60,43 @@
}, },
"ext.isekai.discover": { "ext.isekai.discover": {
"scripts": [ "scripts": [
"feedList/ext.isekai.feedList.js" "discover/ext.isekai.discover.js",
"discover/ext.isekai.discover.base.js"
], ],
"styles": [ "styles": [
"feedList/ext.isekai.feedList.less" "discover/ext.isekai.discover.base.less"
], ],
"dependencies": [ "dependencies": [
"oojs", "oojs",
"oojs-ui-core", "oojs-ui-core",
"vue" "oojs-ui.styles.icons-interactions"
], ],
"targets": [ "targets": [
"desktop", "desktop",
"mobile" "mobile"
],
"messages": [
"isekai-discover-change-btn",
"isekai-discover-readmore-btn",
"isekai-discover-error-cannotload"
] ]
}, },
"ext.isekai.feedList": { "ext.isekai.feedList": {
"scripts": [ "scripts": [
"discover/ext.isekai.discover.js", "feedList/ext.isekai.feedList.js"
"discover/ext.isekai.discover.base.js"
], ],
"styles": [ "styles": [
"discover/ext.isekai.discover.base.less" "feedList/ext.isekai.feedList.less"
], ],
"dependencies": [ "dependencies": [
"oojs", "oojs",
"oojs-ui-core", "oojs-ui-core",
"oojs-ui.styles.icons-interactions" "oojs-ui.styles.icons-movement",
"vue"
], ],
"targets": [ "targets": [
"desktop", "desktop",
"mobile" "mobile"
],
"messages": [
"isekai-discover-change-btn",
"isekai-discover-readmore-btn",
"isekai-discover-error-cannotload"
] ]
}, },
"ext.isekai.previewCard": { "ext.isekai.previewCard": {
@ -149,5 +154,10 @@
} }
} }
}, },
"config": {
"IsekaiWidgetInformationTextSeparator": {
"value": ": "
}
},
"manifest_version": 2 "manifest_version": 2
} }

@ -23,5 +23,7 @@
"isekai-font-error-invalid-params": "Please specify name attributes.", "isekai-font-error-invalid-params": "Please specify name attributes.",
"isekai-font-error-font-name-invalid": "Font name cannot contain special characters.", "isekai-font-error-font-name-invalid": "Font name cannot contain special characters.",
"isekai-font-error-font-not-imported": "Font \"$1\" not imported." "isekai-font-error-font-not-imported": "Font \"$1\" not imported.",
"isekai-information-error-invalid-type": "Information \"type\" unsupported."
} }

@ -25,5 +25,7 @@
"isekai-font-error-invalid-params": "请提供name参数。", "isekai-font-error-invalid-params": "请提供name参数。",
"isekai-font-error-font-name-invalid": "字体名中不能包含特殊字符。", "isekai-font-error-font-name-invalid": "字体名中不能包含特殊字符。",
"isekai-font-error-font-not-imported": "未导入字体: \"$1\"。" "isekai-font-error-font-not-imported": "未导入字体: \"$1\"。",
"isekai-information-error-invalid-type": "提供的信息框类型错误"
} }

@ -23,5 +23,7 @@
"isekai-font-error-invalid-params": "請提供name參數。", "isekai-font-error-invalid-params": "請提供name參數。",
"isekai-font-error-font-name-invalid": "字體名中不能包含特殊字元。", "isekai-font-error-font-name-invalid": "字體名中不能包含特殊字元。",
"isekai-font-error-font-not-imported": "未導入字體: \"$1\"。" "isekai-font-error-font-not-imported": "未導入字體: \"$1\"。",
"isekai-information-error-invalid-type": "提供的信息框類型錯誤"
} }

@ -9,8 +9,8 @@ class CreatePageWidget {
return [$template, "markerType" => 'nowiki']; return [$template, "markerType" => 'nowiki'];
} }
public static function create($text, $params, $parser, $frame){ public static function create($text, $params, \Parser $parser, \PPFrame $frame){
$parser->getOutput()->addModules('ext.isekai.createPage'); $parser->getOutput()->addModules(['ext.isekai.createPage']);
return self::getHtml(); return self::getHtml();
} }

@ -9,8 +9,8 @@ class DiscoverWidget {
return [$template, "markerType" => 'nowiki']; return [$template, "markerType" => 'nowiki'];
} }
public static function create($text, $params, \Parser $parser, $frame){ public static function create($text, $params, \Parser $parser, \PPFrame $frame){
$parser->getOutput()->addModules('ext.isekai.discover'); $parser->getOutput()->addModules(['ext.isekai.discover']);
return self::getHtml(); return self::getHtml();
} }

@ -4,11 +4,11 @@ namespace Isekai\Widgets;
use Html; use Html;
class ExtraFontWidget { class ExtraFontWidget {
public static function create($text, $params, $parser, $frame){ public static function create($text, $params, \Parser $parser, \PPFrame $frame){
$existsFonts = $parser->extIsekaiWidgetsCache->get('extraFonts', INF, []); $existsFonts = $parser->extIsekaiWidgetsCache->get('extraFonts', INF, []);
$content = $text = $parser->recursiveTagParse($text, $frame); $content = $text = $parser->recursiveTagParse($text, $frame);
if (!isset($params['name']) || empty($params['name'])) { if (empty($params['name'])) {
return '<span class="error">' . wfMessage('isekai-font-error-invalid-params')->parse() . '</span>' . $content; return '<span class="error">' . wfMessage('isekai-font-error-invalid-params')->parse() . '</span>' . $content;
} }

@ -9,8 +9,8 @@ class FeedListWidget {
return [$template, "markerType" => 'nowiki']; return [$template, "markerType" => 'nowiki'];
} }
public static function create($text, $params, \Parser $parser, $frame){ public static function create($text, $params, \Parser $parser, \PPFrame $frame){
$parser->getOutput()->addModules('ext.isekai.feedList'); $parser->getOutput()->addModules(['ext.isekai.feedList']);
return self::getHtml(); return self::getHtml();
} }

@ -10,10 +10,10 @@ class FontFaceWidget {
* @param array $params * @param array $params
* @param \Parser $parser * @param \Parser $parser
* @param \PPFrame $frame * @param \PPFrame $frame
* @return string|string[]
*/ */
public static function create($text, $params, $parser, $frame) { public static function create($text, $params, \Parser $parser, \PPFrame $frame) {
if (!isset($params['src']) || !isset($params['name']) || if (empty($params['src']) || empty($params['name'])) {
empty($params['src']) || empty($params['name'])) {
return '<span class="error">' . wfMessage('isekai-fontface-error-invalid-params')->parse() . '</span>'; return '<span class="error">' . wfMessage('isekai-fontface-error-invalid-params')->parse() . '</span>';
} }

@ -5,7 +5,7 @@ use Html;
class Html5Widget { class Html5Widget {
public static function createDetails(string $text, array $args, \Parser $parser, \PPFrame $frame) { public static function createDetails(string $text, array $args, \Parser $parser, \PPFrame $frame) {
$parser->getOutput()->addModules('ext.isekai.collapse'); $parser->getOutput()->addModules(['ext.isekai.collapse']);
$allowedAttr = ['class']; $allowedAttr = ['class'];
$htmlArgs = array_filter($args, function($k) use($allowedAttr) { $htmlArgs = array_filter($args, function($k) use($allowedAttr) {
return in_array($k, $allowedAttr); return in_array($k, $allowedAttr);

@ -0,0 +1,140 @@
<?php
namespace Isekai\Widgets;
use MediaWiki\MediaWikiServices;
class InformationWidget {
public static function parseContent($content, $dataMap, $title) {
$lines = explode("\n", str_replace($content, "\r\n", "\n"));
$prevData = null;
$finalData = [];
foreach ($lines as $lineNum => $line) {
// 静态文本数据
$sep = Utils::strContains($line, [':', '']);
if ($sep) {
list($key, $value) = Utils::getKeyValue($sep, $line);
$data = [
'type' => 'pair',
'label' => $key,
'text' => $value,
];
$prevData = &$data;
$finalData[] = &$data;
continue;
}
// 动态文本数据
$sep = Utils::strContains($line, ['=']);
if ($sep) {
list($key, $value) = Utils::getKeyValue($sep, $line);
if (isset($dataMap[$value])) {
$data = [
'type' => 'pair',
'label' => $key,
'text' => $dataMap[$value],
];
} else {
$data = [
'type' => 'pair',
'label' => $key,
'text' => '#' . $value,
];
}
$prevData = &$data;
$finalData[] = &$data;
continue;
}
// 多行数据,附加到上一行
if (preg_match('/^[ \t]+/', $line) && $prevData && isset($prevData['text'])) {
$prevData['text'] .= "\n\n" . trim($line);
continue;
}
if ($lineNum === 0) {
$title = trim($line);
continue;
}
// 归类为分栏数据
$data = [
'type' => 'banner',
'text' => trim($line)
];
$prevData = &$data;
$finalData[] = &$data;
}
return [$finalData, $title];
}
public static function buildText(\Parser $parser, \PPFrame $frame, array $dataMap, $title, $picture, $float) {
$config = MediaWikiServices::getInstance()->getConfigFactory()->makeConfig('IsekaiWidget');
$sep = $config->get('IsekaiWidgetInformationTextSeparator');
$stringBuilder = [];
foreach ($dataMap as $information) {
if ($information['type'] === 'pair') {
$stringBuilder[] = $information['label'] . $sep .
Utils::makeParagraph($parser->recursiveTagParse($information['text'], $frame), false, true);
}
}
return [implode('', $stringBuilder), 'markerType' => 'nowiki'];
}
public static function buildTable(\Parser $parser, \PPFrame $frame, array $dataMap, $title, $picture, $float) {
}
/**
* @param \Parser $parser
* @param \PPFrame $frame
* @param $args
* @return array|string
*/
public static function create(\Parser $parser, \PPFrame $frame, $args) {
$configKeys = ['type', 'float', 'content', 'title_key', 'picture'];
$configArgs = [];
$infoArgs = [];
foreach ($args as $key => $value) {
if (in_array($key, $configKeys)) {
$configArgs[$key] = $value;
} else {
$infoArgs[$key] = $value;
}
}
$type = $configArgs['type'] ?? 'text';
$picture = $configArgs['picture'] ?? null;
$float = $configArgs['float'] ?? '';
$titleKey = $configArgs['title_key'] ?? null;
$title = null;
// 文本模式中没有title
if ($type === 'text') {
$titleKey = null;
}
$dataMap = [];
foreach ($infoArgs as $key => $value) {
if ((is_int($key) && !$titleKey) || ($titleKey && $key === $titleKey)) {
$title = $value;
unset($dataMap[$key]);
} else {
$dataMap[$key] = $value;
}
}
if (isset($configArgs['content'])) {
list($dataMap, $title) = static::parseContent($configArgs['content'], $dataMap, $title);
}
switch ($type) {
case 'text':
return static::buildText($parser, $frame, $dataMap, $title, $picture, $float);
default:
return '<span class="error">' . wfMessage('isekai-information-error-invalid-type')->parse() . '</span>';
}
}
}

@ -10,8 +10,8 @@ class PreviewCardWidget {
return [$template, "markerType" => 'nowiki']; return [$template, "markerType" => 'nowiki'];
} }
public static function create($text, $params, $parser, $frame){ public static function create($text, $params, \Parser $parser, \PPFrame $frame) {
$parser->getOutput()->addModules('ext.isekai.previewCard'); $parser->getOutput()->addModules(['ext.isekai.previewCard']);
$titleChunk = explode('/', $text); $titleChunk = explode('/', $text);
$len = count($titleChunk); $len = count($titleChunk);

@ -24,7 +24,7 @@ class TileWidget {
} }
public static function create(string $text, array $args, \Parser $parser, \PPFrame $frame){ public static function create(string $text, array $args, \Parser $parser, \PPFrame $frame){
$parser->getOutput()->addModules('ext.isekai.tile'); $parser->getOutput()->addModules(['ext.isekai.tile']);
$content = ''; $content = '';
if ($text) { if ($text) {

@ -6,7 +6,7 @@ class Utils {
return str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($input)); return str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($input));
} }
public static function makeParagraph($text, $hasUniq = false) { public static function makeParagraph($text, $hasUniq = false, $indent = false) {
$text = str_replace("\r\n", "\n", $text); $text = str_replace("\r\n", "\n", $text);
if (strpos($text, "\n\n") === false) { if (strpos($text, "\n\n") === false) {
return $text; return $text;
@ -29,7 +29,49 @@ class Utils {
$text = substr($text, strlen($matches[0])); $text = substr($text, strlen($matches[0]));
} }
} }
$lines = explode("\n\n", $text); $lines = explode("\n\n", $text);
return $prepend . "<p>" . implode("</p>\n<p>", $lines) . "</p>" . $append;
$stringBuilder = [$prepend];
foreach ($lines as $lineNum => $line) {
if ($lineNum > 0 && $indent) {
$elemAttr = [
'class' => 'paragraph-indent'
];
} else {
$elemAttr = [];
}
$stringBuilder[] = \Html::rawElement('p', $elemAttr, $line);
}
$stringBuilder[] = $append;
return implode('', $stringBuilder);
}
public static function strContains(string $haystack, array $needle) {
foreach ($needle as $one) {
if (strpos($haystack, $one) !== false) {
return $one;
}
}
return false;
}
public static function trimEach(array $arr) {
foreach ($arr as $key => $value) {
$arr[$key] = trim($value);
}
return $arr;
}
public static function getKeyValue(string $separator, string $str) {
$sepLen = strlen($separator);
$sepOffset = strpos($str, $separator);
if ($sepOffset === false) {
return [null, $str];
} else {
$key = trim(substr($str, 0, $sepOffset));
$value = trim(substr($str, $sepOffset + $sepLen));
return [$key, $value];
}
} }
} }

@ -7,6 +7,8 @@ use Parser;
class Widgets { class Widgets {
/** /**
* @param \Parser $parser * @param \Parser $parser
* @return bool
* @throws \MWException
*/ */
public static function onParserSetup(&$parser){ public static function onParserSetup(&$parser){
$parser->extIsekaiWidgetsCache = new MapCacheLRU( 100 ); // 100 is arbitrary $parser->extIsekaiWidgetsCache = new MapCacheLRU( 100 ); // 100 is arbitrary
@ -29,7 +31,9 @@ class Widgets {
} }
public static function onLoad(\OutputPage $outputPage) { public static function onLoad(\OutputPage $outputPage) {
$outputPage->addModuleStyles("ext.isekai.widgets.global"); $outputPage->addModuleStyles([
$outputPage->addModuleStyles("ext.isekai.collapse"); "ext.isekai.widgets.global",
"ext.isekai.collapse"
]);
} }
} }

@ -1,4 +1,5 @@
@height: 20rem; @height: 20rem;
@mobile-height: 60vh;
@text-size: 0.85rem; @text-size: 0.85rem;
.discover-card { .discover-card {
@ -65,6 +66,16 @@
margin: 0 0.4rem; margin: 0 0.4rem;
font-size: @text-size; font-size: @text-size;
} }
@media (max-width: 850px) {
.loading {
height: @mobile-height;
}
.card-content {
height: @mobile-height;
}
}
} }
&.discover-card-zh { &.discover-card-zh {

@ -16,6 +16,7 @@
border-bottom: 1px solid rgba(0,0,0,.125); border-bottom: 1px solid rgba(0,0,0,.125);
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between;
&:first-child { &:first-child {
border-radius: calc(.25rem - 1px) calc(.25rem - 1px) 0 0; border-radius: calc(.25rem - 1px) calc(.25rem - 1px) 0 0;
@ -25,7 +26,7 @@
font-size: 1.25rem; font-size: 1.25rem;
} }
.card-header-buttons { .card-header-extra {
margin-left: auto; margin-left: auto;
} }
} }

@ -1,4 +1,5 @@
@feed-list-height: 24rem; @feed-list-height: 24rem;
@feed-list-height-mobile: 70vh;
.isekai-feed-list-card > .card-header { .isekai-feed-list-card > .card-header {
height: 2.25rem; height: 2.25rem;
@ -27,6 +28,10 @@
width: 100%; width: 100%;
} }
} }
@media (max-width: 850px) {
height: @feed-list-height-mobile;
}
} }
.isekai-list { .isekai-list {
@ -42,6 +47,7 @@
-webkit-box-align: center; -webkit-box-align: center;
-ms-flex-align: center; -ms-flex-align: center;
align-items: center; align-items: center;
gap: 0.25rem;
-webkit-box-sizing: border-box; -webkit-box-sizing: border-box;
box-sizing: border-box; box-sizing: border-box;
min-height: 3rem; min-height: 3rem;
@ -68,8 +74,8 @@
-webkit-box-flex: 1; -webkit-box-flex: 1;
-ms-flex-positive: 1; -ms-flex-positive: 1;
flex-grow: 1; flex-grow: 1;
padding-top: 0.875rem; padding-top: 0.625rem;
padding-bottom: 0.875rem; padding-bottom: 0.625rem;
font-weight: 400; font-weight: 400;
font-size: 1rem; font-size: 1rem;
line-height: 1.25rem; line-height: 1.25rem;

@ -17,6 +17,9 @@
<div class="isekai-list-item-title">{{ feedItem.title }}</div> <div class="isekai-list-item-title">{{ feedItem.title }}</div>
<div class="isekai-list-item-text">{{ feedItem.description }}</div> <div class="isekai-list-item-text">{{ feedItem.description }}</div>
</div> </div>
<div class="isekai-list-item-icon">
<span class="oo-ui-widget oo-ui-widget-enabled oo-ui-iconElement oo-ui-iconElement-icon oo-ui-image-progressive oo-ui-icon-next oo-ui-labelElement-invisible oo-ui-iconWidget" aria-disabled="false"></span>
</div>
</a> </a>
</ul> </ul>
</div> </div>

Loading…
Cancel
Save