diff --git a/IsekaiWidgets.zip b/IsekaiWidgets.zip
new file mode 100644
index 0000000..25feedd
Binary files /dev/null and b/IsekaiWidgets.zip differ
diff --git a/docs/previewCard-design.md b/docs/previewCard-design.md
new file mode 100644
index 0000000..e2c02fa
--- /dev/null
+++ b/docs/previewCard-design.md
@@ -0,0 +1,10 @@
+## 预览卡片设计
+```html
+
+ [[链接1]]
+ [[链接2]]
+
+
+
+
+```
diff --git a/extension.json b/extension.json
index 8446546..6a141a3 100644
--- a/extension.json
+++ b/extension.json
@@ -19,6 +19,11 @@
"ParserFirstCallInit": "Isekai\\Widgets\\Widgets::onParserSetup"
},
"ResourceModules": {
+ "ext.isekai.widgets.global": {
+ "styles": [
+ "ext.isekai.alert.less"
+ ]
+ },
"ext.isekai.createPage": {
"scripts": [
"createPage/ext.isekai.createPage.js",
diff --git a/i18n/en.json b/i18n/en.json
index f92341e..e5b8827 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -14,5 +14,14 @@
"isekai-discover-loading": "Loading...",
"isekai-discover-change-btn": "Another",
"isekai-discover-readmore-btn": "Detail",
- "isekai-discover-error-cannotload": "Cannot load page from server."
+ "isekai-discover-error-cannotload": "Cannot load page from server.",
+
+ "isekai-fontface-error-invalid-params": "Please specify src and name attributes.",
+ "isekai-fontface-error-font-name-invalid": "Font name cannot contain special characters.",
+ "isekai-fontface-error-font-not-exists": "Font file \"$1\" not exists.",
+ "isekai-fontface-error-font-already-defined": "Font \"$1\" already imported, please check.",
+
+ "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-not-imported": "Font \"$1\" not imported."
}
\ No newline at end of file
diff --git a/i18n/zh-hans.json b/i18n/zh-hans.json
index 0c3bd95..a2fef24 100644
--- a/i18n/zh-hans.json
+++ b/i18n/zh-hans.json
@@ -14,5 +14,14 @@
"isekai-discover-loading": "加载中……",
"isekai-discover-change-btn": "换一个",
"isekai-discover-readmore-btn": "查看",
- "isekai-discover-error-cannotload": "无法从服务器加载数据"
+ "isekai-discover-error-cannotload": "无法从服务器加载数据",
+
+ "isekai-fontface-error-invalid-params": "请提供src和name参数。",
+ "isekai-fontface-error-font-name-invalid": "字体名中不能包含特殊字符。",
+ "isekai-fontface-error-font-not-exists": "字体文件 \"$1\" 不存在。",
+ "isekai-fontface-error-font-already-defined": "字体 \"$1\" 已引用,请检查重复引用。",
+
+ "isekai-font-error-invalid-params": "请提供name参数。",
+ "isekai-font-error-font-name-invalid": "字体名中不能包含特殊字符。",
+ "isekai-font-error-font-not-imported": "未导入字体: \"$1\"。"
}
\ No newline at end of file
diff --git a/i18n/zh-hant.json b/i18n/zh-hant.json
index 89d9db6..464c574 100644
--- a/i18n/zh-hant.json
+++ b/i18n/zh-hant.json
@@ -14,5 +14,14 @@
"isekai-discover-loading": "讀取中……",
"isekai-discover-change-btn": "換一個",
"isekai-discover-readmore-btn": "詳情",
- "isekai-discover-error-cannotload": "無法從伺服器讀取數據"
+ "isekai-discover-error-cannotload": "無法從伺服器讀取數據",
+
+ "isekai-fontface-error-invalid-params": "請提供src和name參數。",
+ "isekai-fontface-error-font-name-invalid": "字體名中不能包含特殊字元。",
+ "isekai-fontface-error-font-not-exists": "字體檔案 \"$1\" 不存在。",
+ "isekai-fontface-error-font-already-defined": "字體 \"$1\" 已被引用,請檢查重複引用。",
+
+ "isekai-font-error-invalid-params": "請提供name參數。",
+ "isekai-font-error-font-name-invalid": "字體名中不能包含特殊字元。",
+ "isekai-font-error-font-not-imported": "未導入字體: \"$1\"。"
}
\ No newline at end of file
diff --git a/includes/ExtraFontWidget.php b/includes/ExtraFontWidget.php
new file mode 100644
index 0000000..3116ef0
--- /dev/null
+++ b/includes/ExtraFontWidget.php
@@ -0,0 +1,39 @@
+extIsekaiWidgetsCache->get('extraFonts', INF, []);
+
+ $content = $text = $frame->expand($text);
+ if (!isset($params['name']) || empty($params['name'])) {
+ return '' . wfMessage('isekai-font-error-invalid-params')->parse() . '' . $content;
+ }
+
+ $fontName = 'extra-' . $params['name'];
+ if (preg_match('/[`~!@#$%^&*()+=<>?:"{}|,.\/;\'\\\\\[\]]\r\n/', $fontName)) {
+ return '' .
+ wfMessage('isekai-font-error-font-name-invalid')->parse() .
+ '' .
+ $content;
+ }
+
+ $existsFonts = $parser->extIsekaiWidgetsCache->get('extraFonts', INF, []);
+ if (!isset($existsFonts[$fontName])) {
+ return '' .
+ wfMessage('isekai-font-error-font-not-imported', $params['name'])->parse() .
+ '' .
+ $content;
+ }
+ $fontId = $existsFonts[$fontName];
+
+ return [
+ Html::rawElement('span', [
+ 'class' => 'isekai-extra-font font-' . $fontId,
+ ], $content),
+ "markerType" => 'nowiki'
+ ];
+ }
+}
\ No newline at end of file
diff --git a/includes/FontFaceWidget.php b/includes/FontFaceWidget.php
new file mode 100644
index 0000000..385c221
--- /dev/null
+++ b/includes/FontFaceWidget.php
@@ -0,0 +1,53 @@
+' . wfMessage('isekai-fontface-error-invalid-params')->parse() . '';
+ }
+
+ $service = MediaWikiServices::getInstance();
+
+ $fontName = 'extra-' . $params['name'];
+ $existsFonts = $parser->extIsekaiWidgetsCache->get('extraFonts', INF, []);
+ if (isset($existsFonts[$fontName])) {
+ return '' .
+ wfMessage('isekai-fontface-error-font-already-defined', $params['name'])->parse() .
+ '';
+ }
+ if (preg_match('/[`~!@#$%^&*()+=<>?:"{}|,.\/;\'\\\\\[\]]\r\n/', $fontName)) {
+ return '' .
+ wfMessage('isekai-fontface-error-font-name-invalid')->parse() .
+ '';
+ }
+
+ $title = Title::newFromText($params['src'], NS_FILE);
+ $file = $service->getRepoGroup()->findFile($title);
+ if (!$file) {
+ return '' .
+ wfMessage('isekai-fontface-error-font-not-exists', $params['src'])->parse() .
+ '';
+ }
+
+ $fontUrl = $file->getUrl();
+ $fontId = substr(Utils::safeBase64Encode(md5($fontName, true)), 0, 8);
+ $css = "";
+
+ $existsFonts[$fontName] = $fontId;
+ $existsFonts = $parser->extIsekaiWidgetsCache->set('extraFonts', $existsFonts);
+
+ return [$css, "markerType" => 'nowiki'];
+ }
+}
\ No newline at end of file
diff --git a/includes/PreviewCardWidget.php b/includes/PreviewCardWidget.php
index 0180793..58be736 100644
--- a/includes/PreviewCardWidget.php
+++ b/includes/PreviewCardWidget.php
@@ -5,7 +5,7 @@ class PreviewCardWidget {
public static function getHtml($variables){
extract($variables);
ob_start();
- include(dirname(__DIR__) . '/modules/previewCard/ext.isekai.previewCard.tpl');
+ include(dirname(__DIR__) . '/modules/previewCard/ext.isekai.previewCard.html');
$template = ob_get_clean();
return [$template, "markerType" => 'nowiki'];
}
diff --git a/includes/Utils.php b/includes/Utils.php
new file mode 100644
index 0000000..d18d572
--- /dev/null
+++ b/includes/Utils.php
@@ -0,0 +1,8 @@
+extIsekaiWidgetsCache = new MapCacheLRU( 100 ); // 100 is arbitrary
+
$parser->setHook('createpage', CreatePageWidget::class . '::create');
$parser->setHook('discoverbox', DiscoverWidget::class . '::create');
$parser->setHook('previewcard', PreviewCardWidget::class . '::create');
$parser->setHook('tile', TileWidget::class . '::create');
$parser->setHook('tilegroup', TileGroupWidget::class . '::create');
+
+ $parser->setHook('fontface', FontFaceWidget::class . '::create');
+ $parser->setHook('exfont', ExtraFontWidget::class . '::create');
return true;
}
}
\ No newline at end of file
diff --git a/modules/ext.isekai.alert.less b/modules/ext.isekai.alert.less
new file mode 100644
index 0000000..e69de29
diff --git a/modules/previewCard/ext.isekai.previewCard.tpl b/modules/previewCard/ext.isekai.previewCard.html
similarity index 91%
rename from modules/previewCard/ext.isekai.previewCard.tpl
rename to modules/previewCard/ext.isekai.previewCard.html
index 4a5d098..93a6f62 100644
--- a/modules/previewCard/ext.isekai.previewCard.tpl
+++ b/modules/previewCard/ext.isekai.previewCard.html
@@ -1,5 +1,5 @@