修复Bug,增加新组件

1. 修复Tile加载图片错误
2. 增加自定义字体组件
3. 增加html5的detail和summary
master
落雨楓 3 years ago
parent 706e051d2e
commit 27ae0bcae7

@ -0,0 +1,7 @@
<?php
$magicWords = [
'en' => [
'htmldetails' => [0, 'htmldetails'],
'htmlsummary' => [0, 'htmlsummary'],
],
];

Binary file not shown.

@ -7,16 +7,23 @@
"descriptionmsg": "isekai-widgets-desc",
"license-name": "GPL-2.0-or-later",
"type": "parserhook",
"requires": {
"MediaWiki": ">= 1.34.0"
},
"MessagesDirs": {
"IsekaiWidgets": [
"i18n"
]
},
"ExtensionMessagesFiles": {
"IsekaiWidgetsMagic": "IsekaiWidgets.i18n.php"
},
"AutoloadNamespaces": {
"Isekai\\Widgets\\": "includes"
},
"Hooks": {
"ParserFirstCallInit": "Isekai\\Widgets\\Widgets::onParserSetup"
"ParserFirstCallInit": "Isekai\\Widgets\\Widgets::onParserSetup",
"BeforePageDisplay": "Isekai\\Widgets\\Widgets::onLoad"
},
"ResourceModules": {
"ext.isekai.widgets.global": {
@ -97,11 +104,33 @@
"desktop",
"mobile"
]
},
"ext.isekai.collapse": {
"scripts": [
"ext.isekai.collapse.js"
],
"styles": [
"ext.isekai.collapse.less"
],
"targets": [
"desktop",
"mobile"
]
}
},
"ResourceFileModulePaths": {
"localBasePath": "modules",
"remoteExtPath": "IsekaiWidgets/modules"
},
"manifest_version": 1
"attributes": {
"CodeMirror": {
"TagModes": {
"tilegroup": "text/mediawiki",
"exfont": "text/mediawiki",
"details": "text/mediawiki",
"summary": "text/mediawiki"
}
}
},
"manifest_version": 2
}

@ -13,5 +13,5 @@
"isekai-discover-loading": "読み込み中...",
"isekai-discover-change-btn": "変える",
"isekai-discover-readmore-btn": "開く",
"isekai-discover-error-cannotload": "サーバからのページを読み取りに失敗しま。"
"isekai-discover-error-cannotload": "サーバからのページを読み取りに失敗しました。"
}

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

