diff --git a/extension.json b/extension.json index 52aec8b..ca8c444 100644 --- a/extension.json +++ b/extension.json @@ -142,6 +142,35 @@ "isekai-ve-formatdropdown-format-mw-heading6" ] }, + "ve.ext.isekai.paste": { + "scripts": [ + "ve.ext.isekai.paste.js" + ], + "targets": [ + "desktop", + "mobile" + ], + "dependencies": [ + "ext.visualEditor.mwcore", + "ext.visualEditor.mwextensions" + ] + }, + "ve.ext.isekai.mainCategory": { + "scripts": [ + "ve.ext.isekai.mainCategory.js" + ], + "targets": [ + "desktop", + "mobile" + ], + "dependencies": [ + "ext.visualEditor.mwcore", + "ext.visualEditor.mwextensions" + ], + "messages": [ + "isekai-ve-dialog-meta-categories-input-maincategorieslabel" + ] + }, "ext.isekai.function-btn": { "scripts": [ "ext.isekai.function-btn.js" @@ -163,7 +192,8 @@ "attributes": { "VisualEditor": { "PluginModules": [ - "ve.ext.isekai.misc" + "ve.ext.isekai.misc", + "ve.ext.isekai.mainCategory" ] } }, @@ -184,6 +214,9 @@ }, "IsekaiActivateEditorRequiredWords": { "value": 300 + }, + "IsekaiMainCategoriesIndexUrl": { + "value": "/index.php?title=Project:MainCategories.json&action=raw" } }, "manifest_version": 2 diff --git a/i18n/en.json b/i18n/en.json index 5124df3..eb990c1 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -45,5 +45,7 @@ "isekai-ve-formatdropdown-format-mw-heading3": "Sub-heading 3", "isekai-ve-formatdropdown-format-mw-heading4": "Sub-heading 4", "isekai-ve-formatdropdown-format-mw-heading5": "Sub-heading 5", - "isekai-ve-formatdropdown-format-mw-heading6": "Sub-heading 6" + "isekai-ve-formatdropdown-format-mw-heading6": "Sub-heading 6", + + "isekai-ve-dialog-meta-categories-input-maincategorieslabel": "Main categories" } \ No newline at end of file diff --git a/i18n/zh-hans.json b/i18n/zh-hans.json index ffbdfa4..b36927d 100644 --- a/i18n/zh-hans.json +++ b/i18n/zh-hans.json @@ -45,5 +45,7 @@ "isekai-ve-formatdropdown-format-mw-heading3": "三级标题", "isekai-ve-formatdropdown-format-mw-heading4": "四级标题", "isekai-ve-formatdropdown-format-mw-heading5": "五级标题", - "isekai-ve-formatdropdown-format-mw-heading6": "六级标题" + "isekai-ve-formatdropdown-format-mw-heading6": "六级标题", + + "isekai-ve-dialog-meta-categories-input-maincategorieslabel": "主要分类" } \ No newline at end of file diff --git a/i18n/zh-hant.json b/i18n/zh-hant.json index b644b88..9b77141 100644 --- a/i18n/zh-hant.json +++ b/i18n/zh-hant.json @@ -45,5 +45,7 @@ "isekai-ve-formatdropdown-format-mw-heading3": "三级標題", "isekai-ve-formatdropdown-format-mw-heading4": "四级標題", "isekai-ve-formatdropdown-format-mw-heading5": "五级標題", - "isekai-ve-formatdropdown-format-mw-heading6": "六级標題" + "isekai-ve-formatdropdown-format-mw-heading6": "六级標題", + + "isekai-ve-dialog-meta-categories-input-maincategorieslabel": "主要分類" } \ No newline at end of file diff --git a/includes/Isekai.php b/includes/Isekai.php index 3594d8e..96e558b 100644 --- a/includes/Isekai.php +++ b/includes/Isekai.php @@ -319,6 +319,7 @@ HTML public static function onResourceLoaderGetConfigVars(array &$vars, string $skin, Config $config){ $vars['wgIsekaiShowAds'] = $config->get('IsekaiShowAds'); + $vars['wgIsekaiMainCategoriesIndexUrl'] = $config->get('IsekaiMainCategoriesIndexUrl'); } public static function onGetPreferences(User $user, array &$preferences){ diff --git a/modules/ext.isekai.ve.js b/modules/ext.isekai.ve.js index a65a123..00cab01 100644 --- a/modules/ext.isekai.ve.js +++ b/modules/ext.isekai.ve.js @@ -31,4 +31,4 @@ if (mw.config.get('skin') === "timeless") { veReadyTimer = setInterval(waitForVE, 500); window.addEventListener('resize', updateToolbar, { passive: true }); -} \ No newline at end of file +} diff --git a/modules/ve.ext.isekai.mainCategory.js b/modules/ve.ext.isekai.mainCategory.js new file mode 100644 index 0000000..a576299 --- /dev/null +++ b/modules/ve.ext.isekai.mainCategory.js @@ -0,0 +1,68 @@ +var _veUiMWCategoryInputWidgetPopulateLookupMenu = ve.ui.MWCategoryInputWidget.prototype.populateLookupMenu; + +ve.ui.MWCategoryInputWidget.prototype.populateLookupMenu = function () { + this.allowSuggestionsWhenEmpty = true; + _veUiMWCategoryInputWidgetPopulateLookupMenu.call(this); +}; + +ve.ui.MWCategoryInputWidget.prototype.isekaiGetCategoryItemFromData = function (data, indent) { + indent = indent || 0; + var items = []; + data.forEach(function (cInfo) { + var item; + var indentText = ' '.repeat(indent * 2); + if (cInfo.isSection) { + item = new OO.ui.MenuSectionOptionWidget({ + data: cInfo.category, + label: indentText + cInfo.label + }); + } else { + item = new OO.ui.MenuOptionWidget({ + data: cInfo.category, + label: indentText + cInfo.label, + }) + } + items.push(item); + + if (Array.isArray(cInfo.children)) { + items = items.concat(this.isekaiGetCategoryItemFromData(cInfo.children, indent + 1)); + } + }.bind(this)); + return items; +}; + +ve.ui.MWCategoryInputWidget.prototype.getLookupMenuItems = function () { + deferred = $.Deferred(); + + if (this.value === '') { + if (this.cachedMainCategories) { + return deferred.resolve(this.cachedMainCategories); + } + + var mcUrl = mw.config.get('wgIsekaiMainCategoriesIndexUrl'); + var itemWidgets = []; + + // Section header + itemWidgets.push( + new OO.ui.MenuSectionOptionWidget({ + data: 'mainCategories', + label: ve.msg('isekai-ve-dialog-meta-categories-input-maincategorieslabel') + }) + ); + + return $.ajax({ + url: mcUrl, + type: 'GET', + dataType: 'json', + }).then(function (data) { + var categoryItems = this.isekaiGetCategoryItemFromData(data); + itemWidgets = itemWidgets.concat(categoryItems); + this.cachedMainCategories = itemWidgets; + return deferred.resolve(itemWidgets); + }.bind(this)); + } else { + return this.getRequestData().then(function (data) { + return this.getLookupMenuOptionsFromData(data); + }.bind(this)); + } +}; \ No newline at end of file diff --git a/modules/ve.ext.isekai.paste.js b/modules/ve.ext.isekai.paste.js new file mode 100644 index 0000000..d4d9d33 --- /dev/null +++ b/modules/ve.ext.isekai.paste.js @@ -0,0 +1,9 @@ +// Paste from office +var _ve_ce_Surface_afterPaste = ve.ce.Surface.prototype.afterPaste; +ve.ce.Surface.prototype.afterPaste = function () { + var beforePasteData = this.beforePasteData || {}; + + console.log('beforePasteData', beforePasteData); + + return _ve_ce_Surface_afterPaste.apply(this, arguments); +} \ No newline at end of file