@ -11,7 +11,7 @@ class FontFaceWidget {
* @param \Parser $parser
* @param \PPFrame $frame
*/
public static function create($text, $params, $parser, $frame){
public static function create($text, $params, $parser, $frame) {
if (!isset($params['src']) || !isset($params['name']) ||
empty($params['src']) || empty($params['name'])) {
return '<span class="error">' . wfMessage('isekai-fontface-error-invalid-params')->parse() . '</span>';
@ -42,8 +42,8 @@ class FontFaceWidget {
$fontUrl = $file->getUrl();
$fontId = substr(Utils::safeBase64Encode(md5($fontName, true)), 0, 8);
$css = "<style>@font-face{src: url('{$fontUrl}');font-family:'{$fontName}'}" .
".isekai-extra-font.font-{$fontId}{font-family:'{$fontName}'}</style>";
$css = "<span><style>@font-face{src: url('{$fontUrl}');font-family:'{$fontName}'}" .
".isekai-extra-font.font-{$fontId}{font-family:'{$fontName}'}</style></span>";
$existsFonts[$fontName] = $fontId;
$existsFonts = $parser->extIsekaiWidgetsCache->set('extraFonts', $existsFonts);

@ -0,0 +1,35 @@
<?php
namespace Isekai\Widgets;
use Html;
class Html5Widget {
public static function createDetails(string $text, array $args, \Parser $parser, \PPFrame $frame) {
$parser->getOutput()->addModules('ext.isekai.collapse');
$allowedAttr = ['class'];
$htmlArgs = array_filter($args, function($k) use($allowedAttr) {
return in_array($k, $allowedAttr);
}, ARRAY_FILTER_USE_KEY);
$content = '';
if ($text) {
$content = $parser->recursiveTagParse($text, $frame);
}
return [Html::rawElement('details', $htmlArgs, $content), "markerType" => 'nowiki'];
}
public static function createSummary(string $text, array $args, \Parser $parser, \PPFrame $frame) {
$allowedAttr = ['class'];
$htmlArgs = array_filter($args, function($k) use($allowedAttr) {
return in_array($k, $allowedAttr);
}, ARRAY_FILTER_USE_KEY);
$content = '';
if ($text) {
$content = $parser->recursiveTagParse($text, $frame);
}
return [Html::rawElement('summary', $htmlArgs, $content), "markerType" => 'nowiki'];
}
}

@ -130,7 +130,7 @@ class TileWidget {
}
private function getImagesArgs(array &$element, array &$content){
/*$service = MediaWikiServices::getInstance();
$service = MediaWikiServices::getInstance();
$this->images = [];
// 提取wikitext图片
preg_match_all('/\[\[(?<title>.+?:.+?)(\|.*?)?\]\]/', $this->content, $matches);
@ -149,13 +149,14 @@ class TileWidget {
preg_match_all('/<img .*?src="(?<src>.*?)".*?srcset="(?<srcset>.*?)"[^\>]+>/', $this->content, $matches);
if (isset($matches['src']) && !empty($matches['src'])) {
$this->images = array_merge($this->images, $matches['src']);
}*/
}
if(!empty($this->images)){
$element['data-effect'] = 'image-set';
foreach($this->images as $image){
$content[] = Html::element('img', [
'src' => $image,
'style' => 'display: none'
]);
}
}

@ -2,20 +2,32 @@
namespace Isekai\Widgets;
use MapCacheLRU;
use Parser;
class Widgets {
/**
* @param \Parser $parser
*/
public static function onParserSetup(&$parser){
$parser->extIsekaiWidgetsCache = new MapCacheLRU( 100 ); // 100 is arbitrary
$parser->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('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('tile', [TileWidget::class, 'create']);
$parser->setHook('tilegroup', [TileGroupWidget::class, 'create']);
$parser->setHook('fontface', FontFaceWidget::class . '::create');
$parser->setHook('exfont', ExtraFontWidget::class . '::create');
return true;
$parser->setHook('fontface', [FontFaceWidget::class, 'create']);
$parser->setHook('exfont', [ExtraFontWidget::class, 'create']);
$parser->setHook('details', [Html5Widget::class, 'createDetails']);
$parser->setHook('summary', [Html5Widget::class, 'createSummary']);
return true;
}
public static function onLoad(\OutputPage $outputPage) {
$outputPage->addModuleStyles("ext.isekai.collapse");
}
}

@ -0,0 +1,33 @@
(function($) {
$('.isekai-collapse').addClass('animate')
$('.isekai-collapse .isekai-collapse-title').on('click', '', function(e) {
e.preventDefault();
var titleElem = $(this);
var containerElem = titleElem.parent('.isekai-collapse');
var contentElem = containerElem.find('.isekai-collapse-content');
if (containerElem.prop('open')) { // 需要收起
var collapsedHeight = titleElem.outerHeight();
var expandedHeight = collapsedHeight + contentElem.outerHeight();
containerElem.css('height', expandedHeight);
console.log('expandedHeight', expandedHeight);
requestAnimationFrame(function() {
console.log('collapsedHeight', collapsedHeight);
containerElem.addClass('closing').css('height', collapsedHeight);
setTimeout(function() {
containerElem.prop('open', false).removeClass('closing'); //.css('height', 'auto');
}, 260);
});
} else { // 需要展开
containerElem.prop('open', true);
var collapsedHeight = titleElem.outerHeight();
containerElem.css('height', collapsedHeight);
requestAnimationFrame(function() {
var expandedHeight = collapsedHeight + contentElem.outerHeight();
containerElem.css('height', expandedHeight);
/*setTimeout(function() {
containerElem.css('height', 'auto');
}, 260);*/
});
}
});
})(jQuery);

@ -0,0 +1,64 @@
.isekai-collapse {
width: 50%;
background: #fff;
margin-bottom: .5rem;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
border-radius: 5px;
overflow: hidden;
@media screen and (max-width: 767px) {
width: 100%;
}
&.animate {
overflow-y: hidden;
will-change: height;
transition: height 250ms ease-in-out;
}
.isekai-collapse-title {
padding: 1rem;
display: block;
background-color: #f7f7f7;
padding-left: 2.2rem;
position: relative;
cursor: pointer;
color: black;
font-size: 1rem;
&::before {
content: '';
border-width: 0.4rem;
border-style: solid;
border-color: transparent transparent transparent #000;
position: absolute;
top: 1.32rem;
left: 1.2rem;
transform: rotate(0);
transform-origin: 0.2rem 50%;
will-change: transform;
transition: transform 250ms ease;
}
&::-webkit-details-marker {
transform: rotate(90deg);
}
}
.isekai-collapse-content {
padding: 1em;
}
&[open] > .isekai-collapse-title:before {
transform: rotate(90deg);
}
&.closing[open] > .isekai-collapse-title:before {
transform: rotate(0);
}
}
.isekai-indent > .isekai-collapse {
padding-left: 0;
margin-left: 8px;
}

@ -519,7 +519,7 @@ isekai.tile.init = function () {
this._createTile = function(){
function switchImage(el, img_src, i){
$.setTimeout(function(){
setTimeout(function(){
el.fadeOut(500, function(){
el.css("background-image", "url(" + img_src + ")");
el.fadeIn();
@ -582,7 +582,11 @@ isekai.tile.init = function () {
element.addClass("image-set");
$.each(element.children("img"), function(){
that.images.push(this);
var imgElem = document.createElement('img');
imgElem.src = this.src;
imgElem.srcset = this.srcset;
imgElem.alt = this.alt;
that.images.push(imgElem);
$(this).remove();
});
@ -592,12 +596,14 @@ isekai.tile.init = function () {
var rnd_index = rand(0, temp.length - 1);
var div = $("<div>").addClass("img -js-img-"+i).css("background-image", "url("+temp[rnd_index].src+")");
element.prepend(div);
temp.splice(rnd_index, 1);
if (temp.length > 1) {
temp.splice(rnd_index, 1);
}
}
var a = [0, 1, 4, 3, 2];
$.setInterval(function(){
setInterval(function(){
var temp = that.images.slice();
var colors = Colors.colors(Colors.PALETTES.ALL), bg;
bg = colors[rand(0, colors.length - 1)];
@ -608,7 +614,9 @@ isekai.tile.init = function () {
var rnd_index = rand(0, temp.length - 1);
var div = element.find(".-js-img-"+a[i]);
switchImage(div, temp[rnd_index].src, i);
temp.splice(rnd_index, 1);
if (temp.length > 1) {
temp.splice(rnd_index, 1);
}
}
a = a.reverse();
@ -619,7 +627,7 @@ isekai.tile.init = function () {
this._runEffects = function(){
var o = this.options;
if (this.effectInterval === false) this.effectInterval = $.setInterval(function(){
if (this.effectInterval === false) this.effectInterval = setInterval(function(){
var current, next;
current = $(this.slides[this.currentSlide]);
@ -641,7 +649,7 @@ isekai.tile.init = function () {
};
this._stopEffects = function(){
$.clearInterval(this.effectInterval);
clearInterval(this.effectInterval);
this.effectInterval = false;
};

Loading…
Cancel
Save