diff options
author | 2022-10-12 09:11:23 -0400 | |
---|---|---|
committer | 2022-10-12 09:11:23 -0400 | |
commit | 16501e80a206d33d4035d044eb30ec639e50f457 (patch) | |
tree | f37192cebd50439d3d1889112773078bb604aa74 /CommentStreams | |
parent | GentooPackages: Fix missing namespace use (diff) | |
download | extensions-16501e80a206d33d4035d044eb30ec639e50f457.tar.gz extensions-16501e80a206d33d4035d044eb30ec639e50f457.tar.bz2 extensions-16501e80a206d33d4035d044eb30ec639e50f457.zip |
Update CommentSteams to version 6.3v1.35.4
Signed-off-by: Brian Evans <grknight@gentoo.org>
Diffstat (limited to 'CommentStreams')
95 files changed, 7749 insertions, 3600 deletions
diff --git a/CommentStreams/.eslintignore b/CommentStreams/.eslintignore new file mode 100644 index 00000000..e9ce6080 --- /dev/null +++ b/CommentStreams/.eslintignore @@ -0,0 +1,2 @@ +/vendor/ +/resources/spin.min.js diff --git a/CommentStreams/.eslintrc.json b/CommentStreams/.eslintrc.json new file mode 100644 index 00000000..860f5014 --- /dev/null +++ b/CommentStreams/.eslintrc.json @@ -0,0 +1,25 @@ +{ + "root": true, + "extends": [ + "wikimedia/client-es5", + "wikimedia/jquery", + "wikimedia/mediawiki" + ], + "rules": { + "camelcase": "off", + "no-implicit-globals": "off", + "no-jquery/no-global-selector": "off", + "no-jquery/no-parse-html-literal": "off", + "no-jquery/no-fade": "off", + "no-jquery/no-slide": "off", + "no-jquery/no-sizzle": "off", + "no-jquery/no-ready-shorthand": "off", + "no-jquery/variable-pattern": "off", + "vars-on-top": "off", + "block-scoped-var": "warn" + }, + "globals": { + "CommentStreamsQuerier": "readonly", + "Spinner": "readonly" + } +} diff --git a/CommentStreams/.gitignore b/CommentStreams/.gitignore index 8ec4b929..1ea82ea0 100644 --- a/CommentStreams/.gitignore +++ b/CommentStreams/.gitignore @@ -1,3 +1,4 @@ node_modules/ vendor/ composer.lock +/.eslintcache diff --git a/CommentStreams/.phan/config.php b/CommentStreams/.phan/config.php new file mode 100644 index 00000000..a12c1349 --- /dev/null +++ b/CommentStreams/.phan/config.php @@ -0,0 +1,19 @@ +<?php +$cfg = require __DIR__ . '/../vendor/mediawiki/mediawiki-phan-config/src/config.php'; + +$cfg['directory_list'] = array_merge( + $cfg['directory_list'], + [ + '../../extensions/Echo', + '../../extensions/SocialProfile', + ] +); +$cfg['exclude_analysis_directory_list'] = array_merge( + $cfg['exclude_analysis_directory_list'], + [ + '../../extensions/Echo', + '../../extensions/SocialProfile', + ] +); + +return $cfg; diff --git a/CommentStreams/.phan/stubs/DIProperty.php b/CommentStreams/.phan/stubs/DIProperty.php new file mode 100644 index 00000000..102647c8 --- /dev/null +++ b/CommentStreams/.phan/stubs/DIProperty.php @@ -0,0 +1,24 @@ +<?php + +namespace SMW; + +use SMWDataItem; + +class DIProperty extends SMWDataItem { + /** + * @param string $key + * @param false $inverse + */ + public function __construct( string $key, $inverse = false ) { + } + + /** + * @param string $label + * @param bool $inverse + * @param false $languageCode + * @return DIProperty + */ + public static function newFromUserLabel( string $label, bool $inverse = false, $languageCode = false ) : self { + return new self( $label ); + } +} diff --git a/CommentStreams/.phan/stubs/DIWikiPage.php b/CommentStreams/.phan/stubs/DIWikiPage.php new file mode 100644 index 00000000..0966e45b --- /dev/null +++ b/CommentStreams/.phan/stubs/DIWikiPage.php @@ -0,0 +1,35 @@ +<?php + +namespace SMW; + +use SMWDataItem; +use Title; + +class DIWikiPage extends SMWDataItem { + /** + * @var Title + */ + private $title; + + /** + * @param Title $title + */ + public function __construct( Title $title ) { + $this->title = $title; + } + + /** + * @param Title $title + * @return DIWikiPage + */ + public static function newFromTitle( Title $title ) : self { + return new self( $title ); + } + + /** + * @return Title + */ + public function getTitle() { + return $this->title; + } +} diff --git a/CommentStreams/.phan/stubs/PropertyRegistry.php b/CommentStreams/.phan/stubs/PropertyRegistry.php new file mode 100644 index 00000000..506817e9 --- /dev/null +++ b/CommentStreams/.phan/stubs/PropertyRegistry.php @@ -0,0 +1,30 @@ +<?php + +namespace SMW; + +class PropertyRegistry { + /** + * @return PropertyRegistry + */ + public static function getInstance(): self { + return new self(); + } + + /** + * @param string $id + * @param string $valueType SMW type id + * @param string|bool $label user label or false (internal property) + * @param bool $isVisible only used if label is given, see isShown() + * @param bool $isAnnotable + * @param bool $isDeclarative + */ + public function registerProperty( + string $id, + string $valueType, + $label = false, + bool $isVisible = false, + bool $isAnnotable = true, + bool $isDeclarative = false + ) { + } +} diff --git a/CommentStreams/.phan/stubs/SMWDIBlob.php b/CommentStreams/.phan/stubs/SMWDIBlob.php new file mode 100644 index 00000000..d3b37a8c --- /dev/null +++ b/CommentStreams/.phan/stubs/SMWDIBlob.php @@ -0,0 +1,9 @@ +<?php + +class SMWDIBlob extends SMWDataItem { + /** + * @param string $string + */ + public function __construct( $string ) { + } +} diff --git a/CommentStreams/.phan/stubs/SMWDINumber.php b/CommentStreams/.phan/stubs/SMWDINumber.php new file mode 100644 index 00000000..59b6214c --- /dev/null +++ b/CommentStreams/.phan/stubs/SMWDINumber.php @@ -0,0 +1,9 @@ +<?php + +class SMWDINumber extends SMWDataItem { + /** + * @param int $number + */ + public function __construct( $number ) { + } +} diff --git a/CommentStreams/.phan/stubs/SMWDataItem.php b/CommentStreams/.phan/stubs/SMWDataItem.php new file mode 100644 index 00000000..25654174 --- /dev/null +++ b/CommentStreams/.phan/stubs/SMWDataItem.php @@ -0,0 +1,38 @@ +<?php + +class SMWDataItem { + const TYPE_STRING = 0; + const TYPE_BLOB = 0; + const TYPE_WIKIPAGE = 0; + + /** + * @var int + */ + private $type = 0; + + /** + * @var Title + */ + private $title = null; + + /** + * @return int + */ + public function getDIType() : int { + return $this->type; + } + + /** + * @return string + */ + public function getString() : string { + return ''; + } + + /** + * @return Title + */ + public function getTitle() : Title { + return $this->title; + } +} diff --git a/CommentStreams/.phan/stubs/SemanticData.php b/CommentStreams/.phan/stubs/SemanticData.php new file mode 100644 index 00000000..979afb6f --- /dev/null +++ b/CommentStreams/.phan/stubs/SemanticData.php @@ -0,0 +1,29 @@ +<?php + +namespace SMW; + +use SMWDataItem; + +class SemanticData { + /** + * @param DIProperty $property + * @return SMWDataItem[] + */ + public function getPropertyValues( DIProperty $property ) { + return []; + } + + /** + * @return DIWikiPage subject + */ + public function getSubject() { + return new DIWikiPage(); + } + + /** + * @param DIProperty $property + * @param SMWDataItem $dataItem + */ + public function addPropertyObjectValue( DIProperty $property, SMWDataItem $dataItem ) { + } +} diff --git a/CommentStreams/.phan/stubs/Store.php b/CommentStreams/.phan/stubs/Store.php new file mode 100644 index 00000000..3c8408bc --- /dev/null +++ b/CommentStreams/.phan/stubs/Store.php @@ -0,0 +1,14 @@ +<?php + +namespace SMW; + +class Store { + /** + * @param DIWikiPage $subject + * @param string[]|bool $filter + * @return SemanticData + */ + public function getSemanticData( DIWikiPage $subject, $filter = false ) : SemanticData { + return new SemanticData(); + } +} diff --git a/CommentStreams/.phan/stubs/StoreFactory.php b/CommentStreams/.phan/stubs/StoreFactory.php new file mode 100644 index 00000000..a5044f0e --- /dev/null +++ b/CommentStreams/.phan/stubs/StoreFactory.php @@ -0,0 +1,13 @@ +<?php + +namespace SMW; + +class StoreFactory { + /** + * @param string|null $class + * @return Store + */ + public static function getStore( $class = null ) : Store { + return new Store(); + } +} diff --git a/CommentStreams/.phan/stubs/UpdateJob.php b/CommentStreams/.phan/stubs/UpdateJob.php new file mode 100644 index 00000000..f01ff735 --- /dev/null +++ b/CommentStreams/.phan/stubs/UpdateJob.php @@ -0,0 +1,70 @@ +<?php + +namespace SMW\MediaWiki\Jobs; + +use IJobSpecification; +use Title; + +class UpdateJob implements IJobSpecification { + + /** + * @param Title $title + * @param array $params + */ + public function __construct( Title $title, $params = [] ) { + } + + /** + * @return bool|void + */ + public function run() : bool { + } + + /** + * @return string + */ + public function getType() : string { + } + + /** + * @return array + */ + public function getParams() : array { + } + + /** + * @return int|null + */ + public function getReleaseTimestamp() : ?int { + } + + /** + * @return bool + */ + public function ignoreDuplicates() : bool { + } + + /** + * @return array + */ + public function getDeduplicationInfo() : array { + } + + /** + * @return array + */ + public function getRootJobParams() : array { + } + + /** + * @return bool + */ + public function hasRootJobParams() : bool { + } + + /** + * @return bool + */ + public function isRootJob() : bool { + } +} diff --git a/CommentStreams/.phpcs.xml b/CommentStreams/.phpcs.xml index 1b870b71..ff090a2a 100644 --- a/CommentStreams/.phpcs.xml +++ b/CommentStreams/.phpcs.xml @@ -1,10 +1,11 @@ <?xml version="1.0"?> <ruleset> <rule ref="./vendor/mediawiki/mediawiki-codesniffer/MediaWiki"> - <exclude name="MediaWiki.Commenting.FunctionComment.MissingDocumentationPrivate" /> + <exclude name="MediaWiki.Commenting.PropertyDocumentation.MissingVar" /> + <exclude name="MediaWiki.Usage.ExtendClassUsage.FunctionVarUsage" /> <exclude name="PSR12.Properties.ConstantVisibility.NotFound" /> </rule> <file>.</file> - <arg name="extensions" value="php,php5,inc" /> + <arg name="extensions" value="php" /> <arg name="encoding" value="UTF-8" /> </ruleset> diff --git a/CommentStreams/.stylelintrc.json b/CommentStreams/.stylelintrc.json new file mode 100644 index 00000000..37e28ed4 --- /dev/null +++ b/CommentStreams/.stylelintrc.json @@ -0,0 +1,7 @@ +{ + "extends": "stylelint-config-wikimedia", + "rules": { + "selector-max-id": null, + "declaration-no-important": null + } +} diff --git a/CommentStreams/Gruntfile.js b/CommentStreams/Gruntfile.js index 9a4c9a39..fc5a2620 100644 --- a/CommentStreams/Gruntfile.js +++ b/CommentStreams/Gruntfile.js @@ -1,28 +1,27 @@ -/*jshint node:true */ +/* eslint-env node, es6 */ module.exports = function ( grunt ) { var conf = grunt.file.readJSON( 'extension.json' ); - grunt.loadNpmTasks( 'grunt-jsonlint' ); grunt.loadNpmTasks( 'grunt-banana-checker' ); + grunt.loadNpmTasks( 'grunt-eslint' ); + grunt.loadNpmTasks( 'grunt-stylelint' ); grunt.initConfig( { - banana: Object.assign( - conf.MessagesDirs, - { - options: { - requireLowerCase: 'initial' - } - } - ), - jsonlint: { + eslint: { + options: { + cache: true + }, + all: '.' + }, + stylelint: { all: [ - '**/*.json', + '**/*.{css,less}', '!node_modules/**', '!vendor/**' ] - } + }, + banana: conf.MessagesDirs } ); - - grunt.registerTask( 'test', [ 'jsonlint', 'banana' ] ); + grunt.registerTask( 'test', [ 'eslint', 'banana', 'stylelint' ] ); grunt.registerTask( 'default', 'test' ); }; diff --git a/CommentStreams/composer.json b/CommentStreams/composer.json index ace3ac5e..20c6a551 100644 --- a/CommentStreams/composer.json +++ b/CommentStreams/composer.json @@ -2,10 +2,11 @@ "name": "mediawiki/comment-streams", "type": "mediawiki-extension", "require-dev": { - "mediawiki/mediawiki-codesniffer": "31.0.0", - "mediawiki/minus-x": "1.1.0", + "mediawiki/mediawiki-codesniffer": "36.0.0", + "mediawiki/mediawiki-phan-config": "0.10.6", + "mediawiki/minus-x": "1.1.1", "php-parallel-lint/php-console-highlighter": "0.5.0", - "php-parallel-lint/php-parallel-lint": "1.2.0" + "php-parallel-lint/php-parallel-lint": "1.3.0" }, "scripts": { "test": [ @@ -16,6 +17,7 @@ "fix": [ "minus-x fix .", "phpcbf" - ] + ], + "phan": "phan -d . --long-progress-bar" } } diff --git a/CommentStreams/extension.json b/CommentStreams/extension.json index aae4b282..125f1b6f 100644 --- a/CommentStreams/extension.json +++ b/CommentStreams/extension.json @@ -1,6 +1,6 @@ { "name": "CommentStreams", - "version": "4.7", + "version": "6.3", "author": [ "[https://www.mediawiki.org/wiki/User:Jji Jason Ji]", "[https://www.mediawiki.org/wiki/User:Cindy.cicalese Cindy Cicalese]" @@ -42,6 +42,7 @@ "mobile" ], "messages": [ + "commentstreams-api-error-invalid", "commentstreams-api-error-notloggedin", "commentstreams-api-error-commentnotfound", "commentstreams-api-error-notacomment", @@ -116,17 +117,20 @@ "localBasePath": "resources", "remoteExtPath": "CommentStreams/resources" }, + "ServiceWiringFiles": [ + "includes/ServiceWiring.php" + ], "AutoloadNamespaces": { "MediaWiki\\Extension\\CommentStreams\\": "includes/" }, "APIModules": { - "csPostComment": "MediaWiki\\Extension\\CommentStreams\\ApiCSPostComment", - "csQueryComment": "MediaWiki\\Extension\\CommentStreams\\ApiCSQueryComment", - "csEditComment": "MediaWiki\\Extension\\CommentStreams\\ApiCSEditComment", - "csDeleteComment": "MediaWiki\\Extension\\CommentStreams\\ApiCSDeleteComment", - "csVote": "MediaWiki\\Extension\\CommentStreams\\ApiCSVote", - "csWatch": "MediaWiki\\Extension\\CommentStreams\\ApiCSWatch", - "csUnwatch": "MediaWiki\\Extension\\CommentStreams\\ApiCSUnwatch" + "cspostcomment": "MediaWiki\\Extension\\CommentStreams\\ApiCSPostComment", + "csquerycomment": "MediaWiki\\Extension\\CommentStreams\\ApiCSQueryComment", + "cseditcomment": "MediaWiki\\Extension\\CommentStreams\\ApiCSEditComment", + "csdeletecomment": "MediaWiki\\Extension\\CommentStreams\\ApiCSDeleteComment", + "csvote": "MediaWiki\\Extension\\CommentStreams\\ApiCSVote", + "cswatch": "MediaWiki\\Extension\\CommentStreams\\ApiCSWatch", + "csunwatch": "MediaWiki\\Extension\\CommentStreams\\ApiCSUnwatch" }, "Hooks": { "LoadExtensionSchemaUpdates": "MediaWiki\\Extension\\CommentStreams\\CommentStreamsHooks::addCommentTableToDatabase", @@ -137,22 +141,26 @@ "ParserFirstCallInit": "MediaWiki\\Extension\\CommentStreams\\CommentStreamsHooks::onParserSetup", "BeforePageDisplay": "MediaWiki\\Extension\\CommentStreams\\CommentStreamsHooks::addCommentsAndInitializeJS", "ShowSearchHitTitle": "MediaWiki\\Extension\\CommentStreams\\CommentStreamsHooks::showSearchHitTitle", - "smwInitProperties": "MediaWiki\\Extension\\CommentStreams\\CommentStreamsHooks::initProperties", - "SMWStore::updateDataBefore": "MediaWiki\\Extension\\CommentStreams\\CommentStreamsHooks::updateData", - "BeforeCreateEchoEvent": "MediaWiki\\Extension\\CommentStreams\\CommentStreamsHooks::onBeforeCreateEchoEvent", - "SMW::Settings::BeforeInitializationComplete": "MediaWiki\\Extension\\CommentStreams\\CommentStreamsHooks::onSMWInitialization" + "BeforeCreateEchoEvent": "MediaWiki\\Extension\\CommentStreams\\CommentStreamsEchoInterface::onBeforeCreateEchoEvent", + "smwInitProperties": "MediaWiki\\Extension\\CommentStreams\\CommentStreamsSMWInterface::initProperties", + "SMWStore::updateDataBefore": "MediaWiki\\Extension\\CommentStreams\\CommentStreamsSMWInterface::updateData", + "SMW::Settings::BeforeInitializationComplete": "MediaWiki\\Extension\\CommentStreams\\CommentStreamsSMWInterface::onSMWInitialization" + }, + "callback": "MediaWiki\\Extension\\CommentStreams\\CommentStreamsHooks::onRegistration", + "ConfigRegistry": { + "CommentStreams": "GlobalVarConfig::newInstance" }, - "callback" : "MediaWiki\\Extension\\CommentStreams\\CommentStreamsHooks::onRegistration", "config": { "CommentStreamsNamespaceIndex": 844, - "CommentStreamsAllowedNamespaces" : null, + "CommentStreamsAllowedNamespaces": null, "CommentStreamsEnableTalk": false, "CommentStreamsNewestStreamsOnTop": true, "CommentStreamsModeratorFastDelete": false, "CommentStreamsShowLabels": true, "CommentStreamsEnableVoting": false, - "CommentStreamsInitiallyCollapsedNamespaces" : [], - "CommentStreamsUserRealNamePropertyName" : null, - "CommentStreamsUserAvatarPropertyName" : null + "CommentStreamsInitiallyCollapsedNamespaces": [], + "CommentStreamsUserRealNamePropertyName": null, + "CommentStreamsUserAvatarPropertyName": null, + "CommentStreamsEnableSearch": true } } diff --git a/CommentStreams/i18n/alt.json b/CommentStreams/i18n/alt.json new file mode 100644 index 00000000..269f9c0a --- /dev/null +++ b/CommentStreams/i18n/alt.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "Kareyac" + ] + }, + "commentstreams-dialog-buttontext-no": "Јок" +} diff --git a/CommentStreams/i18n/ar.json b/CommentStreams/i18n/ar.json index bda729dd..35e5936e 100644 --- a/CommentStreams/i18n/ar.json +++ b/CommentStreams/i18n/ar.json @@ -9,49 +9,49 @@ "commentstreams-error-prohibitedaction": "جراء $1 غير مسموح به في صفحات التعليقات.", "commentstreams-error-comment-on-deleted-page": "الصفحة التي يرتبط بها هذا التعليق تم حذفها.", "commentstreams-author-anonymous": "مجهول", - "apihelp-csQueryComment-description": "أعد العنوان، والمستخدم والطابع الزمني للإنشاء ونص الويكي للتعليق، يجب توفير إما معرف أو عنوان الصفحة.", - "apihelp-csQueryComment-summary": "أعد العنوان، والمستخدم والطابع الزمني للإنشاء ونص الويكي للتعليق، يجب توفير إما معرف أو عنوان الصفحة.", - "apihelp-csQueryComment-param-pageid": "معرف الصفحة للصفحة التي تحمل التعليق للاستعلام", - "apihelp-csQueryComment-param-title": "عنوان الصفحة للصفحة التي تحمل التعليق للاستعلام", - "apihelp-csQueryComment-pageid-example": "تعليق الاستعلام بمعرف الصفحة 3 في نص الويكي", - "apihelp-csQueryComment-title-example": "تعليق الاستعلام بعنوان الصفحة CommentStreams:3 في نص الويكي", - "apihelp-csDeleteComment-description": "احذف تعليقا، يجب توفير إما معرف أو عنوان الصفحة.", - "apihelp-csDeleteComment-summary": "احذف تعليقا، يجب توفير إما معرف أو عنوان الصفحة.", - "apihelp-csDeleteComment-param-pageid": "معرف الصفحة للصفحة التي تحمل التعليق لحذفه", - "apihelp-csDeleteComment-param-title": "معرف الصفحة للصفحة التي تحمل التعليق لحذفه", - "apihelp-csDeleteComment-pageid-example": "حذف التعليق بمعرف الصفحة 3", - "apihelp-csDeleteComment-title-example": "حذف التعليق بعنوان الصفحة CommentStreams:3", - "apihelp-csPostComment-description": "انشر تعليقا جديدا.", - "apihelp-csPostComment-summary": "انشر تعليقا جديدا.", - "apihelp-csPostComment-param-commenttitle": "عنوان اختياري للتعليق.", - "apihelp-csPostComment-param-wikitext": "نص الويكي للتعليق.", - "apihelp-csPostComment-param-associatedid": "الصفحة التي يرتبط بها هذا التعليق.", - "apihelp-csPostComment-param-parentid": "معرف الصفحة للتعليق الأصلي إذا كان هذا ردا.", - "apihelp-csEditComment-description": "تحرير تعليق موجود; يجب توفير إما معرف أو عنوان الصفحة.", - "apihelp-csEditComment-summary": "تحرير تعليق موجود; يجب توفير إما معرف أو عنوان الصفحة.", - "apihelp-csEditComment-param-pageid": "معرف الصفحة للصفحة التي تحمل التعليق للتعديل", - "apihelp-csEditComment-param-title": "عنوان الصفحة للصفحة التي تحمل التعليق للتعديل", - "apihelp-csEditComment-param-commenttitle": "عنوان اختياري للتعليق.", - "apihelp-csEditComment-param-wikitext": "نص الويكي للتعليق", - "apihelp-csVote-description": "التصويت (أعلى أو أسفل أو محايد) على تعليق.", - "apihelp-csVote-summary": "التصويت (أعلى أو أسفل أو محايد) على تعليق.", - "apihelp-csVote-param-pageid": "معرف الصفحة للصفحة التي تحمل التعليق ليتم التصويت فييها", - "apihelp-csVote-param-title": "عنوان الصفحة للصفحة التي تحمل التعليق ليتم التصويت فييها", - "apihelp-csVote-param-vote": "صوت (1 أو -1 أو 0).", - "apihelp-csVote-pageid-example": "التصويت على التعليق بمعرف الصفحة 3", - "apihelp-csVote-title-example": "التصويت على التعليق بعنوان الصفحة CommentStreams: 3", - "apihelp-csWatch-description": "راقب تعليقا ليتم إخطارك عندما يتلقى ردودا", - "apihelp-csWatch-summary": "راقب تعليقا ليتم إخطارك عندما يتلقى ردودا", - "apihelp-csWatch-param-pageid": "معرف الصفحة للصفحة التي تحمل التعليق المراد مراقبته", - "apihelp-csWatch-param-title": "عنوان الصفحة للصفحة التي تحمل التعليق المراد مراقبته", - "apihelp-csWatch-pageid-example": "مراقبة تعليق بمعرف الصفحة 3", - "apihelp-csWatch-title-example": "مراقبة تعليق بعنوان الصفحة CommentStreams: 3", - "apihelp-csUnwatch-description": "عدم مراقبة تعليق لكي لا يتم إخطارك عندما يتلقى ردودا", - "apihelp-csUnwatch-summary": "عدم مراقبة تعليق لكي لا يتم إخطارك عندما يتلقى ردودا", - "apihelp-csUnwatch-param-pageid": "عنوان الصفحة للصفحة التي تحمل التعليق المراد عدم مراقبته", - "apihelp-csUnwatch-param-title": "عنوان الصفحة للصفحة التي تحمل التعليق المراد عدم مراقبته", - "apihelp-csUnwatch-pageid-example": "عدم مراقبة تعليق بمعرف الصفحة 3", - "apihelp-csUnwatch-title-example": "عدم مراقبة تعليق بعنوان الصفحة CommentStreams: 3", + "apihelp-csquerycomment-description": "أعد العنوان، والمستخدم والطابع الزمني للإنشاء ونص الويكي للتعليق، يجب توفير إما معرف أو عنوان الصفحة.", + "apihelp-csquerycomment-summary": "أعد العنوان، والمستخدم والطابع الزمني للإنشاء ونص الويكي للتعليق، يجب توفير إما معرف أو عنوان الصفحة.", + "apihelp-csquerycomment-param-pageid": "معرف الصفحة للصفحة التي تحمل التعليق للاستعلام", + "apihelp-csquerycomment-param-title": "عنوان الصفحة للصفحة التي تحمل التعليق للاستعلام", + "apihelp-csquerycomment-pageid-example": "تعليق الاستعلام بمعرف الصفحة 3 في نص الويكي", + "apihelp-csquerycomment-title-example": "تعليق الاستعلام بعنوان الصفحة CommentStreams:3 في نص الويكي", + "apihelp-csdeletecomment-description": "احذف تعليقا، يجب توفير إما معرف أو عنوان الصفحة.", + "apihelp-csdeletecomment-summary": "احذف تعليقا، يجب توفير إما معرف أو عنوان الصفحة.", + "apihelp-csdeletecomment-param-pageid": "معرف الصفحة للصفحة التي تحمل التعليق لحذفه", + "apihelp-csdeletecomment-param-title": "معرف الصفحة للصفحة التي تحمل التعليق لحذفه", + "apihelp-csdeletecomment-pageid-example": "حذف التعليق بمعرف الصفحة 3", + "apihelp-csdeletecomment-title-example": "حذف التعليق بعنوان الصفحة CommentStreams:3", + "apihelp-cspostcomment-description": "انشر تعليقا جديدا.", + "apihelp-cspostcomment-summary": "انشر تعليقا جديدا.", + "apihelp-cspostcomment-param-commenttitle": "عنوان اختياري للتعليق.", + "apihelp-cspostcomment-param-wikitext": "نص الويكي للتعليق", + "apihelp-cspostcomment-param-associatedid": "الصفحة التي يرتبط بها هذا التعليق.", + "apihelp-cspostcomment-param-parentid": "معرف الصفحة للتعليق الأصلي إذا كان هذا ردا.", + "apihelp-cseditcomment-description": "تحرير تعليق موجود; يجب توفير إما معرف أو عنوان الصفحة.", + "apihelp-cseditcomment-summary": "تحرير تعليق موجود; يجب توفير إما معرف أو عنوان الصفحة.", + "apihelp-cseditcomment-param-pageid": "معرف الصفحة للصفحة التي تحمل التعليق للتعديل", + "apihelp-cseditcomment-param-title": "عنوان الصفحة للصفحة التي تحمل التعليق للتعديل", + "apihelp-cseditcomment-param-commenttitle": "عنوان اختياري للتعليق.", + "apihelp-cseditcomment-param-wikitext": "نص الويكي للتعليق.", + "apihelp-csvote-description": "التصويت (أعلى أو أسفل أو محايد) على تعليق.", + "apihelp-csvote-summary": "التصويت (أعلى أو أسفل أو محايد) على تعليق.", + "apihelp-csvote-param-pageid": "معرف الصفحة للصفحة التي تحمل التعليق ليتم التصويت فييها", + "apihelp-csvote-param-title": "عنوان الصفحة للصفحة التي تحمل التعليق ليتم التصويت فييها", + "apihelp-csvote-param-vote": "صوت (1 أو -1 أو 0).", + "apihelp-csvote-pageid-example": "التصويت على التعليق بمعرف الصفحة 3", + "apihelp-csvote-title-example": "التصويت على التعليق بعنوان الصفحة CommentStreams: 3", + "apihelp-cswatch-description": "راقب تعليقا ليتم إخطارك عندما يتلقى ردودا", + "apihelp-cswatch-summary": "راقب تعليقا ليتم إخطارك عندما يتلقى ردودا", + "apihelp-cswatch-param-pageid": "معرف الصفحة للصفحة التي تحمل التعليق المراد مراقبته", + "apihelp-cswatch-param-title": "عنوان الصفحة للصفحة التي تحمل التعليق المراد مراقبته", + "apihelp-cswatch-pageid-example": "مراقبة تعليق بمعرف الصفحة 3", + "apihelp-cswatch-title-example": "مراقبة تعليق بعنوان الصفحة CommentStreams: 3", + "apihelp-csunwatch-description": "عدم مراقبة تعليق لكي لا يتم إخطارك عندما يتلقى ردودا", + "apihelp-csunwatch-summary": "عدم مراقبة تعليق لكي لا يتم إخطارك عندما يتلقى ردودا", + "apihelp-csunwatch-param-pageid": "عنوان الصفحة للصفحة التي تحمل التعليق المراد عدم مراقبته", + "apihelp-csunwatch-param-title": "عنوان الصفحة للصفحة التي تحمل التعليق المراد عدم مراقبته", + "apihelp-csunwatch-pageid-example": "عدم مراقبة تعليق بمعرف الصفحة 3", + "apihelp-csunwatch-title-example": "عدم مراقبة تعليق بعنوان الصفحة CommentStreams: 3", "commentstreams-api-error-notloggedin": "يجب أن تكون مسجلا.", "commentstreams-api-error-commentnotfound": "لم يتم العثور على التعليق المطلوب.", "commentstreams-api-error-notacomment": "لا يشير معرف الصفحة الذي تم توفيره إلى تعليق صالح.", diff --git a/CommentStreams/i18n/ast.json b/CommentStreams/i18n/ast.json index b3bf6b3d..19a66e29 100644 --- a/CommentStreams/i18n/ast.json +++ b/CommentStreams/i18n/ast.json @@ -8,28 +8,28 @@ "commentstreams-error-prohibitedaction": "L'aición $1 nun se permite nes páxines de comentarios.", "commentstreams-error-comment-on-deleted-page": "La páxina cola que ta asociáu esti comentariu desanicióse.", "commentstreams-author-anonymous": "anónimu", - "apihelp-csQueryComment-description": "Devuelve'l títulu. usuariu, hora de creación y testu wiki d'un comentariu. Tien de dase l'identificador de páxina o'l títulu.", - "apihelp-csQueryComment-summary": "Devuelve'l títulu. usuariu, hora de creación y testu wiki d'un comentariu. Tien de dase l'identificador de páxina o'l títulu.", - "apihelp-csQueryComment-param-pageid": "identificador de la páxina que tien el comentariu a consultar", - "apihelp-csQueryComment-param-title": "títulu de la páxina que tien el comentariu a consultar", - "apihelp-csQueryComment-pageid-example": "consultar el comentariu con identificador de páxina 3 en testu wiki", - "apihelp-csQueryComment-title-example": "consultar el comentariu con títulu de páxina CommentStreams:3 en testu wiki", - "apihelp-csDeleteComment-description": "Desaniciar un comentariu. Tien de dase l'identificador de páxina o'l títulu.", - "apihelp-csDeleteComment-summary": "Desaniciar un comentariu. Tien de dase l'identificador de páxina o'l títulu.", - "apihelp-csDeleteComment-param-pageid": "identificador de la páxina que tien el comentariu a desaniciar", - "apihelp-csDeleteComment-param-title": "títulu de la páxina que tien el comentariu a desaniciar", - "apihelp-csDeleteComment-pageid-example": "desaniciar el comentariu con identificador de páxina 3", - "apihelp-csDeleteComment-title-example": "desaniciar el comentariu con títulu de páxina CommentStreams:3", - "apihelp-csPostComment-description": "Publicar un comentariu nuevu.", - "apihelp-csPostComment-summary": "Publicar un comentariu nuevu.", - "apihelp-csPostComment-param-commenttitle": "títulu opcional pal comentariu.", - "apihelp-csPostComment-param-wikitext": "testu wiki pal comentariu.", - "apihelp-csPostComment-param-associatedid": "páxina cola que ta asociáu esti comentariu", - "apihelp-csPostComment-param-parentid": "identificador de la páxina del comentariu padre, si ye una respuesta.", - "apihelp-csEditComment-description": "Editar un comentariu esistiente. Tien de dase l'identificador de páxina o'l títulu.", - "apihelp-csEditComment-summary": "Editar un comentariu esistiente. Tien de dase l'identificador de páxina o'l títulu.", - "apihelp-csEditComment-param-pageid": "identificador de la páxina que tien el comentariu a editar", - "apihelp-csEditComment-param-title": "títulu de la páxina que tien el comentariu a editar", - "apihelp-csEditComment-param-commenttitle": "títulu opcional pal comentariu.", - "apihelp-csEditComment-param-wikitext": "testu wiki pal comentariu." + "apihelp-csquerycomment-description": "Devuelve'l títulu. usuariu, hora de creación y testu wiki d'un comentariu. Tien de dase l'identificador de páxina o'l títulu.", + "apihelp-csquerycomment-summary": "Devuelve'l títulu. usuariu, hora de creación y testu wiki d'un comentariu. Tien de dase l'identificador de páxina o'l títulu.", + "apihelp-csquerycomment-param-pageid": "identificador de la páxina que tien el comentariu a consultar", + "apihelp-csquerycomment-param-title": "títulu de la páxina que tien el comentariu a consultar", + "apihelp-csquerycomment-pageid-example": "consultar el comentariu con identificador de páxina 3 en testu wiki", + "apihelp-csquerycomment-title-example": "consultar el comentariu con títulu de páxina CommentStreams:3 en testu wiki", + "apihelp-csdeletecomment-description": "Desaniciar un comentariu. Tien de dase l'identificador de páxina o'l títulu.", + "apihelp-csdeletecomment-summary": "Desaniciar un comentariu. Tien de dase l'identificador de páxina o'l títulu.", + "apihelp-csdeletecomment-param-pageid": "identificador de la páxina que tien el comentariu a desaniciar", + "apihelp-csdeletecomment-param-title": "títulu de la páxina que tien el comentariu a desaniciar", + "apihelp-csdeletecomment-pageid-example": "desaniciar el comentariu con identificador de páxina 3", + "apihelp-csdeletecomment-title-example": "desaniciar el comentariu con títulu de páxina CommentStreams:3", + "apihelp-cspostcomment-description": "Publicar un comentariu nuevu.", + "apihelp-cspostcomment-summary": "Publicar un comentariu nuevu.", + "apihelp-cspostcomment-param-commenttitle": "títulu opcional pal comentariu.", + "apihelp-cspostcomment-param-wikitext": "testu wiki pal comentariu.", + "apihelp-cspostcomment-param-associatedid": "páxina cola que ta asociáu esti comentariu", + "apihelp-cspostcomment-param-parentid": "identificador de la páxina del comentariu padre, si ye una respuesta.", + "apihelp-cseditcomment-description": "Editar un comentariu esistiente. Tien de dase l'identificador de páxina o'l títulu.", + "apihelp-cseditcomment-summary": "Editar un comentariu esistiente. Tien de dase l'identificador de páxina o'l títulu.", + "apihelp-cseditcomment-param-pageid": "identificador de la páxina que tien el comentariu a editar", + "apihelp-cseditcomment-param-title": "títulu de la páxina que tien el comentariu a editar", + "apihelp-cseditcomment-param-commenttitle": "títulu opcional pal comentariu.", + "apihelp-cseditcomment-param-wikitext": "testu wiki pal comentariu." } diff --git a/CommentStreams/i18n/ban.json b/CommentStreams/i18n/ban.json new file mode 100644 index 00000000..e6004e2b --- /dev/null +++ b/CommentStreams/i18n/ban.json @@ -0,0 +1,14 @@ +{ + "@metadata": { + "authors": [ + "Chinamoonroll" + ] + }, + "commentstreams-buttontext-add": "Wewehin penampen", + "commentstreams-buttontooltip-add": "wewehin penampen", + "commentstreams-dialog-buttontext-yes": "Inggih", + "notification-link-label-commentstreams-comment-on-watched-page": "Rauhin penampen", + "commentstreams-allcomments-label-page": "Kaca Penampen", + "commentstreams-allcomments-label-commenttitle": "Penampen Murda", + "commentstreams-allcomments-label-wikitext": "Panampen" +} diff --git a/CommentStreams/i18n/bg.json b/CommentStreams/i18n/bg.json index 535d249b..ff4970d9 100644 --- a/CommentStreams/i18n/bg.json +++ b/CommentStreams/i18n/bg.json @@ -1,6 +1,7 @@ { "@metadata": { "authors": [ + "Kareyac", "StanProg", "Ted Masters", "Vlad5250" @@ -10,9 +11,11 @@ "commentstreams-error-prohibitedaction": "Действието $1 не е разрешено на страници за коментари.", "commentstreams-error-comment-on-deleted-page": "Страницата, към която е бил свързан коментарът, е изтрита.", "commentstreams-author-anonymous": "анонимен", - "apihelp-csQueryComment-description": "Връщане на заглавието, потребителя, времето и датата и уики текста на коментара. Трябва да се посочи идентификация на страницата или заглавие.", - "apihelp-csQueryComment-summary": "Връщане на заглавието, потребителя, времето и датата, и уики текста на коментара. Трябва да се посочи идентификационен номер на страницата или заглавие.", + "apihelp-csquerycomment-description": "Връщане на заглавието, потребителя, времето и датата и уики текста на коментара. Трябва да се посочи идентификация на страницата или заглавие.", + "apihelp-csquerycomment-summary": "Връщане на заглавието, потребителя, времето и датата, и уики текста на коментара. Трябва да се посочи идентификационен номер на страницата или заглавие.", "commentstreams-buttontooltip-delete": "изтриване", "commentstreams-buttontooltip-cancel": "Отказ", - "commentstreams-dialog-buttontext-cancel": "Отказ" + "commentstreams-dialog-buttontext-cancel": "Отказ", + "commentstreams-dialog-buttontext-yes": "Да", + "commentstreams-allcomments-label-author": "Автор" } diff --git a/CommentStreams/i18n/bn.json b/CommentStreams/i18n/bn.json index bc294d6c..225d8399 100644 --- a/CommentStreams/i18n/bn.json +++ b/CommentStreams/i18n/bn.json @@ -8,7 +8,7 @@ "commentstreams-desc": "উইকি পাতাগুলিতে মন্তব্য করতে দেয়", "commentstreams-error-prohibitedaction": "মন্তব্যের পাতায় $1 কর্ম অনুমোদিত নয়।", "commentstreams-author-anonymous": "নামহীন", - "apihelp-csVote-param-vote": "ভোট (1, -1, বা 0)।", + "apihelp-csvote-param-vote": "ভোট (1, -1, বা 0)।", "commentstreams-api-error-delete": "মন্তব্য অপসারণের সময় ত্রুটি।", "commentstreams-api-error-vote-notloggedin": "ভোট দিতে হলে আপনাকে অবশ্যই প্রবেশ করতে হবে।", "commentstreams-buttontext-add": "একটি মন্তব্য যোগ করুন", diff --git a/CommentStreams/i18n/ce.json b/CommentStreams/i18n/ce.json index a63087f8..fa2fb09c 100644 --- a/CommentStreams/i18n/ce.json +++ b/CommentStreams/i18n/ce.json @@ -6,6 +6,6 @@ }, "commentstreams-buttontext-add": "ТӀетоха коммент", "commentstreams-buttontext-reply": "Жоп ло", - "commentstreams-buttontooltip-cancel": "юхаяккхар", + "commentstreams-buttontooltip-cancel": "йухайаккхар", "commentstreams-allcomments-button-previous": "Хьалхара" } diff --git a/CommentStreams/i18n/cs.json b/CommentStreams/i18n/cs.json index d54180a6..6926af7a 100644 --- a/CommentStreams/i18n/cs.json +++ b/CommentStreams/i18n/cs.json @@ -3,7 +3,8 @@ "authors": [ "Dvorapa", "Ilimanaq29", - "Patriccck" + "Patriccck", + "Patrik L." ] }, "commentstreams-buttontext-add": "Přidat komentář", diff --git a/CommentStreams/i18n/da.json b/CommentStreams/i18n/da.json index eb939354..2b8274ae 100644 --- a/CommentStreams/i18n/da.json +++ b/CommentStreams/i18n/da.json @@ -5,6 +5,7 @@ ] }, "commentstreams-author-anonymous": "anonym", + "apihelp-csvote-param-vote": "stem (1, -1 eller 0).", "commentstreams-buttontext-add": "Tilføj kommentar", "commentstreams-buttontext-reply": "Svar", "commentstreams-buttontooltip-add": "tilføj kommentar", @@ -14,6 +15,7 @@ "commentstreams-dialog-buttontext-yes": "Ja", "commentstreams-dialog-buttontext-no": "Nej", "commentstreams-title-field-placeholder": "Indtast titel...", + "logentry-commentstreams-comment-delete": "$1 {{GENDER:$2|slettede}} kommentaren $3", "commentstreamsallcomments": "Alle kommentarer", "commentstreams-allcomments-label-commenttitle": "Kommentartitel", "commentstreams-allcomments-label-wikitext": "Kommentar", diff --git a/CommentStreams/i18n/de.json b/CommentStreams/i18n/de.json index 8a506d84..b72ea796 100644 --- a/CommentStreams/i18n/de.json +++ b/CommentStreams/i18n/de.json @@ -9,46 +9,50 @@ "commentstreams-error-prohibitedaction": "Die Aktion $1 ist auf Kommentarseiten nicht erlaubt.", "commentstreams-error-comment-on-deleted-page": "Die Seite, die mit diesem Kommentar verbunden ist, wurde gelöscht.", "commentstreams-author-anonymous": "Anonym", - "apihelp-csQueryComment-param-pageid": "Kennung der Seite, die den abzurufenden Kommentar enthält.", - "apihelp-csQueryComment-param-title": "Titel der Seite, die den abzurufenden Kommentar enthält.", - "apihelp-csQueryComment-pageid-example": "Ruft den Kommentar mit der Seitenkennung 3 in Wikitext ab", - "apihelp-csQueryComment-title-example": "Ruft den Kommentar mit dem Seitentitel CommentStreams:3 in Wikitext ab", - "apihelp-csDeleteComment-description": "Löscht einen Kommentar. Entweder muss pageid oder title angegeben werden.", - "apihelp-csDeleteComment-summary": "Löscht einen Kommentar. Es muss entweder pageid oder title angegeben werden.", - "apihelp-csDeleteComment-param-pageid": "Kennung der Seite, die den zu löschenden Kommentar enthält.", - "apihelp-csDeleteComment-param-title": "Titel der Seite, die den zu löschenden Kommentar enthält.", - "apihelp-csDeleteComment-pageid-example": "Löscht den Kommentar mit der Seitenkennung 3", - "apihelp-csDeleteComment-title-example": "Löscht den Kommentar mit dem Seitentitel CommentStreams:3", - "apihelp-csPostComment-description": "Speichert einen neuen Kommentar.", - "apihelp-csPostComment-summary": "Speichert einen neuen Kommentar.", - "apihelp-csPostComment-param-commenttitle": "optionaler Titel für den Kommentar.", - "apihelp-csPostComment-param-wikitext": "Wikitext für den Kommentar.", - "apihelp-csPostComment-param-associatedid": "Seite, mit der dieser Kommentar verknüpft ist.", - "apihelp-csPostComment-param-parentid": "Seitenkennung des übergeordneten Kommentars, falls dies eine Antwort ist.", - "apihelp-csEditComment-description": "Bearbeitet einen vorhandenen Kommentar. Entweder pageid oder title muss angegeben werden.", - "apihelp-csEditComment-summary": "Bearbeitet einen vorhandenen Kommentar. Entweder muss pageid oder title angegeben werden.", - "apihelp-csEditComment-param-pageid": "Kennung der Seite, die den zu bearbeitenden Kommentar enthält.", - "apihelp-csEditComment-param-title": "Titel der Seite, die den zu bearbeitenden Kommentar enthält.", - "apihelp-csEditComment-param-commenttitle": "Optionaler Titel für den Kommentar.", - "apihelp-csEditComment-param-wikitext": "Wikitext für den Kommentar.", - "apihelp-csVote-description": "Stimmt über einen Kommentar ab (Gefällt mir, Gefällt mir nicht oder neutral).", - "apihelp-csVote-summary": "Stimmt über einen Kommentar ab (Gefällt mir, Gefällt mir nicht oder neutral).", - "apihelp-csVote-param-title": "Titel der Seite, die den Kommentar enthält, über den abgestimmt werden soll.", - "apihelp-csVote-param-vote": "Stimmt ab (1, -1 oder 0).", - "apihelp-csVote-pageid-example": "Stimmt über den Kommentar mit der Seitenkennung 3 ab", - "apihelp-csVote-title-example": "Stimmt über den Kommentar mit dem Seitentitel CommentStreams:3 ab", - "apihelp-csWatch-description": "Beobachtet einen Kommentar, um benachrichtigt zu werden, wenn er Antworten erhält.", - "apihelp-csWatch-summary": "Beobachtet einen Kommentar, um benachrichtigt zu werden, wenn er Antworten erhält.", - "apihelp-csWatch-param-pageid": "Kennung der Seite, die den zu beobachtenden Kommentar enthält.", - "apihelp-csWatch-param-title": "Titel der Seite, die den zu beobachtenden Kommentar enthält.", - "apihelp-csWatch-pageid-example": "Beobachtet den Kommentar mit der Seitenkennung 3", - "apihelp-csWatch-title-example": "Beobachtet den Kommentar mit dem Seitentitel CommentStreams:3", - "apihelp-csUnwatch-description": "Beobachtet einen Kommentar nicht mehr, um nicht mehr benachrichtigt zu werden, wenn er Antworten erhält.", - "apihelp-csUnwatch-summary": "Beobachtet einen Kommentar nicht mehr, um nicht länger benachrichtigt zu werden, wenn er Antworten erhält.", - "apihelp-csUnwatch-param-pageid": "Kennung der Seite, die den nicht mehr zu beobachtenden Kommentar enthält.", - "apihelp-csUnwatch-param-title": "Titel der Seite, die den nicht mehr zu beobachtenden Kommentar enthält.", - "apihelp-csUnwatch-pageid-example": "Beobachtet den Kommentar mit der Seitenkennung 3 nicht mehr", - "apihelp-csUnwatch-title-example": "Beobachtet den Kommentar mit dem Seitentitel CommentStreams:3 nicht mehr", + "apihelp-csquerycomment-description": "Gibt den Titel, den Benutzer, den Zeitstempel der Erstellung und den Wikitext eines Kommentars zurück. Entweder pageid oder title müssen angegeben werden.", + "apihelp-csquerycomment-summary": "Gibt den Titel, den Benutzer, den Erstellungszeitstempel und den Wikitext eines Kommentars zurück. Entweder pageid oder title müssen angegeben werden.", + "apihelp-csquerycomment-param-pageid": "Kennung der Seite, die den abzurufenden Kommentar enthält.", + "apihelp-csquerycomment-param-title": "Titel der Seite, die den abzurufenden Kommentar enthält.", + "apihelp-csquerycomment-pageid-example": "Ruft den Kommentar mit der Seitenkennung 3 in Wikitext ab", + "apihelp-csquerycomment-title-example": "Ruft den Kommentar mit dem Seitentitel CommentStreams:3 in Wikitext ab", + "apihelp-csdeletecomment-description": "Löscht einen Kommentar. Entweder muss pageid oder title angegeben werden.", + "apihelp-csdeletecomment-summary": "Löscht einen Kommentar. Es muss entweder pageid oder title angegeben werden.", + "apihelp-csdeletecomment-param-pageid": "Kennung der Seite, die den zu löschenden Kommentar enthält.", + "apihelp-csdeletecomment-param-title": "Titel der Seite, die den zu löschenden Kommentar enthält.", + "apihelp-csdeletecomment-pageid-example": "Löscht den Kommentar mit der Seitenkennung 3", + "apihelp-csdeletecomment-title-example": "Löscht den Kommentar mit dem Seitentitel CommentStreams:3", + "apihelp-cspostcomment-description": "Speichert einen neuen Kommentar.", + "apihelp-cspostcomment-summary": "Speichert einen neuen Kommentar.", + "apihelp-cspostcomment-param-commenttitle": "optionaler Titel für den Kommentar.", + "apihelp-cspostcomment-param-wikitext": "Wikitext für den Kommentar.", + "apihelp-cspostcomment-param-associatedid": "Seite, mit der dieser Kommentar verknüpft ist.", + "apihelp-cspostcomment-param-parentid": "Seitenkennung des übergeordneten Kommentars, falls dies eine Antwort ist.", + "apihelp-cseditcomment-description": "Bearbeitet einen vorhandenen Kommentar. Entweder pageid oder title muss angegeben werden.", + "apihelp-cseditcomment-summary": "Bearbeitet einen vorhandenen Kommentar. Entweder muss pageid oder title angegeben werden.", + "apihelp-cseditcomment-param-pageid": "Kennung der Seite, die den zu bearbeitenden Kommentar enthält.", + "apihelp-cseditcomment-param-title": "Titel der Seite, die den zu bearbeitenden Kommentar enthält.", + "apihelp-cseditcomment-param-commenttitle": "Optionaler Titel für den Kommentar.", + "apihelp-cseditcomment-param-wikitext": "Wikitext für den Kommentar.", + "apihelp-csvote-description": "Stimmt über einen Kommentar ab (Gefällt mir, Gefällt mir nicht oder neutral).", + "apihelp-csvote-summary": "Stimmt über einen Kommentar ab (Gefällt mir, Gefällt mir nicht oder neutral).", + "apihelp-csvote-param-pageid": "Seiten-ID der Seite, auf der sich der abzustimmende Kommentar befindet", + "apihelp-csvote-param-title": "Titel der Seite, die den Kommentar enthält, über den abgestimmt werden soll.", + "apihelp-csvote-param-vote": "Stimmt ab (1, -1 oder 0).", + "apihelp-csvote-pageid-example": "Stimmt über den Kommentar mit der Seitenkennung 3 ab", + "apihelp-csvote-title-example": "Stimmt über den Kommentar mit dem Seitentitel CommentStreams:3 ab", + "apihelp-cswatch-description": "Beobachtet einen Kommentar, um benachrichtigt zu werden, wenn er Antworten erhält.", + "apihelp-cswatch-summary": "Beobachtet einen Kommentar, um benachrichtigt zu werden, wenn er Antworten erhält.", + "apihelp-cswatch-param-pageid": "Kennung der Seite, die den zu beobachtenden Kommentar enthält.", + "apihelp-cswatch-param-title": "Titel der Seite, die den zu beobachtenden Kommentar enthält.", + "apihelp-cswatch-pageid-example": "Beobachtet den Kommentar mit der Seitenkennung 3", + "apihelp-cswatch-title-example": "Beobachtet den Kommentar mit dem Seitentitel CommentStreams:3", + "apihelp-csunwatch-description": "Beobachtet einen Kommentar nicht mehr, um nicht mehr benachrichtigt zu werden, wenn er Antworten erhält.", + "apihelp-csunwatch-summary": "Beobachtet einen Kommentar nicht mehr, um nicht länger benachrichtigt zu werden, wenn er Antworten erhält.", + "apihelp-csunwatch-param-pageid": "Kennung der Seite, die den nicht mehr zu beobachtenden Kommentar enthält.", + "apihelp-csunwatch-param-title": "Titel der Seite, die den nicht mehr zu beobachtenden Kommentar enthält.", + "apihelp-csunwatch-pageid-example": "Beobachtet den Kommentar mit der Seitenkennung 3 nicht mehr", + "apihelp-csunwatch-title-example": "Beobachtet den Kommentar mit dem Seitentitel CommentStreams:3 nicht mehr", + "commentstreams-api-error-invalid": "Ungültige API-Antwort", "commentstreams-api-error-notloggedin": "Du musst angemeldet sein.", "commentstreams-api-error-commentnotfound": "Der angeforderte Kommentar wurde nicht gefunden.", "commentstreams-api-error-notacomment": "Die angegebene Seitenkennung bezieht sich nicht auf einen gültigen Kommentar.", diff --git a/CommentStreams/i18n/el.json b/CommentStreams/i18n/el.json index cc47b457..3fb3d763 100644 --- a/CommentStreams/i18n/el.json +++ b/CommentStreams/i18n/el.json @@ -1,14 +1,15 @@ { "@metadata": { "authors": [ + "NikosLikomitros", "Nikosgranturismogt" ] }, "commentstreams-author-anonymous": "ανώνυμος", - "apihelp-csPostComment-description": "Αποστολή νέου σχολίου.", - "apihelp-csPostComment-summary": "Αποστολή νέου σχολίου.", - "apihelp-csPostComment-param-commenttitle": "προαιρετικός τίτλος για το σχόλιο.", - "apihelp-csPostComment-param-wikitext": "βικικείμενο για το σχόλιο.", + "apihelp-cspostcomment-description": "Αποστολή νέου σχολίου.", + "apihelp-cspostcomment-summary": "Αποστολή νέου σχολίου.", + "apihelp-cspostcomment-param-commenttitle": "προαιρετικός τίτλος για το σχόλιο.", + "apihelp-cseditcomment-param-wikitext": "βικικείμενο για το σχόλιο.", "commentstreams-api-error-vote-notloggedin": "Πρέπει να είστε συνδεδεμένοι για να ψηφίσετε.", "commentstreams-buttontext-add": "Πρόσθεση σχόλιου", "commentstreams-buttontext-reply": "Απάντηση", diff --git a/CommentStreams/i18n/en.json b/CommentStreams/i18n/en.json index c776dff9..233cc47d 100644 --- a/CommentStreams/i18n/en.json +++ b/CommentStreams/i18n/en.json @@ -9,49 +9,50 @@ "commentstreams-error-prohibitedaction": "Action $1 is not allowed on comment pages.", "commentstreams-error-comment-on-deleted-page": "The page with which this comment is associated has been deleted.", "commentstreams-author-anonymous": "anonymous", - "apihelp-csQueryComment-description": "Return the title, user, creation timestamp, and wikitext of a comment. Either pageid or title must be provided.", - "apihelp-csQueryComment-summary": "Return the title, user, creation timestamp, and wikitext of a comment. Either pageid or title must be provided.", - "apihelp-csQueryComment-param-pageid": "page ID of the page which holds the comment to query", - "apihelp-csQueryComment-param-title": "title of the page which holds the comment to query", - "apihelp-csQueryComment-pageid-example": "query comment with page ID 3 in wikitext", - "apihelp-csQueryComment-title-example": "query comment with page title CommentStreams:3 in wikitext", - "apihelp-csDeleteComment-description": "Delete a comment. Either pageid or title must be provided.", - "apihelp-csDeleteComment-summary": "Delete a comment. Either pageid or title must be provided.", - "apihelp-csDeleteComment-param-pageid": "page ID of the page which holds the comment to delete", - "apihelp-csDeleteComment-param-title": "title of the page which holds the comment to delete", - "apihelp-csDeleteComment-pageid-example": "delete comment with page ID 3", - "apihelp-csDeleteComment-title-example": "delete comment with page title CommentStreams:3", - "apihelp-csPostComment-description": "Post a new comment.", - "apihelp-csPostComment-summary": "Post a new comment.", - "apihelp-csPostComment-param-commenttitle": "optional title for comment.", - "apihelp-csPostComment-param-wikitext": "wikitext for comment.", - "apihelp-csPostComment-param-associatedid": "page with which this comment is associated.", - "apihelp-csPostComment-param-parentid": "page ID of parent comment if this is a reply.", - "apihelp-csEditComment-description": "Edit an existing comment. Either pageid or title must be provided.", - "apihelp-csEditComment-summary": "Edit an existing comment. Either pageid or title must be provided.", - "apihelp-csEditComment-param-pageid": "page ID of the page which holds the comment to edit", - "apihelp-csEditComment-param-title": "title of the page which holds the comment to edit", - "apihelp-csEditComment-param-commenttitle": "optional title for comment.", - "apihelp-csEditComment-param-wikitext": "wikitext for comment.", - "apihelp-csVote-description": "Vote (up, down, or neutral) on a comment.", - "apihelp-csVote-summary": "Vote (up, down, or neutral) on a comment.", - "apihelp-csVote-param-pageid": "page ID of the page which holds the comment to be voted on", - "apihelp-csVote-param-title": "title of the page which holds the comment to be voted on", - "apihelp-csVote-param-vote": "vote (1, -1, or 0).", - "apihelp-csVote-pageid-example": "vote on comment with page ID 3", - "apihelp-csVote-title-example": "vote on comment with page title CommentStreams:3", - "apihelp-csWatch-description": "Watch a comment to be notified when it receives replies", - "apihelp-csWatch-summary": "Watch a comment to be notified when it receives replies", - "apihelp-csWatch-param-pageid": "page ID of the page which holds the comment to be watched", - "apihelp-csWatch-param-title": "title of the page which holds the comment to be watched", - "apihelp-csWatch-pageid-example": "watch comment with page ID 3", - "apihelp-csWatch-title-example": "watch comment with page title CommentStreams:3", - "apihelp-csUnwatch-description": "Unwatch a comment to no longer be notified when it receives replies", - "apihelp-csUnwatch-summary": "Unwatch a comment to no longer be notified when it receives replies", - "apihelp-csUnwatch-param-pageid": "page ID of the page which holds the comment to be unwatched", - "apihelp-csUnwatch-param-title": "title of the page which holds the comment to be unwatched", - "apihelp-csUnwatch-pageid-example": "unwatch comment with page ID 3", - "apihelp-csUnwatch-title-example": "unwatch comment with page title CommentStreams:3", + "apihelp-csquerycomment-description": "Return the title, user, creation timestamp, and wikitext of a comment. Either pageid or title must be provided.", + "apihelp-csquerycomment-summary": "Return the title, user, creation timestamp, and wikitext of a comment. Either pageid or title must be provided.", + "apihelp-csquerycomment-param-pageid": "page ID of the page which holds the comment to query", + "apihelp-csquerycomment-param-title": "title of the page which holds the comment to query", + "apihelp-csquerycomment-pageid-example": "query comment with page ID 3 in wikitext", + "apihelp-csquerycomment-title-example": "query comment with page title CommentStreams:3 in wikitext", + "apihelp-csdeletecomment-description": "Delete a comment. Either pageid or title must be provided.", + "apihelp-csdeletecomment-summary": "Delete a comment. Either pageid or title must be provided.", + "apihelp-csdeletecomment-param-pageid": "page ID of the page which holds the comment to delete", + "apihelp-csdeletecomment-param-title": "title of the page which holds the comment to delete", + "apihelp-csdeletecomment-pageid-example": "delete comment with page ID 3", + "apihelp-csdeletecomment-title-example": "delete comment with page title CommentStreams:3", + "apihelp-cspostcomment-description": "Post a new comment.", + "apihelp-cspostcomment-summary": "Post a new comment.", + "apihelp-cspostcomment-param-commenttitle": "optional title for comment.", + "apihelp-cspostcomment-param-wikitext": "wikitext for comment.", + "apihelp-cspostcomment-param-associatedid": "page with which this comment is associated.", + "apihelp-cspostcomment-param-parentid": "page ID of parent comment if this is a reply.", + "apihelp-cseditcomment-description": "Edit an existing comment. Either pageid or title must be provided.", + "apihelp-cseditcomment-summary": "Edit an existing comment. Either pageid or title must be provided.", + "apihelp-cseditcomment-param-pageid": "page ID of the page which holds the comment to edit", + "apihelp-cseditcomment-param-title": "title of the page which holds the comment to edit", + "apihelp-cseditcomment-param-commenttitle": "optional title for comment.", + "apihelp-cseditcomment-param-wikitext": "wikitext for comment.", + "apihelp-csvote-description": "Vote (up, down, or neutral) on a comment.", + "apihelp-csvote-summary": "Vote (up, down, or neutral) on a comment.", + "apihelp-csvote-param-pageid": "page ID of the page which holds the comment to be voted on", + "apihelp-csvote-param-title": "title of the page which holds the comment to be voted on", + "apihelp-csvote-param-vote": "vote (1, -1, or 0).", + "apihelp-csvote-pageid-example": "vote on comment with page ID 3", + "apihelp-csvote-title-example": "vote on comment with page title CommentStreams:3", + "apihelp-cswatch-description": "Watch a comment to be notified when it receives replies", + "apihelp-cswatch-summary": "Watch a comment to be notified when it receives replies", + "apihelp-cswatch-param-pageid": "page ID of the page which holds the comment to be watched", + "apihelp-cswatch-param-title": "title of the page which holds the comment to be watched", + "apihelp-cswatch-pageid-example": "watch comment with page ID 3", + "apihelp-cswatch-title-example": "watch comment with page title CommentStreams:3", + "apihelp-csunwatch-description": "Unwatch a comment to no longer be notified when it receives replies", + "apihelp-csunwatch-summary": "Unwatch a comment to no longer be notified when it receives replies", + "apihelp-csunwatch-param-pageid": "page ID of the page which holds the comment to be unwatched", + "apihelp-csunwatch-param-title": "title of the page which holds the comment to be unwatched", + "apihelp-csunwatch-pageid-example": "unwatch comment with page ID 3", + "apihelp-csunwatch-title-example": "unwatch comment with page title CommentStreams:3", + "commentstreams-api-error-invalid": "Invalid API response.", "commentstreams-api-error-notloggedin": "You must be logged in.", "commentstreams-api-error-commentnotfound": "The requested comment was not found.", "commentstreams-api-error-notacomment": "The supplied page ID does not refer to a valid comment.", @@ -153,6 +154,7 @@ "commentstreams-allcomments-label-created": "Created", "commentstreams-allcomments-label-lasteditor": "Last Editor", "commentstreams-allcomments-label-lastedited": "Last Edited", + "commentstreams-allcomments-label-blockid": "Block Id", "commentstreams-allcomments-button-next": "Next", "commentstreams-allcomments-button-previous": "Previous", "commentstreams-ve-conversion-error": "Error converting between wikitext and HTML for VisualEditor" diff --git a/CommentStreams/i18n/es.json b/CommentStreams/i18n/es.json index cdf44c78..57a32140 100644 --- a/CommentStreams/i18n/es.json +++ b/CommentStreams/i18n/es.json @@ -9,11 +9,11 @@ "commentstreams-error-prohibitedaction": "No se permite efectuar la acción $1 en las páginas de comentarios.", "commentstreams-error-comment-on-deleted-page": "Se eliminó la página que estaba asociada con este comentario.", "commentstreams-author-anonymous": "anónimo", - "apihelp-csPostComment-description": "Publicar un comentario nuevo.", - "apihelp-csPostComment-summary": "Publicar un comentario nuevo.", - "apihelp-csPostComment-param-commenttitle": "título opcional para el comentario.", - "apihelp-csVote-summary": "Votar (a favor, en contra o como indiferente) un comentario.", - "apihelp-csVote-param-vote": "votar (1, −1 o 0).", + "apihelp-cspostcomment-description": "Publicar un comentario nuevo.", + "apihelp-cspostcomment-summary": "Publicar un comentario nuevo.", + "apihelp-cspostcomment-param-commenttitle": "título opcional para el comentario.", + "apihelp-csvote-summary": "Votar (a favor, en contra o como indiferente) un comentario.", + "apihelp-csvote-param-vote": "votar (1, −1 o 0).", "commentstreams-api-error-commentnotfound": "No se encontró el comentario solicitado.", "commentstreams-api-error-post-parentpagedoesnotexist": "No existe el comentario al que se está respondiendo.", "commentstreams-api-error-post": "Error al añadir el comentario.", diff --git a/CommentStreams/i18n/fr.json b/CommentStreams/i18n/fr.json index 040383ca..ed1cbaaa 100644 --- a/CommentStreams/i18n/fr.json +++ b/CommentStreams/i18n/fr.json @@ -3,62 +3,64 @@ "authors": [ "Gomoko", "Thibaut120094", + "Verdy p", "Wladek92" ] }, "commentstreams-desc": "Permet de commenter les pages wiki", "commentstreams-error-prohibitedaction": "L’action $1 n’est pas permise sur les pages de commentaire.", - "commentstreams-error-comment-on-deleted-page": "La page à laquelle ce commentaire est associé, a été supprimée.", + "commentstreams-error-comment-on-deleted-page": "La page à laquelle ce commentaire est associé a été supprimée.", "commentstreams-author-anonymous": "anonyme", - "apihelp-csQueryComment-description": "Renvoyer le titre, l’utilisateur, l’horodatage de création et le wikitexte d’un commentaire. Le pageid ou le titre doit être fourni.", - "apihelp-csQueryComment-summary": "Renvoyer le titre, l’utilisateur, l’horodatage de création et le wikitexte d’un commentaire. Le pageid ou le titre doit être fourni.", - "apihelp-csQueryComment-param-pageid": "ID de la page qui contient le commentaire à rechercher", - "apihelp-csQueryComment-param-title": "titre de la page qui contient le commentaire à rechercher", - "apihelp-csQueryComment-pageid-example": "rechercher le commentaire de la page d’ID 3 en wikitexte", - "apihelp-csQueryComment-title-example": "rechercher le commentaire de la page de titre CommentStreams:3 en wikitexte", - "apihelp-csDeleteComment-description": "Supprimer un commentaire. Le pageid ou le titre doit être fourni.", - "apihelp-csDeleteComment-summary": "Supprimer un commentaire. Le pageid ou le titre doit être fourni.", - "apihelp-csDeleteComment-param-pageid": "l’ID de la page qui contient le commentaire à supprimer", - "apihelp-csDeleteComment-param-title": "le titre de la page qui contient le commentaire à supprimer", - "apihelp-csDeleteComment-pageid-example": "supprimer le commentaire de la page d’ID 3", - "apihelp-csDeleteComment-title-example": "supprimer le commentaire de la page de titre CommentStreams:3", - "apihelp-csPostComment-description": "Publier un nouveau commentaire.", - "apihelp-csPostComment-summary": "Publier un nouveau commentaire.", - "apihelp-csPostComment-param-commenttitle": "titre facultatif pour le commentaire.", - "apihelp-csPostComment-param-wikitext": "wikitexte pour le commentaire.", - "apihelp-csPostComment-param-associatedid": "page à laquelle est associé le commentaire.", - "apihelp-csPostComment-param-parentid": "ID de page ou commentaire parent si c’est une réponse.", - "apihelp-csEditComment-description": "Modifier un commentaire existant. Le pageid ou le titre doit être fourni.", - "apihelp-csEditComment-summary": "Modifier un commentaire existant. Le pageid ou le titre doit être fourni.", - "apihelp-csEditComment-param-pageid": "ID de la page qui contient le commentaire à modifier", - "apihelp-csEditComment-param-title": "titre de la page qui contient le commentaire à modifier", - "apihelp-csEditComment-param-commenttitle": "titre facultatif pour le commentaire.", - "apihelp-csEditComment-param-wikitext": "wikitexte pour le commentaire.", - "apihelp-csVote-description": "Vote (positif, négatif ou neutre) sur un commentaire.", - "apihelp-csVote-summary": "Vote (positif, négatif ou neutre) sur un commentaire.", - "apihelp-csVote-param-pageid": "ID de la page qui contient le commentaire pour lequel voter", - "apihelp-csVote-param-title": "titre de la page qui contient le commentaire pour lequel voter", - "apihelp-csVote-param-vote": "vote (1, -1, ou 0).", - "apihelp-csVote-pageid-example": "voter pour le commentaire de la page d’ID 3", - "apihelp-csVote-title-example": "voter pour le commentaire de la page ayant pour titre CommentStreams:3", - "apihelp-csWatch-description": "Surveiller un commentaire à notifier quand il reçoit des réponses", - "apihelp-csWatch-summary": "Surveiller un commentaire à notifier quand il reçoit des réponses", - "apihelp-csWatch-param-pageid": "ID de la page qui contient le commentaire à surveiller", - "apihelp-csWatch-param-title": "titre de la page qui contient le commentaire à surveiller", - "apihelp-csWatch-pageid-example": "surveiller le commentaire de la page d’ID 3", - "apihelp-csWatch-title-example": "surveiller le commentaire de la page de titre CommentStreams:3", - "apihelp-csUnwatch-description": "Ne plus surveiller un commentaire pour ne plus être notifié quand il reçoit des réponses", - "apihelp-csUnwatch-summary": "Ne plus surveiller un commentaire pour ne plus être notifié quand il reçoit des réponses", - "apihelp-csUnwatch-param-pageid": "ID de la page qui contient le commentaire à ne plus surveiller", - "apihelp-csUnwatch-param-title": "titre de la page qui contient le commentaire à ne plus surveiller", - "apihelp-csUnwatch-pageid-example": "ne plus surveiller le commentaire de la page d’ID 3", - "apihelp-csUnwatch-title-example": "ne plus surveiller le commentaire de la page de titre CommentStreams:3", + "apihelp-csquerycomment-description": "Renvoyer le titre, l’utilisateur, l’horodatage de création et le wikitexte d’un commentaire. Le pageid ou le titre doit être fourni.", + "apihelp-csquerycomment-summary": "Renvoyer le titre, l’utilisateur, l’horodatage de création et le wikitexte d’un commentaire. Le ''pageid'' ou le titre doit être fourni.", + "apihelp-csquerycomment-param-pageid": "ID de la page qui contient le commentaire à rechercher", + "apihelp-csquerycomment-param-title": "titre de la page qui contient le commentaire à rechercher", + "apihelp-csquerycomment-pageid-example": "rechercher le commentaire de la page d’ID 3 en wikitexte", + "apihelp-csquerycomment-title-example": "rechercher le commentaire de la page de titre ''CommentStreams:3'' en wikitexte", + "apihelp-csdeletecomment-description": "Supprimer un commentaire. Le ''pageid'' ou le titre doit être fourni.", + "apihelp-csdeletecomment-summary": "Supprimer un commentaire. Le ''pageid'' ou le titre doit être fourni.", + "apihelp-csdeletecomment-param-pageid": "l’ID de la page qui contient le commentaire à supprimer", + "apihelp-csdeletecomment-param-title": "le titre de la page qui contient le commentaire à supprimer", + "apihelp-csdeletecomment-pageid-example": "supprimer le commentaire de la page d’ID 3", + "apihelp-csdeletecomment-title-example": "supprimer le commentaire de la page de titre ''CommentStreams:3''", + "apihelp-cspostcomment-description": "Publier un nouveau commentaire.", + "apihelp-cspostcomment-summary": "Publier un nouveau commentaire.", + "apihelp-cspostcomment-param-commenttitle": "titre facultatif pour le commentaire.", + "apihelp-cspostcomment-param-wikitext": "wikitexte pour le commentaire.", + "apihelp-cspostcomment-param-associatedid": "page à laquelle est associé le commentaire.", + "apihelp-cspostcomment-param-parentid": "ID de page ou commentaire parent si c’est une réponse.", + "apihelp-cseditcomment-description": "Modifier un commentaire existant. Le ''pageid'' ou le titre doit être fourni.", + "apihelp-cseditcomment-summary": "Modifier un commentaire existant. Le ''pageid'' ou le titre doit être fourni.", + "apihelp-cseditcomment-param-pageid": "ID de la page qui contient le commentaire à modifier", + "apihelp-cseditcomment-param-title": "titre de la page qui contient le commentaire à modifier", + "apihelp-cseditcomment-param-commenttitle": "titre facultatif pour le commentaire.", + "apihelp-cseditcomment-param-wikitext": "wikitexte pour le commentaire.", + "apihelp-csvote-description": "Vote (positif, négatif ou neutre) sur un commentaire.", + "apihelp-csvote-summary": "Vote (positif, négatif ou neutre) sur un commentaire.", + "apihelp-csvote-param-pageid": "ID de la page qui contient le commentaire pour lequel voter", + "apihelp-csvote-param-title": "titre de la page qui contient le commentaire pour lequel voter", + "apihelp-csvote-param-vote": "vote (1, -1, ou 0).", + "apihelp-csvote-pageid-example": "voter pour le commentaire de la page d’ID 3", + "apihelp-csvote-title-example": "voter pour le commentaire de la page ayant pour titre ''CommentStreams:3''", + "apihelp-cswatch-description": "Surveiller un commentaire à notifier quand il reçoit des réponses", + "apihelp-cswatch-summary": "Surveiller un commentaire à notifier quand il reçoit des réponses", + "apihelp-cswatch-param-pageid": "ID de la page qui contient le commentaire à surveiller", + "apihelp-cswatch-param-title": "titre de la page qui contient le commentaire à surveiller", + "apihelp-cswatch-pageid-example": "surveiller le commentaire de la page d’ID 3", + "apihelp-cswatch-title-example": "surveiller le commentaire de la page de titre ''CommentStreams:3''", + "apihelp-csunwatch-description": "Ne plus surveiller un commentaire pour ne plus être notifié quand il reçoit des réponses", + "apihelp-csunwatch-summary": "Ne plus surveiller un commentaire pour ne plus être notifié quand il reçoit des réponses", + "apihelp-csunwatch-param-pageid": "ID de la page qui contient le commentaire à ne plus surveiller", + "apihelp-csunwatch-param-title": "titre de la page qui contient le commentaire à ne plus surveiller", + "apihelp-csunwatch-pageid-example": "ne plus surveiller le commentaire de la page d’ID 3", + "apihelp-csunwatch-title-example": "ne plus surveiller le commentaire de la page de titre ''CommentStreams:3''", + "commentstreams-api-error-invalid": "Réponse d’API non valide.", "commentstreams-api-error-notloggedin": "Vous devez être connecté.", "commentstreams-api-error-commentnotfound": "Le commentaire demandé n’a pas été trouvé.", "commentstreams-api-error-notacomment": "L’ID de page fourni ne fait pas référence à un commentaire valide.", "commentstreams-api-error-missingcommenttitle": "Un titre de commentaire doit être fourni pour les commentaires qui ne sont pas des réponses.", "commentstreams-api-error-post-permissions": "L’utilisateur n’a pas le droit de publier un commentaire.", - "commentstreams-api-error-post-parentandtitle": "Vous ne devez pas spécifier à la fois l’id parent et le titre du commentaire.", + "commentstreams-api-error-post-parentandtitle": "Vous ne devez pas spécifier à la fois l’ID parent et le titre du commentaire.", "commentstreams-api-error-post-parentpagedoesnotexist": "Le commentaire auquel vous répondez n’existe pas.", "commentstreams-api-error-post-associatedpageidmismatch": "La page commentée ne correspond pas à la page du commentaire parent.", "commentstreams-api-error-post-associatedpagedoesnotexist": "La page commentée n’existe pas.", @@ -98,34 +100,34 @@ "commentstreams-buttontooltip-unwatch": "ne plus surveiller", "commentstreams-buttontooltip-submit": "soumettre", "commentstreams-buttontooltip-cancel": "annuler", - "commentstreams-dialog-delete-message": "Êtes-vous sûr de vouloir supprimer ce commentaire ?", + "commentstreams-dialog-delete-message": "Êtes-vous sûr{{GENDER:||e}} de vouloir supprimer ce commentaire ?", "commentstreams-dialog-anonymous-message": "Vous n’êtes pas connecté. Si vous poursuivez l’enregistrement de ce commentaire, votre adresse IP sera enregistrée, et vous ne pourrez plus modifier ou supprimer ce commentaire.", "commentstreams-dialog-buttontext-ok": "OK", "commentstreams-dialog-buttontext-cancel": "Annuler", "commentstreams-dialog-buttontext-yes": "Oui", "commentstreams-dialog-buttontext-no": "Non", - "commentstreams-urldialog-instructions": "Copier et coller l’URL ci-dessous pour partager un lien permanent vers ce commentaire. Appuyez sur Échap pour faire disparaître cette fenêtre.", + "commentstreams-urldialog-instructions": "Copier et coller l’URL ci-dessous pour partager un lien permanent vers ce commentaire. Appuyez sur Échap pour fermer ce panneau.", "commentstreams-datetext-postedon": "Publié le", "commentstreams-datetext-lasteditedon": "Dernière modification le", "commentstreams-datetext-moderated": "modéré", - "commentstreams-title-field-placeholder": "Saisir le titre…", - "commentstreams-body-field-placeholder": "Saisir le nouveau texte du commentaire…", + "commentstreams-title-field-placeholder": "Saisir le titre...", + "commentstreams-body-field-placeholder": "Saisir le nouveau texte du commentaire...", "echo-category-title-commentstreams-notification-category": "Nouveaux commentaires et réponses", - "notification-header-commentstreams-comment-on-watched-page": "$1 {{GENDER:$4|a commenté}} \"<i>$2</i>\" sur la page \"<i>$3</i>\", que {{GENDER:$6|vous}} lisez.", - "notification-header-commentstreams-reply-on-watched-page": "$1 {{GENDER:$4|a répondu}} au commentaire \"<i>$2</i>\" sur la page \"<i>$3</i>\", que {{GENDER:$6|vous}} lisez.", - "notification-header-commentstreams-reply-to-watched-comment": "$1 {{GENDER:$4|a répondu}} au commentaire \"<i>$2</i>\", que {{GENDER:$6|vous}} lisez, sur la page \"<i>$3</i>\".", - "notification-subject-commentstreams-comment-on-watched-page": "Quelqu’un a commenté une page que vous surveillez.", - "notification-subject-commentstreams-reply-on-watched-page": "Quelqu’un a répondu à un commentaire sur une page que vous surveillez", - "notification-subject-commentstreams-reply-to-watched-comment": "Quelqu’un a répondu à un commentaire que vous surveillez", - "notification-body-commentstreams-comment-on-watched-page": "Le commentaire est :\n\n\n$5", - "notification-body-commentstreams-reply-on-watched-page": "La réponse est :\n\n\n$5", - "notification-body-commentstreams-reply-to-watched-comment": "La réponse est :\n\n\n$5", + "notification-header-commentstreams-comment-on-watched-page": "$1{{GENDER:$4|}} a commenté « <i>$2</i> » sur la page « <i>$3</i> » que {{GENDER:$6|}}vous lisez.", + "notification-header-commentstreams-reply-on-watched-page": "$1{{GENDER:$4|}} a répondu au commentaire « <i>$2</i> » sur la page « <i>$3</i> » que {{GENDER:$6|}}vous lisez.", + "notification-header-commentstreams-reply-to-watched-comment": "$1{{GENDER:$4|}} a répondu au commentaire « <i>$2</i> » sur la page « <i>$3</i> » que {{GENDER:$6|vous}} lisez.", + "notification-subject-commentstreams-comment-on-watched-page": "Quelqu’un a commenté une page que vous suivez.", + "notification-subject-commentstreams-reply-on-watched-page": "Quelqu’un a répondu à un commentaire sur une page que vous suivez.", + "notification-subject-commentstreams-reply-to-watched-comment": "Quelqu’un a répondu à un commentaire que vous suivez.", + "notification-body-commentstreams-comment-on-watched-page": "Le commentaire est :\n\n\n$5", + "notification-body-commentstreams-reply-on-watched-page": "La réponse est :\n\n\n$5", + "notification-body-commentstreams-reply-to-watched-comment": "La réponse est :\n\n\n$5", "notification-link-label-commentstreams-comment-on-watched-page": "Visiter le commentaire", "notification-link-label-commentstreams-reply-on-watched-page": "Visiter la réponse", "notification-link-label-commentstreams-reply-to-watched-comment": "Visiter la réponse", "group-csmoderator": "Modérateurs (CommentStreams)", - "group-csmoderator-member": "{{GENDER:$1|modérateur|modératrice}} (CommentStreams)", - "grouppage-csmoderator": "{{ns:project}}:Moderators (CommentStreams)", + "group-csmoderator-member": "modérat{{GENDER:$1|eur|rice}} (CommentStreams)", + "grouppage-csmoderator": "{{ns:project}}:Modérateurs (CommentStreams)", "right-cs-comment": "Publier, modifier et supprimer les commentaires appartenant à l’utilisateur", "action-cs-comment": "publier, modifier ou supprimer des commentaires", "right-cs-moderator-edit": "Modifier les commentaires de n’importe quel utilisateur", @@ -134,18 +136,18 @@ "action-cs-moderator-delete": "supprimer les commentaires des autres utilisateurs", "log-name-commentstreams": "Journal de CommentStreams", "log-description-commentstreams": "Ces événements tracent quand les événements de CommentStreams se produisent.", - "logentry-commentstreams-comment-create": "$1 {{GENDER:$2|a créé}} le commentaire $3", - "logentry-commentstreams-reply-create": "$1 {{GENDER:$2|a écrit}} la réponse $3", - "logentry-commentstreams-comment-edit": "$1 {{GENDER:$2|a modifié}} le commentaire $3", - "logentry-commentstreams-comment-moderator-edit": "$1 {{GENDER:$2|(modérateur) a modifié}} le commentaire $3", - "logentry-commentstreams-reply-edit": "$1 {{GENDER:$2|a modifié}} la réponse $3", - "logentry-commentstreams-reply-moderator-edit": "$1 {{GENDER:$2|(modérateur)|(modératrice)}} a modifié la réponse $3", - "logentry-commentstreams-comment-delete": "$1 {{GENDER:$2|a supprimé}} le commentaire $3", - "logentry-commentstreams-comment-moderator-delete": "$1 {{GENDER:$2|(modérateur)|(modératrice)}} a supprimé le commentaire $3", - "logentry-commentstreams-reply-delete": "$1 {{GENDER:$2|a supprimé}} la réponse $3", - "logentry-commentstreams-reply-moderator-delete": "$1 {{GENDER:$2|(modérateur) a supprimé}} la réponse $3", + "logentry-commentstreams-comment-create": "$1{{GENDER:$2|}} a créé le commentaire $3", + "logentry-commentstreams-reply-create": "$1{{GENDER:$2|}} a écrit la réponse $3", + "logentry-commentstreams-comment-edit": "$1{{GENDER:$2|}} a modifié le commentaire $3", + "logentry-commentstreams-comment-moderator-edit": "$1 (modérat{{GENDER:$2|eur|rice}}) a modifié le commentaire $3", + "logentry-commentstreams-reply-edit": "$1{{GENDER:$2|}} a modifié la réponse $3", + "logentry-commentstreams-reply-moderator-edit": "$1 (modérat{{GENDER:$2|eur|rice}}) a modifié la réponse $3", + "logentry-commentstreams-comment-delete": "$1{{GENDER:$2|}} a supprimé le commentaire $3", + "logentry-commentstreams-comment-moderator-delete": "$1 (modérat{{GENDER:$2|eur|rice}}) a supprimé le commentaire $3", + "logentry-commentstreams-reply-delete": "$1{{GENDER:$2|}} a supprimé la réponse $3", + "logentry-commentstreams-reply-moderator-delete": "$1 (modérat{{GENDER:$2|eur|rice}}) a supprimé la réponse $3", "commentstreamsallcomments": "Tous les commentaires", - "commentstreams-allcomments-nocommentsfound": "Pas de commentaire trouvé.", + "commentstreams-allcomments-nocommentsfound": "Aucun commentaire trouvé.", "commentstreams-allcomments-label-page": "Page de commentaire", "commentstreams-allcomments-label-associatedpage": "Page associée", "commentstreams-allcomments-label-commenttitle": "Titre du commentaire", @@ -156,5 +158,5 @@ "commentstreams-allcomments-label-lastedited": "Dernière modification", "commentstreams-allcomments-button-next": "Suivant", "commentstreams-allcomments-button-previous": "Précédent", - "commentstreams-ve-conversion-error": "Erreur de conversion entre wikitexte et HTML pour VisualEditor" + "commentstreams-ve-conversion-error": "Erreur de conversion entre le wikitexte et le code HTML pour l’ÉditeurVisuel" } diff --git a/CommentStreams/i18n/fy.json b/CommentStreams/i18n/fy.json index a06e46fd..985f2a71 100644 --- a/CommentStreams/i18n/fy.json +++ b/CommentStreams/i18n/fy.json @@ -4,5 +4,6 @@ "PiefPafPier" ] }, + "commentstreams-api-error-notloggedin": "Jo moatte ynlogd wêze.", "echo-category-title-commentstreams-notification-category": "Nij kommentaar en antwurd" } diff --git a/CommentStreams/i18n/gl.json b/CommentStreams/i18n/gl.json index 19fd3d54..349d1512 100644 --- a/CommentStreams/i18n/gl.json +++ b/CommentStreams/i18n/gl.json @@ -1,29 +1,30 @@ { "@metadata": { "authors": [ + "ArenaL5", "Athena in Wonderland", "Elisardojm" ] }, "commentstreams-desc": "Permite deixar comentarios nas páxinas da wiki", "commentstreams-author-anonymous": "anónimo", - "apihelp-csPostComment-description": "Publicar un novo comentario.", - "apihelp-csPostComment-summary": "Publicar un novo comentario.", - "apihelp-csPostComment-param-commenttitle": "título opcional para o comentario.", - "apihelp-csPostComment-param-wikitext": "texto wiki para o comentario.", - "apihelp-csEditComment-param-commenttitle": "título opcional para o comentario.", - "apihelp-csEditComment-param-wikitext": "texto wiki para o comentario.", - "apihelp-csVote-description": "Votar (positivo, negativo ou neutro) nun comentario.", - "apihelp-csVote-summary": "Votar (positivo, negativo ou neutro) nun comentario.", - "apihelp-csVote-param-vote": "votar (1, −1 ou 0).", + "apihelp-cspostcomment-description": "Publicar un novo comentario.", + "apihelp-cspostcomment-summary": "Publicar un novo comentario.", + "apihelp-cspostcomment-param-commenttitle": "título opcional para o comentario.", + "apihelp-cspostcomment-param-wikitext": "texto wiki para o comentario.", + "apihelp-cseditcomment-param-commenttitle": "título opcional para o comentario.", + "apihelp-cseditcomment-param-wikitext": "texto wiki para o comentario.", + "apihelp-csvote-description": "Votar (positivo, negativo ou neutro) nun comentario.", + "apihelp-csvote-summary": "Votar (positivo, negativo ou neutro) nun comentario.", + "apihelp-csvote-param-vote": "votar (1, −1 ou 0).", "commentstreams-api-error-notloggedin": "Debe estar conectado.", "commentstreams-api-error-commentnotfound": "Non se atopou o comentario solicitado.", "commentstreams-api-error-post": "Erro ó engadir o comentario.", "commentstreams-api-error-edit": "Erro ó editar o comentario.", "commentstreams-api-error-delete-notloggedin": "Debe estar conectado para borrar.", "commentstreams-api-error-delete": "Erro ó borrar o comentario.", - "commentstreams-buttontext-add": "ENGADIR UN COMENTARIO", - "commentstreams-buttontext-reply": "RESPONDER", + "commentstreams-buttontext-add": "Engadir comentario", + "commentstreams-buttontext-reply": "Responder", "commentstreams-buttontooltip-add": "engadir un comentario", "commentstreams-buttontooltip-reply": "responder", "commentstreams-buttontooltip-edit": "editar", diff --git a/CommentStreams/i18n/he.json b/CommentStreams/i18n/he.json index d1e8a779..8fd213dd 100644 --- a/CommentStreams/i18n/he.json +++ b/CommentStreams/i18n/he.json @@ -9,49 +9,49 @@ "commentstreams-error-prohibitedaction": "הפעולה $1 אינה מותרת בדפי תגובות.", "commentstreams-error-comment-on-deleted-page": "הדף שהתגובה הזאת משויכת אליו נמחק.", "commentstreams-author-anonymous": "אנונימי", - "apihelp-csQueryComment-description": "החזרת הכותרת, המשתמש, מועד היצירה וטקסט הוויקי של תגובה. יש לציין את מזהה הדף או את כותרתו.", - "apihelp-csQueryComment-summary": "החזרת הכותרת, המשתמש, מועד היצירה וטקסט הוויקי של תגובה. יש לציין את מזהה הדף או את כותרתו.", - "apihelp-csQueryComment-param-pageid": "מזהה הדף שבו נמצאת התגובה שעליה תבוצע השאילתה", - "apihelp-csQueryComment-param-title": "כותרת הדף שבו נמצאת התגובה שעליה תבוצע השאילתה", - "apihelp-csQueryComment-pageid-example": "שאילתה על תגובה בדף שהמזהה שלו הוא 3 בטקסט ויקי", - "apihelp-csQueryComment-title-example": "שאילתה על תגובה בדף שהכותרת שלו היא CommentStreams:3 בקוד ויקי", - "apihelp-csDeleteComment-description": "מחיקת תגובה. יש לציין את מזהה הדף או את כותרתו.", - "apihelp-csDeleteComment-summary": "מחיקת תגובה. יש לציין את מזהה הדף או את כותרתו.", - "apihelp-csDeleteComment-param-pageid": "מזהה הדף שבו נמצאת התגובה שתימחק", - "apihelp-csDeleteComment-param-title": "כותרת הדף שבו נמצאת התגובה שתימחק", - "apihelp-csDeleteComment-pageid-example": "מחיקת תגובה בדף שהמזהה שלו הוא 3", - "apihelp-csDeleteComment-title-example": "מחיקת תגובה בדף שהכותרת שלו היא CommentStreams:3", - "apihelp-csPostComment-description": "הוספת תגובה חדשה.", - "apihelp-csPostComment-summary": "הוספת תגובה חדשה.", - "apihelp-csPostComment-param-commenttitle": "כותרת לתגובה (לא חובה).", - "apihelp-csPostComment-param-wikitext": "טקסט הוויקי של התגובה.", - "apihelp-csPostComment-param-associatedid": "הדף שאליו תשויך התגובה.", - "apihelp-csPostComment-param-parentid": "אם זו תשובה לתגובה אחרת, מזהה הדף של התגובה שעליה תיכתב התשובה.", - "apihelp-csEditComment-description": "עריכת תגובה קיימת. יש לציין את מזהה הדף או את כותרתו.", - "apihelp-csEditComment-summary": "עריכת תגובה קיימת. יש לציין את מזהה הדף או את כותרתו.", - "apihelp-csEditComment-param-pageid": "מזהה הדף שבו נמצאת התגובה שתיערך", - "apihelp-csEditComment-param-title": "כותרת הדף שבו נמצאת התגובה שתיערך", - "apihelp-csEditComment-param-commenttitle": "כותרת לתגובה (לא חובה).", - "apihelp-csEditComment-param-wikitext": "טקסט הוויקי של התגובה.", - "apihelp-csVote-description": "הצבעה (אהבתי, לא אהבתי או נייטרלי) על תגובה.", - "apihelp-csVote-summary": "הצבעה (אהבתי, לא אהבתי או נייטרלי) על תגובה.", - "apihelp-csVote-param-pageid": "מזהה הדף שבו נמצאת התגובה שעליה תבוצע ההצבעה", - "apihelp-csVote-param-title": "כותרת הדף שבו נמצאת התגובה שעליה תבוצע ההצבעה", - "apihelp-csVote-param-vote": "הצבעה (1, <span dir=\"ltr\">-1</span> או 0).", - "apihelp-csVote-pageid-example": "הצבעה על תגובה בדף שהמזהה שלו הוא 3", - "apihelp-csVote-title-example": "הצבעה על תגובה בדף שהכותרת שלו היא CommentStreams:3", - "apihelp-csWatch-description": "מעקב אחרי תגובה כדי לקבל התראות כשמישהו משיב עליה", - "apihelp-csWatch-summary": "מעקב אחרי תגובה כדי לקבל התראות כשמישהו משיב עליה", - "apihelp-csWatch-param-pageid": "מזהה הדף שבו נמצאת התגובה שברצונך לעקוב אחריה", - "apihelp-csWatch-param-title": "כותרת הדף שבו נמצאת התגובה שברצונך לעקוב אחריה", - "apihelp-csWatch-pageid-example": "מעקב אחרי תגובה בדף שהמזהה שלו הוא 3", - "apihelp-csWatch-title-example": "מעקב אחרי תגובה בדף שהכותרת שלו היא CommentStreams:3", - "apihelp-csUnwatch-description": "הפסקת המעקב אחרי תגובה כדי להפסיק לקבל התראות כשמישהו משיב עליה", - "apihelp-csUnwatch-summary": "הפסקת המעקב אחרי תגובה כדי להפסיק לקבל התראות כשמישהו משיב עליה", - "apihelp-csUnwatch-param-pageid": "מזהה הדף שבו נמצאת התגובה שברצונך להפסיק לעקוב אחריה", - "apihelp-csUnwatch-param-title": "כותרת הדף שבו נמצאת התגובה שברצונך להפסיק לעקוב אחריה", - "apihelp-csUnwatch-pageid-example": "הפסקת המעקב אחרי תגובה בדף שהמזהה שלו הוא 3", - "apihelp-csUnwatch-title-example": "הפסקת המעקב אחרי תגובה בדף שהכותרת שלו היא CommentStreams:3", + "apihelp-csquerycomment-description": "החזרת הכותרת, המשתמש, מועד היצירה וטקסט הוויקי של תגובה. יש לציין את מזהה הדף או את כותרתו.", + "apihelp-csquerycomment-summary": "החזרת הכותרת, המשתמש, מועד היצירה וטקסט הוויקי של תגובה. יש לציין את מזהה הדף או את כותרתו.", + "apihelp-csquerycomment-param-pageid": "מזהה הדף שבו נמצאת התגובה שעליה תבוצע השאילתה", + "apihelp-csquerycomment-param-title": "כותרת הדף שבו נמצאת התגובה שעליה תבוצע השאילתה", + "apihelp-csquerycomment-pageid-example": "שאילתה על תגובה בדף שהמזהה שלו הוא 3 בטקסט ויקי", + "apihelp-csquerycomment-title-example": "שאילתה על תגובה בדף שהכותרת שלו היא CommentStreams:3 בקוד ויקי", + "apihelp-csdeletecomment-description": "מחיקת תגובה. יש לציין את מזהה הדף או את כותרתו.", + "apihelp-csdeletecomment-summary": "מחיקת תגובה. יש לציין את מזהה הדף או את כותרתו.", + "apihelp-csdeletecomment-param-pageid": "מזהה הדף שבו נמצאת התגובה שתימחק", + "apihelp-csdeletecomment-param-title": "כותרת הדף שבו נמצאת התגובה שתימחק", + "apihelp-csdeletecomment-pageid-example": "מחיקת תגובה בדף שהמזהה שלו הוא 3", + "apihelp-csdeletecomment-title-example": "מחיקת תגובה בדף שהכותרת שלו היא CommentStreams:3", + "apihelp-cspostcomment-description": "הוספת תגובה חדשה.", + "apihelp-cspostcomment-summary": "הוספת תגובה חדשה.", + "apihelp-cspostcomment-param-commenttitle": "כותרת לתגובה (לא חובה).", + "apihelp-cspostcomment-param-wikitext": "טקסט הוויקי של התגובה.", + "apihelp-cspostcomment-param-associatedid": "הדף שאליו תשויך התגובה.", + "apihelp-cspostcomment-param-parentid": "אם זו תשובה לתגובה אחרת, מזהה הדף של התגובה שעליה תיכתב התשובה.", + "apihelp-cseditcomment-description": "עריכת תגובה קיימת. יש לציין את מזהה הדף או את כותרתו.", + "apihelp-cseditcomment-summary": "עריכת תגובה קיימת. יש לציין את מזהה הדף או את כותרתו.", + "apihelp-cseditcomment-param-pageid": "מזהה הדף שבו נמצאת התגובה שתיערך", + "apihelp-cseditcomment-param-title": "כותרת הדף שבו נמצאת התגובה שתיערך", + "apihelp-cseditcomment-param-commenttitle": "כותרת לתגובה (לא חובה).", + "apihelp-cseditcomment-param-wikitext": "טקסט הוויקי של התגובה.", + "apihelp-csvote-description": "הצבעה (אהבתי, לא אהבתי או נייטרלי) על תגובה.", + "apihelp-csvote-summary": "הצבעה (אהבתי, לא אהבתי או נייטרלי) על תגובה.", + "apihelp-csvote-param-pageid": "מזהה הדף שבו נמצאת התגובה שעליה תבוצע ההצבעה", + "apihelp-csvote-param-title": "כותרת הדף שבו נמצאת התגובה שעליה תבוצע ההצבעה", + "apihelp-csvote-param-vote": "הצבעה (1, <span dir=\"ltr\">-1</span> או 0).", + "apihelp-csvote-pageid-example": "הצבעה על תגובה בדף שהמזהה שלו הוא 3", + "apihelp-csvote-title-example": "הצבעה על תגובה בדף שהכותרת שלו היא CommentStreams:3", + "apihelp-cswatch-description": "מעקב אחרי תגובה כדי לקבל התראות כשמישהו משיב עליה", + "apihelp-cswatch-summary": "מעקב אחרי תגובה כדי לקבל התראות כשמישהו משיב עליה", + "apihelp-cswatch-param-pageid": "מזהה הדף שבו נמצאת התגובה שברצונך לעקוב אחריה", + "apihelp-cswatch-param-title": "כותרת הדף שבו נמצאת התגובה שברצונך לעקוב אחריה", + "apihelp-cswatch-pageid-example": "מעקב אחרי תגובה בדף שהמזהה שלו הוא 3", + "apihelp-cswatch-title-example": "מעקב אחרי תגובה בדף שהכותרת שלו היא CommentStreams:3", + "apihelp-csunwatch-description": "הפסקת המעקב אחרי תגובה כדי להפסיק לקבל התראות כשמישהו משיב עליה", + "apihelp-csunwatch-summary": "הפסקת המעקב אחרי תגובה כדי להפסיק לקבל התראות כשמישהו משיב עליה", + "apihelp-csunwatch-param-pageid": "מזהה הדף שבו נמצאת התגובה שברצונך להפסיק לעקוב אחריה", + "apihelp-csunwatch-param-title": "כותרת הדף שבו נמצאת התגובה שברצונך להפסיק לעקוב אחריה", + "apihelp-csunwatch-pageid-example": "הפסקת המעקב אחרי תגובה בדף שהמזהה שלו הוא 3", + "apihelp-csunwatch-title-example": "הפסקת המעקב אחרי תגובה בדף שהכותרת שלו היא CommentStreams:3", "commentstreams-api-error-notloggedin": "יש להיכנס לחשבון.", "commentstreams-api-error-commentnotfound": "התגובה שביקשת לא נמצאה.", "commentstreams-api-error-notacomment": "מזהה הדף שסופק אינו תואם לתגובה תקינה.", diff --git a/CommentStreams/i18n/hi.json b/CommentStreams/i18n/hi.json index fafb97c3..d3b0dc06 100644 --- a/CommentStreams/i18n/hi.json +++ b/CommentStreams/i18n/hi.json @@ -5,7 +5,7 @@ "Rishi.Singh" ] }, - "apihelp-csWatch-summary": "उत्तर प्राप्त होने पर अधिसूचित होने के लिए एक टिप्पणी देखें", + "apihelp-cswatch-summary": "उत्तर प्राप्त होने पर अधिसूचित होने के लिए एक टिप्पणी देखें", "commentstreams-api-error-post-permissions": "उपयोगकर्ता को एक टिप्पणी पोस्ट करने की अनुमति नहीं है।", "commentstreams-buttontext-add": "टिप्पणी जोड़ें", "commentstreams-buttontext-reply": "प्रत्युत्तर", diff --git a/CommentStreams/i18n/hsb.json b/CommentStreams/i18n/hsb.json new file mode 100644 index 00000000..b9f4c123 --- /dev/null +++ b/CommentStreams/i18n/hsb.json @@ -0,0 +1,10 @@ +{ + "@metadata": { + "authors": [ + "J budissin" + ] + }, + "commentstreams-buttontooltip-watch": "wobkedźbować", + "commentstreams-buttontooltip-unwatch": "hižo njewobkedźbować", + "commentstreams-allcomments-nocommentsfound": "Žane komentary namakane." +} diff --git a/CommentStreams/i18n/hyw.json b/CommentStreams/i18n/hyw.json index 9b23dade..1bbb1d3b 100644 --- a/CommentStreams/i18n/hyw.json +++ b/CommentStreams/i18n/hyw.json @@ -4,6 +4,7 @@ "Kareyac" ] }, + "commentstreams-buttontooltip-edit": "խմբագրել", "commentstreams-buttontooltip-permalink": "մշտական յղում", "commentstreams-dialog-buttontext-ok": "Լաւ", "commentstreams-dialog-buttontext-yes": "Այո" diff --git a/CommentStreams/i18n/io.json b/CommentStreams/i18n/io.json index d0aaaca1..ffbfb509 100644 --- a/CommentStreams/i18n/io.json +++ b/CommentStreams/i18n/io.json @@ -7,5 +7,6 @@ "commentstreams-buttontooltip-edit": "redaktar", "commentstreams-buttontooltip-delete": "efacar", "commentstreams-buttontooltip-cancel": "anular", - "commentstreams-dialog-buttontext-cancel": "Nuligar" + "commentstreams-dialog-buttontext-cancel": "Nuligar", + "commentstreams-allcomments-label-author": "Autoro" } diff --git a/CommentStreams/i18n/it.json b/CommentStreams/i18n/it.json index 2c818c03..187ce337 100644 --- a/CommentStreams/i18n/it.json +++ b/CommentStreams/i18n/it.json @@ -1,11 +1,13 @@ { "@metadata": { "authors": [ + "Ajeje Brazorf", "Beta16" ] }, "commentstreams-author-anonymous": "anonimo", - "apihelp-csVote-param-vote": "voto (1, -1, o 0).", + "apihelp-csvote-param-vote": "voto (1, -1, o 0).", + "commentstreams-api-error-invalid": "Risposta API non valida.", "commentstreams-api-error-delete-permissions": "L'utente non dispone dell'autorizzazione per cancellare il commento.", "commentstreams-api-error-vote-notloggedin": "Devi aver effettuato l'accesso per votare.", "commentstreams-buttontext-add": "Aggiungi commento", @@ -16,7 +18,9 @@ "commentstreams-buttontooltip-delete": "cancella", "commentstreams-buttontooltip-collapse": "comprimi", "commentstreams-buttontooltip-expand": "espandi", + "commentstreams-buttontooltip-submit": "invia", "commentstreams-buttontooltip-cancel": "annulla", + "commentstreams-dialog-buttontext-ok": "OK", "commentstreams-dialog-buttontext-cancel": "Annulla", "commentstreams-dialog-buttontext-yes": "Sì", "commentstreams-dialog-buttontext-no": "No", @@ -25,5 +29,7 @@ "action-cs-moderator-edit": "modificare i commenti degli altri utenti", "logentry-commentstreams-comment-create": "$1 {{GENDER:$2|ha creato}} il commento $3", "commentstreams-allcomments-nocommentsfound": "Nessun commento trovato.", + "commentstreams-allcomments-label-wikitext": "Commento", + "commentstreams-allcomments-label-author": "Autore", "commentstreams-allcomments-label-lastedited": "Ultima modifica" } diff --git a/CommentStreams/i18n/ko.json b/CommentStreams/i18n/ko.json index 60638140..da81009c 100644 --- a/CommentStreams/i18n/ko.json +++ b/CommentStreams/i18n/ko.json @@ -8,24 +8,25 @@ "commentstreams-error-prohibitedaction": "$1 동작은 댓글 문서에서 허용되지 않습니다.", "commentstreams-error-comment-on-deleted-page": "이 댓글이 속하는 문서가 삭제되었습니다.", "commentstreams-author-anonymous": "익명", - "apihelp-csQueryComment-description": "댓글의 제목, 사용자, 작성 타임스탬프, 위키텍스트를 반환합니다. pageid 또는 title을 지정해야 합니다.", - "apihelp-csQueryComment-summary": "댓글의 제목, 사용자, 작성 타임스탬프, 위키텍스트를 반환합니다. pageid나 title을 지정해야 합니다.", - "apihelp-csDeleteComment-description": "댓글을 삭제합니다. pageid 또는 title을 지정해야 합니다.", - "apihelp-csDeleteComment-summary": "댓글을 삭제합니다. pageid나 title을 지정해야 합니다.", - "apihelp-csDeleteComment-pageid-example": "문서 ID 3의 댓글 삭제", - "apihelp-csPostComment-description": "새로운 댓글을 게시합니다.", - "apihelp-csPostComment-summary": "새 댓글을 게시합니다.", - "apihelp-csPostComment-param-commenttitle": "댓글의 선택적 제목입니다.", - "apihelp-csPostComment-param-associatedid": "이 댓글이 속한 문서.", - "apihelp-csEditComment-description": "기존의 댓글을 편집합니다. pageid 또는 title을 지정해야 합니다.", - "apihelp-csEditComment-param-wikitext": "댓글의 위키텍스트입니다.", - "apihelp-csVote-description": "댓글에 투표(찬성, 반대, 중립)합니다.", - "apihelp-csVote-summary": "댓글에 투표(찬성, 반대, 중립)합니다.", - "apihelp-csVote-param-vote": "투표 (1, -1, 0).", - "apihelp-csVote-pageid-example": "문서 ID 3의 댓글에 투표", - "apihelp-csWatch-description": "답변을 받으면 알림을 받을 댓글을 주시합니다", - "apihelp-csUnwatch-description": "응답을 받을 때 더 이상 알림을 받지 않도록 댓글의 주시를 해제합니다", - "apihelp-csUnwatch-pageid-example": "문서 ID 3의 댓글의 주시를 해제합니다", + "apihelp-csquerycomment-description": "댓글의 제목, 사용자, 작성 타임스탬프, 위키텍스트를 반환합니다. pageid 또는 title을 지정해야 합니다.", + "apihelp-csquerycomment-summary": "댓글의 제목, 사용자, 작성 타임스탬프, 위키텍스트를 반환합니다. pageid나 title을 지정해야 합니다.", + "apihelp-csdeletecomment-description": "댓글을 삭제합니다. pageid 또는 title을 지정해야 합니다.", + "apihelp-csdeletecomment-summary": "댓글을 삭제합니다. pageid나 title을 지정해야 합니다.", + "apihelp-csdeletecomment-pageid-example": "문서 ID 3의 댓글 삭제", + "apihelp-cspostcomment-description": "새로운 댓글을 게시합니다.", + "apihelp-cspostcomment-summary": "새 댓글을 게시합니다.", + "apihelp-cspostcomment-param-commenttitle": "댓글의 선택적 제목입니다.", + "apihelp-cspostcomment-param-wikitext": "댓글의 위키텍스트입니다.", + "apihelp-cspostcomment-param-associatedid": "이 댓글이 속한 문서.", + "apihelp-cseditcomment-description": "기존의 댓글을 편집합니다. pageid 또는 title을 지정해야 합니다.", + "apihelp-csvote-description": "댓글에 투표(찬성, 반대, 중립)합니다.", + "apihelp-csvote-summary": "댓글에 투표(찬성, 반대, 중립)합니다.", + "apihelp-csvote-param-vote": "투표 (1, -1, 0).", + "apihelp-csvote-pageid-example": "문서 ID 3의 댓글에 투표", + "apihelp-cswatch-description": "답변을 받으면 알림을 받을 댓글을 주시합니다", + "apihelp-csunwatch-description": "응답을 받을 때 더 이상 알림을 받지 않도록 댓글의 주시를 해제합니다", + "apihelp-csunwatch-pageid-example": "문서 ID 3의 댓글의 주시를 해제합니다", + "commentstreams-api-error-invalid": "유효하지 않은 API 응답입니다.", "commentstreams-api-error-notloggedin": "로그인해야 합니다.", "commentstreams-api-error-commentnotfound": "요청하신 댓글을 찾을 수 없습니다.", "commentstreams-api-error-notacomment": "지정된 문서 ID는 유효한 댓글을 참조하지 않습니다.", diff --git a/CommentStreams/i18n/lb.json b/CommentStreams/i18n/lb.json index e8975cf3..255ad135 100644 --- a/CommentStreams/i18n/lb.json +++ b/CommentStreams/i18n/lb.json @@ -1,25 +1,26 @@ { "@metadata": { "authors": [ + "Les Meloures", "Robby" ] }, "commentstreams-error-prohibitedaction": "D'Aktioun $1 ass op Bemierkungssäiten net erlaabt.", "commentstreams-error-comment-on-deleted-page": "D'Säit mat där dës Bemierkung associéiert ass gouf geläscht.", "commentstreams-author-anonymous": "anonym", - "apihelp-csPostComment-description": "Eng nei Bemierkung publizéieren.", - "apihelp-csPostComment-summary": "En nei Bemierkung publizéieren.", - "apihelp-csPostComment-param-commenttitle": "fakultativen Titel fir d'Bemierkung.", - "apihelp-csPostComment-param-wikitext": "Wikitext fir d'Bemierkung.", - "apihelp-csEditComment-param-commenttitle": "fakultativen Titel fir d'Bemierkung.", - "apihelp-csVote-param-vote": "ofstëmmen (1,-1, oder 0)", + "apihelp-cspostcomment-description": "Eng nei Bemierkung publizéieren.", + "apihelp-cspostcomment-summary": "En nei Bemierkung publizéieren.", + "apihelp-cspostcomment-param-commenttitle": "fakultativen Titel fir d'Bemierkung.", + "apihelp-cseditcomment-param-commenttitle": "fakultativen Titel fir d'Bemierkung.", + "apihelp-cseditcomment-param-wikitext": "Wikitext fir d'Bemierkung.", + "apihelp-csvote-param-vote": "ofstëmmen (1,-1, oder 0)", "commentstreams-api-error-notloggedin": "Dir musst ageloggt sinn.", "commentstreams-api-error-edit-notloggedin": "Dir musst ageloggt si fir z'änneren.", "commentstreams-api-error-delete": "Feeler beim Läsche vun der Bemierkung.", "commentstreams-api-error-vote-notloggedin": "Dir musst ageloggt si fir kënnen ofzestëmmen.", "commentstreams-buttontext-add": "Bemierkung derbäisetzen", "commentstreams-buttontext-reply": "Äntwerten", - "commentstreams-buttontooltip-add": "eng Bemierkung dobäisetzen", + "commentstreams-buttontooltip-add": "eng Bemierkung derbäisetzen", "commentstreams-buttontooltip-reply": "äntwerten", "commentstreams-buttontooltip-edit": "änneren", "commentstreams-buttontooltip-delete": "läschen", diff --git a/CommentStreams/i18n/lv.json b/CommentStreams/i18n/lv.json index 3e60a9b4..77a888dd 100644 --- a/CommentStreams/i18n/lv.json +++ b/CommentStreams/i18n/lv.json @@ -5,7 +5,7 @@ ] }, "commentstreams-author-anonymous": "anonīms", - "apihelp-csVote-param-vote": "balsot (1, -1 vai 0).", + "apihelp-csvote-param-vote": "balsot (1, -1 vai 0).", "commentstreams-buttontext-add": "Pievienot komentāru", "commentstreams-buttontext-reply": "Atbildēt", "commentstreams-buttontooltip-add": "pievienot komentāru", diff --git a/CommentStreams/i18n/mk.json b/CommentStreams/i18n/mk.json index a5e48c5c..a13289a3 100644 --- a/CommentStreams/i18n/mk.json +++ b/CommentStreams/i18n/mk.json @@ -8,32 +8,50 @@ "commentstreams-error-prohibitedaction": "Дејството $1 не е дозволено на страници со коментари.", "commentstreams-error-comment-on-deleted-page": "Страницата со која е поврзан коментарот е избришана.", "commentstreams-author-anonymous": "анонимен", - "apihelp-csQueryComment-description": "Дај го насловот, корисникот, времето и датумот и викитекстот на коментарот. Мора да се укаже назнака на страницата или наслов.", - "apihelp-csQueryComment-summary": "Дај го насловот, корисникот, времето и датумот и викитекстот на коментарот. Мора да се укаже назнака на страницата или наслов.", - "apihelp-csQueryComment-param-pageid": "назнака на страницата каде се наоѓа коментарот што се бара", - "apihelp-csQueryComment-param-title": "наслов на страницата каде се наоѓа коментарот што се бара", - "apihelp-csQueryComment-pageid-example": "побарај коментар со назнака на страницата 3 во викитекстот", - "apihelp-csQueryComment-title-example": "побарај коментар со наслов на страница CommentStreams:3 во викитекстот", - "apihelp-csDeleteComment-description": "Избришете коментар. Треба да се укаже назнака или наслов на страницата.", - "apihelp-csDeleteComment-summary": "Избришете коментар. Треба да се укаже назнака или наслов на страницата.", - "apihelp-csDeleteComment-param-pageid": "назнака на страницата каде се наоѓа коментарот што за бришење", - "apihelp-csDeleteComment-param-title": "наслов на страницата каде се наоѓа коментарот што за бришење", - "apihelp-csDeleteComment-pageid-example": "избриши коментар со назнака на страницата 3", - "apihelp-csDeleteComment-title-example": "избриши коментар до наслов на страница CommentStreams:3", - "apihelp-csPostComment-description": "Ставете нов коментар.", - "apihelp-csPostComment-summary": "Ставете нов коментар.", - "apihelp-csPostComment-param-commenttitle": "незадолжителен наслов на коментарот.", - "apihelp-csPostComment-param-wikitext": "викитекст за коментарот.", - "apihelp-csPostComment-param-associatedid": "со која страница е поврзан коментаров.", - "apihelp-csPostComment-param-parentid": "назнака на матичниот коментар, ако ова е одговор.", - "apihelp-csEditComment-description": "Изменете постоечки коментар. Треба да се укаже назнака или наслов на страницата.", - "apihelp-csEditComment-summary": "Изменете постоечки коменар. Треба да се укаже назнака или наслов на страницата.", - "apihelp-csEditComment-param-commenttitle": "незадолжителен наслов на коментарот.", - "apihelp-csEditComment-param-wikitext": "викитекст за коментарот.", - "apihelp-csVote-description": "Гласај (за, против или воздржан) по коментарот.", - "apihelp-csVote-summary": "Гласај (за, против или воздржан) по коментарот.", - "apihelp-csVote-param-vote": "глас (1, -1 или 0).", - "apihelp-csVote-pageid-example": "гласај за коментар со назнака на страницата 3", + "apihelp-csquerycomment-description": "Дај го насловот, корисникот, времето и датумот и викитекстот на коментарот. Мора да се укаже назнака на страницата или наслов.", + "apihelp-csquerycomment-summary": "Дај го насловот, корисникот, времето и датумот и викитекстот на коментарот. Мора да се укаже назнака на страницата или наслов.", + "apihelp-csquerycomment-param-pageid": "назнака на страницата каде се наоѓа коментарот што се бара", + "apihelp-csquerycomment-param-title": "наслов на страницата каде се наоѓа коментарот што се бара", + "apihelp-csquerycomment-pageid-example": "побарај коментар со назнака на страницата 3 во викитекстот", + "apihelp-csquerycomment-title-example": "побарај коментар со наслов на страница CommentStreams:3 во викитекстот", + "apihelp-csdeletecomment-description": "Избришете коментар. Треба да се укаже назнака или наслов на страницата.", + "apihelp-csdeletecomment-summary": "Избришете коментар. Треба да се укаже назнака или наслов на страницата.", + "apihelp-csdeletecomment-param-pageid": "назнака на страницата каде се наоѓа коментарот за бришење", + "apihelp-csdeletecomment-param-title": "наслов на страницата каде се наоѓа коментарот за бришење", + "apihelp-csdeletecomment-pageid-example": "избриши коментар со назнака на страницата 3", + "apihelp-csdeletecomment-title-example": "избриши коментар со наслов на страница CommentStreams:3", + "apihelp-cspostcomment-description": "Ставете нов коментар.", + "apihelp-cspostcomment-summary": "Ставете нов коментар.", + "apihelp-cspostcomment-param-commenttitle": "незадолжителен наслов на коментарот.", + "apihelp-cspostcomment-param-wikitext": "викитекст за коментарот.", + "apihelp-cspostcomment-param-associatedid": "со која страница е поврзан коментаров.", + "apihelp-cspostcomment-param-parentid": "назнака на матичниот коментар, ако ова е одговор.", + "apihelp-cseditcomment-description": "Изменете постоечки коментар. Треба да се укаже назнака или наслов на страницата.", + "apihelp-cseditcomment-summary": "Изменете постоечки коменар. Треба да се укаже назнака или наслов на страницата.", + "apihelp-cseditcomment-param-pageid": "назнака на страницата каде се наоѓа коментарот за уредување", + "apihelp-cseditcomment-param-title": "наслов на страницата каде се наоѓа коментарот за уредување", + "apihelp-cseditcomment-param-commenttitle": "незадолжителен наслов на коментарот.", + "apihelp-cseditcomment-param-wikitext": "викитекст за коментарот.", + "apihelp-csvote-description": "Гласај (за, против или воздржан) по коментарот.", + "apihelp-csvote-summary": "Гласај (за, против или воздржан) по коментарот.", + "apihelp-csvote-param-pageid": "назнака на страницата каде се наоѓа коментарот по кој се гласа", + "apihelp-csvote-param-title": "наслов на страницата каде се наоѓа коментарот по кој се гласа", + "apihelp-csvote-param-vote": "глас (1, -1 или 0).", + "apihelp-csvote-pageid-example": "гласај за коментар со назнака на страницата 3", + "apihelp-csvote-title-example": "гласај по коментар со наслов на страница CommentStreams:3", + "apihelp-cswatch-description": "Набљудувајте коментар за да бидете известени кога ќе добие одговори", + "apihelp-cswatch-summary": "Набљудувајте коментар за да бидете известени кога ќе добие одговори", + "apihelp-cswatch-param-pageid": "назнака на страницата каде се наоѓа коментарот за набљудување", + "apihelp-cswatch-param-title": "наслов на страницата каде се наоѓа коментарот за набљудување", + "apihelp-cswatch-pageid-example": "набљудувај коментар со назнака на страницата 3", + "apihelp-cswatch-title-example": "набљудувај коментар со наслов на страница CommentStreams:3", + "apihelp-csunwatch-description": "Отстранете коментар од набљудувани за повеќе да не добивате известувања кога ќе добие одговори", + "apihelp-csunwatch-summary": "Отстранете коментар од набљудувани за повеќе да не добивате известувања кога ќе добие одговори", + "apihelp-csunwatch-param-pageid": "назнака на страницата каде се наоѓа коментарот за тргање од набљудувани", + "apihelp-csunwatch-param-title": "наслов на страницата каде се наоѓа коментарот за тргање од набљудувани", + "apihelp-csunwatch-pageid-example": "отстрани од набљудувани коментар со назнака на страницата 3", + "apihelp-csunwatch-title-example": "отстрани до набљудувани коментар со наслов на страница CommentStreams:3", + "commentstreams-api-error-invalid": "Неважечки одѕив од приложникот.", "commentstreams-api-error-notloggedin": "Мора да сте најавени.", "commentstreams-api-error-commentnotfound": "Не го најдов бараниот коментар.", "commentstreams-api-error-notacomment": "Укажаната назнака на страницата не се однесува на важечки коментар.", @@ -49,6 +67,7 @@ "commentstreams-api-error-edit": "Грешка при измена на коментарот.", "commentstreams-api-error-delete-notloggedin": "Мора да сте најавени за да бришете.", "commentstreams-api-error-delete-permissions": "Корисникот нема дозвола за бришење на коментарот.", + "commentstreams-api-error-delete-haschildren": "Не можам да избришам тема која има одговори. Превчитајте ја страницата за да го видите подновениот тек со коментари.", "commentstreams-api-error-delete": "Грешка при бришењето на коментарот.", "commentstreams-api-error-vote-notloggedin": "Мора да сте најавени за да гласате.", "commentstreams-api-error-vote-novoteonreply": "Гласањето за одговори не е дозволено.", @@ -84,6 +103,7 @@ "commentstreams-dialog-buttontext-cancel": "Откажи", "commentstreams-dialog-buttontext-yes": "Да", "commentstreams-dialog-buttontext-no": "Не", + "commentstreams-urldialog-instructions": "Прекопирајте ја долуприкажаната URL за да споделите трајна врска до коментаров. Стиснете на Esc за да го тргнете дијалогов.", "commentstreams-datetext-postedon": "Објавено на", "commentstreams-datetext-lasteditedon": "Последно уредување:", "commentstreams-datetext-moderated": "модерирано", @@ -134,5 +154,6 @@ "commentstreams-allcomments-label-lasteditor": "Последен уредник", "commentstreams-allcomments-label-lastedited": "Последно уредување", "commentstreams-allcomments-button-next": "Следно", - "commentstreams-allcomments-button-previous": "Претходно" + "commentstreams-allcomments-button-previous": "Претходно", + "commentstreams-ve-conversion-error": "Грешка при претворањето од викитекст во HTML за Нагледниот уредник" } diff --git a/CommentStreams/i18n/nb.json b/CommentStreams/i18n/nb.json index 3974279b..73700c52 100644 --- a/CommentStreams/i18n/nb.json +++ b/CommentStreams/i18n/nb.json @@ -10,49 +10,49 @@ "commentstreams-error-prohibitedaction": "Handlingen $1 er ikke tillatt på kommentarsider.", "commentstreams-error-comment-on-deleted-page": "Siden kommentaren assosieres med har blitt slettet.", "commentstreams-author-anonymous": "anonym", - "apihelp-csQueryComment-description": "Returner tittelen, brukeren, opprettelsestidspunktet og wikiteksten til en kommentar. Enten pageid eller title må angis.", - "apihelp-csQueryComment-summary": "Returnerer tittelen, brukeren, opprettelsestidsstempelet og wikiteksten til en kommentar. Enten pageid eller title må oppgis.", - "apihelp-csQueryComment-param-pageid": "Side-ID-en til siden som inneholder kommentaren det skal spørres mot", - "apihelp-csQueryComment-param-title": "Tittelen til siden som inneholder kommentaren det skal spørres mot", - "apihelp-csQueryComment-pageid-example": "spørringskommentar med side-ID 3 i wikitekst", - "apihelp-csQueryComment-title-example": "Spør mot kommentar med sidetittelen CommentStreams:3 i wikitekst", - "apihelp-csDeleteComment-description": "Slett en kommentar. Enten pageid eller title må angis.", - "apihelp-csDeleteComment-summary": "Slett en kommentar. Enten pageid eller title må oppgis.", - "apihelp-csDeleteComment-param-pageid": "Side-ID-en til siden som inneholder kommentaren som skal slettes", - "apihelp-csDeleteComment-param-title": "Tittelen til siden som inneholder kommentaren som skal slettes", - "apihelp-csDeleteComment-pageid-example": "slett kommentar med side-ID 3", - "apihelp-csDeleteComment-title-example": "Slett kommentar med sidetittel CommentStreams:3", - "apihelp-csPostComment-description": "Post en ny kommentar.", - "apihelp-csPostComment-summary": "Post en ny kommentar.", - "apihelp-csPostComment-param-commenttitle": "valgfri tittel på kommentar.", - "apihelp-csPostComment-param-wikitext": "Wikitekst for kommentaren.", - "apihelp-csPostComment-param-associatedid": "Side kommentaren assosieres med.", - "apihelp-csPostComment-param-parentid": "Side-ID-en til den overordnede kommentaren hvis det finnes et svar.", - "apihelp-csEditComment-description": "Redigere en eksisterende kommentar. Enten pageid eller title må oppgis.", - "apihelp-csEditComment-summary": "Rediger en eksisterende kommentar. Enten pageid eller title må oppgis.", - "apihelp-csEditComment-param-pageid": "Side-ID-en til siden som inneholder kommentaren som skal redigeres", - "apihelp-csEditComment-param-title": "Tittelen til siden som inneholder kommentaren som skal redigeres", - "apihelp-csEditComment-param-commenttitle": "Valgfri tittel på kommentar.", - "apihelp-csEditComment-param-wikitext": "wikitekst for kommentar.", - "apihelp-csVote-description": "Stem (opp, ned eller nøytralt) på en kommentar.", - "apihelp-csVote-summary": "Stem (opp, ned eller nøytralt) på en kommentar.", - "apihelp-csVote-param-pageid": "Side-ID-en til siden som inneholder kommentaren som skal stemmes på", - "apihelp-csVote-param-title": "tittelen på siden som inneholder kommentaren det skal stemmes på", - "apihelp-csVote-param-vote": "stem (1, -1 eller 0).", - "apihelp-csVote-pageid-example": "stem på kommentar med side-ID 3", - "apihelp-csVote-title-example": "Stem på kommentar med sidetittelen CommentStreams:3", - "apihelp-csWatch-description": "Overvåk en kommentar for å få varsel når den får svar", - "apihelp-csWatch-summary": "Overvåk en kommentar for å få varsel når det kommer svar", - "apihelp-csWatch-param-pageid": "Side-ID-en til siden som inneholder kommentaren som skal overvåkes", - "apihelp-csWatch-param-title": "tittelen på siden som inneholder kommentaren som skal overvåkes", - "apihelp-csWatch-pageid-example": "Overvåk kommentar med side-ID 3", - "apihelp-csWatch-title-example": "overvåk kommentaren med sidetittelen CommentStreams:3", - "apihelp-csUnwatch-description": "Fjern overvåking av en kommentar for ikke lenger å få varsel når den får svar", - "apihelp-csUnwatch-summary": "Fjern overvåkning av en kommentar for ikke lenger å motta varsler når den får svar", - "apihelp-csUnwatch-param-pageid": "Side-ID-en til siden som inneholder kommentaren som skal fjernes fra overvåkning", - "apihelp-csUnwatch-param-title": "Tittelen til siden som inneholder kommentaren som skal fjernes fra overvåkning", - "apihelp-csUnwatch-pageid-example": "fjern overvåking av kommentaren med side-ID 3", - "apihelp-csUnwatch-title-example": "Fjern overvåkning av en kommentar med sidetittel CommentStreams:3", + "apihelp-csquerycomment-description": "Returner tittelen, brukeren, opprettelsestidspunktet og wikiteksten til en kommentar. Enten pageid eller title må angis.", + "apihelp-csquerycomment-summary": "Returnerer tittelen, brukeren, opprettelsestidsstempelet og wikiteksten til en kommentar. Enten pageid eller title må oppgis.", + "apihelp-csquerycomment-param-pageid": "Side-ID-en til siden som inneholder kommentaren det skal spørres mot", + "apihelp-csquerycomment-param-title": "Tittelen til siden som inneholder kommentaren det skal spørres mot", + "apihelp-csquerycomment-pageid-example": "spørringskommentar med side-ID 3 i wikitekst", + "apihelp-csquerycomment-title-example": "Spør mot kommentar med sidetittelen CommentStreams:3 i wikitekst", + "apihelp-csdeletecomment-description": "Slett en kommentar. Enten pageid eller title må angis.", + "apihelp-csdeletecomment-summary": "Slett en kommentar. Enten pageid eller title må oppgis.", + "apihelp-csdeletecomment-param-pageid": "Side-ID-en til siden som inneholder kommentaren som skal slettes", + "apihelp-csdeletecomment-param-title": "Tittelen til siden som inneholder kommentaren som skal slettes", + "apihelp-csdeletecomment-pageid-example": "slett kommentar med side-ID 3", + "apihelp-csdeletecomment-title-example": "Slett kommentar med sidetittel CommentStreams:3", + "apihelp-cspostcomment-description": "Post en ny kommentar.", + "apihelp-cspostcomment-summary": "Post en ny kommentar.", + "apihelp-cspostcomment-param-commenttitle": "valgfri tittel på kommentar.", + "apihelp-cspostcomment-param-wikitext": "wikitekst for kommentar.", + "apihelp-cspostcomment-param-associatedid": "Side kommentaren assosieres med.", + "apihelp-cspostcomment-param-parentid": "Side-ID-en til den overordnede kommentaren hvis det finnes et svar.", + "apihelp-cseditcomment-description": "Redigere en eksisterende kommentar. Enten pageid eller title må oppgis.", + "apihelp-cseditcomment-summary": "Rediger en eksisterende kommentar. Enten pageid eller title må oppgis.", + "apihelp-cseditcomment-param-pageid": "Side-ID-en til siden som inneholder kommentaren som skal redigeres", + "apihelp-cseditcomment-param-title": "Tittelen til siden som inneholder kommentaren som skal redigeres", + "apihelp-cseditcomment-param-commenttitle": "Valgfri tittel på kommentar.", + "apihelp-cseditcomment-param-wikitext": "Wikitekst for kommentaren.", + "apihelp-csvote-description": "Stem (opp, ned eller nøytralt) på en kommentar.", + "apihelp-csvote-summary": "Stem (opp, ned eller nøytralt) på en kommentar.", + "apihelp-csvote-param-pageid": "Side-ID-en til siden som inneholder kommentaren som skal stemmes på", + "apihelp-csvote-param-title": "tittelen på siden som inneholder kommentaren det skal stemmes på", + "apihelp-csvote-param-vote": "stem (1, -1 eller 0).", + "apihelp-csvote-pageid-example": "stem på kommentar med side-ID 3", + "apihelp-csvote-title-example": "Stem på kommentar med sidetittelen CommentStreams:3", + "apihelp-cswatch-description": "Overvåk en kommentar for å få varsel når den får svar", + "apihelp-cswatch-summary": "Overvåk en kommentar for å få varsel når det kommer svar", + "apihelp-cswatch-param-pageid": "Side-ID-en til siden som inneholder kommentaren som skal overvåkes", + "apihelp-cswatch-param-title": "tittelen på siden som inneholder kommentaren som skal overvåkes", + "apihelp-cswatch-pageid-example": "Overvåk kommentar med side-ID 3", + "apihelp-cswatch-title-example": "overvåk kommentaren med sidetittelen CommentStreams:3", + "apihelp-csunwatch-description": "Fjern overvåking av en kommentar for ikke lenger å få varsel når den får svar", + "apihelp-csunwatch-summary": "Fjern overvåkning av en kommentar for ikke lenger å motta varsler når den får svar", + "apihelp-csunwatch-param-pageid": "Side-ID-en til siden som inneholder kommentaren som skal fjernes fra overvåkning", + "apihelp-csunwatch-param-title": "Tittelen til siden som inneholder kommentaren som skal fjernes fra overvåkning", + "apihelp-csunwatch-pageid-example": "fjern overvåking av kommentaren med side-ID 3", + "apihelp-csunwatch-title-example": "Fjern overvåkning av en kommentar med sidetittel CommentStreams:3", "commentstreams-api-error-notloggedin": "Du må være innlogget.", "commentstreams-api-error-commentnotfound": "Den etterspurte kommentaren ble ikke funnet.", "commentstreams-api-error-notacomment": "Den gitte side-ID-en refererer ikke til en gyldig kommentar.", diff --git a/CommentStreams/i18n/nl.json b/CommentStreams/i18n/nl.json index 2a5881e5..b90adcd4 100644 --- a/CommentStreams/i18n/nl.json +++ b/CommentStreams/i18n/nl.json @@ -2,7 +2,8 @@ "@metadata": { "authors": [ "Hzjethro", - "Mainframe98" + "Mainframe98", + "Romaine" ] }, "commentstreams-author-anonymous": "anoniem", @@ -31,6 +32,7 @@ "commentstreams-dialog-buttontext-no": "Nee", "commentstreams-datetext-postedon": "Geplaatst op", "commentstreams-datetext-lasteditedon": "Laatste bewerkt op", + "commentstreams-datetext-moderated": "gemodereerd", "commentstreams-title-field-placeholder": "Voer titel in...", "commentstreams-body-field-placeholder": "Vul tekst nieuw commentaar in...", "notification-link-label-commentstreams-reply-on-watched-page": "Bekijk reactie", diff --git a/CommentStreams/i18n/pl.json b/CommentStreams/i18n/pl.json index 394b5df0..b60198f9 100644 --- a/CommentStreams/i18n/pl.json +++ b/CommentStreams/i18n/pl.json @@ -4,7 +4,7 @@ "Chrumps" ] }, - "apihelp-csVote-param-vote": "głos (1, -1 albo 0).", + "apihelp-csvote-param-vote": "głos (1, -1 albo 0).", "commentstreams-api-error-notloggedin": "Musisz się zalogować.", "commentstreams-api-error-post": "Błąd dodawania komentarza.", "commentstreams-api-error-edit-notloggedin": "Aby edytować, musisz się zalogować.", diff --git a/CommentStreams/i18n/pnb.json b/CommentStreams/i18n/pnb.json new file mode 100644 index 00000000..e81bd00b --- /dev/null +++ b/CommentStreams/i18n/pnb.json @@ -0,0 +1,9 @@ +{ + "@metadata": { + "authors": [ + "Abbas dhothar" + ] + }, + "commentstreams-buttontooltip-cancel": "منسوخ کرو", + "commentstreams-dialog-buttontext-cancel": "منسوخ" +} diff --git a/CommentStreams/i18n/pt-br.json b/CommentStreams/i18n/pt-br.json index 98bad75f..fbf49fa2 100644 --- a/CommentStreams/i18n/pt-br.json +++ b/CommentStreams/i18n/pt-br.json @@ -1,56 +1,58 @@ { "@metadata": { "authors": [ - "Eduardo Addad de Oliveira" + "Eduardo Addad de Oliveira", + "Eduardoaddad" ] }, "commentstreams-desc": "Permite deixar comentários nas páginas da wiki", "commentstreams-error-prohibitedaction": "A ação $1 não é permitida nas páginas de comentários.", "commentstreams-error-comment-on-deleted-page": "A página à qual este comentário está associado foi eliminada.", "commentstreams-author-anonymous": "anônimo", - "apihelp-csQueryComment-description": "Devolver o título, o usuário, a data e hora de criação, e o texto wiki de um comentário. Tem de ser fornecido o identificador da página ou o título.", - "apihelp-csQueryComment-summary": "Devolver o título, o usuário, a data e hora de criação, e o texto wiki de um comentário. Tem de ser fornecido o identificador da página ou o título.", - "apihelp-csQueryComment-param-pageid": "identificador da página que contém o comentário a ser consultado", - "apihelp-csQueryComment-param-title": "título da página que contém o comentário a ser consultado", - "apihelp-csQueryComment-pageid-example": "consultar o comentário com o identificador de página 3 em texto wiki", - "apihelp-csQueryComment-title-example": "consultar o comentário com o título de página CommentStreams:3 em texto wiki", - "apihelp-csDeleteComment-description": "Eliminar um comentário. Tem de ser fornecido o identificador da página ou o título.", - "apihelp-csDeleteComment-summary": "Eliminar um comentário. Tem de ser fornecido o identificador da página ou o título.", - "apihelp-csDeleteComment-param-pageid": "identificador da página que contém o comentário para ser eliminado", - "apihelp-csDeleteComment-param-title": "título da página que contém o comentário para ser eliminado", - "apihelp-csDeleteComment-pageid-example": "eliminar o comentário com o identificador de página 3", - "apihelp-csDeleteComment-title-example": "eliminar o comentário com o título de página CommentStreams:3", - "apihelp-csPostComment-description": "Publicar um comentário novo.", - "apihelp-csPostComment-summary": "Publicar um comentário novo.", - "apihelp-csPostComment-param-commenttitle": "título opcional para o comentário.", - "apihelp-csPostComment-param-wikitext": "texto wiki para o comentário.", - "apihelp-csPostComment-param-associatedid": "página à qual este comentário está associado.", - "apihelp-csPostComment-param-parentid": "identificador de página do comentário mãe se isto for uma resposta.", - "apihelp-csEditComment-description": "Editar um comentário existente. Tem de ser fornecido o identificador da página ou o título.", - "apihelp-csEditComment-summary": "Editar um comentário existente. Tem de ser fornecido o identificador da página ou o título.", - "apihelp-csEditComment-param-pageid": "identificador da página que contém o comentário a ser editado", - "apihelp-csEditComment-param-title": "título da página que contém o comentário para ser editado", - "apihelp-csEditComment-param-commenttitle": "título opcional para o comentário.", - "apihelp-csEditComment-param-wikitext": "texto wiki para o comentário.", - "apihelp-csVote-description": "Votar (positivo, negativo ou neutro) num comentário.", - "apihelp-csVote-summary": "Votar (positivo, negativo ou neutro) num comentário.", - "apihelp-csVote-param-pageid": "identificador da página que contém o comentário para ser votado", - "apihelp-csVote-param-title": "título da página que contém o comentário para ser votado", - "apihelp-csVote-param-vote": "voto (1, -1 ou 0).", - "apihelp-csVote-pageid-example": "votar no comentário com o identificador de página 3", - "apihelp-csVote-title-example": "votar no comentário com o título de página CommentStreams:3", - "apihelp-csWatch-description": "Vigiar um comentário para ser notificado quando ele receber respostas", - "apihelp-csWatch-summary": "Vigiar um comentário para ser notificado quando ele receber respostas", - "apihelp-csWatch-param-pageid": "identificador da página que contém o comentário para ser vigiado", - "apihelp-csWatch-param-title": "título da página que contém o comentário para ser vigiado", - "apihelp-csWatch-pageid-example": "vigiar o comentário com o identificador de página 3", - "apihelp-csWatch-title-example": "vigiar o comentário com o título de página CommentStreams:3", - "apihelp-csUnwatch-description": "Deixar de vigiar um comentário para não ser notificado quando ele receber respostas", - "apihelp-csUnwatch-summary": "Deixar de vigiar um comentário para não ser notificado quando ele receber respostas", - "apihelp-csUnwatch-param-pageid": "identificador da página que contém o comentário a deixar de ser vigiado", - "apihelp-csUnwatch-param-title": "título da página que contém o comentário para deixar de ser vigiado", - "apihelp-csUnwatch-pageid-example": "deixar de vigiar o comentário com o identificador de página 3", - "apihelp-csUnwatch-title-example": "deixar de vigiar o comentário com o título de página CommentStreams:3", + "apihelp-csquerycomment-description": "Devolver o título, o usuário, a data e hora de criação, e o texto wiki de um comentário. Tem de ser fornecido o identificador da página ou o título.", + "apihelp-csquerycomment-summary": "Devolver o título, o usuário, a data e hora de criação, e o texto wiki de um comentário. Tem de ser fornecido o identificador da página ou o título.", + "apihelp-csquerycomment-param-pageid": "identificador da página que contém o comentário a ser consultado", + "apihelp-csquerycomment-param-title": "título da página que contém o comentário a ser consultado", + "apihelp-csquerycomment-pageid-example": "consultar o comentário com o identificador de página 3 em texto wiki", + "apihelp-csquerycomment-title-example": "consultar o comentário com o título de página CommentStreams:3 em texto wiki", + "apihelp-csdeletecomment-description": "Eliminar um comentário. Tem de ser fornecido o identificador da página ou o título.", + "apihelp-csdeletecomment-summary": "Eliminar um comentário. Tem de ser fornecido o identificador da página ou o título.", + "apihelp-csdeletecomment-param-pageid": "identificador da página que contém o comentário para ser eliminado", + "apihelp-csdeletecomment-param-title": "título da página que contém o comentário para ser eliminado", + "apihelp-csdeletecomment-pageid-example": "eliminar o comentário com o identificador de página 3", + "apihelp-csdeletecomment-title-example": "eliminar o comentário com o título de página CommentStreams:3", + "apihelp-cspostcomment-description": "Publicar um comentário novo.", + "apihelp-cspostcomment-summary": "Publicar um comentário novo.", + "apihelp-cspostcomment-param-commenttitle": "título opcional para o comentário.", + "apihelp-cspostcomment-param-wikitext": "texto wiki para o comentário.", + "apihelp-cspostcomment-param-associatedid": "página à qual este comentário está associado.", + "apihelp-cspostcomment-param-parentid": "identificador de página do comentário mãe se isto for uma resposta.", + "apihelp-cseditcomment-description": "Editar um comentário existente. Tem de ser fornecido o identificador da página ou o título.", + "apihelp-cseditcomment-summary": "Editar um comentário existente. Tem de ser fornecido o identificador da página ou o título.", + "apihelp-cseditcomment-param-pageid": "identificador da página que contém o comentário a ser editado", + "apihelp-cseditcomment-param-title": "título da página que contém o comentário para ser editado", + "apihelp-cseditcomment-param-commenttitle": "título opcional para o comentário.", + "apihelp-cseditcomment-param-wikitext": "texto wiki para o comentário.", + "apihelp-csvote-description": "Votar (positivo, negativo ou neutro) num comentário.", + "apihelp-csvote-summary": "Votar (positivo, negativo ou neutro) num comentário.", + "apihelp-csvote-param-pageid": "identificador da página que contém o comentário para ser votado", + "apihelp-csvote-param-title": "título da página que contém o comentário para ser votado", + "apihelp-csvote-param-vote": "voto (1, -1 ou 0).", + "apihelp-csvote-pageid-example": "votar no comentário com o identificador de página 3", + "apihelp-csvote-title-example": "votar no comentário com o título de página CommentStreams:3", + "apihelp-cswatch-description": "Vigiar um comentário para ser notificado quando ele receber respostas", + "apihelp-cswatch-summary": "Vigiar um comentário para ser notificado quando ele receber respostas", + "apihelp-cswatch-param-pageid": "identificador da página que contém o comentário para ser vigiado", + "apihelp-cswatch-param-title": "título da página que contém o comentário para ser vigiado", + "apihelp-cswatch-pageid-example": "vigiar o comentário com o identificador de página 3", + "apihelp-cswatch-title-example": "vigiar o comentário com o título de página CommentStreams:3", + "apihelp-csunwatch-description": "Deixar de vigiar um comentário para não ser notificado quando ele receber respostas", + "apihelp-csunwatch-summary": "Deixar de vigiar um comentário para não ser notificado quando ele receber respostas", + "apihelp-csunwatch-param-pageid": "identificador da página que contém o comentário a deixar de ser vigiado", + "apihelp-csunwatch-param-title": "título da página que contém o comentário para deixar de ser vigiado", + "apihelp-csunwatch-pageid-example": "deixar de vigiar o comentário com o identificador de página 3", + "apihelp-csunwatch-title-example": "deixar de vigiar o comentário com o título de página CommentStreams:3", + "commentstreams-api-error-invalid": "Resposta inválida da API.", "commentstreams-api-error-notloggedin": "Você deve estar logado.", "commentstreams-api-error-commentnotfound": "O comentário solicitado não foi encontrado.", "commentstreams-api-error-notacomment": "O identificador de página fornecido não remete para um comentário válido.", diff --git a/CommentStreams/i18n/pt.json b/CommentStreams/i18n/pt.json index 32344948..2184b9dd 100644 --- a/CommentStreams/i18n/pt.json +++ b/CommentStreams/i18n/pt.json @@ -9,49 +9,49 @@ "commentstreams-error-prohibitedaction": "A ação $1 não é permitida nas páginas de comentários.", "commentstreams-error-comment-on-deleted-page": "A página à qual este comentário está associado foi eliminada.", "commentstreams-author-anonymous": "anónimo", - "apihelp-csQueryComment-description": "Devolver o título, o utilizador, a data e hora de criação, e o texto wiki de um comentário. Tem de ser fornecido o identificador da página ou o título.", - "apihelp-csQueryComment-summary": "Devolver o título, o utilizador, a data e hora de criação, e o texto wiki de um comentário. Tem de ser fornecido o identificador da página ou o título.", - "apihelp-csQueryComment-param-pageid": "identificador da página que contém o comentário a ser consultado", - "apihelp-csQueryComment-param-title": "título da página que contém o comentário a ser consultado", - "apihelp-csQueryComment-pageid-example": "consultar o comentário com o identificador de página 3 em texto wiki", - "apihelp-csQueryComment-title-example": "consultar o comentário com o título de página CommentStreams:3 em texto wiki", - "apihelp-csDeleteComment-description": "Eliminar um comentário. Tem de ser fornecido o identificador da página ou o título.", - "apihelp-csDeleteComment-summary": "Eliminar um comentário. Tem de ser fornecido o identificador da página ou o título.", - "apihelp-csDeleteComment-param-pageid": "identificador da página que contém o comentário a ser eliminado", - "apihelp-csDeleteComment-param-title": "título da página que contém o comentário a ser eliminado", - "apihelp-csDeleteComment-pageid-example": "eliminar o comentário com o identificador de página 3", - "apihelp-csDeleteComment-title-example": "eliminar o comentário com o título de página CommentStreams:3", - "apihelp-csPostComment-description": "Publicar um comentário novo.", - "apihelp-csPostComment-summary": "Publicar um comentário novo.", - "apihelp-csPostComment-param-commenttitle": "título opcional para o comentário.", - "apihelp-csPostComment-param-wikitext": "texto wiki para o comentário.", - "apihelp-csPostComment-param-associatedid": "página à qual este comentário está associado.", - "apihelp-csPostComment-param-parentid": "identificador de página do comentário mãe se isto for uma resposta.", - "apihelp-csEditComment-description": "Editar um comentário existente. Tem de ser fornecido o identificador da página ou o título.", - "apihelp-csEditComment-summary": "Editar um comentário existente. Tem de ser fornecido o identificador da página ou o título.", - "apihelp-csEditComment-param-pageid": "identificador da página que contém o comentário a ser editado", - "apihelp-csEditComment-param-title": "título da página que contém o comentário a ser editado", - "apihelp-csEditComment-param-commenttitle": "título opcional para o comentário.", - "apihelp-csEditComment-param-wikitext": "texto wiki para o comentário.", - "apihelp-csVote-description": "Votar (positivo, negativo ou neutro) num comentário.", - "apihelp-csVote-summary": "Votar (positivo, negativo ou neutro) num comentário.", - "apihelp-csVote-param-pageid": "identificador da página que contém o comentário a ser votado", - "apihelp-csVote-param-title": "título da página que contém o comentário a ser votado", - "apihelp-csVote-param-vote": "voto (1, -1 ou 0).", - "apihelp-csVote-pageid-example": "votar no comentário com o identificador de página 3", - "apihelp-csVote-title-example": "votar no comentário com o título de página CommentStreams:3", - "apihelp-csWatch-description": "Vigiar um comentário para ser notificado quando ele receber respostas", - "apihelp-csWatch-summary": "Vigiar um comentário para ser notificado quando ele receber respostas", - "apihelp-csWatch-param-pageid": "identificador da página que contém o comentário a ser vigiado", - "apihelp-csWatch-param-title": "título da página que contém o comentário a ser vigiado", - "apihelp-csWatch-pageid-example": "vigiar o comentário com o identificador de página 3", - "apihelp-csWatch-title-example": "vigiar o comentário com o título de página CommentStreams:3", - "apihelp-csUnwatch-description": "Deixar de vigiar um comentário para não ser notificado quando ele receber respostas", - "apihelp-csUnwatch-summary": "Deixar de vigiar um comentário para não ser notificado quando ele receber respostas", - "apihelp-csUnwatch-param-pageid": "identificador da página que contém o comentário a deixar de ser vigiado", - "apihelp-csUnwatch-param-title": "título da página que contém o comentário a deixar de ser vigiado", - "apihelp-csUnwatch-pageid-example": "deixar de vigiar o comentário com o identificador de página 3", - "apihelp-csUnwatch-title-example": "deixar de vigiar o comentário com o título de página CommentStreams:3", + "apihelp-csquerycomment-description": "Devolver o título, o utilizador, a data e hora de criação, e o texto wiki de um comentário. Tem de ser fornecido o identificador da página ou o título.", + "apihelp-csquerycomment-summary": "Devolver o título, o utilizador, a data e hora de criação, e o texto wiki de um comentário. Tem de ser fornecido o identificador da página ou o título.", + "apihelp-csquerycomment-param-pageid": "identificador da página que contém o comentário a ser consultado", + "apihelp-csquerycomment-param-title": "título da página que contém o comentário a ser consultado", + "apihelp-csquerycomment-pageid-example": "consultar o comentário com o identificador de página 3 em texto wiki", + "apihelp-csquerycomment-title-example": "consultar o comentário com o título de página CommentStreams:3 em texto wiki", + "apihelp-csdeletecomment-description": "Eliminar um comentário. Tem de ser fornecido o identificador da página ou o título.", + "apihelp-csdeletecomment-summary": "Eliminar um comentário. Tem de ser fornecido o identificador da página ou o título.", + "apihelp-csdeletecomment-param-pageid": "identificador da página que contém o comentário a ser eliminado", + "apihelp-csdeletecomment-param-title": "título da página que contém o comentário a ser eliminado", + "apihelp-csdeletecomment-pageid-example": "eliminar o comentário com o identificador de página 3", + "apihelp-csdeletecomment-title-example": "eliminar o comentário com o título de página CommentStreams:3", + "apihelp-cspostcomment-description": "Publicar um comentário novo.", + "apihelp-cspostcomment-summary": "Publicar um comentário novo.", + "apihelp-cspostcomment-param-commenttitle": "título opcional para o comentário.", + "apihelp-cspostcomment-param-wikitext": "texto wiki para o comentário.", + "apihelp-cspostcomment-param-associatedid": "página à qual este comentário está associado.", + "apihelp-cspostcomment-param-parentid": "identificador de página do comentário mãe se isto for uma resposta.", + "apihelp-cseditcomment-description": "Editar um comentário existente. Tem de ser fornecido o identificador da página ou o título.", + "apihelp-cseditcomment-summary": "Editar um comentário existente. Tem de ser fornecido o identificador da página ou o título.", + "apihelp-cseditcomment-param-pageid": "identificador da página que contém o comentário a ser editado", + "apihelp-cseditcomment-param-title": "título da página que contém o comentário a ser editado", + "apihelp-cseditcomment-param-commenttitle": "título opcional para o comentário.", + "apihelp-cseditcomment-param-wikitext": "texto wiki para o comentário.", + "apihelp-csvote-description": "Votar (positivo, negativo ou neutro) num comentário.", + "apihelp-csvote-summary": "Votar (positivo, negativo ou neutro) num comentário.", + "apihelp-csvote-param-pageid": "identificador da página que contém o comentário a ser votado", + "apihelp-csvote-param-title": "título da página que contém o comentário a ser votado", + "apihelp-csvote-param-vote": "voto (1, -1 ou 0).", + "apihelp-csvote-pageid-example": "votar no comentário com o identificador de página 3", + "apihelp-csvote-title-example": "votar no comentário com o título de página CommentStreams:3", + "apihelp-cswatch-description": "Vigiar um comentário para ser notificado quando ele receber respostas", + "apihelp-cswatch-summary": "Vigiar um comentário para ser notificado quando ele receber respostas", + "apihelp-cswatch-param-pageid": "identificador da página que contém o comentário a ser vigiado", + "apihelp-cswatch-param-title": "título da página que contém o comentário a ser vigiado", + "apihelp-cswatch-pageid-example": "vigiar o comentário com o identificador de página 3", + "apihelp-cswatch-title-example": "vigiar o comentário com o título de página CommentStreams:3", + "apihelp-csunwatch-description": "Deixar de vigiar um comentário para não ser notificado quando ele receber respostas", + "apihelp-csunwatch-summary": "Deixar de vigiar um comentário para não ser notificado quando ele receber respostas", + "apihelp-csunwatch-param-pageid": "identificador da página que contém o comentário a deixar de ser vigiado", + "apihelp-csunwatch-param-title": "título da página que contém o comentário a deixar de ser vigiado", + "apihelp-csunwatch-pageid-example": "deixar de vigiar o comentário com o identificador de página 3", + "apihelp-csunwatch-title-example": "deixar de vigiar o comentário com o título de página CommentStreams:3", "commentstreams-api-error-notloggedin": "Tem de ter uma sessão iniciada.", "commentstreams-api-error-commentnotfound": "O comentário solicitado não foi encontrado.", "commentstreams-api-error-notacomment": "O identificador de página fornecido não remete para um comentário válido.", diff --git a/CommentStreams/i18n/qqq.json b/CommentStreams/i18n/qqq.json index 72fb8202..4cb036b9 100644 --- a/CommentStreams/i18n/qqq.json +++ b/CommentStreams/i18n/qqq.json @@ -11,49 +11,50 @@ "commentstreams-error-prohibitedaction": "Error message.", "commentstreams-error-comment-on-deleted-page": "Error message.", "commentstreams-author-anonymous": "The name displayed for anonymous comment authors\n{{Identical|Anonymous}}", - "apihelp-csQueryComment-description": "{{doc-apihelp-description|csQueryComment}}", - "apihelp-csQueryComment-summary": "{{doc-apihelp-summary|csQueryComment}}", - "apihelp-csQueryComment-param-pageid": "{{doc-apihelp-param|csQueryComment|pageid}}", - "apihelp-csQueryComment-param-title": "{{doc-apihelp-param|csQueryComment|title}}", - "apihelp-csQueryComment-pageid-example": "{{doc-apihelp-example|csQueryComment}}", - "apihelp-csQueryComment-title-example": "{{doc-apihelp-example|csQueryComment}}", - "apihelp-csDeleteComment-description": "{{doc-apihelp-description|csDeleteComment}}", - "apihelp-csDeleteComment-summary": "{{doc-apihelp-summary|csDeleteComment}}", - "apihelp-csDeleteComment-param-pageid": "{{doc-apihelp-param|csDeleteComment|pageid}}", - "apihelp-csDeleteComment-param-title": "{{doc-apihelp-param|csDeleteComment|title}}", - "apihelp-csDeleteComment-pageid-example": "{{doc-apihelp-example|csDeleteComment}}", - "apihelp-csDeleteComment-title-example": "{{doc-apihelp-example|csDeleteComment}}", - "apihelp-csPostComment-description": "{{doc-apihelp-description|csPostComment}}", - "apihelp-csPostComment-summary": "{{doc-apihelp-summary|csPostComment}}", - "apihelp-csPostComment-param-commenttitle": "{{doc-apihelp-param|csPostComment|commenttitle}}", - "apihelp-csPostComment-param-wikitext": "{{doc-apihelp-param|csPostComment|wikitext}}", - "apihelp-csPostComment-param-associatedid": "{{doc-apihelp-param|csPostComment|associatedid}}", - "apihelp-csPostComment-param-parentid": "{{doc-apihelp-param|csPostComment|parentid}}", - "apihelp-csEditComment-description": "{{doc-apihelp-description|csEditComment}}", - "apihelp-csEditComment-summary": "{{doc-apihelp-summary|csEditComment}}", - "apihelp-csEditComment-param-pageid": "{{doc-apihelp-param|csEditComment|pageid}}", - "apihelp-csEditComment-param-title": "{{doc-apihelp-param|csEditComment|title}}", - "apihelp-csEditComment-param-commenttitle": "{{doc-apihelp-param|csEditComment|commenttitle}}", - "apihelp-csEditComment-param-wikitext": "{{doc-apihelp-param|csEditComment|wikitext}}", - "apihelp-csVote-description": "{{doc-apihelp-description|csVote}}", - "apihelp-csVote-summary": "{{doc-apihelp-summary|csVote}}", - "apihelp-csVote-param-pageid": "{{doc-apihelp-param|csVote|pageid}}", - "apihelp-csVote-param-title": "{{doc-apihelp-param|csVote|title}}", - "apihelp-csVote-param-vote": "{{doc-apihelp-param|csVote|vote}}", - "apihelp-csVote-pageid-example": "{{doc-apihelp-example|csVote}}", - "apihelp-csVote-title-example": "{{doc-apihelp-example|csVote}}", - "apihelp-csWatch-description": "{{doc-apihelp-description|csWatch}}", - "apihelp-csWatch-summary": "{{doc-apihelp-summary|csWatch}}", - "apihelp-csWatch-param-pageid": "{{doc-apihelp-param|csWatch|pageid}}", - "apihelp-csWatch-param-title": "{{doc-apihelp-param|csWatch|title}}", - "apihelp-csWatch-pageid-example": "{{doc-apihelp-example|csWatch}}", - "apihelp-csWatch-title-example": "{{doc-apihelp-example|csWatch}}", - "apihelp-csUnwatch-description": "{{doc-apihelp-description|csUnwatch}}", - "apihelp-csUnwatch-summary": "{{doc-apihelp-summary|csUnwatch}}", - "apihelp-csUnwatch-param-pageid": "{{doc-apihelp-param|csUnwatch|pageid}}", - "apihelp-csUnwatch-param-title": "{{doc-apihelp-param|csUnwatch|title}}", - "apihelp-csUnwatch-pageid-example": "{{doc-apihelp-example|csUnwatch}}", - "apihelp-csUnwatch-title-example": "{{doc-apihelp-example|csUnwatch}}", + "apihelp-csquerycomment-description": "{{doc-apihelp-description|csquerycomment}}", + "apihelp-csquerycomment-summary": "{{doc-apihelp-summary|csquerycomment}}", + "apihelp-csquerycomment-param-pageid": "{{doc-apihelp-param|csquerycomment|pageid}}", + "apihelp-csquerycomment-param-title": "{{doc-apihelp-param|csquerycomment|title}}", + "apihelp-csquerycomment-pageid-example": "{{doc-apihelp-example|csquerycomment}}", + "apihelp-csquerycomment-title-example": "{{doc-apihelp-example|csquerycomment}}", + "apihelp-csdeletecomment-description": "{{doc-apihelp-description|csdeletecomment}}", + "apihelp-csdeletecomment-summary": "{{doc-apihelp-summary|csdeletecomment}}", + "apihelp-csdeletecomment-param-pageid": "{{doc-apihelp-param|csdeletecomment|pageid}}", + "apihelp-csdeletecomment-param-title": "{{doc-apihelp-param|csdeletecomment|title}}", + "apihelp-csdeletecomment-pageid-example": "{{doc-apihelp-example|csdeletecomment}}", + "apihelp-csdeletecomment-title-example": "{{doc-apihelp-example|csdeletecomment}}", + "apihelp-cspostcomment-description": "{{doc-apihelp-description|cspostcomment}}", + "apihelp-cspostcomment-summary": "{{doc-apihelp-summary|cspostcomment}}", + "apihelp-cspostcomment-param-commenttitle": "{{doc-apihelp-param|cspostcomment|commenttitle}}", + "apihelp-cspostcomment-param-wikitext": "{{doc-apihelp-param|cspostcomment|wikitext}}", + "apihelp-cspostcomment-param-associatedid": "{{doc-apihelp-param|cspostcomment|associatedid}}", + "apihelp-cspostcomment-param-parentid": "{{doc-apihelp-param|cspostcomment|parentid}}", + "apihelp-cseditcomment-description": "{{doc-apihelp-description|cseditcomment}}", + "apihelp-cseditcomment-summary": "{{doc-apihelp-summary|cseditcomment}}", + "apihelp-cseditcomment-param-pageid": "{{doc-apihelp-param|cseditcomment|pageid}}", + "apihelp-cseditcomment-param-title": "{{doc-apihelp-param|cseditcomment|title}}", + "apihelp-cseditcomment-param-commenttitle": "{{doc-apihelp-param|cseditcomment|commenttitle}}", + "apihelp-cseditcomment-param-wikitext": "{{doc-apihelp-param|cseditcomment|wikitext}}", + "apihelp-csvote-description": "{{doc-apihelp-description|csvote}}", + "apihelp-csvote-summary": "{{doc-apihelp-summary|csvote}}", + "apihelp-csvote-param-pageid": "{{doc-apihelp-param|csvote|pageid}}", + "apihelp-csvote-param-title": "{{doc-apihelp-param|csvote|title}}", + "apihelp-csvote-param-vote": "{{doc-apihelp-param|csvote|vote}}", + "apihelp-csvote-pageid-example": "{{doc-apihelp-example|csvote}}", + "apihelp-csvote-title-example": "{{doc-apihelp-example|csvote}}", + "apihelp-cswatch-description": "{{doc-apihelp-description|cswatch}}", + "apihelp-cswatch-summary": "{{doc-apihelp-summary|cswatch}}", + "apihelp-cswatch-param-pageid": "{{doc-apihelp-param|cswatch|pageid}}", + "apihelp-cswatch-param-title": "{{doc-apihelp-param|cswatch|title}}", + "apihelp-cswatch-pageid-example": "{{doc-apihelp-example|cswatch}}", + "apihelp-cswatch-title-example": "{{doc-apihelp-example|cswatch}}", + "apihelp-csunwatch-description": "{{doc-apihelp-description|csunwatch}}", + "apihelp-csunwatch-summary": "{{doc-apihelp-summary|csunwatch}}", + "apihelp-csunwatch-param-pageid": "{{doc-apihelp-param|csunwatch|pageid}}", + "apihelp-csunwatch-param-title": "{{doc-apihelp-param|csunwatch|title}}", + "apihelp-csunwatch-pageid-example": "{{doc-apihelp-example|csunwatch}}", + "apihelp-csunwatch-title-example": "{{doc-apihelp-example|csunwatch}}", + "commentstreams-api-error-invalid": "Error message.", "commentstreams-api-error-notloggedin": "Error message.", "commentstreams-api-error-commentnotfound": "Error message.", "commentstreams-api-error-notacomment": "Error message.", @@ -155,6 +156,7 @@ "commentstreams-allcomments-label-created": "Table column label", "commentstreams-allcomments-label-lasteditor": "Table column label", "commentstreams-allcomments-label-lastedited": "Table column label", + "commentstreams-allcomments-label-blockid": "Table column label", "commentstreams-allcomments-button-next": "Button label\n{{Identical|Next}}", "commentstreams-allcomments-button-previous": "Button label\n{{Identical|Previous}}", "commentstreams-ve-conversion-error": "Error message" diff --git a/CommentStreams/i18n/sco.json b/CommentStreams/i18n/sco.json new file mode 100644 index 00000000..c1ce16f0 --- /dev/null +++ b/CommentStreams/i18n/sco.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "MJL" + ] + }, + "commentstreams-dialog-buttontext-yes": "Aye" +} diff --git a/CommentStreams/i18n/sd.json b/CommentStreams/i18n/sd.json index 751aab5e..31f453d6 100644 --- a/CommentStreams/i18n/sd.json +++ b/CommentStreams/i18n/sd.json @@ -6,8 +6,8 @@ "Tweety" ] }, - "apihelp-csPostComment-description": "نيئن راءِ درج ڪيو.", - "apihelp-csPostComment-summary": "نيئن راءِ ڏيو", + "apihelp-cspostcomment-description": "نيئن راءِ درج ڪيو.", + "apihelp-cspostcomment-summary": "نيئن راءِ ڏيو", "commentstreams-buttontooltip-add": "راءِ شامل ڪيو", "commentstreams-buttontooltip-reply": "ورندي ڏيو", "commentstreams-buttontooltip-edit": "سنواريو", diff --git a/CommentStreams/i18n/skr-arab.json b/CommentStreams/i18n/skr-arab.json index 343c1f34..d74dafe4 100644 --- a/CommentStreams/i18n/skr-arab.json +++ b/CommentStreams/i18n/skr-arab.json @@ -5,8 +5,8 @@ ] }, "commentstreams-author-anonymous": "گمنام", - "apihelp-csPostComment-description": "نویں رائے ݙیوو", - "apihelp-csPostComment-summary": "نویں رائے ݙیوو", + "apihelp-cspostcomment-description": "نویں رائے ݙیوو", + "apihelp-cspostcomment-summary": "نویں رائے ݙیوو", "commentstreams-buttontext-add": "تبصرہ کرو", "commentstreams-buttontext-reply": "جواب", "commentstreams-buttontooltip-reply": "جواب", diff --git a/CommentStreams/i18n/sl.json b/CommentStreams/i18n/sl.json new file mode 100644 index 00000000..854d4319 --- /dev/null +++ b/CommentStreams/i18n/sl.json @@ -0,0 +1,15 @@ +{ + "@metadata": { + "authors": [ + "Eleassar" + ] + }, + "commentstreams-buttontooltip-edit": "uredi", + "commentstreams-buttontooltip-submit": "objavi", + "commentstreams-buttontooltip-cancel": "prekliči", + "commentstreams-dialog-buttontext-cancel": "Prekliči", + "commentstreams-dialog-buttontext-yes": "Da", + "commentstreams-dialog-buttontext-no": "Ne", + "commentstreams-allcomments-label-author": "Avtor", + "commentstreams-allcomments-button-next": "Naprej" +} diff --git a/CommentStreams/i18n/smn.json b/CommentStreams/i18n/smn.json index 56fe0d30..944a6a9f 100644 --- a/CommentStreams/i18n/smn.json +++ b/CommentStreams/i18n/smn.json @@ -4,5 +4,7 @@ "Yupik" ] }, + "commentstreams-datetext-lasteditedon": "Majemustáá nubástittum", + "commentstreams-allcomments-label-lastedited": "Majemustáá nubástittum", "commentstreams-allcomments-button-next": "Čuávuvâš" } diff --git a/CommentStreams/i18n/sr-el.json b/CommentStreams/i18n/sr-el.json new file mode 100644 index 00000000..b0622b54 --- /dev/null +++ b/CommentStreams/i18n/sr-el.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "Kareyac" + ] + }, + "commentstreams-dialog-buttontext-yes": "Da" +} diff --git a/CommentStreams/i18n/sv.json b/CommentStreams/i18n/sv.json index f6ab8849..0a743cbd 100644 --- a/CommentStreams/i18n/sv.json +++ b/CommentStreams/i18n/sv.json @@ -9,49 +9,49 @@ "commentstreams-error-prohibitedaction": "Åtärden $1 tillåts inte på kommentarssidor.", "commentstreams-error-comment-on-deleted-page": "Sidan som denna kommentar associeras med har raderats.", "commentstreams-author-anonymous": "anonym", - "apihelp-csQueryComment-description": "Returnera en kommentars titel, författare, tidsstämpel och wikitext. Sidans titel eller ID måste anges.", - "apihelp-csQueryComment-summary": "Returnera en kommentars titel, författare, tidsstämpel och wikitext. Sidans titel eller ID måste anges.", - "apihelp-csQueryComment-param-pageid": "sid-ID för sidan som innehåller kommentaren i fråga", - "apihelp-csQueryComment-param-title": "titel på sidan som innehåller kommentaren i fråga", - "apihelp-csQueryComment-pageid-example": "fråga efter kommentar med sid-ID 3 i wikitext", - "apihelp-csQueryComment-title-example": "fråga efter kommentar med sidtiteln CommentStreams:3 i wikitext", - "apihelp-csDeleteComment-description": "Radera en kommentar. Antingen sid-ID eller titel måste anges.", - "apihelp-csDeleteComment-summary": "Radera en kommentar. Sid-ID eller titel måste anges.", - "apihelp-csDeleteComment-param-pageid": "sid-ID för sidan som innehåller kommentaren att radera", - "apihelp-csDeleteComment-param-title": "titel för sidan som innehåller kommentaren att radera", - "apihelp-csDeleteComment-pageid-example": "radera kommentar med sid-ID 3", - "apihelp-csDeleteComment-title-example": "radera kommentar med sidtitel CommentStreams:3", - "apihelp-csPostComment-description": "Publicera en ny kommentar.", - "apihelp-csPostComment-summary": "Kommentera.", - "apihelp-csPostComment-param-commenttitle": "alternativ titel på kommentar", - "apihelp-csPostComment-param-wikitext": "kommentarens wikikod.", - "apihelp-csPostComment-param-associatedid": "sidan som kommenterats.", - "apihelp-csPostComment-param-parentid": "sid-ID för överordnad kommentar om detta är ett svar.", - "apihelp-csEditComment-description": "Redigera en kommentar. Sidans titel eller ID-nummer måste uppges.", - "apihelp-csEditComment-summary": "Redigera en befintlig kommentar. Sidans titel eller ID måste anges.", - "apihelp-csEditComment-param-pageid": "sid-ID för sidan som innehåller kommentaren att redigera", - "apihelp-csEditComment-param-title": "titel på sidan som innehåller kommentaren att redigera", - "apihelp-csEditComment-param-commenttitle": "kommentarens titel (behöver inte uppges).", - "apihelp-csEditComment-param-wikitext": "wikitext för kommentar.", - "apihelp-csVote-description": "Rösta (upp, ned eller neutralt) på en kommentar.", - "apihelp-csVote-summary": "Rösta (upp, ned eller neutralt) på en kommentar.", - "apihelp-csVote-param-pageid": "sid-ID för sidan som innehåller kommentaren att rösta på", - "apihelp-csVote-param-title": "titeln på sidan som innehåller kommentaren att rösta på", - "apihelp-csVote-param-vote": "rösta (1, -1 eller 0).", - "apihelp-csVote-pageid-example": "rösta på kommentaren med sid-ID 3", - "apihelp-csVote-title-example": "rösta på kommentaren med sidtiteln CommentStreams:3", - "apihelp-csWatch-description": "Bevaka en kommentar att notifieras när den får svar", - "apihelp-csWatch-summary": "Bevaka en kommentar att notifieras när den får svar", - "apihelp-csWatch-param-pageid": "sid-ID för sidan som innehåller kommentaren att bevaka", - "apihelp-csWatch-param-title": "titel på sidan där kommentaren att bevaka finns", - "apihelp-csWatch-pageid-example": "bevaka kommentaren med sid-ID 3", - "apihelp-csWatch-title-example": "bevaka kommentaren med sidtiteln CommentStreams:3", - "apihelp-csUnwatch-description": "Sluta bevaka kommentaren för att inte längre bli notifierad när den får svar", - "apihelp-csUnwatch-summary": "Sluta bevaka kommentaren för att inte längre bli notifierad när den får svar", - "apihelp-csUnwatch-param-pageid": "sid-ID för sidan som innehåller kommentaren att sluta bevaka", - "apihelp-csUnwatch-param-title": "titeln på sidan som innehåller kommentaren att sluta bevaka", - "apihelp-csUnwatch-pageid-example": "sluta bevaka kommentar med sid-ID 3", - "apihelp-csUnwatch-title-example": "sluta bevaka kommentaren med sidtiteln CommentStreams:3", + "apihelp-csquerycomment-description": "Returnera en kommentars titel, författare, tidsstämpel och wikitext. Sidans titel eller ID måste anges.", + "apihelp-csquerycomment-summary": "Returnera en kommentars titel, författare, tidsstämpel och wikitext. Sidans titel eller ID måste anges.", + "apihelp-csquerycomment-param-pageid": "sid-ID för sidan som innehåller kommentaren i fråga", + "apihelp-csquerycomment-param-title": "titel på sidan som innehåller kommentaren i fråga", + "apihelp-csquerycomment-pageid-example": "fråga efter kommentar med sid-ID 3 i wikitext", + "apihelp-csquerycomment-title-example": "fråga efter kommentar med sidtiteln CommentStreams:3 i wikitext", + "apihelp-csdeletecomment-description": "Radera en kommentar. Antingen sid-ID eller titel måste anges.", + "apihelp-csdeletecomment-summary": "Radera en kommentar. Sid-ID eller titel måste anges.", + "apihelp-csdeletecomment-param-pageid": "sid-ID för sidan som innehåller kommentaren att radera", + "apihelp-csdeletecomment-param-title": "titel för sidan som innehåller kommentaren att radera", + "apihelp-csdeletecomment-pageid-example": "radera kommentar med sid-ID 3", + "apihelp-csdeletecomment-title-example": "radera kommentar med sidtitel CommentStreams:3", + "apihelp-cspostcomment-description": "Publicera en ny kommentar.", + "apihelp-cspostcomment-summary": "Kommentera.", + "apihelp-cspostcomment-param-commenttitle": "alternativ titel på kommentar", + "apihelp-cspostcomment-param-wikitext": "wikitext för kommentar.", + "apihelp-cspostcomment-param-associatedid": "sidan som kommenterats.", + "apihelp-cspostcomment-param-parentid": "sid-ID för överordnad kommentar om detta är ett svar.", + "apihelp-cseditcomment-description": "Redigera en kommentar. Sidans titel eller ID-nummer måste uppges.", + "apihelp-cseditcomment-summary": "Redigera en befintlig kommentar. Sidans titel eller ID måste anges.", + "apihelp-cseditcomment-param-pageid": "sid-ID för sidan som innehåller kommentaren att redigera", + "apihelp-cseditcomment-param-title": "titel på sidan som innehåller kommentaren att redigera", + "apihelp-cseditcomment-param-commenttitle": "kommentarens titel (behöver inte uppges).", + "apihelp-cseditcomment-param-wikitext": "kommentarens wikikod.", + "apihelp-csvote-description": "Rösta (upp, ned eller neutralt) på en kommentar.", + "apihelp-csvote-summary": "Rösta (upp, ned eller neutralt) på en kommentar.", + "apihelp-csvote-param-pageid": "sid-ID för sidan som innehåller kommentaren att rösta på", + "apihelp-csvote-param-title": "titeln på sidan som innehåller kommentaren att rösta på", + "apihelp-csvote-param-vote": "rösta (1, -1 eller 0).", + "apihelp-csvote-pageid-example": "rösta på kommentaren med sid-ID 3", + "apihelp-csvote-title-example": "rösta på kommentaren med sidtiteln CommentStreams:3", + "apihelp-cswatch-description": "Bevaka en kommentar att notifieras när den får svar", + "apihelp-cswatch-summary": "Bevaka en kommentar att notifieras när den får svar", + "apihelp-cswatch-param-pageid": "sid-ID för sidan som innehåller kommentaren att bevaka", + "apihelp-cswatch-param-title": "titel på sidan där kommentaren att bevaka finns", + "apihelp-cswatch-pageid-example": "bevaka kommentaren med sid-ID 3", + "apihelp-cswatch-title-example": "bevaka kommentaren med sidtiteln CommentStreams:3", + "apihelp-csunwatch-description": "Sluta bevaka kommentaren för att inte längre bli notifierad när den får svar", + "apihelp-csunwatch-summary": "Sluta bevaka kommentaren för att inte längre bli notifierad när den får svar", + "apihelp-csunwatch-param-pageid": "sid-ID för sidan som innehåller kommentaren att sluta bevaka", + "apihelp-csunwatch-param-title": "titeln på sidan som innehåller kommentaren att sluta bevaka", + "apihelp-csunwatch-pageid-example": "sluta bevaka kommentar med sid-ID 3", + "apihelp-csunwatch-title-example": "sluta bevaka kommentaren med sidtiteln CommentStreams:3", "commentstreams-api-error-notloggedin": "Du måste vara inloggad.", "commentstreams-api-error-commentnotfound": "Den efterfrågade kommentaren kunde inte hittas.", "commentstreams-api-error-notacomment": "Angivet sid-ID hänvisar inte till en giltig kommentar.", diff --git a/CommentStreams/i18n/th.json b/CommentStreams/i18n/th.json new file mode 100644 index 00000000..22e93775 --- /dev/null +++ b/CommentStreams/i18n/th.json @@ -0,0 +1,29 @@ +{ + "@metadata": { + "authors": [ + "Achia70", + "Aefgh39622" + ] + }, + "commentstreams-desc": "อนุญาตให้แสดงความคิดเห็นในหน้า Wiki", + "commentstreams-error-prohibitedaction": "การกระทำ $1 ไม่อนุญาตในหน้าความคิดเห็น", + "commentstreams-error-comment-on-deleted-page": "หน้าที่สัมพันธ์กับความคิดเห็นนี้ถูกลบไปแล้ว", + "commentstreams-author-anonymous": "ไม่ระบุตัวตน", + "apihelp-csquerycomment-description": "ส่งกลับชื่อเรื่อง ผู้ใช้ การประทับเวลาการสร้าง และ Wikitext ของข้อคิดเห็น ต้องระบุ pageid หรือชื่อเรื่องอย่างใดอย่างหนึ่ง", + "apihelp-csquerycomment-summary": "ส่งกลับชื่อเรื่อง ผู้ใช้ การประทับเวลาการสร้าง และ Wikitext ของข้อคิดเห็น ต้องระบุ pageid หรือชื่อเรื่องอย่างใดอย่างหนึ่ง", + "apihelp-csquerycomment-param-pageid": "รหัสหน้าของหน้าที่เก็บความคิดเห็นที่จะสอบถาม", + "apihelp-csquerycomment-param-title": "ชื่อของหน้าที่เก็บความคิดเห็นที่จะสอบถาม", + "apihelp-csquerycomment-pageid-example": "สอบถามความคิดเห็นพร้อม ID หน้า 3 ใน wikitext", + "apihelp-csdeletecomment-description": "ลบความคิดเห็น ต้องระบุ pageid หรือ title", + "apihelp-csdeletecomment-summary": "ลบความคิดเห็น ต้องระบุ pageid หรือ title", + "apihelp-csdeletecomment-param-pageid": "รหัสหน้าของหน้าที่เก็บความคิดเห็นที่จะลบ", + "apihelp-csdeletecomment-param-title": "ชื่อของหน้าที่เก็บความคิดเห็นที่จะลบ", + "apihelp-csdeletecomment-pageid-example": "ลบความคิดเห็นด้วยรหัสหน้า 3", + "apihelp-cspostcomment-param-commenttitle": "ชื่อที่ไม่บังคับสำหรับความคิดเห็น", + "apihelp-cspostcomment-param-wikitext": "wikitext สำหรับความคิดเห็น", + "apihelp-cspostcomment-param-associatedid": "หน้าที่เกี่ยวข้องกับความคิดเห็นนี้", + "apihelp-cspostcomment-param-parentid": "รหัสหน้าของความคิดเห็นหลักหากเป็นการตอบกลับ", + "apihelp-cseditcomment-description": "แก้ไขความคิดเห็นที่มีอยู่ ต้องระบุ pageid หรือ title", + "apihelp-cseditcomment-summary": "แก้ไขความคิดเห็นที่มีอยู่ ต้องระบุ pageid หรือ title", + "apihelp-cseditcomment-param-pageid": "รหัสหน้าของหน้าที่เก็บความคิดเห็นเพื่อแก้ไข" +} diff --git a/CommentStreams/i18n/ti.json b/CommentStreams/i18n/ti.json index d4e17134..e13ce33b 100644 --- a/CommentStreams/i18n/ti.json +++ b/CommentStreams/i18n/ti.json @@ -4,6 +4,7 @@ "Joanmp17" ] }, + "commentstreams-buttontooltip-expand": "ዘርግሕ", "commentstreams-buttontooltip-submit": "ኣረክብ", - "commentstreams-allcomments-label-created": "ተፈጢሩ" + "commentstreams-allcomments-label-created": "ዝተፈጠረ" } diff --git a/CommentStreams/i18n/tr.json b/CommentStreams/i18n/tr.json index 6061b9fb..4d7d27f4 100644 --- a/CommentStreams/i18n/tr.json +++ b/CommentStreams/i18n/tr.json @@ -2,6 +2,7 @@ "@metadata": { "authors": [ "BaRaN6161 TURK", + "Joseph", "MuratTheTurkish", "Sayginer" ] @@ -10,49 +11,50 @@ "commentstreams-error-prohibitedaction": "Yorum sayfalarında $1 eylemine izin verilmiyor.", "commentstreams-error-comment-on-deleted-page": "Bu yorumla bağlantılı olan sayfa silinmiş.", "commentstreams-author-anonymous": "anonim", - "apihelp-csQueryComment-description": "Bir yorumun başlığını, kullanıcısını, oluşturma zaman damgasını ve vikimetin değerini döndürün. Sayfa kimliği veya başlık sağlanmalıdır.", - "apihelp-csQueryComment-summary": "Bir yorumun başlığını, kullanıcısını, oluşturma zaman damgasını ve vikimetin değerini döndürün. Sayfa kimliği veya başlık sağlanmalıdır.", - "apihelp-csQueryComment-param-pageid": "sorgulanacak yorumu tutan sayfanın sayfa kimliği", - "apihelp-csQueryComment-param-title": "sorgulanacak yorumu içeren sayfanın başlığı", - "apihelp-csQueryComment-pageid-example": "vikimetinde sayfa kimliği 3 ile sorgu yorumu", - "apihelp-csQueryComment-title-example": "yorum başlığıyla yorum sorgusu CommentStreams:3 vikimetinde", - "apihelp-csDeleteComment-description": "Bir yorumu silin. Sayfa kimliği veya başlık sağlanmalıdır.", - "apihelp-csDeleteComment-summary": "Bir yorumu silin. Sayfa kimliği veya başlık sağlanmalıdır.", - "apihelp-csDeleteComment-param-pageid": "silinecek yorumu içeren sayfanın sayfa kimliği", - "apihelp-csDeleteComment-param-title": "silinecek yorumu içeren sayfanın başlığı", - "apihelp-csDeleteComment-pageid-example": "sayfa kimliği 3 ile yorumu sil", - "apihelp-csDeleteComment-title-example": "sayfa başlığı CommentStreams:3 ile yorumu sil", - "apihelp-csPostComment-description": "Yeni bir yorum gönderin.", - "apihelp-csPostComment-summary": "Yeni bir yorum gönder.", - "apihelp-csPostComment-param-commenttitle": "yorum için isteğe bağlı başlık.", - "apihelp-csPostComment-param-wikitext": "yorum için vikimetin.", - "apihelp-csPostComment-param-associatedid": "bu yorumun ilişkilendirildiği sayfa.", - "apihelp-csPostComment-param-parentid": "bu bir yanıtsa üst yorumun sayfa kimliği.", - "apihelp-csEditComment-description": "Mevcut bir yorumu düzenleyin. Sayfa kimliği veya başlık sağlanmalıdır.", - "apihelp-csEditComment-summary": "Mevcut bir yorumu düzenleyin. Sayfa kimliği veya başlık sağlanmalıdır.", - "apihelp-csEditComment-param-pageid": "düzenlenecek yorumu içeren sayfanın sayfa kimliği", - "apihelp-csEditComment-param-title": "düzenlenecek yorumu içeren sayfanın başlığı", - "apihelp-csEditComment-param-commenttitle": "yorum için isteğe bağlı başlık.", - "apihelp-csEditComment-param-wikitext": "yorum için vikimetin.", - "apihelp-csVote-description": "Bir yoruma oy verin (yukarı, aşağı veya nötr).", - "apihelp-csVote-summary": "Bir yoruma oy verin (yukarı, aşağı veya nötr).", - "apihelp-csVote-param-pageid": "oylanacak yorumu içeren sayfanın sayfa kimliği", - "apihelp-csVote-param-title": "oylanacak yorumu içeren sayfanın başlığı", - "apihelp-csVote-param-vote": "oyla (1, -1, veya 0).", - "apihelp-csVote-pageid-example": "sayfa kimliği 3 ile yorumu oylayın", - "apihelp-csVote-title-example": "sayfa başlığı CommentStreams:3 ile yoruma oy verin", - "apihelp-csWatch-description": "Yanıt aldığında bildirim almak için bir yorumu izleyin", - "apihelp-csWatch-summary": "Yanıt aldığında bildirim almak için bir yorumu izleyin", - "apihelp-csWatch-param-pageid": "izlenecek yorumu içeren sayfanın sayfa kimliği", - "apihelp-csWatch-param-title": "izlenecek yorumu içeren sayfanın sayfa kimliği", - "apihelp-csWatch-pageid-example": "sayfa kimliği 3 ile yorumu izleyin", - "apihelp-csWatch-title-example": "sayfa başlığı CommentStreams:3 ile yorumu izleyin", - "apihelp-csUnwatch-description": "Yanıt aldığında artık bildirim gönderilmeyecek bir yorumu izlemeyin", - "apihelp-csUnwatch-summary": "Yanıt aldığında artık bildirim gönderilmeyecek bir yorumu izlemeyin", - "apihelp-csUnwatch-param-pageid": "izlenecek yorumu tutan sayfanın sayfa kimliği", - "apihelp-csUnwatch-param-title": "izlenecek yorumu içeren sayfanın başlığı", - "apihelp-csUnwatch-pageid-example": "sayfa kimliği 3 ile yorumu izlemeyin", - "apihelp-csUnwatch-title-example": "sayfa başlığı CommentStreams:3 ile yorumu izlemeyin", + "apihelp-csquerycomment-description": "Bir yorumun başlığını, kullanıcısını, oluşturma zaman damgasını ve vikimetin değerini döndürün. Sayfa kimliği veya başlık sağlanmalıdır.", + "apihelp-csquerycomment-summary": "Bir yorumun başlığını, kullanıcısını, oluşturma zaman damgasını ve vikimetin değerini döndürün. Sayfa kimliği veya başlık sağlanmalıdır.", + "apihelp-csquerycomment-param-pageid": "sorgulanacak yorumu tutan sayfanın sayfa kimliği", + "apihelp-csquerycomment-param-title": "sorgulanacak yorumu içeren sayfanın başlığı", + "apihelp-csquerycomment-pageid-example": "vikimetinde sayfa kimliği 3 ile sorgu yorumu", + "apihelp-csquerycomment-title-example": "yorum başlığıyla yorum sorgusu CommentStreams:3 vikimetinde", + "apihelp-csdeletecomment-description": "Bir yorumu silin. Sayfa kimliği veya başlık sağlanmalıdır.", + "apihelp-csdeletecomment-summary": "Bir yorumu silin. Sayfa kimliği veya başlık sağlanmalıdır.", + "apihelp-csdeletecomment-param-pageid": "silinecek yorumu içeren sayfanın sayfa kimliği", + "apihelp-csdeletecomment-param-title": "silinecek yorumu içeren sayfanın başlığı", + "apihelp-csdeletecomment-pageid-example": "sayfa kimliği 3 ile yorumu sil", + "apihelp-csdeletecomment-title-example": "sayfa başlığı CommentStreams:3 ile yorumu sil", + "apihelp-cspostcomment-description": "Yeni bir yorum gönderin.", + "apihelp-cspostcomment-summary": "Yeni bir yorum gönder.", + "apihelp-cspostcomment-param-commenttitle": "yorum için isteğe bağlı başlık.", + "apihelp-cspostcomment-param-wikitext": "yorum için vikimetin.", + "apihelp-cspostcomment-param-associatedid": "bu yorumun ilişkilendirildiği sayfa.", + "apihelp-cspostcomment-param-parentid": "bu bir yanıtsa üst yorumun sayfa kimliği.", + "apihelp-cseditcomment-description": "Mevcut bir yorumu düzenleyin. Sayfa kimliği veya başlık sağlanmalıdır.", + "apihelp-cseditcomment-summary": "Mevcut bir yorumu düzenleyin. Sayfa kimliği veya başlık sağlanmalıdır.", + "apihelp-cseditcomment-param-pageid": "düzenlenecek yorumu içeren sayfanın sayfa kimliği", + "apihelp-cseditcomment-param-title": "düzenlenecek yorumu içeren sayfanın başlığı", + "apihelp-cseditcomment-param-commenttitle": "yorum için isteğe bağlı başlık.", + "apihelp-cseditcomment-param-wikitext": "yorum için vikimetin.", + "apihelp-csvote-description": "Bir yoruma oy verin (yukarı, aşağı veya nötr).", + "apihelp-csvote-summary": "Bir yoruma oy verin (yukarı, aşağı veya nötr).", + "apihelp-csvote-param-pageid": "oylanacak yorumu içeren sayfanın sayfa kimliği", + "apihelp-csvote-param-title": "oylanacak yorumu içeren sayfanın başlığı", + "apihelp-csvote-param-vote": "oyla (1, -1, veya 0).", + "apihelp-csvote-pageid-example": "sayfa kimliği 3 ile yorumu oylayın", + "apihelp-csvote-title-example": "sayfa başlığı CommentStreams:3 ile yoruma oy verin", + "apihelp-cswatch-description": "Yanıt aldığında bildirim almak için bir yorumu izleyin", + "apihelp-cswatch-summary": "Yanıt aldığında bildirim almak için bir yorumu izleyin", + "apihelp-cswatch-param-pageid": "izlenecek yorumu içeren sayfanın sayfa kimliği", + "apihelp-cswatch-param-title": "izlenecek yorumu içeren sayfanın sayfa kimliği", + "apihelp-cswatch-pageid-example": "sayfa kimliği 3 ile yorumu izleyin", + "apihelp-cswatch-title-example": "sayfa başlığı CommentStreams:3 ile yorumu izleyin", + "apihelp-csunwatch-description": "Yanıt aldığında artık bildirim gönderilmeyecek bir yorumu izlemeyin", + "apihelp-csunwatch-summary": "Yanıt aldığında artık bildirim gönderilmeyecek bir yorumu izlemeyin", + "apihelp-csunwatch-param-pageid": "izlenecek yorumu tutan sayfanın sayfa kimliği", + "apihelp-csunwatch-param-title": "izlenecek yorumu içeren sayfanın başlığı", + "apihelp-csunwatch-pageid-example": "sayfa kimliği 3 ile yorumu izlemeyin", + "apihelp-csunwatch-title-example": "sayfa başlığı CommentStreams:3 ile yorumu izlemeyin", + "commentstreams-api-error-invalid": "Geçersiz API cevabı.", "commentstreams-api-error-notloggedin": "Oturum açmalısınız.", "commentstreams-api-error-commentnotfound": "İstenen yorum bulunamadı.", "commentstreams-api-error-notacomment": "Verilen sayfa kimliği geçerli bir açıklamaya gönderme yapmıyor.", diff --git a/CommentStreams/i18n/ug-arab.json b/CommentStreams/i18n/ug-arab.json deleted file mode 100644 index 95f45453..00000000 --- a/CommentStreams/i18n/ug-arab.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "@metadata": { - "authors": [ - "Uzdil", - "چۈشكۈن" - ] - }, - "commentstreams-buttontext-add": "باھا قوشۇش", - "commentstreams-buttontext-reply": "جاۋاپ قايتۇرۇش" -} diff --git a/CommentStreams/i18n/uk.json b/CommentStreams/i18n/uk.json index 6411c4cd..9403ac0c 100644 --- a/CommentStreams/i18n/uk.json +++ b/CommentStreams/i18n/uk.json @@ -9,49 +9,49 @@ "commentstreams-error-prohibitedaction": "Дія $1 недозволена на сторінках для коментарів.", "commentstreams-error-comment-on-deleted-page": "Сторінку, з якою пов'язаний цей коментар, вилучено.", "commentstreams-author-anonymous": "анонім", - "apihelp-csQueryComment-description": "Вивести назву, користувача, час створення та вікірозмітку коментаря. Слід вказати або pageid або назву.", - "apihelp-csQueryComment-summary": "Вивести назву, користувача, час створення та вікірозмітку коментаря. Слід вказати або pageid або назву.", - "apihelp-csQueryComment-param-pageid": "ідентифікатор сторінки, яка містить коментар, щодо якого слід надіслати запит", - "apihelp-csQueryComment-param-title": "назва сторінки, яка містить коментар, щодо якого слід надіслати запит", - "apihelp-csQueryComment-pageid-example": "надіслати запит щодо коментаря з ідентифікатором сторінки 3 у вікірозмітці", - "apihelp-csQueryComment-title-example": "надіслати запит щодо коментаря із назвою сторінки CommentStreams:3 у вікірозмітці", - "apihelp-csDeleteComment-description": "Вилучити коментар. Слід вказати або pageid, або назву.", - "apihelp-csDeleteComment-summary": "Вилучити коментар. Слід вказати або pageid, або назву.", - "apihelp-csDeleteComment-param-pageid": "ідентифікатор сторінки, яка містить коментар, який слід вилучити", - "apihelp-csDeleteComment-param-title": "назва сторінки, яка містить коментар, який слід вилучити", - "apihelp-csDeleteComment-pageid-example": "вилучити коментар з ідентифікатором сторінки 3", - "apihelp-csDeleteComment-title-example": "вилучити коментар з назвою сторінки CommentStreams:3", - "apihelp-csPostComment-description": "Опублікувати новий коментар.", - "apihelp-csPostComment-summary": "Опублікувати новий коментар.", - "apihelp-csPostComment-param-commenttitle": "необов'язкова назва коментаря.", - "apihelp-csPostComment-param-wikitext": "вікірозмітка для коментаря.", - "apihelp-csPostComment-param-associatedid": "сторінка, з якою пов'язаний цей коментар.", - "apihelp-csPostComment-param-parentid": "ідентифікатор сторінки батьківського коментаря, якщо це — відповідь.", - "apihelp-csEditComment-description": "Редагувати наявний коментар. Слід вказати або pageid, або назву.", - "apihelp-csEditComment-summary": "Редагувати наявний коментар. Слід вказати або pageid, або назву.", - "apihelp-csEditComment-param-pageid": "ідентифікатор сторінки, яка містить коментар, який треба відредагувати", - "apihelp-csEditComment-param-title": "назва сторінки, яка містить коментар, який треба відредагувати", - "apihelp-csEditComment-param-commenttitle": "необов'язкова назва коментаря.", - "apihelp-csEditComment-param-wikitext": "вікірозмітка для коментаря.", - "apihelp-csVote-description": "Проголосувати (позитивно, негативно, чи нейтрально) щодо коментаря.", - "apihelp-csVote-summary": "Проголосувати (позитивно, негативно, чи нейтрально) щодо коментаря.", - "apihelp-csVote-param-pageid": "ідентифікатор сторінки, яка містить коментар, щодо якого слід проголосувати", - "apihelp-csVote-param-title": "назва сторінки, яка містить коментар, щодо якого слід проголосувати", - "apihelp-csVote-param-vote": "голос (1, -1 або 0).", - "apihelp-csVote-pageid-example": "голосування щодо коментаря з ідентифікатором сторінки 3", - "apihelp-csVote-title-example": "голосування щодо коментаря з назвою сторінки CommentStreams:3", - "apihelp-csWatch-description": "Спостерігати за коментарем, щоб отримати сповіщення, коли він отримає якісь відповіді", - "apihelp-csWatch-summary": "Спостерігати за коментарем, щоб отримати сповіщення, коли він отримає якісь відповіді", - "apihelp-csWatch-param-pageid": "ідентифікатор сторінки, яка містить коментар, за яким слід спостерігати", - "apihelp-csWatch-param-title": "назва сторінки, яка містить коментар, за яким слід спостерігати", - "apihelp-csWatch-pageid-example": "спостерігати за коментарем з ідентифікатором 3", - "apihelp-csWatch-title-example": "спостерігати за коментарем з назвою сторінки CommentStreams:3", - "apihelp-csUnwatch-description": "Припинити спостереження за коментарем, щоб більше не отримувати сповіщень, коли він отримуватиме відповіді", - "apihelp-csUnwatch-summary": "Припинити спостереження за коментарем, щоб більше не отримувати сповіщень, коли він отримуватиме відповіді", - "apihelp-csUnwatch-param-pageid": "ідентифікатор сторінки, яка містить коментар, спостереження за яким слід припинити", - "apihelp-csUnwatch-param-title": "назва сторінки, яка містить коментар, спостереження за яким слід припинити", - "apihelp-csUnwatch-pageid-example": "припинити спостереження за коментарем з ідентифікатором сторінки 3", - "apihelp-csUnwatch-title-example": "припинити спостереження за коментарем з назвою сторінки CommentStreams:3", + "apihelp-csquerycomment-description": "Вивести назву, користувача, час створення та вікірозмітку коментаря. Слід вказати або pageid або назву.", + "apihelp-csquerycomment-summary": "Вивести назву, користувача, час створення та вікірозмітку коментаря. Слід вказати або pageid або назву.", + "apihelp-csquerycomment-param-pageid": "ідентифікатор сторінки, яка містить коментар, щодо якого слід надіслати запит", + "apihelp-csquerycomment-param-title": "назва сторінки, яка містить коментар, щодо якого слід надіслати запит", + "apihelp-csquerycomment-pageid-example": "надіслати запит щодо коментаря з ідентифікатором сторінки 3 у вікірозмітці", + "apihelp-csquerycomment-title-example": "надіслати запит щодо коментаря із назвою сторінки CommentStreams:3 у вікірозмітці", + "apihelp-csdeletecomment-description": "Вилучити коментар. Слід вказати або pageid, або назву.", + "apihelp-csdeletecomment-summary": "Вилучити коментар. Слід вказати або pageid, або назву.", + "apihelp-csdeletecomment-param-pageid": "ідентифікатор сторінки, яка містить коментар, який слід вилучити", + "apihelp-csdeletecomment-param-title": "назва сторінки, яка містить коментар, який слід вилучити", + "apihelp-csdeletecomment-pageid-example": "вилучити коментар з ідентифікатором сторінки 3", + "apihelp-csdeletecomment-title-example": "вилучити коментар з назвою сторінки CommentStreams:3", + "apihelp-cspostcomment-description": "Опублікувати новий коментар.", + "apihelp-cspostcomment-summary": "Опублікувати новий коментар.", + "apihelp-cspostcomment-param-commenttitle": "необов'язкова назва коментаря.", + "apihelp-cspostcomment-param-wikitext": "вікірозмітка для коментаря.", + "apihelp-cspostcomment-param-associatedid": "сторінка, з якою пов'язаний цей коментар.", + "apihelp-cspostcomment-param-parentid": "ідентифікатор сторінки батьківського коментаря, якщо це — відповідь.", + "apihelp-cseditcomment-description": "Редагувати наявний коментар. Слід вказати або pageid, або назву.", + "apihelp-cseditcomment-summary": "Редагувати наявний коментар. Слід вказати або pageid, або назву.", + "apihelp-cseditcomment-param-pageid": "ідентифікатор сторінки, яка містить коментар, який треба відредагувати", + "apihelp-cseditcomment-param-title": "назва сторінки, яка містить коментар, який треба відредагувати", + "apihelp-cseditcomment-param-commenttitle": "необов'язкова назва коментаря.", + "apihelp-cseditcomment-param-wikitext": "вікірозмітка для коментаря.", + "apihelp-csvote-description": "Проголосувати (позитивно, негативно, чи нейтрально) щодо коментаря.", + "apihelp-csvote-summary": "Проголосувати (позитивно, негативно, чи нейтрально) щодо коментаря.", + "apihelp-csvote-param-pageid": "ідентифікатор сторінки, яка містить коментар, щодо якого слід проголосувати", + "apihelp-csvote-param-title": "назва сторінки, яка містить коментар, щодо якого слід проголосувати", + "apihelp-csvote-param-vote": "голос (1, -1 або 0).", + "apihelp-csvote-pageid-example": "голосування щодо коментаря з ідентифікатором сторінки 3", + "apihelp-csvote-title-example": "голосування щодо коментаря з назвою сторінки CommentStreams:3", + "apihelp-cswatch-description": "Спостерігати за коментарем, щоб отримати сповіщення, коли він отримає якісь відповіді", + "apihelp-cswatch-summary": "Спостерігати за коментарем, щоб отримати сповіщення, коли він отримає якісь відповіді", + "apihelp-cswatch-param-pageid": "ідентифікатор сторінки, яка містить коментар, за яким слід спостерігати", + "apihelp-cswatch-param-title": "назва сторінки, яка містить коментар, за яким слід спостерігати", + "apihelp-cswatch-pageid-example": "спостерігати за коментарем з ідентифікатором 3", + "apihelp-cswatch-title-example": "спостерігати за коментарем з назвою сторінки CommentStreams:3", + "apihelp-csunwatch-description": "Припинити спостереження за коментарем, щоб більше не отримувати сповіщень, коли він отримуватиме відповіді", + "apihelp-csunwatch-summary": "Припинити спостереження за коментарем, щоб більше не отримувати сповіщень, коли він отримуватиме відповіді", + "apihelp-csunwatch-param-pageid": "ідентифікатор сторінки, яка містить коментар, спостереження за яким слід припинити", + "apihelp-csunwatch-param-title": "назва сторінки, яка містить коментар, спостереження за яким слід припинити", + "apihelp-csunwatch-pageid-example": "припинити спостереження за коментарем з ідентифікатором сторінки 3", + "apihelp-csunwatch-title-example": "припинити спостереження за коментарем з назвою сторінки CommentStreams:3", "commentstreams-api-error-notloggedin": "Ви повинні увійти в систему.", "commentstreams-api-error-commentnotfound": "Запитуваний коментар не знайдено.", "commentstreams-api-error-notacomment": "Вказаний ідентифікатор сторінки не пов'язаний з валідним коментарем.", diff --git a/CommentStreams/i18n/zgh.json b/CommentStreams/i18n/zgh.json new file mode 100644 index 00000000..d85f0ef6 --- /dev/null +++ b/CommentStreams/i18n/zgh.json @@ -0,0 +1,9 @@ +{ + "@metadata": { + "authors": [ + "Hakim1bal" + ] + }, + "commentstreams-dialog-buttontext-yes": "ⵢⴰⵀ", + "commentstreams-dialog-buttontext-no": "ⵓⵀⵓ" +} diff --git a/CommentStreams/i18n/zh-hans.json b/CommentStreams/i18n/zh-hans.json index eedbca36..85e92536 100644 --- a/CommentStreams/i18n/zh-hans.json +++ b/CommentStreams/i18n/zh-hans.json @@ -9,49 +9,49 @@ "commentstreams-error-prohibitedaction": "操作$1不允许在评论页面上进行。", "commentstreams-error-comment-on-deleted-page": "此评论所分配的页面已删除。", "commentstreams-author-anonymous": "匿名", - "apihelp-csQueryComment-description": "返回评论标题、用户、创建时间戳和wiki文本。必须提供页面id或标题。", - "apihelp-csQueryComment-summary": "返回评论标题、用户、创建时间戳和wiki文本。必须提供页面id或标题。", - "apihelp-csQueryComment-param-pageid": "保留评论用于查询的页面的页面ID", - "apihelp-csQueryComment-param-title": "保留评论用于查询的页面的标题", - "apihelp-csQueryComment-pageid-example": "查询wiki文本中,页面ID为3的评论", - "apihelp-csQueryComment-title-example": "查询wiki文本中,页面标题为CommentStreams:3的评论", - "apihelp-csDeleteComment-description": "删除评论。必须提供页面id或标题。", - "apihelp-csDeleteComment-summary": "删除评论。必须提供页面id或标题。", - "apihelp-csDeleteComment-param-pageid": "保留评论用于删除的页面的页面ID", - "apihelp-csDeleteComment-param-title": "保留评论用于删除的页面的标题", - "apihelp-csDeleteComment-pageid-example": "删除页面ID为3的评论", - "apihelp-csDeleteComment-title-example": "删除页面标题为CommentStreams:3的评论", - "apihelp-csPostComment-description": "发布新评论。", - "apihelp-csPostComment-summary": "发布新评论。", - "apihelp-csPostComment-param-commenttitle": "评论的可选标题。", - "apihelp-csPostComment-param-wikitext": "评论的wiki文本。", - "apihelp-csPostComment-param-associatedid": "与此评论相关联的页面。", - "apihelp-csPostComment-param-parentid": "如果该评论是回复的话,父评论的页面ID。", - "apihelp-csEditComment-description": "编辑现有评论。必须提供页面id或标题。", - "apihelp-csEditComment-summary": "编辑现有评论。必须提供页面id或标题。", - "apihelp-csEditComment-param-pageid": "保留评论用于编辑的页面的页面ID", - "apihelp-csEditComment-param-title": "保留评论用于编辑的页面的标题", - "apihelp-csEditComment-param-commenttitle": "评论的可选标题。", - "apihelp-csEditComment-param-wikitext": "评论的wiki文本。", - "apihelp-csVote-description": "评论上的投票(上、下或中立)。", - "apihelp-csVote-summary": "评论上的投票(上、下或中立)。", - "apihelp-csVote-param-pageid": "保留评论用于投票的页面的页面ID", - "apihelp-csVote-param-title": "保留评论用于投票的页面的标题", - "apihelp-csVote-param-vote": "投票(1、-1或0)。", - "apihelp-csVote-pageid-example": "在页面ID为3的评论上投票", - "apihelp-csVote-title-example": "在页面标题为CommentStreams:3的评论上投票", - "apihelp-csWatch-description": "当评论收到回复时,监视评论以获得通知", - "apihelp-csWatch-summary": "当评论收到回复时,监视评论以获得通知", - "apihelp-csWatch-param-pageid": "保留评论用于监视的页面的页面ID", - "apihelp-csWatch-param-title": "保留评论用于监视的页面的标题", - "apihelp-csWatch-pageid-example": "监视页面ID为3的评论", - "apihelp-csWatch-title-example": "监视页面标题为CommentStreams:3的评论", - "apihelp-csUnwatch-description": "取消监视评论,这样在评论收到回复时就不再收到通知", - "apihelp-csUnwatch-summary": "取消监视评论,这样在评论收到回复时就不再收到通知", - "apihelp-csUnwatch-param-pageid": "保留评论用于取消监视的页面的页面ID", - "apihelp-csUnwatch-param-title": "保留评论用于取消监视的页面的标题", - "apihelp-csUnwatch-pageid-example": "取消监视页面ID为3的评论", - "apihelp-csUnwatch-title-example": "取消监视页面标题为CommentStreams:3的评论", + "apihelp-csquerycomment-description": "返回评论标题、用户、创建时间戳和wiki文本。必须提供页面id或标题。", + "apihelp-csquerycomment-summary": "返回评论标题、用户、创建时间戳和wiki文本。必须提供页面id或标题。", + "apihelp-csquerycomment-param-pageid": "保留评论用于查询的页面的页面ID", + "apihelp-csquerycomment-param-title": "保留评论用于查询的页面的标题", + "apihelp-csquerycomment-pageid-example": "查询wiki文本中,页面ID为3的评论", + "apihelp-csquerycomment-title-example": "查询wiki文本中,页面标题为CommentStreams:3的评论", + "apihelp-csdeletecomment-description": "删除评论。必须提供页面id或标题。", + "apihelp-csdeletecomment-summary": "删除评论。必须提供页面id或标题。", + "apihelp-csdeletecomment-param-pageid": "保留评论用于删除的页面的页面ID", + "apihelp-csdeletecomment-param-title": "保留评论用于删除的页面的标题", + "apihelp-csdeletecomment-pageid-example": "删除页面ID为3的评论", + "apihelp-csdeletecomment-title-example": "删除页面标题为CommentStreams:3的评论", + "apihelp-cspostcomment-description": "发布新评论。", + "apihelp-cspostcomment-summary": "发布新评论。", + "apihelp-cspostcomment-param-commenttitle": "评论的可选标题。", + "apihelp-cspostcomment-param-wikitext": "评论的wiki文本。", + "apihelp-cspostcomment-param-associatedid": "与此评论相关联的页面。", + "apihelp-cspostcomment-param-parentid": "如果该评论是回复的话,父评论的页面ID。", + "apihelp-cseditcomment-description": "编辑现有评论。必须提供页面id或标题。", + "apihelp-cseditcomment-summary": "编辑现有评论。必须提供页面id或标题。", + "apihelp-cseditcomment-param-pageid": "保留评论用于编辑的页面的页面ID", + "apihelp-cseditcomment-param-title": "保留评论用于编辑的页面的标题", + "apihelp-cseditcomment-param-commenttitle": "评论的可选标题。", + "apihelp-cseditcomment-param-wikitext": "评论的wiki文本。", + "apihelp-csvote-description": "评论上的投票(上、下或中立)。", + "apihelp-csvote-summary": "评论上的投票(上、下或中立)。", + "apihelp-csvote-param-pageid": "保留评论用于投票的页面的页面ID", + "apihelp-csvote-param-title": "保留评论用于投票的页面的标题", + "apihelp-csvote-param-vote": "投票(1、-1或0)。", + "apihelp-csvote-pageid-example": "在页面ID为3的评论上投票", + "apihelp-csvote-title-example": "在页面标题为CommentStreams:3的评论上投票", + "apihelp-cswatch-description": "当评论收到回复时,监视评论以获得通知", + "apihelp-cswatch-summary": "当评论收到回复时,监视评论以获得通知", + "apihelp-cswatch-param-pageid": "保留评论用于监视的页面的页面ID", + "apihelp-cswatch-param-title": "保留评论用于监视的页面的标题", + "apihelp-cswatch-pageid-example": "监视页面ID为3的评论", + "apihelp-cswatch-title-example": "监视页面标题为CommentStreams:3的评论", + "apihelp-csunwatch-description": "取消监视评论,这样在评论收到回复时就不再收到通知", + "apihelp-csunwatch-summary": "取消监视评论,这样在评论收到回复时就不再收到通知", + "apihelp-csunwatch-param-pageid": "保留评论用于取消监视的页面的页面ID", + "apihelp-csunwatch-param-title": "保留评论用于取消监视的页面的标题", + "apihelp-csunwatch-pageid-example": "取消监视页面ID为3的评论", + "apihelp-csunwatch-title-example": "取消监视页面标题为CommentStreams:3的评论", "commentstreams-api-error-notloggedin": "您必须登录。", "commentstreams-api-error-commentnotfound": "找不到请求的评论。", "commentstreams-api-error-notacomment": "提供的页面ID并不指向有效的评论。", diff --git a/CommentStreams/i18n/zh-hant.json b/CommentStreams/i18n/zh-hant.json index d8571753..4799b109 100644 --- a/CommentStreams/i18n/zh-hant.json +++ b/CommentStreams/i18n/zh-hant.json @@ -9,49 +9,50 @@ "commentstreams-error-prohibitedaction": "在評論頁面上不允許 $1 操作。", "commentstreams-error-comment-on-deleted-page": "與此評論關聯的頁面已被刪除。", "commentstreams-author-anonymous": "匿名", - "apihelp-csQueryComment-description": "返回標題、使用者、創建時間戳記、以及評論的 wiki 文字。需提供頁面 ID 或標題。", - "apihelp-csQueryComment-summary": "返回標題、使用者、創建時間戳記、以及評論的 wiki 文字。需提供頁面 ID 或標題。", - "apihelp-csQueryComment-param-pageid": "含有要查詢評論的頁面 ID", - "apihelp-csQueryComment-param-title": "含有要查詢評論的頁面標題", - "apihelp-csQueryComment-pageid-example": "查詢在 wiki 文字上頁面 ID 為 3 的評論", - "apihelp-csQueryComment-title-example": "查詢在 wiki 文字上頁面標題爲 CommentStreams:3 的評論", - "apihelp-csDeleteComment-description": "刪除評論。需提供頁面 ID 或標題。", - "apihelp-csDeleteComment-summary": "刪除評論。需提供頁面 ID 或標題。", - "apihelp-csDeleteComment-param-pageid": "含有要刪除評論的頁面 ID", - "apihelp-csDeleteComment-param-title": "含有要刪除評論的頁面標題", - "apihelp-csDeleteComment-pageid-example": "刪除頁面 ID 為 3 的評論", - "apihelp-csDeleteComment-title-example": "刪除頁面標題為 CommentStreams:3 的評論", - "apihelp-csPostComment-description": "發佈新評論。", - "apihelp-csPostComment-summary": "發佈新評論。", - "apihelp-csPostComment-param-commenttitle": "評論的選用標題。", - "apihelp-csPostComment-param-wikitext": "用於評論的 wiki 文字。", - "apihelp-csPostComment-param-associatedid": "與此評論關聯的頁面。", - "apihelp-csPostComment-param-parentid": "父評論的頁面 ID,若此為回覆的情況下。", - "apihelp-csEditComment-description": "編輯現有評論。需提供頁面 ID 或標題。", - "apihelp-csEditComment-summary": "編輯現有評論。需提供頁面 ID 或標題。", - "apihelp-csEditComment-param-pageid": "含有要編輯評論的頁面 ID", - "apihelp-csEditComment-param-title": "含有要編輯評論的頁面標題", - "apihelp-csEditComment-param-commenttitle": "用於評論的選用標題。", - "apihelp-csEditComment-param-wikitext": "用於評論的 wiki 文字。", - "apihelp-csVote-description": "在評論上投票(贊成、反對、或中立)。", - "apihelp-csVote-summary": "在評論上投票(贊成、反對、或中立)。", - "apihelp-csVote-param-pageid": "含有要評論投票的頁面 ID", - "apihelp-csVote-param-title": "含有要評論投票的頁面標題", - "apihelp-csVote-param-vote": "投票(1、-1、或 0)。", - "apihelp-csVote-pageid-example": "在頁面 ID 為 3 的評論上投票", - "apihelp-csVote-title-example": "在頁面 ID 為 CommentStreams:3 的評論上投票", - "apihelp-csWatch-description": "監視評論在接收到回覆時會得到通知", - "apihelp-csWatch-summary": "監視評論在接收到回覆時會得到通知", - "apihelp-csWatch-param-pageid": "含有要監視評論的頁面 ID", - "apihelp-csWatch-param-title": "含有要監視評論的頁面標題", - "apihelp-csWatch-pageid-example": "監視頁面 ID 為 3 的評論", - "apihelp-csWatch-title-example": "監視頁面標題為 CommentStreams:3 的評論", - "apihelp-csUnwatch-description": "取消監視評論後在接收到回覆時不會再得到通知", - "apihelp-csUnwatch-summary": "取消監視評論後在接收到回覆時不會再得到通知", - "apihelp-csUnwatch-param-pageid": "含有要取消監視評論的頁面 ID", - "apihelp-csUnwatch-param-title": "含有要取消監視評論的頁面標題", - "apihelp-csUnwatch-pageid-example": "取消監視頁面 ID 為 3 的評論", - "apihelp-csUnwatch-title-example": "取消監視頁面標題為 CommentStreams:3 的評論", + "apihelp-csquerycomment-description": "返回標題、使用者、創建時間戳記、以及評論的 wiki 文字。需提供頁面 ID 或標題。", + "apihelp-csquerycomment-summary": "返回標題、使用者、創建時間戳記、以及評論的 wiki 文字。需提供頁面 ID 或標題。", + "apihelp-csquerycomment-param-pageid": "含有要查詢評論的頁面 ID", + "apihelp-csquerycomment-param-title": "含有要查詢評論的頁面標題", + "apihelp-csquerycomment-pageid-example": "查詢在 wiki 文字上頁面 ID 為 3 的評論", + "apihelp-csquerycomment-title-example": "查詢在 wiki 文字上頁面標題爲 CommentStreams:3 的評論", + "apihelp-csdeletecomment-description": "刪除評論。需提供頁面 ID 或標題。", + "apihelp-csdeletecomment-summary": "刪除評論。需提供頁面 ID 或標題。", + "apihelp-csdeletecomment-param-pageid": "含有要刪除評論的頁面 ID", + "apihelp-csdeletecomment-param-title": "含有要刪除評論的頁面標題", + "apihelp-csdeletecomment-pageid-example": "刪除頁面 ID 為 3 的評論", + "apihelp-csdeletecomment-title-example": "刪除頁面標題為 CommentStreams:3 的評論", + "apihelp-cspostcomment-description": "發佈新評論。", + "apihelp-cspostcomment-summary": "發佈新評論。", + "apihelp-cspostcomment-param-commenttitle": "評論的選用標題。", + "apihelp-cspostcomment-param-wikitext": "用於評論的 wiki 文字。", + "apihelp-cspostcomment-param-associatedid": "與此評論關聯的頁面。", + "apihelp-cspostcomment-param-parentid": "父評論的頁面 ID,若此為回覆的情況下。", + "apihelp-cseditcomment-description": "編輯現有評論。需提供頁面 ID 或標題。", + "apihelp-cseditcomment-summary": "編輯現有評論。需提供頁面 ID 或標題。", + "apihelp-cseditcomment-param-pageid": "含有要編輯評論的頁面 ID", + "apihelp-cseditcomment-param-title": "含有要編輯評論的頁面標題", + "apihelp-cseditcomment-param-commenttitle": "用於評論的選用標題。", + "apihelp-cseditcomment-param-wikitext": "用於評論的 wiki 文字。", + "apihelp-csvote-description": "在評論上投票(贊成、反對、或中立)。", + "apihelp-csvote-summary": "在評論上投票(贊成、反對、或中立)。", + "apihelp-csvote-param-pageid": "含有要評論投票的頁面 ID", + "apihelp-csvote-param-title": "含有要評論投票的頁面標題", + "apihelp-csvote-param-vote": "投票(1、-1、或 0)。", + "apihelp-csvote-pageid-example": "在頁面 ID 為 3 的評論上投票", + "apihelp-csvote-title-example": "在頁面 ID 為 CommentStreams:3 的評論上投票", + "apihelp-cswatch-description": "監視評論在接收到回覆時會得到通知", + "apihelp-cswatch-summary": "監視評論在接收到回覆時會得到通知", + "apihelp-cswatch-param-pageid": "含有要監視評論的頁面 ID", + "apihelp-cswatch-param-title": "含有要監視評論的頁面標題", + "apihelp-cswatch-pageid-example": "監視頁面 ID 為 3 的評論", + "apihelp-cswatch-title-example": "監視頁面標題為 CommentStreams:3 的評論", + "apihelp-csunwatch-description": "取消監視評論後在接收到回覆時不會再得到通知", + "apihelp-csunwatch-summary": "取消監視評論後在接收到回覆時不會再得到通知", + "apihelp-csunwatch-param-pageid": "含有要取消監視評論的頁面 ID", + "apihelp-csunwatch-param-title": "含有要取消監視評論的頁面標題", + "apihelp-csunwatch-pageid-example": "取消監視頁面 ID 為 3 的評論", + "apihelp-csunwatch-title-example": "取消監視頁面標題為 CommentStreams:3 的評論", + "commentstreams-api-error-invalid": "無效 API 回應。", "commentstreams-api-error-notloggedin": "您必須要先登入。", "commentstreams-api-error-commentnotfound": "找不到請求的評論。", "commentstreams-api-error-notacomment": "提供的頁面 ID 沒有參照到有效的評論。", diff --git a/CommentStreams/includes/ApiCSBase.php b/CommentStreams/includes/ApiCSBase.php index 51ec172e..4b777ead 100644 --- a/CommentStreams/includes/ApiCSBase.php +++ b/CommentStreams/includes/ApiCSBase.php @@ -24,50 +24,73 @@ namespace MediaWiki\Extension\CommentStreams; use ApiBase; -use ApiMessage; +use ApiMain; +use ApiUsageException; use ManualLogEntry; +use MediaWiki\Linker\LinkTarget; +use MediaWiki\MediaWikiServices; +use MWException; +use Title; abstract class ApiCSBase extends ApiBase { - + /** + * whether this API module will be editing the database + * @var bool + */ private $edit; + + /** + * @var Comment + */ protected $comment; /** + * @var CommentStreamsFactory + */ + protected $commentStreamsFactory; + + /** * @param ApiMain $main main module * @param string $action name of this module * @param bool $edit whether this API module will be editing the database */ - public function __construct( $main, $action, $edit = false ) { + public function __construct( ApiMain $main, string $action, bool $edit = false ) { parent::__construct( $main, $action ); $this->edit = $edit; + $services = MediaWikiServices::getInstance(); + $this->commentStreamsFactory = $services->getService( 'CommentStreamsFactory' ); } /** * execute the API request + * @throws ApiUsageException + * @throws MWException */ public function execute() { $params = $this->extractRequestParams(); - $wikipage = $this->getTitleOrPageId( $params, - $this->edit ? 'frommasterdb' : 'fromdb' ); - $this->comment = Comment::newFromWikiPage( $wikipage ); - if ( $this->comment === null ) { - $this->dieCustomUsageMessage( 'commentstreams-api-error-notacomment' ); - } - $result = $this->executeBody(); - if ( $result !== null ) { - $this->getResult()->addValue( null, $this->getModuleName(), $result ); + $wikipage = $this->getTitleOrPageId( $params, $this->edit ? 'frommasterdb' : 'fromdb' ); + $comment = $this->commentStreamsFactory->newFromWikiPage( $wikipage ); + if ( $comment === null ) { + $this->dieWithError( 'commentstreams-api-error-notacomment' ); + } else { + $this->comment = $comment; + $result = $this->executeBody(); + if ( $result !== null ) { + $this->getResult()->addValue( null, $this->getModuleName(), $result ); + } } } /** * the real body of the execute function + * @return ?array result of API request */ - abstract protected function executeBody(); + abstract protected function executeBody() : ?array; /** * @return array allowed parameters */ - public function getAllowedParams() { + public function getAllowedParams(): array { return [ 'pageid' => [ ApiBase::PARAM_TYPE => 'integer', @@ -83,17 +106,17 @@ abstract class ApiCSBase extends ApiBase { /** * @return array examples of the use of this API module */ - public function getExamplesMessages() { + public function getExamplesMessages(): array { return [ 'action=' . $this->getModuleName() . '&pageid=3' => - 'apihelp-' . $this->getModuleName() . '-pageid-example', + 'apihelp-' . $this->getModuleName() . '-pageid-example', 'action=' . $this->getModuleName() . '&title=CommentStreams:3' => - 'apihelp-' . $this->getModuleName() . '-title-example' + 'apihelp-' . $this->getModuleName() . '-title-example' ]; } /** - * @return string indicates that this API module requires a CSRF token + * @return string|false indicates that this API module requires a CSRF token */ public function needsToken() { if ( $this->edit ) { @@ -106,30 +129,18 @@ abstract class ApiCSBase extends ApiBase { /** * log action * @param string $action the name of the action to be logged - * @param string|null $title the title of the page for the comment that the - * action was performed upon, if differen from the current comment + * @param LinkTarget|Title|null $title the title of the page for the comment that the + * action was performed upon, if different from the current comment + * @throws MWException */ - protected function logAction( $action, $title = null ) { + protected function logAction( string $action, $title = null ) { $logEntry = new ManualLogEntry( 'commentstreams', $action ); $logEntry->setPerformer( $this->getUser() ); if ( $title ) { $logEntry->setTarget( $title ); } else { - $logEntry->setTarget( $this->comment->getWikiPage()->getTitle() ); + $logEntry->setTarget( $this->comment->getTitle() ); } - $logid = $logEntry->insert(); - } - - /** - * die with a custom usage message - * @param string $message_name the name of the custom message - */ - protected function dieCustomUsageMessage( $message_name ) { - $error_message = wfMessage( $message_name ); - $this->dieUsageMsg( - [ - ApiMessage::create( $error_message ) - ] - ); + $logEntry->insert(); } } diff --git a/CommentStreams/includes/ApiCSDeleteComment.php b/CommentStreams/includes/ApiCSDeleteComment.php index 345a314f..ecfa1720 100644 --- a/CommentStreams/includes/ApiCSDeleteComment.php +++ b/CommentStreams/includes/ApiCSDeleteComment.php @@ -23,107 +23,121 @@ namespace MediaWiki\Extension\CommentStreams; +use ApiMain; +use ApiUsageException; +use ConfigException; +use MediaWiki\MediaWikiServices; +use MWException; +use User; + class ApiCSDeleteComment extends ApiCSBase { + /** + * @var bool + */ + private $moderatorFastDelete; /** * @param ApiMain $main main module * @param string $action name of this module + * @throws ConfigException */ - public function __construct( $main, $action ) { + public function __construct( ApiMain $main, string $action ) { parent::__construct( $main, $action, true ); + $this->moderatorFastDelete = (bool)MediaWikiServices::getInstance()->getConfigFactory()-> + makeConfig( 'CommentStreams' )->get( 'CommentStreamsModeratorFastDelete' ); } /** * the real body of the execute function * - * @return result of API request + * @return ?array result of API request + * @throws ApiUsageException + * @throws MWException */ - protected function executeBody() { + protected function executeBody() : ?array { $user = $this->getUser(); if ( $user->isAnon() ) { - $this->dieCustomUsageMessage( - 'commentstreams-api-error-delete-notloggedin' ); + $this->dieWithError( 'commentstreams-api-error-delete-notloggedin' ); + } + + if ( $this->comment->getParentId() !== null ) { + $replyCount = 0; + } else { + $replyCount = $this->comment->getNumReplies(); } - if ( $this->getUser()->getId() === - $this->comment->getWikiPage()->getOldestRevision()->getUser() && - $this->comment->getNumReplies() === 0 ) { + if ( $user->getId() === $this->comment->getAuthor()->getId() && + $replyCount === 0 ) { $action = 'cs-comment'; } else { $action = 'cs-moderator-delete'; } - $title = $this->comment->getWikiPage()->getTitle(); - if ( class_exists( 'MediaWiki\Permissions\PermissionManager' ) ) { - // MW 1.33+ - if ( !\MediaWiki\MediaWikiServices::getInstance() - ->getPermissionManager() - ->userCan( $action, $user, $title ) - ) { - $this->dieCustomUsageMessage( - 'commentstreams-api-error-delete-permissions' ); - } - } else { - if ( !$title->userCan( $action, $user ) ) { - $this->dieCustomUsageMessage( - 'commentstreams-api-error-delete-permissions' ); + if ( $replyCount > 0 ) { + if ( $this->moderatorFastDelete ) { + $this->deleteReplies( $this->comment, $action, $user ); + } else { + $this->dieWithError( 'commentstreams-api-error-delete-haschildren' ); } } - $childCount = $this->comment->getNumReplies(); - if ( $childCount > 0 ) { - if ( $GLOBALS['wgCommentStreamsModeratorFastDelete'] ) { - $result = $this->recursiveDelete( $this->comment ); + $this->deleteComment( $this->comment, $action, $user ); + + return null; + } + + /** + * @param Comment $comment + * @param string $action + * @param User $user + * @throws ApiUsageException + * @throws MWException + */ + private function deleteComment( Comment $comment, string $action, User $user ) { + $title = $comment->getTitle(); + if ( !CommentStreamsUtils::userCan( $action, $user, $title ) ) { + $this->dieWithError( 'commentstreams-api-error-delete-permissions' ); + } + + $result = $comment->delete( $user ); + if ( !$result ) { + $this->dieWithError( 'commentstreams-api-error-delete' ); + } + if ( $action === 'cs-comment' ) { + if ( $comment->getParentId() === null ) { + $this->logAction( 'comment-delete' ); } else { - $this->dieCustomUsageMessage( - 'commentstreams-api-error-delete-haschildren' ); + $this->logAction( 'reply-delete' ); } } else { - $result = $this->comment->delete( $user ); - if ( $action === 'cs-comment' ) { - if ( $this->comment->getParentId() === null ) { - $this->logAction( 'comment-delete' ); - } else { - $this->logAction( 'reply-delete' ); - } + if ( $comment->getParentId() === null ) { + $this->logAction( 'comment-moderator-delete' ); } else { - if ( $this->comment->getParentId() === null ) { - $this->logAction( 'comment-moderator-delete' ); - } else { - $this->logAction( 'reply-moderator-delete' ); - } + $this->logAction( 'reply-moderator-delete' ); } } - - if ( !$result ) { - $this->dieCustomUsageMessage( - 'commentstreams-api-error-delete' ); - } - - return null; } /** * recursively delete comment and replies * * @param Comment $comment the comment to recursively delete - * @return bool + * @param string $action + * @param User $user + * @throws ApiUsageException + * @throws MWException */ - private function recursiveDelete( $comment ) { - $replies = Comment::getReplies( $comment->getId() ); - foreach ( $replies as $reply ) { - $result = $this->recursiveDelete( $reply ); - if ( !$result ) { - return $result; + private function deleteReplies( Comment $comment, string $action, User $user ) { + $commentStreamsStore = MediaWikiServices::getInstance()->getService( 'CommentStreamsStore' ); + $replies = $commentStreamsStore->getReplies( $comment->getId() ); + foreach ( $replies as $page_id ) { + $wikipage = CommentStreamsUtils::newWikiPageFromId( $page_id ); + if ( $wikipage !== null ) { + $reply = $this->commentStreamsFactory->newFromWikiPage( $wikipage ); + if ( $reply !== null ) { + $this->deleteComment( $reply, $action, $user ); + } } } - $result = $comment->delete( $this->getUser() ); - $title = $comment->getWikiPage()->getTitle(); - if ( $comment->getParentId() === null ) { - $this->logAction( 'comment-moderator-delete', $title ); - } else { - $this->logAction( 'reply-moderator-delete', $title ); - } - return $result; } } diff --git a/CommentStreams/includes/ApiCSEditComment.php b/CommentStreams/includes/ApiCSEditComment.php index c40f035c..24753b45 100644 --- a/CommentStreams/includes/ApiCSEditComment.php +++ b/CommentStreams/includes/ApiCSEditComment.php @@ -24,63 +24,52 @@ namespace MediaWiki\Extension\CommentStreams; use ApiBase; +use ApiMain; +use ApiUsageException; +use MWException; class ApiCSEditComment extends ApiCSBase { - /** * @param ApiMain $main main module * @param string $action name of this module */ - public function __construct( $main, $action ) { + public function __construct( ApiMain $main, string $action ) { parent::__construct( $main, $action, true ); } /** * the real body of the execute function - * - * @return result of API request + * @return ?array result of API request + * @throws ApiUsageException + * @throws MWException */ - protected function executeBody() { - if ( $this->getUser()->isAnon() ) { - $this->dieCustomUsageMessage( - 'commentstreams-api-error-edit-notloggedin' ); + protected function executeBody() : ?array { + $user = $this->getUser(); + if ( $user->isAnon() ) { + $this->dieWithError( 'commentstreams-api-error-edit-notloggedin' ); } - if ( $this->getUser()->getId() === - $this->comment->getWikiPage()->getOldestRevision()->getUser() ) { + if ( $user->getId() === $this->comment->getAuthor()->getId() ) { $action = 'cs-comment'; } else { $action = 'cs-moderator-edit'; } - $title = $this->comment->getWikiPage()->getTitle(); - if ( class_exists( 'MediaWiki\Permissions\PermissionManager' ) ) { - // MW 1.33+ - if ( !\MediaWiki\MediaWikiServices::getInstance() - ->getPermissionManager() - ->userCan( $action, $this->getUser(), $title ) - ) { - $this->dieCustomUsageMessage( - 'commentstreams-api-error-edit-permissions' ); - } - } else { - if ( !$title->userCan( $action, $this->getUser() ) ) { - $this->dieCustomUsageMessage( - 'commentstreams-api-error-edit-permissions' ); - } + $title = $this->comment->getTitle(); + if ( !CommentStreamsUtils::userCan( $action, $user, $title ) ) { + $this->dieWithError( 'commentstreams-api-error-edit-permissions' ); } $comment_title = $this->getMain()->getVal( 'commenttitle' ); $wikitext = $this->getMain()->getVal( 'wikitext' ); if ( $this->comment->getParentId() === null && $comment_title === null ) { - $this->dieCustomUsageMessage( - 'commentstreams-api-error-missingcommenttitle' ); + $this->dieWithError( 'commentstreams-api-error-missingcommenttitle' ); } $result = $this->comment->update( $comment_title, $wikitext, $this->getUser() ); if ( !$result ) { - $this->dieCustomUsageMessage( 'commentstreams-api-error-edit' ); + $this->dieWithError( 'commentstreams-api-error-edit' ); } if ( $action === 'cs-comment' ) { @@ -97,22 +86,13 @@ class ApiCSEditComment extends ApiCSBase { } } - $json = $this->comment->getJSON(); - - if ( $this->comment->getParentId() === null ) { - if ( $GLOBALS['wgCommentStreamsEnableVoting'] ) { - $json['vote'] = $this->comment->getVote( $this->getUser() ); - } - $json['watching'] = $this->comment->isWatching( $this->getUser() ) ? 1 : 0; - } - - $this->getResult()->addValue( null, $this->getModuleName(), $json ); + return null; } /** * @return array allowed parameters */ - public function getAllowedParams() { + public function getAllowedParams() : array { return array_merge( parent::getAllowedParams(), [ 'commenttitle' => @@ -132,14 +112,14 @@ class ApiCSEditComment extends ApiCSBase { /** * @return array examples of the use of this API module */ - public function getExamplesMessages() { + public function getExamplesMessages() : array { return []; } /** * @return string indicates that this API module requires a CSRF toekn */ - public function needsToken() { + public function needsToken() : string { return 'csrf'; } } diff --git a/CommentStreams/includes/ApiCSPostComment.php b/CommentStreams/includes/ApiCSPostComment.php index c37d6a3d..bbede380 100644 --- a/CommentStreams/includes/ApiCSPostComment.php +++ b/CommentStreams/includes/ApiCSPostComment.php @@ -24,95 +24,116 @@ namespace MediaWiki\Extension\CommentStreams; use ApiBase; -use ApiMessage; -use EchoEvent; -use ExtensionRegistry; +use ApiMain; +use ApiUsageException; use ManualLogEntry; -use WikiPage; +use MediaWiki\Linker\LinkTarget; +use MediaWiki\MediaWikiServices; +use MWException; +use Title; class ApiCSPostComment extends ApiBase { + /** + * @var CommentStreamsFactory + */ + private $commentStreamsFactory; + + /** + * @var CommentStreamsEchoInterface + */ + private $echoInterface; /** * @param ApiMain $main main module * @param string $action name of this module */ - public function __construct( $main, $action ) { + public function __construct( ApiMain $main, string $action ) { parent::__construct( $main, $action ); + $services = MediaWikiServices::getInstance(); + $this->commentStreamsFactory = $services->getService( 'CommentStreamsFactory' ); + $this->echoInterface = $services->getService( 'CommentStreamsEchoInterface' ); } /** * execute the API request + * @throws ApiUsageException + * @throws MWException */ public function execute() { - if ( !in_array( 'cs-comment', $this->getUser()->getRights() ) || - $this->getUser()->isBlocked() ) { - $this->dieCustomUsageMessage( - 'commentstreams-api-error-post-permissions' ); + if ( !CommentStreamsUtils::userHasRight( $this->getUser(), 'cs-comment' ) ) { + $this->dieWithError( 'commentstreams-api-error-post-permissions' ); } $associatedid = $this->getMain()->getVal( 'associatedid' ); $parentid = $this->getMain()->getVal( 'parentid' ); $comment_title = $this->getMain()->getVal( 'commenttitle' ); $wikitext = $this->getMain()->getVal( 'wikitext' ); + $commentblockid = $this->getMain()->getVal( 'commentblockid' ); if ( $parentid === null && $comment_title === null ) { - $this->dieCustomUsageMessage( - 'commentstreams-api-error-missingcommenttitle' ); + $this->dieWithError( 'commentstreams-api-error-missingcommenttitle' ); } if ( $parentid !== null && $comment_title !== null ) { - $this->dieCustomUsageMessage( - 'commentstreams-api-error-post-parentandtitle' ); + $this->dieWithError( 'commentstreams-api-error-post-parentandtitle' ); } + $parent_comment_title = null; if ( $parentid !== null ) { - $parent_page = WikiPage::newFromId( $parentid ); + $parentid = (int)$parentid; + $parent_page = CommentStreamsUtils::newWikiPageFromId( $parentid ); if ( $parent_page === null || !$parent_page->getTitle()->exists() ) { - $this->dieCustomUsageMessage( - 'commentstreams-api-error-post-parentpagedoesnotexist' ); - } - $parent_comment = Comment::newFromWikiPage( $parent_page ); - if ( $parent_comment->getAssociatedId() !== (int)$associatedid ) { - $this->dieCustomUsageMessage( - 'commentstreams-api-error-post-associatedpageidmismatch' ); + $this->dieWithError( 'commentstreams-api-error-post-parentpagedoesnotexist' ); + } else { + $parent_comment = $this->commentStreamsFactory->newFromWikiPage( $parent_page ); + if ( $parent_comment->getAssociatedId() !== (int)$associatedid ) { + $this->dieWithError( 'commentstreams-api-error-post-associatedpageidmismatch' ); + } + $parent_comment_title = $parent_comment->getCommentTitle(); } } - $associated_page = WikiPage::newFromId( $associatedid ); + $associatedid = (int)$associatedid; + $associated_page = CommentStreamsUtils::newWikiPageFromId( $associatedid ); if ( $associated_page === null || !$associated_page->getTitle()->exists() ) { - $this->dieCustomUsageMessage( - 'commentstreams-api-error-post-associatedpagedoesnotexist' ); - } - - $comment = Comment::newFromValues( $associatedid, $parentid, - $comment_title, $wikitext, $this->getUser() ); - if ( !$comment ) { - $this->dieCustomUsageMessage( 'commentstreams-api-error-post' ); - } - - $title = $comment->getWikiPage()->getTitle(); - if ( $comment->getParentId() === null ) { - $this->logAction( 'comment-create', $title ); + $this->dieWithError( 'commentstreams-api-error-post-associatedpagedoesnotexist' ); } else { - $this->logAction( 'reply-create', $title ); - } - - $json = $comment->getJSON(); - if ( ExtensionRegistry::getInstance()->isLoaded( 'Echo' ) && - $comment->getParentId() === null - ) { - $json['watching'] = 1; + $comment = $this->commentStreamsFactory->newFromValues( + $commentblockid, + $associatedid, + $parentid, + $comment_title, + $wikitext, + $this->getUser() + ); + + if ( !$comment ) { + $this->dieWithError( 'commentstreams-api-error-post' ); + } else { + $title = $comment->getTitle(); + if ( $comment->getParentId() === null ) { + $this->logAction( 'comment-create', $title ); + } else { + $this->logAction( 'reply-create', $title ); + } + + $this->getResult()->addValue( null, $this->getModuleName(), $comment->getId() ); + + $this->echoInterface->sendNotifications( + $comment, + $associated_page, + $this->getUser(), + $parent_comment_title ?: $comment_title + ); + } } - $this->getResult()->addValue( null, $this->getModuleName(), $json ); - - $this->sendNotifications( $comment, $associated_page ); } /** * @return array allowed parameters */ - public function getAllowedParams() { + public function getAllowedParams() : array { return [ 'commenttitle' => [ ApiBase::PARAM_TYPE => 'string', @@ -129,6 +150,10 @@ class ApiCSPostComment extends ApiBase { 'parentid' => [ ApiBase::PARAM_TYPE => 'integer', ApiBase::PARAM_REQUIRED => false + ], + 'commentblockid' => [ + ApiBase::PARAM_TYPE => 'string', + ApiBase::PARAM_REQUIRED => false ] ]; } @@ -136,106 +161,21 @@ class ApiCSPostComment extends ApiBase { /** * @return string indicates that this API module requires a CSRF token */ - public function needstoken() { + public function needstoken() : string { return 'csrf'; } /** - * Send Echo notifications if Echo is installed. - * - * @param Comment $comment the comment to send notifications for - * @param WikiPage $associated_page the associated page for the comment - * @return not used - */ - private function sendNotifications( $comment, $associated_page ) { - if ( !ExtensionRegistry::getInstance()->isLoaded( 'Echo' ) ) { - return; - } - - $parent_id = $comment->getParentId(); - if ( $parent_id === null ) { - $comment_title = $comment->getCommentTitle(); - } else { - $parent_page = WikiPage::newFromId( $parent_id ); - if ( $parent_page === null ) { - return; - } - $parent_comment = Comment::newFromWikiPage( $parent_page ); - if ( $parent_comment === null ) { - return; - } else { - $comment_title = $parent_comment->getCommentTitle(); - } - } - - $associated_page_display_title = - $associated_page->getTitle()->getPrefixedText(); - if ( class_exists( 'PageProps' ) ) { - $associated_title = $associated_page->getTitle(); - $values = \PageProps::getInstance()->getProperties( $associated_title, - 'displaytitle' ); - if ( array_key_exists( $associated_title->getArticleID(), $values ) ) { - $associated_page_display_title = - $values[$associated_title->getArticleID()]; - } - } - - $extra = [ - 'comment_id' => $comment->getId(), - 'parent_id' => $comment->getParentId(), - 'comment_author_username' => $comment->getUsername(), - 'comment_author_display_name' => $comment->getUserDisplayNameUnlinked(), - 'comment_title' => $comment_title, - 'associated_page_display_title' => $associated_page_display_title, - 'comment_wikitext' => $comment->getWikitext() - ]; - - if ( $parent_id !== null ) { - EchoEvent::create( [ - 'type' => 'commentstreams-reply-on-watched-page', - 'title' => $associated_page->getTitle(), - 'extra' => $extra, - 'agent' => $this->getUser() - ] ); - EchoEvent::create( [ - 'type' => 'commentstreams-reply-to-watched-comment', - 'title' => $associated_page->getTitle(), - 'extra' => $extra, - 'agent' => $this->getUser() - ] ); - } else { - EchoEvent::create( [ - 'type' => 'commentstreams-comment-on-watched-page', - 'title' => $associated_page->getTitle(), - 'extra' => $extra, - 'agent' => $this->getUser() - ] ); - } - } - - /** * log action * @param string $action the name of the action to be logged - * @param string|null $title the title of the page for the comment that the - * action was performed upon + * @param LinkTarget|Title $target the title of the page for the comment that the + * action was performed upon, if different from the current comment + * @throws MWException */ - protected function logAction( $action, $title ) { + protected function logAction( string $action, $target ) { $logEntry = new ManualLogEntry( 'commentstreams', $action ); $logEntry->setPerformer( $this->getUser() ); - $logEntry->setTarget( $title ); - $logid = $logEntry->insert(); - } - - /** - * die with a custom usage message - * @param string $message_name the name of the custom message - */ - private function dieCustomUsageMessage( $message_name ) { - $error_message = wfMessage( $message_name ); - $this->dieUsageMsg( - [ - ApiMessage::create( $error_message ) - ] - ); + $logEntry->setTarget( $target ); + $logEntry->insert(); } } diff --git a/CommentStreams/includes/ApiCSQueryComment.php b/CommentStreams/includes/ApiCSQueryComment.php index a27196ee..8112b7ee 100644 --- a/CommentStreams/includes/ApiCSQueryComment.php +++ b/CommentStreams/includes/ApiCSQueryComment.php @@ -23,22 +23,22 @@ namespace MediaWiki\Extension\CommentStreams; -class ApiCSQueryComment extends ApiCSBase { +use ApiMain; +class ApiCSQueryComment extends ApiCSBase { /** * @param ApiMain $main main module * @param string $action name of this module */ - public function __construct( $main, $action ) { + public function __construct( ApiMain $main, string $action ) { parent::__construct( $main, $action ); } /** * the real body of the execute function - * - * @return result of API request + * @return ?array result of API request */ - protected function executeBody() { - return $this->comment->getJSON(); + protected function executeBody() : ?array { + return $this->comment->getJSON( $this ); } } diff --git a/CommentStreams/includes/ApiCSUnwatch.php b/CommentStreams/includes/ApiCSUnwatch.php index 27251f97..219eb2be 100644 --- a/CommentStreams/includes/ApiCSUnwatch.php +++ b/CommentStreams/includes/ApiCSUnwatch.php @@ -23,56 +23,56 @@ namespace MediaWiki\Extension\CommentStreams; -class ApiCSUnwatch extends ApiCSBase { +use ApiMain; +use ApiUsageException; +class ApiCSUnwatch extends ApiCSBase { /** * @param ApiMain $main main module * @param string $action name of this module */ - public function __construct( $main, $action ) { + public function __construct( ApiMain $main, string $action ) { parent::__construct( $main, $action, true ); } /** * the real body of the execute function - * - * @return result of API request + * @return ?array result of API request + * @throws ApiUsageException */ - protected function executeBody() { + protected function executeBody() : ?array { if ( $this->getUser()->isAnon() ) { - $this->dieCustomUsageMessage( - 'commentstreams-api-error-unwatch-notloggedin' ); + $this->dieWithError( 'commentstreams-api-error-unwatch-notloggedin' ); } if ( $this->comment->getParentId() !== null ) { - $this->dieCustomUsageMessage( - 'commentstreams-api-error-unwatch-nounwatchonreply' ); + $this->dieWithError( 'commentstreams-api-error-unwatch-nounwatchonreply' ); } - $result = $this->comment->unwatch( $this->getUser() ); + $result = $this->comment->unwatch( $this->getUser()->getId() ); if ( !$result ) { - $this->dieCustomUsageMessage( 'commentstreams-api-error-unwatch' ); + $this->dieWithError( 'commentstreams-api-error-unwatch' ); } - $this->getResult()->addValue( null, $this->getModuleName(), '' ); + return null; } /** * @return array examples of the use of this API module */ - public function getExamplesMessages() { + public function getExamplesMessages() : array { return [ 'action=' . $this->getModuleName() . '&pageid=3' => - 'apihelp-' . $this->getModuleName() . '-pageid-example', + 'apihelp-' . $this->getModuleName() . '-pageid-example', 'action=' . $this->getModuleName() . '&title=CommentStreams:3' => - 'apihelp-' . $this->getModuleName() . '-title-example' + 'apihelp-' . $this->getModuleName() . '-title-example' ]; } /** * @return string indicates that this API module requires a CSRF toekn */ - public function needsToken() { + public function needsToken() : string { return 'csrf'; } } diff --git a/CommentStreams/includes/ApiCSVote.php b/CommentStreams/includes/ApiCSVote.php index 3e92c346..c88d0e3f 100644 --- a/CommentStreams/includes/ApiCSVote.php +++ b/CommentStreams/includes/ApiCSVote.php @@ -24,47 +24,46 @@ namespace MediaWiki\Extension\CommentStreams; use ApiBase; +use ApiMain; +use ApiUsageException; class ApiCSVote extends ApiCSBase { - /** * @param ApiMain $main main module * @param string $action name of this module */ - public function __construct( $main, $action ) { + public function __construct( ApiMain $main, string $action ) { parent::__construct( $main, $action, true ); } /** * the real body of the execute function - * - * @return result of API request + * @return ?array result of API request + * @throws ApiUsageException */ - protected function executeBody() { + protected function executeBody() : ?array { if ( $this->getUser()->isAnon() ) { - $this->dieCustomUsageMessage( - 'commentstreams-api-error-vote-notloggedin' ); + $this->dieWithError( 'commentstreams-api-error-vote-notloggedin' ); } $vote = $this->getMain()->getVal( 'vote' ); if ( $this->comment->getParentId() !== null ) { - $this->dieCustomUsageMessage( - 'commentstreams-api-error-vote-novoteonreply' ); + $this->dieWithError( 'commentstreams-api-error-vote-novoteonreply' ); } $result = $this->comment->vote( $vote, $this->getUser() ); if ( !$result ) { - $this->dieCustomUsageMessage( 'commentstreams-api-error-vote' ); + $this->dieWithError( 'commentstreams-api-error-vote' ); } - $this->getResult()->addValue( null, $this->getModuleName(), '' ); + return null; } /** * @return array allowed parameters */ - public function getAllowedParams() { + public function getAllowedParams() : array { return array_merge( parent::getAllowedParams(), [ 'vote' => @@ -79,19 +78,19 @@ class ApiCSVote extends ApiCSBase { /** * @return array examples of the use of this API module */ - public function getExamplesMessages() { + public function getExamplesMessages() : array { return [ 'action=' . $this->getModuleName() . '&pageid=3&vote=1' => - 'apihelp-' . $this->getModuleName() . '-pageid-example', + 'apihelp-' . $this->getModuleName() . '-pageid-example', 'action=' . $this->getModuleName() . '&title=CommentStreams:3&vote=-1' => - 'apihelp-' . $this->getModuleName() . '-title-example' + 'apihelp-' . $this->getModuleName() . '-title-example' ]; } /** * @return string indicates that this API module requires a CSRF toekn */ - public function needsToken() { + public function needsToken() : string { return 'csrf'; } } diff --git a/CommentStreams/includes/ApiCSWatch.php b/CommentStreams/includes/ApiCSWatch.php index 8c4e9e8c..af51d5bb 100644 --- a/CommentStreams/includes/ApiCSWatch.php +++ b/CommentStreams/includes/ApiCSWatch.php @@ -23,56 +23,56 @@ namespace MediaWiki\Extension\CommentStreams; -class ApiCSWatch extends ApiCSBase { +use ApiMain; +use ApiUsageException; +class ApiCSWatch extends ApiCSBase { /** * @param ApiMain $main main module * @param string $action name of this module */ - public function __construct( $main, $action ) { + public function __construct( ApiMain $main, string $action ) { parent::__construct( $main, $action, true ); } /** * the real body of the execute function - * - * @return result of API request + * @return ?array result of API request + * @throws ApiUsageException */ - protected function executeBody() { + protected function executeBody() : ?array { if ( $this->getUser()->isAnon() ) { - $this->dieCustomUsageMessage( - 'commentstreams-api-error-watch-notloggedin' ); + $this->dieWithError( 'commentstreams-api-error-watch-notloggedin' ); } if ( $this->comment->getParentId() !== null ) { - $this->dieCustomUsageMessage( - 'commentstreams-api-error-watch-nowatchonreply' ); + $this->dieWithError( 'commentstreams-api-error-watch-nowatchonreply' ); } - $result = $this->comment->watch( $this->getUser() ); + $result = $this->comment->watch( $this->getUser()->getId() ); if ( !$result ) { - $this->dieCustomUsageMessage( 'commentstreams-api-error-watch' ); + $this->dieWithError( 'commentstreams-api-error-watch' ); } - $this->getResult()->addValue( null, $this->getModuleName(), '' ); + return null; } /** * @return array examples of the use of this API module */ - public function getExamplesMessages() { + public function getExamplesMessages() : array { return [ 'action=' . $this->getModuleName() . '&pageid=3' => - 'apihelp-' . $this->getModuleName() . '-pageid-example', + 'apihelp-' . $this->getModuleName() . '-pageid-example', 'action=' . $this->getModuleName() . '&title=CommentStreams:3' => - 'apihelp-' . $this->getModuleName() . '-title-example' + 'apihelp-' . $this->getModuleName() . '-title-example' ]; } /** * @return string indicates that this API module requires a CSRF toekn */ - public function needsToken() { + public function needsToken() : string { return 'csrf'; } } diff --git a/CommentStreams/includes/Comment.php b/CommentStreams/includes/Comment.php index 755c24c3..4769a4ca 100644 --- a/CommentStreams/includes/Comment.php +++ b/CommentStreams/includes/Comment.php @@ -23,537 +23,374 @@ namespace MediaWiki\Extension\CommentStreams; +use ConfigException; +use FatalError; use Html; -use MediaWiki\MediaWikiServices; +use IContextSource; +use MediaWiki\Linker\LinkRenderer; +use MediaWiki\User\UserIdentity; +use MWException; use MWTimestamp; -use Parser; -use ParserOptions; -use SMWDataItem; -use SMWUpdateJob; +use PageProps; use Title; use User; -use wAvatar; +use Wikimedia\Assert\Assert; use WikiPage; -use WikitextContent; class Comment { + public const CONSTRUCTOR_OPTIONS = [ + 'CommentStreamsUserAvatarPropertyName', + 'CommentStreamsUserRealNamePropertyName', + 'CommentStreamsEnableVoting' + ]; - // wiki page object for this comment wiki page - private $wikipage = null; - - // data for this comment has been loaded from the database - private $loaded = false; - - // int page ID for the wikipage this comment is on - private $assoc_page_id; - - // int page ID for the wikipage this comment is in reply to or null - private $parent_page_id; + /** + * @var CommentStreamsStore + */ + private $commentStreamsStore; - // string title of comment - private $comment_title; + /** + * @var CommentStreamsEchoInterface + */ + private $echoInterface; - // string wikitext of comment - private $wikitext = null; + /** + * @var CommentStreamsSMWInterface + */ + private $smwInterface; - // string HTML of comment - private $html = null; + /** + * @var CommentStreamsSocialProfileInterface + */ + private $socialProfileInterface; - // User user object for the author of this comment - private $user = null; + /** + * @var LinkRenderer + */ + private $linkRenderer; - // Avatar for author of this comment - private $avatar = null; + /** + * @var string + */ + private $userAvatarPropertyName; - // MWTimestamp the earliest revision date for this comment - private $creation_timestamp = null; + /** + * @var string + */ + private $userRealNamePropertyName; - // MWTimestamp the latest revision date for this comment - private $modification_timestamp = null; + /** + * @var mixed + */ + private $enableVoting; - // number of replies to this comment - private $num_replies = null; + /** + * wiki page object for this comment wiki page + * @var WikiPage + */ + private $wikipage; - // number of up votes for this comment - private $num_up_votes = null; + /** + * unique id to identify comment block in a page + * @var ?string + */ + private $comment_block_id; - // number of dow votes for this comment - private $num_down_votes = null; + /** + * page ID for the wiki page this comment is on + * @var int + */ + private $assoc_page_id; /** - * create a new Comment object from existing wiki page - * - * @param WikiPage $wikipage WikiPage object corresponding to comment page - * @return Comment|null the newly created comment or null if there was an - * error + * page ID for the wiki page this comment is in reply to or null + * @var ?int */ - public static function newFromWikiPage( $wikipage ) { - if ( $wikipage !== null && - $wikipage->getTitle()->getNamespace() === NS_COMMENTSTREAMS ) { - $comment = new Comment( $wikipage ); - if ( $wikipage->exists() ) { - $comment->loadFromDatabase(); - } - return $comment; - } - return null; - } + private $parent_page_id; /** - * create a new Comment object from values and save to database - * NOTE: since only head comments can contain a comment title, either - * $comment_title or $parent_page_id must be non null, but not both - * - * @param int $assoc_page_id page ID for the wikipage this comment is on - * @param int $parent_page_id page ID for the wikipage this comment is in - * reply to or null - * @param string $comment_title string title of comment - * @param string $wikitext the wikitext to add - * @param User $user the user - * @return Comment|null new comment object or null if there was a problem - * creating it + * title of comment + * @var ?string */ - public static function newFromValues( $assoc_page_id, $parent_page_id, - $comment_title, $wikitext, $user ) { - if ( $comment_title === null && $parent_page_id === null ) { - return null; - } - if ( $comment_title !== null && $parent_page_id !== null ) { - return null; - } - $annotated_wikitext = self::addAnnotations( $wikitext, $comment_title, - $assoc_page_id ); - $content = new WikitextContent( $annotated_wikitext ); - $success = false; - while ( !$success ) { - $index = wfRandomString(); - $title = Title::newFromText( (string)$index, NS_COMMENTSTREAMS ); - if ( !$title->isDeletedQuick() && !$title->exists() ) { - if ( class_exists( 'MediaWiki\Permissions\PermissionManager' ) ) { - // MW 1.33+ - if ( !MediaWikiServices::getInstance() - ->getPermissionManager() - ->userCan( 'cs-comment', $user, $title ) - ) { - return null; - } - } else { - if ( !$title->userCan( 'cs-comment' ) ) { - return null; - } - } + private $comment_title; - $wikipage = new WikiPage( $title ); - $status = $wikipage->doEditContent( $content, '', - EDIT_NEW | EDIT_SUPPRESS_RC, false, $user, null ); - if ( !$status->isOK() && !$status->isGood() ) { - if ( $status->getMessage()->getKey() == 'edit-already-exists' ) { - $index = wfRandomString(); - } else { - return null; - } - } else { - $success = true; - } - } else { - $index = wfRandomString(); - } - } - $comment = new Comment( $wikipage ); - $comment->wikitext = $wikitext; + /** + * wikitext of comment + * @var ?string + */ + private $wikitext; - $dbw = wfGetDB( DB_MASTER ); - $result = $dbw->insert( - 'cs_comment_data', - [ - 'cst_page_id' => $wikipage->getId(), - 'cst_assoc_page_id' => $assoc_page_id, - 'cst_parent_page_id' => $parent_page_id, - 'cst_comment_title' => $comment_title - ], - __METHOD__ - ); - if ( !$result ) { - return null; - } - $comment->loadFromValues( $assoc_page_id, $parent_page_id, $comment_title ); + /** + * number of replies to this comment + * @var ?int + */ + private $num_replies; - if ( $parent_page_id === null ) { - $comment->watch( $user ); - } else { - self::watchComment( $parent_page_id, $user ); - } + /** + * user object for the author of this comment + * @var User + */ + private $author; - if ( defined( 'SMW_VERSION' ) ) { - $job = new SMWUpdateJob( $title, [] ); - \JobQueueGroup::singleton()->push( $job ); - } + /** + * user object for the last editor of this comment + * @var ?UserIdentity + */ + private $lastEditor; - return $comment; - } + /** + * Avatar for author of this comment + * @var ?string + */ + private $avatar; /** - * constructor - * - * @param WikiPage $wikipage WikiPage object corresponding to comment page + * @var array */ - private function __construct( $wikipage ) { - $this->wikipage = $wikipage; - } + private static $avatarCache = []; /** - * load comment data from database + * the earliest revision date for this comment + * @var ?MWTimestamp */ - private function loadFromDatabase() { - $dbr = wfGetDB( DB_REPLICA ); - $result = $dbr->selectRow( - 'cs_comment_data', - [ - 'cst_assoc_page_id', - 'cst_parent_page_id', - 'cst_comment_title' - ], - [ - 'cst_page_id' => $this->getId() - ], - __METHOD__ - ); - if ( $result ) { - $this->assoc_page_id = (int)$result->cst_assoc_page_id; - $this->parent_page_id = $result->cst_parent_page_id; - if ( $this->parent_page_id !== null ) { - $this->parent_page_id = (int)$this->parent_page_id; - } - $this->comment_title = $result->cst_comment_title; - $this->loaded = true; - } - } + private $creation_timestamp; /** - * load comment data from values - * - * @param int $assoc_page_id page ID for the wikipage this comment is on - * @param int $parent_page_id page ID for the wikipage this comment is in - * reply to or null - * @param string $comment_title string title of comment + * the latest revision date for this comment + * @var ?MWTimestamp */ - private function loadFromValues( $assoc_page_id, $parent_page_id, - $comment_title ) { - $this->assoc_page_id = (int)$assoc_page_id; + private $modification_timestamp; + + /** + * Do not instantiate directly. Use CommentStreamsFactory instead. + * @param \MediaWiki\Config\ServiceOptions|\Config $options + * @param CommentStreamsStore $commentStreamsStore + * @param CommentStreamsEchoInterface $echoInterface + * @param CommentStreamsSMWInterface $smwInterface + * @param CommentStreamsSocialProfileInterface $socialProfileInterface + * @param LinkRenderer $linkRenderer + * @param WikiPage $wikipage WikiPage object corresponding to comment page + * @param ?string $comment_block_id + * @param int $assoc_page_id + * @param ?int $parent_page_id + * @param ?string $comment_title + * @param string $wikitext + * @throws ConfigException + */ + public function __construct( + $options, + CommentStreamsStore $commentStreamsStore, + CommentStreamsEchoInterface $echoInterface, + CommentStreamsSMWInterface $smwInterface, + CommentStreamsSocialProfileInterface $socialProfileInterface, + LinkRenderer $linkRenderer, + WikiPage $wikipage, + ?string $comment_block_id, + int $assoc_page_id, + ?int $parent_page_id, + ?string $comment_title, + string $wikitext + ) { + if ( class_exists( '\MediaWiki\Config\ServiceOptions' ) ) { + $options->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS ); + } + $this->userAvatarPropertyName = $options->get( 'CommentStreamsUserAvatarPropertyName' ); + $this->userRealNamePropertyName = $options->get( 'CommentStreamsUserRealNamePropertyName' ); + $this->enableVoting = (bool)$options->get( 'CommentStreamsEnableVoting' ); + $this->commentStreamsStore = $commentStreamsStore; + $this->echoInterface = $echoInterface; + $this->smwInterface = $smwInterface; + $this->socialProfileInterface = $socialProfileInterface; + $this->linkRenderer = $linkRenderer; + $this->wikipage = $wikipage; + $this->comment_block_id = $comment_block_id; + $this->assoc_page_id = $assoc_page_id; $this->parent_page_id = $parent_page_id; - if ( $this->parent_page_id !== null ) { - $this->parent_page_id = (int)$this->parent_page_id; - } $this->comment_title = $comment_title; - $this->loaded = true; + $this->wikitext = $wikitext; + $this->num_replies = $commentStreamsStore->getNumReplies( $wikipage->getId() ); + $title = $wikipage->getTitle(); + $user = CommentStreamsUtils::getAuthor( $title ); + if ( $user !== null ) { + $this->author = $user; + } + $this->setAvatar(); + $this->lastEditor = CommentStreamsUtils::getLastEditor( $wikipage ) ?: $this->author; + $timestamp = CommentStreamsUtils::getCreationTimestamp( $title ); + if ( $timestamp !== null ) { + $this->creation_timestamp = MWTimestamp::getLocalInstance( $timestamp ); + } + $this->setModificationTimestamp(); } /** - * @return int page ID of the comment's wikipage + * @return int page ID of the comment's wiki page */ - public function getId() { + public function getId() : int { return $this->wikipage->getId(); } /** - * @return WikiPage wiki page object associate with this comment page + * @return Title Title object associated with this comment page */ - public function getWikiPage() { - return $this->wikipage; + public function getTitle() : Title { + return $this->wikipage->getTitle(); } /** - * @return int page ID for the wikipage this comment is on + * @return ?string comment block id */ - public function getAssociatedId() { - if ( $this->loaded === false ) { - $this->loadFromDatabase(); - } + public function getBlockId() : ?string { + return $this->comment_block_id; + } + + /** + * @return int page ID for the wiki page this comment is on + */ + public function getAssociatedId() : int { return $this->assoc_page_id; } /** - * @return int|null page ID for the wikipage this comment is in reply to or + * @return int|null page ID for the wiki page this comment is in reply to or * null if this comment is a discussion, not a reply */ - public function getParentId() { - if ( $this->loaded === false ) { - $this->loadFromDatabase(); - } + public function getParentId() : ?int { return $this->parent_page_id; } /** - * @return string the title of the comment + * @return ?string the title of the comment */ - public function getCommentTitle() { - if ( $this->loaded === false ) { - $this->loadFromDatabase(); - } + public function getCommentTitle() : ?string { return $this->comment_title; } /** * @return string wikitext of the comment */ - public function getWikiText() { - if ( $this->wikitext === null ) { - $wikitext = \ContentHandler::getContentText( $this->wikipage->getContent( - \Revision::RAW ) ); - $wikitext = $this->removeAnnotations( $wikitext ); - $this->wikitext = $wikitext; - } + public function getWikiText() : string { return $this->wikitext; } /** + * @param IContextSource $context * @return string parsed HTML of the comment */ - public function getHTML() { - if ( $this->html === null ) { - $this->getWikiText(); - if ( $this->wikitext !== null ) { - if ( class_exists( \ParserFactory::class ) ) { - // @requires MediaWiki >= 1.32.0 - $parser = MediaWikiServices::getInstance()->getParserFactory()->create(); - } else { - $parser = new Parser(); - } - - $this->html = $parser->parse( $this->wikitext, - $this->wikipage->getTitle(), new ParserOptions )->getText(); - } - } - return $this->html; + public function getHTML( IContextSource $context ) : string { + return CommentStreamsUtils::parse( $this->wikitext, $this->wikipage, $context ); } /** - * @return User the author of this comment + * @return int number of replies */ - public function getUser() { - if ( $this->user === null ) { - $user_id = $this->wikipage->getOldestRevision()->getUser(); - $this->user = User::newFromId( $user_id ); - } - return $this->user; + public function getNumReplies() : int { + return $this->num_replies; } /** - * @return bool true if the last edit to this comment was not done by the - * original author + * @return ?User the author of this comment */ - public function isLastEditModerated() { - $author = $this->wikipage->getOldestRevision()->getUser(); - $lastEditor = $this->wikipage->getRevision()->getUser(); - return $author !== $lastEditor; + public function getAuthor() : ?User { + return $this->author; } /** * @return string username of the author of this comment */ - public function getUsername() { - return $this->getUser()->getName(); + public function getUsername() : string { + return $this->author->getName(); } /** * @return string display name of the author of this comment linked to * the user's user page if it exists */ - public function getUserDisplayName() { - return self::getDisplayNameFromUser( $this->getUser() ); + public function getUserDisplayName() : string { + return $this->getDisplayNameFromUser( $this->author, true ); } /** * @return string display name of the author of this comment */ - public function getUserDisplayNameUnlinked() { - return self::getDisplayNameFromUser( $this->getUser(), false ); - } - - /** - * @return string the URL of the avatar of the author of this comment - */ - public function getAvatar() { - if ( $this->avatar === null ) { - if ( class_exists( 'wAvatar' ) ) { - // from Extension:SocialProfile - $avatar = new wAvatar( $this->getUser()->getId(), 'l' ); - $this->avatar = $GLOBALS['wgUploadPath'] . '/avatars/' . - $avatar->getAvatarImage(); - } else { - $this->avatar = self::getAvatarFromUser( $this->getUser() ); - } - } - return $this->avatar; + public function getUserDisplayNameUnlinked() : string { + return $this->getDisplayNameFromUser( $this->author, false ); } /** - * @return MWTimestamp the earliest revision date for this + * @return UserIdentity the last editor of this comment */ - public function getCreationTimestamp() { - if ( $this->creation_timestamp === null ) { - $this->creation_timestamp = MWTimestamp::getLocalInstance( - $this->wikipage->getTitle()->getEarliestRevTime() ); - } - return $this->creation_timestamp; + public function getLastEditor() : UserIdentity { + return $this->lastEditor; } /** - * @return MWTimestamp the earliest revision date for this + * @return bool true if the last edit to this comment was not done by the + * original author */ - public function getCreationDate() { - if ( $this->getCreationTimestamp() !== null ) { - return $this->creation_timestamp->format( "M j \a\\t g:i a" ); - } - return ""; + public function isLastEditModerated() : bool { + return $this->author->getId() !== $this->lastEditor->getId(); } /** - * @return MWTimestamp the latest revision date for this + * @return MWTimestamp */ - public function getModificationTimestamp() { - if ( $this->modification_timestamp === null ) { - $title = $this->wikipage->getTitle(); - if ( $title->getFirstRevision()->getId() === $title->getLatestRevID() ) { - return null; - } - - $revStore = MediaWikiServices::getInstance()->getRevisionStore(); - $latestRev = $title->getLatestRevId(); - if ( version_compare( MW_VERSION, '1.34', '<' ) ) { - $timestamp = $revStore->getTimestampFromId( $title, $latestRev ); - } else { - $timestamp = $revStore->getTimestampFromId( $latestRev ); - } - - $this->modification_timestamp = MWTimestamp::getLocalInstance( - $timestamp ); - } - return $this->modification_timestamp; + public function getCreationTimestamp() : MWTimestamp { + return $this->creation_timestamp; } /** - * @return MWTimestamp the earliest revision date for this + * @return string */ - public function getModificationDate() { - if ( $this->getModificationTimestamp() !== null ) { - return $this->modification_timestamp->format( "M j \a\\t g:i a" ); - } - return null; + public function getCreationDate() : string { + return $this->creation_timestamp->format( "M j \a\\t g:i a" ); } /** - * @return int number of replies + * @return ?string */ - public function getNumReplies() { - if ( $this->num_replies === null ) { - $dbr = wfGetDB( DB_REPLICA ); - $this->num_replies = $dbr->selectRowCount( - 'cs_comment_data', - '*', - [ - 'cst_parent_page_id' => $this->getId() - ], - __METHOD__ - ); - } - return $this->num_replies; + public function getModificationDate() : ?string { + return $this->modification_timestamp ? + $this->modification_timestamp->format( "M j \a\\t g:i a" ) : null; } /** + * @param IContextSource $context * @return array get comment data in array suitable for JSON */ - public function getJSON() { + public function getJSON( IContextSource $context ) : array { $json = [ - 'commenttitle' => $this->getCommentTitle(), + 'pageid' => $this->wikipage->getId(), + 'commentblockid' => $this->comment_block_id, + 'associatedid' => $this->assoc_page_id, + 'parentid' => $this->parent_page_id, + 'commenttitle' => $this->comment_title, + 'wikitext' => htmlentities( $this->wikitext ), + 'html' => $this->getHTML( $context ), 'username' => $this->getUsername(), + 'numreplies' => $this->num_replies, 'userdisplayname' => $this->getUserDisplayName(), - 'avatar' => $this->getAvatar(), - 'created' => $this->getCreationDate(), - 'created_timestamp' => $this->getCreationTimestamp()->format( "U" ), - 'modified' => $this->getModificationDate(), + 'avatar' => $this->avatar, 'moderated' => $this->isLastEditModerated() ? "moderated" : null, - 'wikitext' => htmlentities( $this->getWikiText() ), - 'html' => $this->getHTML(), - 'pageid' => $this->getId(), - 'associatedid' => $this->getAssociatedId(), - 'parentid' => $this->getParentId(), - 'numreplies' => $this->getNumReplies(), + 'created' => $this->getCreationDate(), + 'created_timestamp' => $this->creation_timestamp->format( "U" ), + 'modified' => $this->getModificationDate() ]; - if ( $GLOBALS['wgCommentStreamsEnableVoting'] ) { - $json['numupvotes'] = $this->getNumUpVotes(); - $json['numdownvotes'] = $this->getNumDownVotes(); - } - return $json; - } - /** - * get vote for user - * - * @param User $user the author of the edit - * @return +1 for up vote, -1 for down vote, 0 for no vote - */ - public function getVote( $user ) { - $dbr = wfGetDB( DB_REPLICA ); - $result = $dbr->selectRow( - 'cs_votes', - [ - 'cst_v_vote' - ], - [ - 'cst_v_page_id' => $this->getId(), - 'cst_v_user_id' => $user->getId() - ], - __METHOD__ - ); - if ( $result ) { - $vote = (int)$result->cst_v_vote; - if ( $vote > 0 ) { - return 1; + $user = $context->getUser(); + if ( $this->parent_page_id === null ) { + if ( $this->enableVoting ) { + $json['numupvotes'] = $this->commentStreamsStore->getNumUpVotes( $this->getId() ); + $json['numdownvotes'] = + $this->commentStreamsStore->getNumDownVotes( $this->getId() ); + $json['vote'] = $this->getVote( $user ); } - if ( $vote < 0 ) { - return -1; + if ( $this->echoInterface->isLoaded() ) { + $json['watching'] = $this->isWatching( $user ) ? 1 : 0; } } - return 0; - } - - /** - * @return int number of up votes - */ - public function getNumUpVotes() { - if ( $this->num_up_votes === null ) { - $dbr = wfGetDB( DB_REPLICA ); - $this->num_up_votes = $dbr->selectRowCount( - 'cs_votes', - '*', - [ - 'cst_v_page_id' => $this->getId(), - 'cst_v_vote' => 1 - ], - __METHOD__ - ); - } - return $this->num_up_votes; - } - /** - * @return int number of down votes - */ - public function getNumDownVotes() { - if ( $this->num_down_votes === null ) { - $dbr = wfGetDB( DB_REPLICA ); - $this->num_down_votes = $dbr->selectRowCount( - 'cs_votes', - '*', - [ - 'cst_v_page_id' => $this->getId(), - 'cst_v_vote' => -1 - ], - __METHOD__ - ); - } - return $this->num_down_votes; + return $json; } /** @@ -563,184 +400,44 @@ class Comment { * @param User $user the user voting on the comment * @return bool database status code */ - public function vote( $vote, $user ) { - if ( $vote !== "-1" && $vote !== "0" && $vote !== "1" ) { - return false; - } - $vote = (int)$vote; - $dbr = wfGetDB( DB_REPLICA ); - $result = $dbr->selectRow( - 'cs_votes', - [ - 'cst_v_vote' - ], - [ - 'cst_v_page_id' => $this->getId(), - 'cst_v_user_id' => $user->getId() - ], - __METHOD__ - ); - if ( $result ) { - if ( $vote === (int)$result->cst_v_vote ) { - return true; - } - if ( $vote === 1 || $vote === -1 ) { - $dbw = wfGetDB( DB_MASTER ); - $result = $dbw->update( - 'cs_votes', - [ - 'cst_v_vote' => $vote - ], - [ - 'cst_v_page_id' => $this->getId(), - 'cst_v_user_id' => $user->getId() - ], - __METHOD__ - ); - } else { - $dbw = wfGetDB( DB_MASTER ); - $result = $dbw->delete( - 'cs_votes', - [ - 'cst_v_page_id' => $this->getId(), - 'cst_v_user_id' => $user->getId() - ], - __METHOD__ - ); - } - } else { - if ( $vote === 0 ) { - return true; - } - $dbw = wfGetDB( DB_MASTER ); - $result = $dbw->insert( - 'cs_votes', - [ - 'cst_v_page_id' => $this->getId(), - 'cst_v_user_id' => $user->getId(), - 'cst_v_vote' => $vote - ], - __METHOD__ - ); - } - return $result; - } - - /** - * watch a comment (get page ID from this comment) - * - * @param User $user the user watching the comment - * @return bool database true for OK, false for error - */ - public function watch( $user ) { - return self::watchComment( $this->getID(), $user ); - } - - /** - * watch a comment (get page ID from parameter) - * - * @param int $pageid the page ID of the comment to watch - * @param User $user the user watching the comment - * @return bool database true for OK, false for error - */ - private static function watchComment( $pageid, $user ) { - if ( self::isWatchingComment( $pageid, $user ) ) { - return true; - } - $dbw = wfGetDB( DB_MASTER ); - $result = $dbw->insert( - 'cs_watchlist', - [ - 'cst_wl_page_id' => $pageid, - 'cst_wl_user_id' => $user->getId() - ], - __METHOD__ - ); + public function vote( string $vote, User $user ) : bool { + Assert::parameter( $vote === "-1" || $vote === "0" || $vote === "1", '$vote', + 'must be "-1", "0", or "1"' ); + $result = $this->commentStreamsStore->vote( (int)$vote, $this->getId(), $user->getId() ); + $this->smwInterface->update( $this->getTitle() ); return $result; } /** - * unwatch a comment - * - * @param User $user the user unwatching the comment - * @return bool database true for OK, false for error + * @param User $user + * @return int */ - public function unwatch( $user ) { - if ( !$this->isWatching( $user ) ) { - return true; - } - $dbw = wfGetDB( DB_MASTER ); - $result = $dbw->delete( - 'cs_watchlist', - [ - 'cst_wl_page_id' => $this->getId(), - 'cst_wl_user_id' => $user->getId() - ], - __METHOD__ - ); - return $result; + public function getVote( User $user ) : int { + return $this->commentStreamsStore->getVote( $this->getId(), $user->getId() ); } /** - * Check if a particular user is watching this comment - * - * @param User $user the user watching the comment - * @return bool database true for OK, false for error + * @param int $user_id + * @return bool */ - public function isWatching( $user ) { - return self::isWatchingComment( $this->getId(), $user ); + public function watch( int $user_id ) : bool { + return $this->commentStreamsStore->watch( $this->getId(), $user_id ); } /** - * Check if a particular user is watching a comment - * - * @param int $pageid the page ID of the comment to check - * @param User $user the user watching the comment - * @return bool database true for OK, false for error + * @param int $user_id + * @return bool */ - private static function isWatchingComment( $pageid, $user ) { - $dbr = wfGetDB( DB_REPLICA ); - $result = $dbr->selectRow( - 'cs_watchlist', - [ - 'cst_wl_page_id' - ], - [ - 'cst_wl_page_id' => $pageid, - 'cst_wl_user_id' => $user->getId() - ], - __METHOD__ - ); - if ( $result ) { - return true; - } - return false; + public function unwatch( int $user_id ) : bool { + return $this->commentStreamsStore->unwatch( $this->getId(), $user_id ); } /** - * Get an array of watchers for this comment - * - * @return array of user IDs + * @param User $user + * @return bool */ - public function getWatchers() { - $dbr = wfGetDB( DB_REPLICA ); - $result = $dbr->select( - 'cs_watchlist', - [ - 'cst_wl_user_id' - ], - [ - 'cst_wl_page_id' => $this->getId() - ], - __METHOD__ - ); - $users = []; - foreach ( $result as $row ) { - $user_id = $row->cst_wl_user_id; - $user = User::newFromId( $user_id ); - $users[$user_id] = $user; - } - return $users; + public function isWatching( User $user ) : bool { + return $this->commentStreamsStore->isWatching( $this->getId(), $user->getId() ); } /** @@ -749,47 +446,43 @@ class Comment { * $comment_title may only be non null if this comment has a null parent id * and vice versa * - * @param string $comment_title the new title for the comment + * @param ?string $comment_title the new title for the comment * @param string $wikitext the wikitext to add * @param User $user the author of the edit * @return bool true if successful - */ - public function update( $comment_title, $wikitext, $user ) { - if ( $comment_title === null && $this->getParentId() === null ) { - return false; - } - if ( $comment_title !== null && $this->getParentId() !== null ) { - return false; - } - $annotated_wikitext = - self::addAnnotations( $wikitext, $comment_title, - $this->getAssociatedId() ); - $content = new WikitextContent( $annotated_wikitext ); - $status = $this->wikipage->doEditContent( $content, '', - EDIT_UPDATE | EDIT_SUPPRESS_RC, false, $user, null ); - if ( !$status->isOK() && !$status->isGood() ) { - return false; - } - $this->wikitext = $wikitext; - $this->modification_timestamp = null; - $this->wikipage = WikiPage::newFromID( $this->wikipage->getId() ); - - $dbw = wfGetDB( DB_MASTER ); - $result = $dbw->update( - 'cs_comment_data', - [ - 'cst_comment_title' => $comment_title - ], - [ - 'cst_page_id' => $this->getId() - ], - __METHOD__ + * @throws MWException + */ + public function update( + ?string $comment_title, + string $wikitext, + User $user + ) : bool { + Assert::parameter( + ( $comment_title === null && $this->parent_page_id !== null ) || + ( $comment_title !== null && $this->parent_page_id === null ), + '$comment_title', + 'must be null if parent page ID is non-null or non-null if parent page ID is null' + ); + $result = $this->commentStreamsStore->updateComment( + $this->wikipage, + $comment_title, + $wikitext, + $user ); if ( !$result ) { return false; } $this->comment_title = $comment_title; - + $this->wikitext = $wikitext; + $this->modification_timestamp = null; + $wikipage = CommentStreamsUtils::newWikiPageFromId( $this->wikipage->getId(), + 'fromdbmaster' ); + if ( $wikipage !== null ) { + $this->wikipage = $wikipage; + } + if ( $this->parent_page_id === null ) { + $this->smwInterface->update( $this->getTitle() ); + } return true; } @@ -798,134 +491,56 @@ class Comment { * * @param User $deleter * @return bool true if successful + * @throws FatalError + * @throws MWException */ - public function delete( User $deleter ) { - if ( version_compare( MW_VERSION, '1.35', '<' ) ) { - $status = $this->getWikiPage()->doDeleteArticleReal( - 'comment deleted', - true - ); - } else { - $status = $this->getWikiPage()->doDeleteArticleReal( - 'comment deleted', - $deleter, - true - ); - } + public function delete( User $deleter ) : bool { + return $this->commentStreamsStore->deleteComment( $this->wikipage, $deleter ); + } - if ( !$status->isOK() && !$status->isGood() ) { - return false; + private function setAvatar() { + if ( array_key_exists( $this->author->getId(), self::$avatarCache ) ) { + $this->avatar = self::$avatarCache[ $this->author->getId() ]; + return; } - $pageid = $this->getId(); - $dbw = wfGetDB( DB_MASTER ); - $result = $dbw->delete( - 'cs_comment_data', - [ - 'cst_page_id' => $pageid - ], - __METHOD__ - ); - return $result; - } + $this->avatar = $this->socialProfileInterface->getAvatar( $this->author ); - /** - * add extra information to wikitext before storage - * - * @param string $wikitext the wikitext to which to add - * @param string $comment_title string title of comment - * @param int $assoc_page_id page ID for the wikipage this comment is on - * @return string annotated wikitext - */ - public static function addAnnotations( $wikitext, $comment_title, - $assoc_page_id ) { - if ( $comment_title !== null ) { - $wikitext .= <<<EOT -{{DISPLAYTITLE: -$comment_title -}} -EOT; + if ( $this->avatar === null && $this->userAvatarPropertyName !== null ) { + $title = $this->smwInterface->getUserProperty( $this->author, + $this->userAvatarPropertyName ); + if ( $title !== null ) { + if ( is_string( $title ) ) { + $title = Title::newFromText( $title ); + } + if ( $title->isKnown() && $title->getNamespace() === NS_FILE ) { + $file = CommentStreamsUtils::findFile( $title->getText() ); + if ( $file ) { + $this->avatar = $file->createThumb( 48, 48 ); + } + } + } } - return $wikitext; + + self::$avatarCache[ $this->author->getId() ] = $this->avatar; } - /** - * add extra information to wikitext before storage - * - * @param string $wikitext the wikitext to which to add - * @return string wikitext without annotations - */ - public function removeAnnotations( $wikitext ) { - $comment_title = $this->getCommentTitle(); - if ( $comment_title !== null ) { - $strip = <<<EOT -{{DISPLAYTITLE: -$comment_title -}} -EOT; - $wikitext = str_replace( $strip, '', $wikitext ); + private function setModificationTimestamp() { + $title = $this->wikipage->getTitle(); + $firstRevisionId = CommentStreamsUtils::getFirstRevisionId( $title ); + if ( $firstRevisionId === null ) { + return; } - return $wikitext; - } - /** - * get comments for the given page - * - * @param int $assoc_page_id ID of page to get comments for - * @return array array of comments for the given page - */ - public static function getAssociatedComments( $assoc_page_id ) { - $dbr = wfGetDB( DB_REPLICA ); - $result = $dbr->select( - 'cs_comment_data', - [ - 'cst_page_id' - ], - [ - 'cst_assoc_page_id' => $assoc_page_id - ], - __METHOD__ - ); - $comments = []; - foreach ( $result as $row ) { - $page_id = $row->cst_page_id; - $wikipage = WikiPage::newFromId( $page_id ); - $comment = self::newFromWikiPage( $wikipage ); - if ( $comment !== null ) { - $comments[] = $comment; - } + $latestRevisionId = $title->getLatestRevId(); + if ( $firstRevisionId === $latestRevisionId ) { + return; } - return $comments; - } - /** - * get replies for the given comment - * - * @param int $parent_page_id ID of page to get comments for - * @return array array of comments for the given page - */ - public static function getReplies( $parent_page_id ) { - $dbr = wfGetDB( DB_REPLICA ); - $result = $dbr->select( - 'cs_comment_data', - [ - 'cst_page_id' - ], - [ - 'cst_parent_page_id' => $parent_page_id - ], - __METHOD__ - ); - $comments = []; - foreach ( $result as $row ) { - $page_id = $row->cst_page_id; - $wikipage = WikiPage::newFromId( $page_id ); - $comment = self::newFromWikiPage( $wikipage ); - if ( $comment !== null ) { - $comments[] = $comment; - } + $timestamp = CommentStreamsUtils::getTimestampFromId( $latestRevisionId, $title ); + if ( $timestamp !== false ) { + $this->modification_timestamp = MWTimestamp::getLocalInstance( $timestamp ); } - return $comments; } /** @@ -933,31 +548,33 @@ EOT; * * @param User $user the user * @param bool $linked whether to link the display name to the user page, - * if it exists + * if it exists * @return string display name for user */ - public static function getDisplayNameFromUser( $user, $linked = true ) { + private function getDisplayNameFromUser( + User $user, + bool $linked + ) : string { if ( $user->isAnon() ) { - $html = Html::openElement( 'span', [ + return Html::openElement( 'span', [ 'class' => 'cs-comment-author-anonymous' ] ) . wfMessage( 'commentstreams-author-anonymous' ) . Html::closeElement( 'span' ); - return $html; } $userpage = $user->getUserPage(); $displayname = null; - if ( $GLOBALS['wgCommentStreamsUserRealNamePropertyName'] !== null ) { - $displayname = self::getUserProperty( $user, - $GLOBALS['wgCommentStreamsUserRealNamePropertyName'] ); + if ( $this->userRealNamePropertyName !== null ) { + $displayname = $this->smwInterface->getUserProperty( + $user, + $this->userRealNamePropertyName + ); } if ( $displayname === null || strlen( $displayname ) == 0 ) { - if ( class_exists( 'PageProps' ) ) { - $values = \PageProps::getInstance()->getProperties( $userpage, - 'displaytitle' ); - if ( array_key_exists( $userpage->getArticleID(), $values ) ) { - $displayname = $values[$userpage->getArticleID()]; - } + $values = PageProps::getInstance()->getProperties( $userpage, + 'displaytitle' ); + if ( array_key_exists( $userpage->getArticleID(), $values ) ) { + $displayname = $values[$userpage->getArticleID()]; } } if ( $displayname === null || strlen( $displayname ) == 0 ) { @@ -967,95 +584,8 @@ EOT; $displayname = $user->getName(); } if ( $linked && $userpage->exists() ) { - $displayname = CommentStreamsUtils::link( $userpage, $displayname ); + $displayname = $this->linkRenderer->makeLink( $userpage, $displayname ); } return $displayname; } - - /** - * return the name of the file page containing the user's avatar - * - * @param User $user the user - * @return string URL of avatar - */ - public static function getAvatarFromUser( $user ) { - $avatar = null; - if ( $GLOBALS['wgCommentStreamsUserAvatarPropertyName'] !== null ) { - $avatar = self::getUserProperty( $user, - $GLOBALS['wgCommentStreamsUserAvatarPropertyName'] ); - if ( $avatar !== null ) { - if ( gettype( $avatar ) === 'string' ) { - $avatar = Title::newFromText( $avatar ); - if ( $avatar === null ) { - return null; - } - } - if ( !get_class( $avatar ) === 'Title' ) { - return null; - } - if ( $avatar->isKnown() && $avatar->getNamespace() === NS_FILE ) { - if ( method_exists( MediaWikiServices::class, 'getRepoGroup' ) ) { - // MediaWiki 1.34+ - $file = MediaWikiServices::getInstance()->getRepoGroup() - ->findFile( $avatar ); - } else { - $file = wfFindFile( $avatar ); - } - if ( $file ) { - return $file->getFullUrl(); - } - } - } - } - return null; - } - - /** - * return the value of a property on a user page - * - * @param User $user the user - * @param string $propertyName the name of the property - * @return string|null the value of the property - */ - private static function getUserProperty( $user, $propertyName ) { - if ( defined( 'SMW_VERSION' ) ) { - $userpage = $user->getUserPage(); - if ( $userpage->exists() ) { - $store = \SMW\StoreFactory::getStore(); - $subject = \SMWDIWikiPage::newFromTitle( $userpage ); - $data = $store->getSemanticData( $subject ); - $property = \SMWDIProperty::newFromUserLabel( $propertyName ); - $values = $data->getPropertyValues( $property ); - if ( count( $values ) > 0 ) { - // this property should only have one value so pick the first one - $value = $values[0]; - if ( ( defined( 'SMWDataItem::TYPE_STRING' ) && - $value->getDIType() == SMWDataItem::TYPE_STRING ) || - $value->getDIType() == SMWDataItem::TYPE_BLOB ) { - return $value->getString(); - } elseif ( $value->getDIType() == SMWDataItem::TYPE_WIKIPAGE ) { - return $value->getTitle(); - } - } - } - } - return null; - } - - /** - * Used by Echo to locate the users watching a comment being replied to. - * @param EchoEvent $event the Echo event - * @return array array mapping user id to User object - */ - public static function locateUsersWatchingComment( $event ) { - $id = $event->getExtraParam( 'parent_id' ); - $wikipage = WikiPage::newFromId( $id ); - if ( $wikipage !== null ) { - $comment = self::newFromWikiPage( $wikipage ); - if ( $comment !== null ) { - return $comment->getWatchers(); - } - } - return []; - } } diff --git a/CommentStreams/includes/CommentStreamsAllComments.php b/CommentStreams/includes/CommentStreamsAllComments.php index c11810e7..17ca75a3 100644 --- a/CommentStreams/includes/CommentStreamsAllComments.php +++ b/CommentStreams/includes/CommentStreamsAllComments.php @@ -25,31 +25,34 @@ namespace MediaWiki\Extension\CommentStreams; use Html; +use MediaWiki\MediaWikiServices; +use MWException; use SpecialPage; -use Title; -use WikiPage; class CommentStreamsAllComments extends SpecialPage { - public function __construct() { parent::__construct( 'CommentStreamsAllComments' ); } /** * @inheritDoc + * @throws MWException */ - public function execute( $par ) { + public function execute( $subPage ) { $request = $this->getRequest(); $this->setHeaders(); $this->getOutput()->addModuleStyles( 'ext.CommentStreamsAllComments' ); - $offset = $request->getText( 'offset', 0 ); + $commentStreamsStore = + MediaWikiServices::getInstance()->getService( 'CommentStreamsStore' ); + + $offset = $request->getText( 'offset', '0' ); $limit = 20; - $pages = self::getCommentPages( $limit + 1, $offset ); + $pages = $commentStreamsStore->getCommentPages( $limit + 1, $offset ); if ( !$pages->valid() ) { $offset = 0; - $pages = self::getCommentPages( $limit + 1, $offset ); + $pages = $commentStreamsStore->getCommentPages( $limit + 1, $offset ); if ( !$pages->valid() ) { $this->displayMessage( wfMessage( 'commentstreams-allcomments-nocommentsfound' ) @@ -75,21 +78,26 @@ class CommentStreamsAllComments extends SpecialPage { '!' . wfMessage( 'commentstreams-allcomments-label-created' ) . PHP_EOL; $wikitext .= '!' . wfMessage( 'commentstreams-allcomments-label-lastedited' ) . PHP_EOL; + $wikitext .= + '!' . wfMessage( 'commentstreams-allcomments-label-blockid' ) . PHP_EOL; + + $commentStreamsFactory = + MediaWikiServices::getInstance()->getService( 'CommentStreamsFactory' ); $index = 0; $more = false; foreach ( $pages as $page ) { if ( $index < $limit ) { - $wikipage = WikiPage::newFromId( $page->page_id ); - $comment = Comment::newFromWikiPage( $wikipage ); + $wikipage = CommentStreamsUtils::newWikiPageFromId( $page->page_id ); + $comment = $commentStreamsFactory->newFromWikiPage( $wikipage ); if ( $comment !== null ) { - $pagename = $comment->getWikiPage()->getTitle()->getPrefixedText(); + $pagename = $comment->getTitle()->getPrefixedText(); $associatedpageid = $comment->getAssociatedId(); - $associatedpage = WikiPage::newFromId( $associatedpageid ); + $associatedpage = CommentStreamsUtils::newWikiPageFromId( $associatedpageid ); if ( $associatedpage !== null ) { $associatedpagename = '[[' . $associatedpage->getTitle()->getPrefixedText() . ']]'; - $author = $comment->getUser(); + $author = $comment->getAuthor(); if ( $author->isAnon() ) { $author = '<i>' . wfMessage( 'commentstreams-author-anonymous' ) . '</i>'; @@ -99,10 +107,10 @@ class CommentStreamsAllComments extends SpecialPage { $modificationdate = $comment->getModificationDate(); if ( $modificationdate === null ) { $lasteditor = ''; + $modificationdate = ''; } else { - $lasteditor = - \User::newFromId( $wikipage->getRevision()->getUser() ); - if ( $lasteditor->isAnon() ) { + $lasteditor = $comment->getLastEditor(); + if ( $lasteditor->getId() === 0 ) { $lasteditor = '<i>' . wfMessage( 'commentstreams-author-anonymous' ) . '</i>'; } else { @@ -113,11 +121,12 @@ class CommentStreamsAllComments extends SpecialPage { $wikitext .= '|[[' . $pagename . ']]' . PHP_EOL; $wikitext .= '| ' . $associatedpagename . PHP_EOL; $wikitext .= '| ' . $comment->getCommentTitle() . PHP_EOL; - $wikitext .= '| ' . $comment->getWikiText() . PHP_EOL; + $wikitext .= '| ' . htmlentities( $comment->getWikiText() ) . PHP_EOL; $wikitext .= '| ' . $author . PHP_EOL; $wikitext .= '| ' . $lasteditor . PHP_EOL; $wikitext .= '| ' . $comment->getCreationDate() . PHP_EOL; $wikitext .= '| ' . $modificationdate . PHP_EOL; + $wikitext .= '| ' . $comment->getBlockId() . PHP_EOL; $index++; } } @@ -127,17 +136,16 @@ class CommentStreamsAllComments extends SpecialPage { } $wikitext .= '|}' . PHP_EOL; - if ( method_exists( 'OutputPage', 'addWikiTextAsInterface' ) ) { - $this->getOutput()->addWikiTextAsInterface( $wikitext ); - } else { - $this->getOutput()->addWikiText( $wikitext ); - } + CommentStreamsUtils::addWikiTextToOutputPage( $wikitext, $this->getOutput() ); if ( $offset > 0 || $more ) { $this->addTableNavigation( $offset, $more, $limit, 'offset' ); } } + /** + * @param string $message + */ private function displayMessage( $message ) { $html = Html::openElement( 'p', [ 'class' => 'csall-message' @@ -147,10 +155,13 @@ class CommentStreamsAllComments extends SpecialPage { $this->getOutput()->addHtml( $html ); } + /** + * @param int $offset + * @param bool $more + * @param int $limit + * @param string $paramname + */ private function addTableNavigation( $offset, $more, $limit, $paramname ) { - $title = Title::newFromText( 'Special:' . __CLASS__ ); - $url = $title->getFullURL(); - $html = Html::openElement( 'table', [ 'class' => 'csall-navigationtable' ] ) @@ -158,7 +169,7 @@ class CommentStreamsAllComments extends SpecialPage { . Html::openElement( 'td' ); if ( $offset > 0 ) { - $prevurl = $url . '?' . $paramname . '=' . ( $offset - $limit ); + $prevurl = $this->getFullTitle()->getFullURL( [ $paramname => ( $offset - $limit ) ] ); $html .= Html::openElement( 'a', [ 'href' => $prevurl, 'class' => 'csall-button' @@ -173,7 +184,7 @@ class CommentStreamsAllComments extends SpecialPage { ] ); if ( $more ) { - $nexturl = $url . '?' . $paramname . '=' . ( $offset + $limit ); + $nexturl = $this->getFullTitle()->getFullURL( [ $paramname => ( $offset + $limit ) ] ); $html .= Html::openElement( 'a', [ 'href' => $nexturl, 'class' => 'csall-button' @@ -187,29 +198,4 @@ class CommentStreamsAllComments extends SpecialPage { . Html::closeElement( 'table' ); $this->getOutput()->addHtml( $html ); } - - private static function getCommentPages( $limit, $offset ) { - $dbr = wfGetDB( DB_REPLICA ); - $pages = $dbr->select( - [ - 'cs_comment_data', - 'page', - 'revision' - ], - [ - 'page_id' - ], - [ - 'cst_page_id = page_id', - 'page_latest = rev_id' - ], - __METHOD__, - [ - 'ORDER BY' => 'rev_timestamp DESC' , - 'LIMIT' => $limit, - 'OFFSET' => $offset - ] - ); - return $pages; - } } diff --git a/CommentStreams/includes/CommentStreamsEchoInterface.php b/CommentStreams/includes/CommentStreamsEchoInterface.php new file mode 100644 index 00000000..255473dc --- /dev/null +++ b/CommentStreams/includes/CommentStreamsEchoInterface.php @@ -0,0 +1,173 @@ +<?php + +/* + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +namespace MediaWiki\Extension\CommentStreams; + +use EchoEvent; +use ExtensionRegistry; +use MediaWiki\MediaWikiServices; +use MWException; +use PageProps; +use User; +use WikiPage; + +class CommentStreamsEchoInterface { + /** + * @var bool + */ + private $isLoaded; + + /** + * @param ExtensionRegistry $extensionRegistry + */ + public function __construct( + ExtensionRegistry $extensionRegistry + ) { + $this->isLoaded = $extensionRegistry->isLoaded( 'Echo' ); + } + + /** + * @return bool + */ + public function isLoaded() : bool { + return $this->isLoaded; + } + + /** + * Send Echo notifications if Echo is installed. + * + * @param Comment $comment the comment to send notifications for + * @param WikiPage $associated_page the associated page for the comment + * @param User $user + * @param string $comment_title + * @throws MWException + */ + public function sendNotifications( + Comment $comment, + WikiPage $associated_page, + User $user, + string $comment_title + ) { + if ( !$this->isLoaded ) { + return; + } + + $associated_page_display_title = + $associated_page->getTitle()->getPrefixedText(); + $associated_title = $associated_page->getTitle(); + $values = PageProps::getInstance()->getProperties( $associated_title, + 'displaytitle' ); + if ( array_key_exists( $associated_title->getArticleID(), $values ) ) { + $associated_page_display_title = + $values[$associated_title->getArticleID()]; + } + + $extra = [ + 'comment_id' => $comment->getId(), + 'parent_id' => $comment->getParentId(), + 'comment_author_username' => $comment->getUsername(), + 'comment_author_display_name' => $comment->getUserDisplayNameUnlinked(), + 'comment_title' => $comment_title, + 'associated_page_display_title' => $associated_page_display_title, + 'comment_wikitext' => $comment->getWikitext() + ]; + + if ( $comment->getParentId() !== null ) { + EchoEvent::create( [ + 'type' => 'commentstreams-reply-on-watched-page', + 'title' => $associated_page->getTitle(), + 'extra' => $extra, + 'agent' => $user + ] ); + EchoEvent::create( [ + 'type' => 'commentstreams-reply-to-watched-comment', + 'title' => $associated_page->getTitle(), + 'extra' => $extra, + 'agent' => $user + ] ); + } else { + EchoEvent::create( [ + 'type' => 'commentstreams-comment-on-watched-page', + 'title' => $associated_page->getTitle(), + 'extra' => $extra, + 'agent' => $user + ] ); + } + } + + /** + * Used by Echo to locate the users watching a comment being replied to. + * @param EchoEvent $event the Echo event + * @return array array mapping user id to User object + */ + public static function locateUsersWatchingComment( EchoEvent $event ) : array { + $id = $event->getExtraParam( 'parent_id' ); + if ( $id === null ) { + $id = $event->getExtraParam( 'comment_id' ); + } + return MediaWikiServices::getInstance()->getService( 'CommentStreamsStore' )-> + getWatchers( $id ); + } + + /** + * @param array &$notifications notifications + * @param array &$notificationCategories notification categories + * @param array &$icons notification icons + * @noinspection PhpUnusedParameterInspection + */ + public static function onBeforeCreateEchoEvent( + array &$notifications, + array &$notificationCategories, + array &$icons + ) { + $notificationCategories['commentstreams-notification-category'] = [ + 'priority' => 3 + ]; + + $notifications['commentstreams-comment-on-watched-page'] = [ + 'category' => 'commentstreams-notification-category', + 'group' => 'positive', + 'section' => 'alert', + 'presentation-model' => EchoCSPresentationModel::class, + 'user-locators' => [ 'EchoUserLocator::locateUsersWatchingTitle' ] + ]; + + $notifications['commentstreams-reply-on-watched-page'] = [ + 'category' => 'commentstreams-notification-category', + 'group' => 'positive', + 'section' => 'alert', + 'presentation-model' => EchoCSPresentationModel::class, + 'user-locators' => [ 'EchoUserLocator::locateUsersWatchingTitle' ], + 'user-filters' => + [ '\MediaWiki\Extension\CommentStreams\CommentStreamsEchoInterface::locateUsersWatchingComment' ] + ]; + + $notifications['commentstreams-reply-to-watched-comment'] = [ + 'category' => 'commentstreams-notification-category', + 'group' => 'positive', + 'section' => 'alert', + 'presentation-model' => EchoCSPresentationModel::class, + 'user-locators' => + [ '\MediaWiki\Extension\CommentStreams\CommentStreamsEchoInterface::locateUsersWatchingComment' ] + ]; + } +} diff --git a/CommentStreams/includes/CommentStreamsFactory.php b/CommentStreams/includes/CommentStreamsFactory.php new file mode 100644 index 00000000..a5f331df --- /dev/null +++ b/CommentStreams/includes/CommentStreamsFactory.php @@ -0,0 +1,193 @@ +<?php + +/* + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +namespace MediaWiki\Extension\CommentStreams; + +use ConfigException; +use MediaWiki\Linker\LinkRenderer; +use MWException; +use User; +use Wikimedia\Assert\Assert; +use WikiPage; + +class CommentStreamsFactory { + /** + * @var \MediaWiki\Config\ServiceOptions|\Config + */ + private $options; + + /** + * @var CommentStreamsStore + */ + private $commentStreamsStore; + + /** + * @var CommentStreamsEchoInterface + */ + private $echoInterface; + + /** + * @var CommentStreamsSMWInterface + */ + private $smwInterface; + + /** + * @var CommentStreamsSocialProfileInterface + */ + private $socialProfileInterface; + + /** + * @var LinkRenderer + */ + private $linkRenderer; + + /** + * @param \MediaWiki\Config\ServiceOptions|\Config $options + * @param CommentStreamsStore $commentStreamsStore + * @param CommentStreamsEchoInterface $echoInterface + * @param CommentStreamsSMWInterface $smwInterface + * @param CommentStreamsSocialProfileInterface $socialProfileInterface + * @param LinkRenderer $linkRenderer + */ + public function __construct( + $options, + CommentStreamsStore $commentStreamsStore, + CommentStreamsEchoInterface $echoInterface, + CommentStreamsSMWInterface $smwInterface, + CommentStreamsSocialProfileInterface $socialProfileInterface, + LinkRenderer $linkRenderer + ) { + $this->options = $options; + $this->commentStreamsStore = $commentStreamsStore; + $this->echoInterface = $echoInterface; + $this->smwInterface = $smwInterface; + $this->socialProfileInterface = $socialProfileInterface; + $this->linkRenderer = $linkRenderer; + } + + /** + * create a new Comment object from existing wiki page + * + * @param WikiPage $wikipage WikiPage object corresponding to comment page + * @return Comment|null the newly created comment or null if there was an + * error + * @throws MWException + * @throws ConfigException + */ + public function newFromWikiPage( WikiPage $wikipage ) : ?Comment { + if ( $wikipage->getTitle()->getNamespace() !== NS_COMMENTSTREAMS || !$wikipage->exists() ) { + return null; + } + + $result = $this->commentStreamsStore->getComment( $wikipage->getId() ); + if ( $result === null ) { + return null; + } + $comment_title = $result['comment_title']; + $wikitext = $this->commentStreamsStore->getWikiText( $wikipage, $comment_title ); + return new Comment( + $this->options, + $this->commentStreamsStore, + $this->echoInterface, + $this->smwInterface, + $this->socialProfileInterface, + $this->linkRenderer, + $wikipage, + $result['comment_block_id'], + $result['assoc_page_id'], + $result['parent_page_id'], + $comment_title, + $wikitext + ); + } + + /** + * create a new Comment object from values and save to database + * NOTE: since only head comments can contain a comment title, either + * $comment_title or $parent_page_id must be non null, but not both + * + * @param ?string $comment_block_id unique id to identify comment block in a page + * @param int $assoc_page_id page ID for the wiki page this comment is on + * @param ?int $parent_page_id page ID for the wiki page this comment is in + * reply to or null + * @param ?string $comment_title string title of comment + * @param string $wikitext the wikitext to add + * @param User $user the user + * @return Comment|null new comment object or null if there was a problem + * creating it + * @throws MWException + * @throws ConfigException + */ + public function newFromValues( + ?string $comment_block_id, + int $assoc_page_id, + ?int $parent_page_id, + ?string $comment_title, + string $wikitext, + User $user + ) : ?Comment { + Assert::parameter( + ( $comment_title === null && $parent_page_id !== null ) || + ( $comment_title !== null && $parent_page_id === null ), + '$comment_title', + 'must be null if parent page ID is non-null or non-null if parent page ID is null' + ); + + $wikipage = $this->commentStreamsStore->insertComment( + $user, + $wikitext, + $comment_block_id, + $assoc_page_id, + $parent_page_id, + $comment_title + ); + + if ( !$wikipage ) { + return null; + } + + $comment = new Comment( + $this->options, + $this->commentStreamsStore, + $this->echoInterface, + $this->smwInterface, + $this->socialProfileInterface, + $this->linkRenderer, + $wikipage, + $comment_block_id, + $assoc_page_id, + $parent_page_id, + $comment_title, + $wikitext + ); + + $this->smwInterface->update( $wikipage->getTitle() ); + + if ( $parent_page_id === null ) { + $this->commentStreamsStore->watch( $wikipage->getId(), $user->getId() ); + } else { + $this->commentStreamsStore->watch( $parent_page_id, $user->getId() ); + } + + return $comment; + } +} diff --git a/CommentStreams/includes/CommentStreams.php b/CommentStreams/includes/CommentStreamsHandler.php index d7426969..54f7302c 100644 --- a/CommentStreams/includes/CommentStreams.php +++ b/CommentStreams/includes/CommentStreamsHandler.php @@ -23,31 +23,55 @@ namespace MediaWiki\Extension\CommentStreams; +use Action; +use ConfigException; use ExtensionRegistry; -use MWNamespace; - -class CommentStreams { - - // CommentStreams singleton instance - private static $instance = null; +use MWException; +use OutputPage; +class CommentStreamsHandler { const COMMENTS_ENABLED = 1; const COMMENTS_DISABLED = -1; const COMMENTS_INHERITED = 0; - // no CommentStreams flag + /** + * no CommentStreams flag + */ private $areCommentsEnabled = self::COMMENTS_INHERITED; /** - * create a CommentStreams singleton instance - * - * @return CommentStreams a singleton CommentStreams instance + * @var bool true if enabled due to wgCommentStreamsAllowedNamespaces */ - public static function singleton() { - if ( self::$instance === null ) { - self::$instance = new CommentStreams(); - } - return self::$instance; + private $isNamespaceEnabled = false; + + /** + * @var CommentStreamsFactory + */ + private $commentStreamsFactory; + + /** + * @var CommentStreamsStore + */ + private $commentStreamsStore; + + /** + * @var CommentStreamsEchoInterface + */ + private $echoInterface; + + /** + * @param CommentStreamsFactory $commentStreamsFactory + * @param CommentStreamsStore $commentStreamsStore + * @param CommentStreamsEchoInterface $echoInterface + */ + public function __construct( + CommentStreamsFactory $commentStreamsFactory, + CommentStreamsStore $commentStreamsStore, + CommentStreamsEchoInterface $echoInterface + ) { + $this->commentStreamsFactory = $commentStreamsFactory; + $this->commentStreamsStore = $commentStreamsStore; + $this->echoInterface = $echoInterface; } /** @@ -64,7 +88,9 @@ class CommentStreams { $this->areCommentsEnabled = self::COMMENTS_DISABLED; } - // initially collapse CommentStreams flag + /** + * initially collapse CommentStreams flag + */ private $initiallyCollapseCommentStreams = false; /** @@ -79,8 +105,10 @@ class CommentStreams { * initializes the display of comments * * @param OutputPage $output OutputPage object + * @throws ConfigException + * @throws MWException */ - public function init( $output ) { + public function init( OutputPage $output ) { if ( $this->checkDisplayComments( $output ) ) { $comments = $this->getComments( $output ); $this->initJS( $output, $comments ); @@ -92,23 +120,27 @@ class CommentStreams { * * @param OutputPage $output the OutputPage object * @return bool true if comments should be displayed on this page + * @throws ConfigException */ - private function checkDisplayComments( $output ) { + private function checkDisplayComments( OutputPage $output ) : bool { // don't display comments on this page if they are explicitly disabled if ( $this->areCommentsEnabled === self::COMMENTS_DISABLED ) { return false; } // don't display comments on any page action other than view action - if ( \Action::getActionName( $output->getContext() ) !== "view" ) { + if ( Action::getActionName( $output->getContext() ) !== "view" ) { return false; } // if $wgCommentStreamsAllowedNamespaces is not set, display comments - // in all content namespaces - $csAllowedNamespaces = $GLOBALS['wgCommentStreamsAllowedNamespaces']; + // in all content namespaces and if set to -1, don't display comments + $config = $output->getConfig(); + $csAllowedNamespaces = $config->get( 'CommentStreamsAllowedNamespaces' ); if ( $csAllowedNamespaces === null ) { - $csAllowedNamespaces = $GLOBALS['wgContentNamespaces']; + $csAllowedNamespaces = $config->get( 'ContentNamespaces' ); + } elseif ( $csAllowedNamespaces === self::COMMENTS_DISABLED ) { + return false; } elseif ( !is_array( $csAllowedNamespaces ) ) { $csAllowedNamespaces = [ $csAllowedNamespaces ]; } @@ -131,6 +163,12 @@ class CommentStreams { return false; } + // if this namespace is one of the explicitly allowed namespace, set flag to enable + // default comment block + if ( in_array( $namespace, $csAllowedNamespaces ) ) { + $this->isNamespaceEnabled = true; + } + // display comments on this page if they are explicitly enabled if ( $this->areCommentsEnabled === self::COMMENTS_ENABLED ) { return true; @@ -143,18 +181,14 @@ class CommentStreams { // 3) comments have been explicitly enabled on that namespace with // <comment-streams/> if ( $title->isTalkPage() ) { - $subject_namespace = MWNamespace::getSubject( $namespace ); - if ( !$GLOBALS['wgCommentStreamsEnableTalk'] && + $subject_namespace = CommentStreamsUtils::getSubjectNamespace( $namespace ); + if ( !$config->get( 'CommentStreamsEnableTalk' ) && !in_array( $subject_namespace, $csAllowedNamespaces ) ) { return false; } - } elseif ( !in_array( $namespace, $csAllowedNamespaces ) ) { - // only display comments in subject namespaces in the list of allowed - // namespaces - return false; } - return true; + return $this->isNamespaceEnabled; } /** @@ -162,26 +196,43 @@ class CommentStreams { * * @param OutputPage $output the OutputPage object for the current page * @return Comment[] array of comments + * @throws MWException + * @throws ConfigException */ - private function getComments( $output ) { + private function getComments( OutputPage $output ) : array { $commentData = []; $pageId = $output->getTitle()->getArticleID(); - $allComments = Comment::getAssociatedComments( $pageId ); - $parentComments = $this->getDiscussions( $allComments, - $GLOBALS['wgCommentStreamsNewestStreamsOnTop'], - $GLOBALS['wgCommentStreamsEnableVoting'] ); + $comment_page_ids = $this->commentStreamsStore->getAssociatedComments( $pageId ); + $allComments = []; + foreach ( $comment_page_ids as $id ) { + $wikipage = CommentStreamsUtils::newWikiPageFromId( $id ); + if ( $wikipage !== null ) { + $comment = $this->commentStreamsFactory->newFromWikiPage( $wikipage ); + if ( $comment !== null ) { + $allComments[] = $comment; + } + } + } + + $config = $output->getConfig(); + $newestStreamsOnTop = $config->get( 'CommentStreamsNewestStreamsOnTop' ); + $votingEnabled = $config->get( 'CommentStreamsEnableVoting' ); + $parentComments = $this->getDiscussions( + $allComments, + $newestStreamsOnTop, + $votingEnabled + ); foreach ( $parentComments as $parentComment ) { - $parentJSON = $parentComment->getJSON(); - if ( $GLOBALS['wgCommentStreamsEnableVoting'] ) { + $parentJSON = $parentComment->getJSON( $output ); + if ( $votingEnabled ) { $parentJSON['vote'] = $parentComment->getVote( $output->getUser() ); } - if ( ExtensionRegistry::getInstance()->isLoaded( 'Echo' ) ) { + if ( $this->echoInterface->isLoaded() ) { $parentJSON['watching'] = $parentComment->isWatching( $output->getUser() ); } - $childComments = $this->getReplies( $allComments, - $parentComment->getId() ); + $childComments = $this->getReplies( $allComments, $parentComment->getId() ); foreach ( $childComments as $childComment ) { - $childJSON = $childComment->getJSON(); + $childJSON = $childComment->getJSON( $output ); $parentJSON['children'][] = $childJSON; } $commentData[] = $parentJSON; @@ -194,50 +245,45 @@ class CommentStreams { * * @param OutputPage $output the OutputPage object * @param Comment[] $comments array of comments on the current page + * @throws ConfigException */ - private function initJS( $output, $comments ) { + private function initJS( OutputPage $output, array $comments ) { // determine if comments should be initially collapsed or expanded // if the namespace is a talk namespace, use state of its subject namespace $title = $output->getTitle(); $namespace = $title->getNamespace(); if ( $title->isTalkPage() ) { - $namespace = MWNamespace::getSubject( $namespace ); + $namespace = CommentStreamsUtils::getSubjectNamespace( $namespace ); } + $config = $output->getConfig(); + if ( $this->initiallyCollapseCommentStreams ) { $initiallyCollapsed = true; } else { - $initiallyCollapsed = in_array( $namespace, - $GLOBALS['wgCommentStreamsInitiallyCollapsedNamespaces'] ); + $initiallyCollapsedNamespaces = + $config->get( 'CommentStreamsInitiallyCollapsedNamespaces' ); + $initiallyCollapsed = in_array( $namespace, $initiallyCollapsedNamespaces ); } $canComment = true; - if ( !in_array( 'cs-comment', $output->getUser()->getRights() ) || - $output->getUser()->isBlocked() ) { + if ( !CommentStreamsUtils::userHasRight( $output->getUser(), 'cs-comment' ) ) { $canComment = false; } $commentStreamsParams = [ 'canComment' => $canComment, - 'moderatorEdit' => in_array( 'cs-moderator-edit', - $output->getUser()->getRights() ), - 'moderatorDelete' => in_array( 'cs-moderator-delete', - $output->getUser()->getRights() ), - 'moderatorFastDelete' => - $GLOBALS['wgCommentStreamsModeratorFastDelete'] ? 1 : 0, - 'showLabels' => - $GLOBALS['wgCommentStreamsShowLabels'] ? 1 : 0, - 'userDisplayName' => - Comment::getDisplayNameFromUser( $output->getUser() ), - 'userAvatar' => - Comment::getAvatarFromUser( $output->getUser() ), - 'newestStreamsOnTop' => - $GLOBALS['wgCommentStreamsNewestStreamsOnTop'] ? 1 : 0, + 'moderatorEdit' => CommentStreamsUtils::userHasRight( $output->getUser(), + 'cs-moderator-edit' ), + 'moderatorDelete' => CommentStreamsUtils::userHasRight( $output->getUser(), + 'cs-moderator-delete' ), + 'moderatorFastDelete' => $config->get( 'CommentStreamsModeratorFastDelete' ) ? 1 : 0, + 'showLabels' => $config->get( 'CommentStreamsShowLabels' ) ? 1 : 0, + 'newestStreamsOnTop' => $config->get( 'CommentStreamsNewestStreamsOnTop' ) ? 1 : 0, 'initiallyCollapsed' => $initiallyCollapsed, - 'enableVoting' => - $GLOBALS['wgCommentStreamsEnableVoting'] ? 1 : 0, - 'enableWatchlist' => - ExtensionRegistry::getInstance()->isLoaded( 'Echo' ) ? 1 : 0, + 'isNamespaceEnabled' => $this->isNamespaceEnabled, + 'enableVoting' => $config->get( 'CommentStreamsEnableVoting' ) ? 1 : 0, + 'enableWatchlist' => $this->echoInterface->isLoaded() ? 1 : 0, 'comments' => $comments ]; $output->addJsConfigVars( 'CommentStreams', $commentStreamsParams ); @@ -256,9 +302,13 @@ class CommentStreams { * @return array an array of all discussions * oldest */ - private function getDiscussions( $allComments, $newestOnTop, $enableVoting ) { + private function getDiscussions( + array $allComments, + bool $newestOnTop, + bool $enableVoting + ) : array { $array = array_filter( - $allComments, function ( $comment ) { + $allComments, static function ( $comment ) { return $comment->getParentId() === null; } ); @@ -266,11 +316,11 @@ class CommentStreams { $date1 = $comment1->getCreationTimestamp()->timestamp; $date2 = $comment2->getCreationTimestamp()->timestamp; if ( $enableVoting ) { - $upvotes1 = $comment1->getNumUpVotes(); - $downvotes1 = $comment1->getNumDownVotes(); + $upvotes1 = $this->commentStreamsStore->getNumUpVotes( $comment1->getId() ); + $downvotes1 = $this->commentStreamsStore->getNumDownVotes( $comment1->getId() ); $votediff1 = $upvotes1 - $downvotes1; - $upvotes2 = $comment2->getNumUpVotes(); - $downvotes2 = $comment2->getNumDownVotes(); + $upvotes2 = $this->commentStreamsStore->getNumUpVotes( $comment2->getId() ); + $downvotes2 = $this->commentStreamsStore->getNumDownVotes( $comment2->getId() ); $votediff2 = $upvotes2 - $downvotes2; if ( $votediff1 === $votediff2 ) { if ( $upvotes1 === $upvotes2 ) { @@ -303,9 +353,9 @@ class CommentStreams { * @param int $parentId the page ID of the discussion to get replies for * @return array an array of replies for the given discussion */ - private function getReplies( $allComments, $parentId ) { + private function getReplies( array $allComments, int $parentId ) : array { $array = array_filter( - $allComments, function ( $comment ) use ( $parentId ) { + $allComments, static function ( $comment ) use ( $parentId ) { if ( $comment->getParentId() === $parentId ) { return true; } @@ -313,7 +363,7 @@ class CommentStreams { } ); usort( - $array, function ( $comment1, $comment2 ) { + $array, static function ( $comment1, $comment2 ) { $date1 = $comment1->getCreationTimestamp()->timestamp; $date2 = $comment2->getCreationTimestamp()->timestamp; return $date1 < $date2 ? -1 : 1; diff --git a/CommentStreams/includes/CommentStreamsHooks.php b/CommentStreams/includes/CommentStreamsHooks.php index 897ce9c8..5dcf727e 100644 --- a/CommentStreams/includes/CommentStreamsHooks.php +++ b/CommentStreams/includes/CommentStreamsHooks.php @@ -26,14 +26,14 @@ namespace MediaWiki\Extension\CommentStreams; use Article; use DatabaseUpdater; use MediaWiki; +use MediaWiki\MediaWikiServices; +use MWException; use OutputPage; +use PageProps; use Parser; use PPFrame; use SearchResult; use Skin; -use SMW\DIWikiPage; -use SMW\DIProperty; -use SMW\PropertyRegistry; use SpecialSearch; use Status; use Title; @@ -42,7 +42,6 @@ use WebRequest; use WikiPage; class CommentStreamsHooks { - /** * Implements LoadExtensionSchemaUpdates hook. * See https://www.mediawiki.org/wiki/Manual:Hooks/LoadExtensionSchemaUpdates @@ -51,9 +50,8 @@ class CommentStreamsHooks { * @param DatabaseUpdater $updater database updater * @return bool continue checking hooks */ - public static function addCommentTableToDatabase( DatabaseUpdater $updater ) { - $dir = $GLOBALS['wgExtensionDirectory'] . DIRECTORY_SEPARATOR . - 'CommentStreams' . DIRECTORY_SEPARATOR . 'sql' . DIRECTORY_SEPARATOR; + public static function addCommentTableToDatabase( DatabaseUpdater $updater ) : bool { + $dir = __DIR__ . '/../sql/'; $updater->addExtensionTable( 'cs_comment_data', $dir . 'commentData.sql' ); $updater->addExtensionTable( 'cs_votes', $dir . 'votes.sql' ); $updater->addExtensionTable( 'cs_watchlist', $dir . 'watch.sql' ); @@ -63,6 +61,8 @@ class CommentStreamsHooks { $dir . 'dropForeignKey1.sql' ); $updater->dropExtensionIndex( 'cs_comment_data', 'cst_assoc_page_id', $dir . 'dropForeignKey2.sql' ); + $updater->addExtensionField( 'cs_comment_data', 'cst_id', + $dir . 'addCommentId.sql' ); return true; } @@ -75,7 +75,7 @@ class CommentStreamsHooks { * corresponding canonical names * @return bool continue checking hooks */ - public static function addCommentStreamsNamespaces( array &$namespaces ) { + public static function addCommentStreamsNamespaces( array &$namespaces ) : bool { $namespaces[NS_COMMENTSTREAMS] = 'CommentStreams'; $namespaces[NS_COMMENTSTREAMS_TALK] = 'CommentStreams_Talk'; return true; @@ -94,10 +94,17 @@ class CommentStreamsHooks { * @param WebRequest $request WebRequest object * @param MediaWiki $wiki MediaWiki object * @return bool continue checking hooks + * @noinspection PhpUnusedParameterInspection + * @throws MWException */ - public static function onMediaWikiPerformAction( OutputPage $output, - Article $article, Title $title, User $user, WebRequest $request, - MediaWiki $wiki ) { + public static function onMediaWikiPerformAction( + OutputPage $output, + Article $article, + Title $title, + User $user, + WebRequest $request, + MediaWiki $wiki + ) : bool { if ( $title->getNamespace() !== NS_COMMENTSTREAMS ) { return true; } @@ -108,10 +115,14 @@ class CommentStreamsHooks { if ( $action !== 'view' ) { $message = wfMessage( 'commentstreams-error-prohibitedaction', $action )->text(); - $output->addHTML( '<p class="error">' . $message . '</p>' ); + $output->addHTML( '<p class="error">' . htmlentities( $message ) . '</p>' ); } + + $commentStreamsFactory = + MediaWikiServices::getInstance()->getService( 'CommentStreamsFactory' ); + $wikipage = new WikiPage( $title ); - $comment = Comment::newFromWikiPage( $wikipage ); + $comment = $commentStreamsFactory->newFromWikiPage( $wikipage ); if ( $comment !== null ) { $commentTitle = $comment->getCommentTitle(); if ( $commentTitle !== null ) { @@ -119,29 +130,25 @@ class CommentStreamsHooks { } $associatedTitle = Title::newFromId( $comment->getAssociatedId() ); if ( $associatedTitle !== null ) { - $values = []; - if ( class_exists( 'PageProps' ) ) { - $values = \PageProps::getInstance()->getProperties( $associatedTitle, - 'displaytitle' ); - } + $values = PageProps::getInstance()->getProperties( $associatedTitle, + 'displaytitle' ); if ( array_key_exists( $comment->getAssociatedId(), $values ) ) { $displaytitle = $values[$comment->getAssociatedId()]; } else { $displaytitle = $associatedTitle->getPrefixedText(); } + $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer(); $output->setSubtitle( - CommentStreamsUtils::link( $associatedTitle, '< ' . $displaytitle ) - ); + $linkRenderer->makeLink( $associatedTitle, '< ' . $displaytitle ) ); } else { $message = wfMessage( 'commentstreams-error-comment-on-deleted-page' )->text(); - $output->addHTML( '<p class="error">' . $message . '</p>' ); - } - if ( method_exists( 'OutputPage', 'addWikiTextAsInterface' ) ) { - $output->addWikiTextAsInterface( $comment->getHTML() ); - } else { - $output->addWikiText( $comment->getHTML() ); + $output->addHTML( '<p class="error">' . htmlentities( $message ) . '</p>' ); } + CommentStreamsUtils::addWikiTextToOutputPage( + $comment->getHTML( $output->getContext() ), + $output + ); } return false; } @@ -156,8 +163,11 @@ class CommentStreamsHooks { * @param Status $status Status object to pass error messages to * @return bool continue checking hooks */ - public static function onMovePageIsValidMove( Title $oldTitle, - Title $newTitle, Status $status ) { + public static function onMovePageIsValidMove( + Title $oldTitle, + Title $newTitle, + Status $status + ) : bool { if ( $oldTitle->getNamespace() === NS_COMMENTSTREAMS || $newTitle->getNamespace() === NS_COMMENTSTREAMS ) { $status->fatal( wfMessage( 'commentstreams-error-prohibitedaction', @@ -172,15 +182,19 @@ class CommentStreamsHooks { * See https://www.mediawiki.org/wiki/Manual:Hooks/userCan * Ensures that only the original author can edit a comment * - * @param Title &$title the title object in question - * @param User &$user the user performing the action + * @param Title $title the title object in question + * @param User $user the user performing the action * @param string $action the action being performed * @param bool &$result true means the user is allowed, false means the * user is not allowed, untouched means this hook has no opinion * @return bool continue checking hooks */ - public static function userCan( Title &$title, User &$user, $action, - &$result ) { + public static function userCan( + Title $title, + User $user, + string $action, + bool &$result + ) : bool { if ( $title->getNamespace() !== NS_COMMENTSTREAMS ) { return true; } @@ -191,22 +205,9 @@ class CommentStreamsHooks { return true; } - if ( $user->isBlocked() ) { - $result = false; - return false; - } - if ( $action === 'cs-comment' ) { - if ( $user->getId() === $wikipage->getOldestRevision()->getUser() ) { - $result = true; - } else { - $result = false; - } - return false; - } - - if ( $action === 'cs-moderator-edit' ) { - if ( in_array( 'cs-moderator-edit', $user->getRights() ) ) { + if ( CommentStreamsUtils::userHasRight( $user, $action ) && + $user->getId() === CommentStreamsUtils::getAuthor( $title )->getId() ) { $result = true; } else { $result = false; @@ -214,12 +215,8 @@ class CommentStreamsHooks { return false; } - if ( $action === 'cs-moderator-delete' ) { - if ( in_array( 'cs-moderator-delete', $user->getRights() ) ) { - $result = true; - } else { - $result = false; - } + if ( in_array( $action, [ 'cs-moderator-edit', 'cs-moderator-delete' ] ) ) { + $result = CommentStreamsUtils::userHasRight( $user, $action ); return false; } @@ -234,8 +231,9 @@ class CommentStreamsHooks { * * @param Parser $parser the parser * @return bool continue checking hooks + * @throws MWException */ - public static function onParserSetup( Parser $parser ) { + public static function onParserSetup( Parser $parser ) : bool { $parser->setHook( 'comment-streams', 'MediaWiki\Extension\CommentStreams\CommentStreamsHooks::enableCommentStreams' ); $parser->setHook( 'no-comment-streams', @@ -249,22 +247,30 @@ class CommentStreamsHooks { * Implements tag function, <comment-streams/>, which enables * CommentStreams on a page. * - * @param string $input input between the tags (ignored) + * @param ?string $input input between the tags (ignored) * @param array $args tag arguments * @param Parser $parser the parser * @param PPFrame $frame the parent frame * @return string to replace tag with + * @noinspection PhpUnusedParameterInspection */ - public static function enableCommentStreams( $input, array $args, - Parser $parser, PPFrame $frame ) { + public static function enableCommentStreams( + ?string $input, + array $args, + Parser $parser, + PPFrame $frame + ) : string { $parser->getOutput()->updateCacheExpiry( 0 ); - $cs = CommentStreams::singleton(); + $cs = MediaWikiServices::getInstance()->getService( 'CommentStreamsHandler' ); $cs->enableCommentsOnPage(); - if ( isset( $args['location'] ) && $args['location'] === 'footer' ) { + if ( isset( $args['id'] ) ) { + $ret = '<div class="cs-comments" id="csc_' . md5( $args['id'] ) . '"></div>'; + } elseif ( isset( $args['location'] ) && $args['location'] === 'footer' ) { $ret = ''; } else { - $ret = '<div id="cs-comments"></div>'; + $ret = '<div class="cs-comments" id="cs-comments"></div>'; } + // @phan-suppress-next-line SecurityCheck-XSS return $ret; } @@ -272,34 +278,44 @@ class CommentStreamsHooks { * Implements tag function, <no-comment-streams/>, which disables * CommentStreams on a page. * - * @param string $input input between the tags (ignored) + * @param ?string $input input between the tags (ignored) * @param array $args tag arguments * @param Parser $parser the parser * @param PPFrame $frame the parent frame * @return string to replace tag with + * @noinspection PhpUnusedParameterInspection */ - public static function disableCommentStreams( $input, array $args, - Parser $parser, PPFrame $frame ) { + public static function disableCommentStreams( + ?string $input, + array $args, + Parser $parser, + PPFrame $frame + ) : string { $parser->getOutput()->updateCacheExpiry( 0 ); - $cs = CommentStreams::singleton(); + $cs = MediaWikiServices::getInstance()->getService( 'CommentStreamsHandler' ); $cs->disableCommentsOnPage(); - return ""; + return ''; } /** * Implements tag function, <comment-streams-initially-collapsed/>, which * makes CommentStreams on a page start as collapsed when the page is viewed. * - * @param string $input input between the tags (ignored) + * @param ?string $input input between the tags (ignored) * @param array $args tag arguments * @param Parser $parser the parser * @param PPFrame $frame the parent frame * @return string to replace tag with + * @noinspection PhpUnusedParameterInspection */ - public static function initiallyCollapseCommentStreams( $input, array $args, - Parser $parser, PPFrame $frame ) { + public static function initiallyCollapseCommentStreams( + ?string $input, + array $args, + Parser $parser, + PPFrame $frame + ) : string { $parser->getOutput()->updateCacheExpiry( 0 ); - $cs = CommentStreams::singleton(); + $cs = MediaWikiServices::getInstance()->getService( 'CommentStreamsHandler' ); $cs->initiallyCollapseCommentsOnPage(); return ""; } @@ -309,13 +325,16 @@ class CommentStreamsHooks { * See https://www.mediawiki.org/wiki/Manual:Hooks/BeforePageDisplay * Gets comments for page and initializes variables to be passed to JavaScript. * - * @param OutputPage &$output OutputPage object - * @param Skin &$skin Skin object that will be used to generate the page + * @param OutputPage $output OutputPage object + * @param Skin $skin Skin object that will be used to generate the page * @return bool continue checking hooks + * @noinspection PhpUnusedParameterInspection */ - public static function addCommentsAndInitializeJS( OutputPage &$output, - Skin &$skin ) { - $cs = CommentStreams::singleton(); + public static function addCommentsAndInitializeJS( + OutputPage $output, + Skin $skin + ) : bool { + $cs = MediaWikiServices::getInstance()->getService( 'CommentStreamsHandler' ); $cs->init( $output ); return true; } @@ -327,15 +346,27 @@ class CommentStreamsHooks { * associated content page instead. * * @param Title &$title title to link to - * @param string &$text text to use for the link + * @param ?string &$text text to use for the link * @param SearchResult $result the search result * @param array $terms the search terms entered * @param SpecialSearch $page the SpecialSearch object * @return bool continue checking hooks + * @noinspection PhpUnusedParameterInspection */ - public static function showSearchHitTitle( Title &$title, &$text, - SearchResult $result, array $terms, SpecialSearch $page ) { - $comment = Comment::newFromWikiPage( WikiPage::factory( $title ) ); + public static function showSearchHitTitle( + Title &$title, + ?string &$text, + SearchResult $result, + array $terms, + SpecialSearch $page + ) : bool { + if ( $title->getNamespace() !== NS_COMMENTSTREAMS ) { + return true; + } + $commentStreamsFactory = + MediaWikiServices::getInstance()->getService( 'CommentStreamsFactory' ); + $comment = $commentStreamsFactory->newFromWikiPage( + CommentStreamsUtils::newWikiPageFromId( $title->getArticleID() ) ); if ( $comment !== null ) { $t = Title::newFromId( $comment->getAssociatedId() ); if ( $t !== null ) { @@ -346,28 +377,16 @@ class CommentStreamsHooks { } /** - * Implements SMW::Settings::BeforeInitializationComplete callback. - * See https://github.com/SemanticMediaWiki/SemanticMediaWiki/blob/master/docs/technical/hooks/hook.settings.beforeinitializationcomplete.md - * Defines CommentStreams namespace constants. - * - * @param array &$configuration An array of the configuration options - */ - public static function onSMWInitialization( array &$configuration ) { - $namespace = $GLOBALS['wgCommentStreamsNamespaceIndex']; - $configuration['smwgNamespacesWithSemanticLinks'][$namespace] = true; - } - - /** * Implements extension registration callback. * See https://www.mediawiki.org/wiki/Manual:Extension_registration#Customizing_registration * Sets configuration constants. - * */ public static function onRegistration() { define( 'NS_COMMENTSTREAMS', $GLOBALS['wgCommentStreamsNamespaceIndex'] ); - define( 'NS_COMMENTSTREAMS_TALK', - $GLOBALS['wgCommentStreamsNamespaceIndex'] + 1 ); - $GLOBALS['wgNamespacesToBeSearchedDefault'][NS_COMMENTSTREAMS] = true; + define( 'NS_COMMENTSTREAMS_TALK', $GLOBALS['wgCommentStreamsNamespaceIndex'] + 1 ); + if ( $GLOBALS['wgCommentStreamsEnableSearch'] ) { + $GLOBALS['wgNamespacesToBeSearchedDefault'][NS_COMMENTSTREAMS] = true; + } $found = false; foreach ( $GLOBALS['wgGroupPermissions'] as $groupperms ) { if ( isset( $groupperms['cs-comment'] ) ) { @@ -383,13 +402,11 @@ class CommentStreamsHooks { } } } - if ( !isset( $GLOBALS['wgGroupPermissions']['csmoderator'] - ['cs-moderator-delete'] ) ) { + if ( !isset( $GLOBALS['wgGroupPermissions']['csmoderator']['cs-moderator-delete'] ) ) { $GLOBALS['wgGroupPermissions']['csmoderator']['cs-moderator-delete'] = true; } - if ( !isset( $GLOBALS['wgGroupPermissions']['csmoderator'] - ['cs-moderator-edit'] ) ) { + if ( !isset( $GLOBALS['wgGroupPermissions']['csmoderator']['cs-moderator-edit'] ) ) { $GLOBALS['wgGroupPermissions']['csmoderator']['cs-moderator-edit'] = false; } @@ -399,125 +416,4 @@ class CommentStreamsHooks { $GLOBALS['wgLogTypes'][] = 'commentstreams'; $GLOBALS['wgLogActionsHandlers']['commentstreams/*'] = 'LogFormatter'; } - - /** - * Initialize extra Semantic MediaWiki properties. - * This won't get called unless Semantic MediaWiki is installed. - */ - public static function initProperties() { - $pr = PropertyRegistry::getInstance(); - $pr->registerProperty( '___CS_ASSOCPG', '_wpg', 'Comment on' ); - $pr->registerProperty( '___CS_REPLYTO', '_wpg', 'Reply to' ); - $pr->registerProperty( '___CS_TITLE', '_txt', 'Comment title of' ); - $pr->registerProperty( '___CS_UPVOTES', '_num', 'Comment up votes' ); - $pr->registerProperty( '___CS_DOWNVOTES', '_num', 'Comment down votes' ); - $pr->registerProperty( '___CS_VOTEDIFF', '_num', 'Comment vote diff' ); - } - - /** - * Implements Semantic MediaWiki SMWStore::updateDataBefore callback. - * This won't get called unless Semantic MediaWiki is installed. - * If the comment has not been added to the database yet, which is indicated - * by a null associated page id, this function will return early, but it - * will be invoked again by an update job. - * - * @param SMW\Store $store semantic data store - * @param SMW\SemanticData $semanticData semantic data for page - * @return bool true to continue - */ - public static function updateData( $store, $semanticData ) { - $subject = $semanticData->getSubject(); - if ( $subject !== null && $subject->getTitle() !== null && - $subject->getTitle()->getNamespace() === NS_COMMENTSTREAMS ) { - $page_id = $subject->getTitle()->getArticleID( Title::GAID_FOR_UPDATE ); - $wikipage = WikiPage::newFromId( $page_id ); - $comment = Comment::newFromWikiPage( $wikipage ); - - if ( $comment === null ) { - return true; - } - - $assoc_page_id = $comment->getAssociatedId(); - if ( $assoc_page_id !== null ) { - $assoc_wikipage = WikiPage::newFromId( $assoc_page_id ); - if ( $assoc_wikipage !== null ) { - $propertyDI = new DIProperty( '___CS_ASSOCPG' ); - $dataItem = - DIWikiPage::newFromTitle( $assoc_wikipage->getTitle() ); - $semanticData->addPropertyObjectValue( $propertyDI, $dataItem ); - } - } - - $parent_page_id = $comment->getParentId(); - if ( $parent_page_id !== null ) { - $parent_wikipage = WikiPage::newFromId( $parent_page_id ); - if ( $parent_wikipage !== null ) { - $propertyDI = new DIProperty( '___CS_REPLYTO' ); - $dataItem = - DIWikiPage::newFromTitle( $parent_wikipage->getTitle() ); - $semanticData->addPropertyObjectValue( $propertyDI, $dataItem ); - } - } - - $commentTitle = $comment->getCommentTitle(); - if ( $commentTitle !== null ) { - $propertyDI = new DIProperty( '___CS_TITLE' ); - $dataItem = new SMWDIBlob( $comment->getCommentTitle() ); - $semanticData->addPropertyObjectValue( $propertyDI, $dataItem ); - } - - if ( $GLOBALS['wgCommentStreamsEnableVoting'] === true ) { - $upvotes = $comment->getNumUpVotes(); - $propertyDI = new DIProperty( '___CS_UPVOTES' ); - $dataItem = new SMWDINumber( $upvotes ); - $semanticData->addPropertyObjectValue( $propertyDI, $dataItem ); - $downvotes = $comment->getNumDownVotes(); - $propertyDI = new DIProperty( '___CS_DOWNVOTES' ); - $dataItem = new SMWDINumber( $downvotes ); - $semanticData->addPropertyObjectValue( $propertyDI, $dataItem ); - $votediff = $upvotes - $downvotes; - $propertyDI = new DIProperty( '___CS_VOTEDIFF' ); - $dataItem = new SMWDINumber( $votediff ); - $semanticData->addPropertyObjectValue( $propertyDI, $dataItem ); - } - } - return true; - } - - /** - * @param array &$notifications notifications - * @param array &$notificationCategories notification categories - * @param array &$icons notification icons - */ - public static function onBeforeCreateEchoEvent( &$notifications, - &$notificationCategories, &$icons ) { - $notificationCategories['commentstreams-notification-category'] = [ - 'priority' => 3 - ]; - - $notifications['commentstreams-comment-on-watched-page'] = [ - 'category' => 'commentstreams-notification-category', - 'group' => 'positive', - 'section' => 'alert', - 'presentation-model' => EchoCSPresentationModel::class, - 'user-locators' => [ 'EchoUserLocator::locateUsersWatchingTitle' ] - ]; - - $notifications['commentstreams-reply-on-watched-page'] = [ - 'category' => 'commentstreams-notification-category', - 'group' => 'positive', - 'section' => 'alert', - 'presentation-model' => EchoCSPresentationModel::class, - 'user-locators' => [ 'EchoUserLocator::locateUsersWatchingTitle' ], - 'user-filters' => [ 'Comment::locateUsersWatchingComment' ] - ]; - - $notifications['commentstreams-reply-to-watched-comment'] = [ - 'category' => 'commentstreams-notification-category', - 'group' => 'positive', - 'section' => 'alert', - 'presentation-model' => EchoCSPresentationModel::class, - 'user-locators' => [ 'Comment::locateUsersWatchingComment' ] - ]; - } } diff --git a/CommentStreams/includes/CommentStreamsSMWInterface.php b/CommentStreams/includes/CommentStreamsSMWInterface.php new file mode 100644 index 00000000..db60dc18 --- /dev/null +++ b/CommentStreams/includes/CommentStreamsSMWInterface.php @@ -0,0 +1,221 @@ +<?php + +/* + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +namespace MediaWiki\Extension\CommentStreams; + +use ConfigException; +use ExtensionRegistry; +use JobQueueGroup; +use MediaWiki\MediaWikiServices; +use SMW\DIProperty; +use SMW\DIWikiPage; +use SMW\MediaWiki\Jobs\UpdateJob; +use SMW\PropertyRegistry; +use SMW\SemanticData; +use SMW\Store; +use SMW\StoreFactory; +use SMWDataItem; +use SMWDIBlob; +use SMWDINumber; +use Title; +use User; + +class CommentStreamsSMWInterface { + /** + * @var bool + */ + private $isLoaded; + + /** + * @param ExtensionRegistry $extensionRegistry + */ + public function __construct( + ExtensionRegistry $extensionRegistry + ) { + $this->isLoaded = $extensionRegistry->isLoaded( 'SemanticMediaWiki' ); + } + + /** + * @return bool + */ + public function isLoaded() : bool { + return $this->isLoaded; + } + + /** + * @param Title $title + */ + public function update( Title $title ) { + if ( !$this->isLoaded ) { + return; + } + $job = new UpdateJob( $title, [] ); + JobQueueGroup::singleton()->push( $job ); + } + + /** + * return the value of a property on a user page + * + * @param User $user the user + * @param string $propertyName the name of the property + * @return string|Title|null the value of the property + */ + public function getUserProperty( User $user, string $propertyName ) { + if ( !$this->isLoaded ) { + return null; + } + $userpage = $user->getUserPage(); + if ( $userpage->exists() ) { + $subject = DIWikiPage::newFromTitle( $userpage ); + $store = StoreFactory::getStore(); + $data = $store->getSemanticData( $subject ); + $property = DIProperty::newFromUserLabel( $propertyName ); + $values = $data->getPropertyValues( $property ); + if ( count( $values ) > 0 ) { + // this property should only have one value so pick the first one + $value = $values[0]; + if ( ( defined( 'SMWDataItem::TYPE_STRING' ) && + $value->getDIType() == SMWDataItem::TYPE_STRING ) || + $value->getDIType() == SMWDataItem::TYPE_BLOB ) { + return $value->getString(); + } elseif ( $value->getDIType() == SMWDataItem::TYPE_WIKIPAGE ) { + return $value->getTitle(); + } + } + } + return null; + } + + /** + * Initialize extra Semantic MediaWiki properties. + * This won't get called unless Semantic MediaWiki is installed. + * @throws ConfigException + */ + public static function initProperties() { + $services = MediaWikiServices::getInstance(); + $config = $services->getConfigFactory()->makeConfig( 'CommentStreams' ); + $enableVoting = (bool)$config->get( 'CommentStreamsEnableVoting' ); + $pr = PropertyRegistry::getInstance(); + $pr->registerProperty( '___CS_ASSOCPG', '_wpg', 'Comment on' ); + $pr->registerProperty( '___CS_REPLYTO', '_wpg', 'Reply to' ); + $pr->registerProperty( '___CS_TITLE', '_txt', 'Comment title of' ); + if ( $enableVoting === true ) { + $pr->registerProperty( '___CS_UPVOTES', '_num', 'Comment up votes' ); + $pr->registerProperty( '___CS_DOWNVOTES', '_num', 'Comment down votes' ); + $pr->registerProperty( '___CS_VOTEDIFF', '_num', 'Comment vote diff' ); + } + } + + /** + * Implements Semantic MediaWiki SMWStore::updateDataBefore callback. + * This won't get called unless Semantic MediaWiki is installed. + * If the comment has not been added to the database yet, which is indicated + * by a null associated page id, this function will return early, but it + * will be invoked again by an update job. + * + * @param Store $store semantic data store + * @param SemanticData $semanticData semantic data for page + * @return bool true to continue + * @noinspection PhpUnusedParameterInspection + * @throws ConfigException + */ + public static function updateData( Store $store, SemanticData $semanticData ) : bool { + $subject = $semanticData->getSubject(); + if ( $subject !== null && $subject->getTitle() !== null && + $subject->getTitle()->getNamespace() === NS_COMMENTSTREAMS ) { + if ( defined( 'Title::READ_LATEST' ) ) { + $page_id = $subject->getTitle()->getArticleID( Title::READ_LATEST ); + } else { + $page_id = $subject->getTitle()->getArticleID( Title::GAID_FOR_UPDATE ); + } + $wikipage = CommentStreamsUtils::newWikiPageFromId( $page_id ); + $commentStreamsFactory = + MediaWikiServices::getInstance()->getService( 'CommentStreamsFactory' ); + $comment = $commentStreamsFactory->newFromWikiPage( $wikipage ); + + if ( $comment === null ) { + return true; + } + + $assoc_page_id = $comment->getAssociatedId(); + if ( $assoc_page_id !== null ) { + $assoc_wikipage = CommentStreamsUtils::newWikiPageFromId( $assoc_page_id ); + if ( $assoc_wikipage !== null ) { + $propertyDI = new DIProperty( '___CS_ASSOCPG' ); + $dataItem = + DIWikiPage::newFromTitle( $assoc_wikipage->getTitle() ); + $semanticData->addPropertyObjectValue( $propertyDI, $dataItem ); + } + } + + $parent_page_id = $comment->getParentId(); + if ( $parent_page_id !== null ) { + $parent_wikipage = CommentStreamsUtils::newWikiPageFromId( $parent_page_id ); + if ( $parent_wikipage !== null ) { + $propertyDI = new DIProperty( '___CS_REPLYTO' ); + $dataItem = + DIWikiPage::newFromTitle( $parent_wikipage->getTitle() ); + $semanticData->addPropertyObjectValue( $propertyDI, $dataItem ); + } + } + + $commentTitle = $comment->getCommentTitle(); + if ( $commentTitle !== null ) { + $propertyDI = new DIProperty( '___CS_TITLE' ); + $dataItem = new SMWDIBlob( $comment->getCommentTitle() ); + $semanticData->addPropertyObjectValue( $propertyDI, $dataItem ); + } + + $services = MediaWikiServices::getInstance(); + $commentStreamsStore = $services->getService( 'CommentStreamsStore' ); + $config = $services->getConfigFactory()->makeConfig( 'CommentStreams' ); + $enableVoting = (bool)$config->get( 'CommentStreamsEnableVoting' ); + if ( $enableVoting === true ) { + $upvotes = $commentStreamsStore->getNumUpVotes( $comment->getId() ); + $propertyDI = new DIProperty( '___CS_UPVOTES' ); + $dataItem = new SMWDINumber( $upvotes ); + $semanticData->addPropertyObjectValue( $propertyDI, $dataItem ); + $downvotes = $commentStreamsStore->getNumDownVotes( $comment->getId() ); + $propertyDI = new DIProperty( '___CS_DOWNVOTES' ); + $dataItem = new SMWDINumber( $downvotes ); + $semanticData->addPropertyObjectValue( $propertyDI, $dataItem ); + $votediff = $upvotes - $downvotes; + $propertyDI = new DIProperty( '___CS_VOTEDIFF' ); + $dataItem = new SMWDINumber( $votediff ); + $semanticData->addPropertyObjectValue( $propertyDI, $dataItem ); + } + } + return true; + } + + /** + * Implements SMW::Settings::BeforeInitializationComplete callback. + * See https://github.com/SemanticMediaWiki/SemanticMediaWiki/blob/master/docs/technical/hooks/hook.settings.beforeinitializationcomplete.md + * Defines CommentStreams namespace constants. + * + * @param array &$configuration An array of the configuration options + */ + public static function onSMWInitialization( array &$configuration ) { + $namespaceIndex = $GLOBALS['wgCommentStreamsNamespaceIndex']; + $configuration['smwgNamespacesWithSemanticLinks'][$namespaceIndex] = true; + } +} diff --git a/CommentStreams/includes/CommentStreamsSocialProfileInterface.php b/CommentStreams/includes/CommentStreamsSocialProfileInterface.php new file mode 100644 index 00000000..f8ed83c8 --- /dev/null +++ b/CommentStreams/includes/CommentStreamsSocialProfileInterface.php @@ -0,0 +1,69 @@ +<?php + +/* + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +namespace MediaWiki\Extension\CommentStreams; + +use ConfigException; +use User; +use wAvatar; + +class CommentStreamsSocialProfileInterface { + public const CONSTRUCTOR_OPTIONS = [ + 'UploadPath' + ]; + + /** + * @var bool + */ + private $isLoaded; + + /** + * @var string + */ + private $uploadPath; + + /** + * @param \MediaWiki\Config\ServiceOptions|\Config $options + * @throws ConfigException + */ + public function __construct( + $options + ) { + if ( class_exists( '\MediaWiki\Config\ServiceOptions' ) ) { + $options->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS ); + } + $this->isLoaded = class_exists( 'wAvatar' ); + $this->uploadPath = $options->get( 'UploadPath' ); + } + + /** + * @param User $user + * @return ?string + */ + public function getAvatar( User $user ) : ?string { + if ( !$this->isLoaded ) { + return null; + } + $avatar = new wAvatar( $user->getId(), 'l' ); + return $this->uploadPath . '/avatars/' . $avatar->getAvatarImage(); + } +} diff --git a/CommentStreams/includes/CommentStreamsStore.php b/CommentStreams/includes/CommentStreamsStore.php new file mode 100644 index 00000000..b3202924 --- /dev/null +++ b/CommentStreams/includes/CommentStreamsStore.php @@ -0,0 +1,601 @@ +<?php + +/* + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +namespace MediaWiki\Extension\CommentStreams; + +use ContentHandler; +use FatalError; +use MWException; +use Title; +use User; +use Wikimedia\Rdbms\IDatabase; +use Wikimedia\Rdbms\ILoadBalancer; +use Wikimedia\Rdbms\IResultWrapper; +use WikiPage; +use WikitextContent; + +class CommentStreamsStore { + /** + * @var ILoadBalancer + */ + private $loadBalancer; + + /** + * @param ILoadBalancer $loadBalancer + */ + public function __construct( ILoadBalancer $loadBalancer ) { + $this->loadBalancer = $loadBalancer; + } + + /** + * @return ILoadBalancer + */ + private function getDBLoadBalancer(): ILoadBalancer { + return $this->loadBalancer; + } + + /** + * @param int $mode DB_MASTER or DB_REPLICA + * @return IDatabase + */ + private function getDBConnection( int $mode ): IDatabase { + $lb = $this->getDBLoadBalancer(); + + return $lb->getConnection( $mode ); + } + + /** + * @param User $user + * @param string $wikitext + * @param ?string $comment_block_id + * @param int $assoc_page_id + * @param ?int $parent_page_id + * @param ?string $comment_title + * @return ?WikiPage + * @throws MWException + */ + public function insertComment( + User $user, + string $wikitext, + ?string $comment_block_id, + int $assoc_page_id, + ?int $parent_page_id, + ?string $comment_title + ): ?WikiPage { + $annotated_wikitext = $this->addAnnotations( $wikitext, $comment_title ); + $content = new WikitextContent( $annotated_wikitext ); + + $success = false; + $index = wfRandomString(); + do { + $title = Title::newFromText( (string)$index, NS_COMMENTSTREAMS ); + $wikipage = new WikiPage( $title ); + $deleted = CommentStreamsUtils::hasDeletedEdits( $title ); + if ( !$deleted && !$title->exists() ) { + if ( !CommentStreamsUtils::userCan( 'cs-comment', $user, $title ) ) { + return null; + } + $status = CommentStreamsUtils::doEditContent( + $wikipage, + $content, + $user, + EDIT_NEW | EDIT_SUPPRESS_RC + ); + if ( !$status->isOK() && !$status->isGood() ) { + if ( $status->getMessage()->getKey() == 'edit-already-exists' ) { + $index = wfRandomString(); + } else { + return null; + } + } else { + $success = true; + } + } else { + $index = wfRandomString(); + } + } while ( !$success ); + + $dbw = $this->getDBConnection( DB_MASTER ); + $result = $dbw->insert( + 'cs_comment_data', + [ + 'cst_page_id' => $wikipage->getId(), + 'cst_id' => $comment_block_id, + 'cst_assoc_page_id' => $assoc_page_id, + 'cst_parent_page_id' => $parent_page_id, + 'cst_comment_title' => $comment_title + ], + __METHOD__ + ); + + if ( !$result ) { + return null; + } + + return $wikipage; + } + + /** + * @param int $id + * @return ?array + */ + public function getComment( int $id ): ?array { + $dbr = $this->getDBConnection( DB_REPLICA ); + $result = $dbr->selectRow( + 'cs_comment_data', + [ + 'cst_id', + 'cst_assoc_page_id', + 'cst_parent_page_id', + 'cst_comment_title' + ], + [ + 'cst_page_id' => $id + ], + __METHOD__ + ); + if ( $result ) { + return [ + 'comment_block_id' => $result->cst_id, + 'assoc_page_id' => (int)$result->cst_assoc_page_id, + 'parent_page_id' => $result->cst_parent_page_id ? (int)$result->cst_parent_page_id + : null, + 'comment_title' => $result->cst_comment_title + ]; + } + + return null; + } + + /** + * @param int $limit + * @param int $offset + * @return IResultWrapper + */ + public function getCommentPages( int $limit, int $offset ) : IResultWrapper { + $dbr = $this->getDBConnection( DB_REPLICA ); + return $dbr->select( + [ + 'cs_comment_data', + 'page', + 'revision' + ], + [ + 'page_id' + ], + [ + 'cst_page_id = page_id', + 'page_latest = rev_id' + ], + __METHOD__, + [ + 'ORDER BY' => 'rev_timestamp DESC' , + 'LIMIT' => $limit, + 'OFFSET' => $offset + ] + ); + } + + /** + * @param WikiPage $wikipage + * @param ?string $comment_title + * @param string $wikitext + * @param User $user + * @return bool + * @throws MWException + */ + public function updateComment( + WikiPage $wikipage, + ?string $comment_title, + string $wikitext, + User $user + ) : bool { + $annotated_wikitext = $this->addAnnotations( $wikitext, $comment_title ); + $content = new WikitextContent( $annotated_wikitext ); + + $status = CommentStreamsUtils::doEditContent( + $wikipage, + $content, + $user, + EDIT_UPDATE | EDIT_SUPPRESS_RC + ); + if ( !$status->isOK() && !$status->isGood() ) { + return false; + } + + $dbw = $this->getDBConnection( DB_MASTER ); + return $dbw->update( + 'cs_comment_data', + [ + 'cst_comment_title' => $comment_title + ], + [ + 'cst_page_id' => $wikipage->getId() + ], + __METHOD__ + ); + } + + /** + * @param WikiPage $wikipage + * @param User $deleter + * @return bool + * @throws FatalError + * @throws MWException + */ + public function deleteComment( WikiPage $wikipage, User $deleter ) : bool { + // must save page ID before deleting page + $pageid = $wikipage->getId(); + + $status = CommentStreamsUtils::deDeleteArticle( + $wikipage, + 'comment deleted', + $deleter + ); + + if ( !$status->isOK() && !$status->isGood() ) { + return false; + } + + $dbw = $this->getDBConnection( DB_MASTER ); + return $dbw->delete( + 'cs_comment_data', + [ + 'cst_page_id' => $pageid + ], + __METHOD__ + ); + } + + /** + * @param int $id + * @return array + */ + public function getAssociatedComments( int $id ) : array { + $dbr = $this->getDBConnection( DB_REPLICA ); + $result = $dbr->select( + 'cs_comment_data', + [ + 'cst_page_id' + ], + [ + 'cst_assoc_page_id' => $id + ], + __METHOD__ + ); + $comment_page_ids = []; + foreach ( $result as $row ) { + $comment_page_ids[] = $row->cst_page_id; + } + return $comment_page_ids; + } + + /** + * @param int $id + * @return array + */ + public function getReplies( int $id ): array { + $dbr = $this->getDBConnection( DB_REPLICA ); + $result = $dbr->select( + 'cs_comment_data', + [ + 'cst_page_id' + ], + [ + 'cst_parent_page_id' => $id + ], + __METHOD__ + ); + $reply_ids = []; + foreach ( $result as $row ) { + $reply_ids[] = $row->cst_page_id; + } + return $reply_ids; + } + + /** + * @param int $id + * @return int + */ + public function getNumReplies( int $id ): int { + $dbr = $this->getDBConnection( DB_REPLICA ); + + return $dbr->selectRowCount( + 'cs_comment_data', + '*', + [ + 'cst_parent_page_id' => $id + ], + __METHOD__ + ); + } + + /** + * @param int $page_id + * @param int $user_id + * @return int -1, 0, or 1 + */ + public function getVote( int $page_id, int $user_id ) : int { + $dbr = $this->getDBConnection( DB_REPLICA ); + $result = $dbr->selectRow( + 'cs_votes', + [ + 'cst_v_vote' + ], + [ + 'cst_v_page_id' => $page_id, + 'cst_v_user_id' => $user_id + ], + __METHOD__ + ); + if ( $result ) { + $vote = (int)$result->cst_v_vote; + if ( $vote > 0 ) { + return 1; + } + if ( $vote < 0 ) { + return -1; + } + } + + return 0; + } + + /** + * @param int $id + * @return int + */ + public function getNumUpVotes( int $id ): int { + return $this->getNumVotes( $id, true ); + } + + /** + * @param int $id + * @return int + */ + public function getNumDownVotes( int $id ): int { + return $this->getNumVotes( $id, false ); + } + + /** + * @param int $id + * @param bool $up + * @return int + */ + private function getNumVotes( int $id, bool $up ): int { + $dbr = $this->getDBConnection( DB_REPLICA ); + + return $dbr->selectRowCount( + 'cs_votes', + '*', + [ + 'cst_v_page_id' => $id, + 'cst_v_vote' => $up ? 1 : -1 + ], + __METHOD__ + ); + } + + /** + * @param int $vote + * @param int $page_id + * @param int $user_id + * @return bool true for OK, false for error + */ + public function vote( int $vote, int $page_id, int $user_id ) : bool { + $dbw = $this->getDBConnection( DB_MASTER ); + $result = $dbw->selectRow( + 'cs_votes', + [ + 'cst_v_vote' + ], + [ + 'cst_v_page_id' => $page_id, + 'cst_v_user_id' => $user_id + ], + __METHOD__ + ); + if ( $result ) { + if ( $vote === (int)$result->cst_v_vote ) { + return true; + } + if ( $vote === 1 || $vote === -1 ) { + return $dbw->update( + 'cs_votes', + [ + 'cst_v_vote' => $vote + ], + [ + 'cst_v_page_id' => $page_id, + 'cst_v_user_id' => $user_id + ], + __METHOD__ + ); + } else { + return $dbw->delete( + 'cs_votes', + [ + 'cst_v_page_id' => $page_id, + 'cst_v_user_id' => $user_id + ], + __METHOD__ + ); + } + } + if ( $vote === 0 ) { + return true; + } + + return $dbw->insert( + 'cs_votes', + [ + 'cst_v_page_id' => $page_id, + 'cst_v_user_id' => $user_id, + 'cst_v_vote' => $vote + ], + __METHOD__ + ); + } + + /** + * @param int $page_id the page ID of the comment to watch + * @param int $user_id the user ID of the user watching the comment + * @return bool true for OK, false for error + */ + public function watch( int $page_id, int $user_id ) : bool { + if ( $this->isWatching( $page_id, $user_id, DB_MASTER ) ) { + return true; + } + $dbw = $this->getDBConnection( DB_MASTER ); + + return $dbw->insert( + 'cs_watchlist', + [ + 'cst_wl_page_id' => $page_id, + 'cst_wl_user_id' => $user_id + ], + __METHOD__ + ); + } + + /** + * @param int $page_id the page ID of the comment to watch + * @param int $user_id the user ID of the user watching the comment + * @return bool true for OK, false for error + */ + public function unwatch( int $page_id, int $user_id ): bool { + if ( !$this->isWatching( $page_id, $user_id, DB_MASTER ) ) { + return true; + } + $dbw = $this->getDBConnection( DB_MASTER ); + + return $dbw->delete( + 'cs_watchlist', + [ + 'cst_wl_page_id' => $page_id, + 'cst_wl_user_id' => $user_id + ], + __METHOD__ + ); + } + + /** + * @param int $page_id the page ID of the comment to check + * @param int $user_id the user ID of the user watching the comment + * @param int $fromdb DB_MASTER or DB_REPLICA + * @return bool database true for OK, false for error + */ + public function isWatching( int $page_id, int $user_id, int $fromdb = DB_REPLICA ): bool { + $db = $this->getDBConnection( $fromdb ); + $result = $db->selectRow( + 'cs_watchlist', + [ + 'cst_wl_page_id' + ], + [ + 'cst_wl_page_id' => $page_id, + 'cst_wl_user_id' => $user_id + ], + __METHOD__ + ); + + if ( $result ) { + return true; + } + + return false; + } + + /** + * @param int $id + * @return array of user IDs + */ + public function getWatchers( int $id ): array { + $dbr = $this->getDBConnection( DB_REPLICA ); + $result = $dbr->select( + 'cs_watchlist', + [ + 'cst_wl_user_id' + ], + [ + 'cst_wl_page_id' => $id + ], + __METHOD__ + ); + $users = []; + foreach ( $result as $row ) { + $user_id = $row->cst_wl_user_id; + $user = User::newFromId( $user_id ); + $users[$user_id] = $user; + } + + return $users; + } + + /** + * @param WikiPage $wikipage + * @param ?string $comment_title + * @return string + * @throws MWException + */ + public function getWikiText( WikiPage $wikipage, ?string $comment_title ) : string { + $wikitext = ContentHandler::getContentText( CommentStreamsUtils::getContent( $wikipage ) ); + return $this->removeAnnotations( $wikitext, $comment_title ); + } + + /** + * add extra information to wikitext before storage + * + * @param string $wikitext the wikitext to which to add + * @param ?string $comment_title string title of comment + * @return string annotated wikitext + */ + private function addAnnotations( string $wikitext, ?string $comment_title ) : string { + if ( $comment_title !== null ) { + $wikitext .= <<<EOT +{{DISPLAYTITLE: +$comment_title +}} +EOT; + } + return $wikitext; + } + + /** + * add extra information to wikitext before storage + * + * @param string $wikitext the wikitext to which to add + * @param ?string $comment_title + * @return string wikitext without annotations + */ + private function removeAnnotations( string $wikitext, ?string $comment_title ) : string { + if ( $comment_title !== null ) { + $strip = <<<EOT +{{DISPLAYTITLE: +$comment_title +}} +EOT; + $wikitext = str_replace( $strip, '', $wikitext ); + } + return $wikitext; + } +} diff --git a/CommentStreams/includes/CommentStreamsUtils.php b/CommentStreams/includes/CommentStreamsUtils.php index 1e09303c..7ab2f70e 100644 --- a/CommentStreams/includes/CommentStreamsUtils.php +++ b/CommentStreams/includes/CommentStreamsUtils.php @@ -21,23 +21,296 @@ namespace MediaWiki\Extension\CommentStreams; -use Linker; +use Content; +use FatalError; +use File; +use IContextSource; +use IDBAccessObject; use MediaWiki\MediaWikiServices; +use MediaWiki\User\UserIdentity; +use MWException; +use MWNamespace; +use OutputPage; +use Parser; +use Status; use Title; +use User; +use WikiPage; +// @phan-file-suppress PhanUndeclaredMethod +// @phan-file-suppress PhanTypeMismatchArgumentReal +// @phan-file-suppress UnusedPluginFileSuppression class CommentStreamsUtils { + /** + * @param string $action + * @param User $user + * @param Title $title + * @return bool + */ + public static function userCan( string $action, User $user, Title $title ) : bool { + if ( class_exists( '\MediaWiki\Permissions\PermissionManager' ) ) { + // MW 1.33+ + return MediaWikiServices::getInstance()->getPermissionManager()-> + userCan( $action, $user, $title ); + } + return $title->userCan( $action, $user ); + } + + /** + * @param User $user + * @param string $right + * @return bool + */ + public static function userHasRight( User $user, string $right ) : bool { + if ( class_exists( '\MediaWiki\Permissions\PermissionManager' ) && + method_exists( '\MediaWiki\Permissions\PermissionManager', 'userHasRight' ) ) { + // MW 1.34+ + $permissionManager = MediaWikiServices::getInstance()->getPermissionManager(); + if ( !$permissionManager->userHasRight( $user, $right ) || + $user->getBlock() !== null ) { + // This is not quite right, since it will prevent a user from commenting if they + // are blocked from any action, which may be overly broad + return false; + } + } elseif ( !in_array( $right, $user->getRights() ) || $user->isBlocked() ) { + return false; + } + return true; + } + + /** + * @param int $id Article ID to load + * @param string|int $from One of the following values: + * - "fromdb" or WikiPage::READ_NORMAL to select from a replica DB + * - "fromdbmaster" or WikiPage::READ_LATEST to select from the master database + * @return WikiPage|null + */ + public static function newWikiPageFromId( int $id, $from = 'fromdb' ) : ?WikiPage { + if ( class_exists( '\MediaWiki\Page\WikiPageFactory' ) ) { + // MW 1.36+ + return MediaWikiServices::getInstance()->getWikiPageFactory()->newFromID( $id, $from ); + } + return WikiPage::newFromId( $id, $from ); + } + + /** + * @param string $wikitext + * @param OutputPage $outputPage + * @throws MWException + */ + public static function addWikiTextToOutputPage( string $wikitext, OutputPage $outputPage ) { + if ( method_exists( 'OutputPage', 'addWikiTextAsInterface' ) ) { + // MW 1.32+ + $outputPage->addWikiTextAsInterface( $wikitext ); + } else { + $outputPage->addWikiText( $wikitext ); + } + } + + /** + * @param Title $title + * @return bool + */ + public static function hasDeletedEdits( Title $title ) : bool { + if ( method_exists( $title, 'hasDeletedEdits' ) ) { + // MW 1.36+ + return $title->hasDeletedEdits(); + } + return $title->isDeletedQuick(); + } + + /** + * @param string $filename + * @return bool|File + */ + public static function findFile( string $filename ) { + if ( method_exists( MediaWikiServices::class, 'getRepoGroup' ) ) { + // MediaWiki 1.34+ + return MediaWikiServices::getInstance()->getRepoGroup()->findFile( $filename ); + } else { + return wfFindFile( $filename, [ 'latest' => true ] ); + } + } + + /** + * @param int $id + * @param Title $title + * @return bool|string + */ + public static function getTimestampFromId( int $id, Title $title ) { + $revStore = MediaWikiServices::getInstance()->getRevisionStore(); + if ( version_compare( MW_VERSION, '1.34', '<' ) ) { + // @phan-suppress-next-line PhanTypeMismatchArgumentProbablyReal + return $revStore->getTimestampFromId( $title, $id ); + } else { + return $revStore->getTimestampFromId( $id ); + } + } + + /** + * @param Title $title + * @return ?string + */ + public static function getCreationTimestamp( Title $title ) : ?string { + if ( class_exists( '\MediaWiki\Revision\RevisionStore' ) && + method_exists( '\MediaWiki\Revision\RevisionStore', 'getFirstRevision' ) ) { + // MW 1.35+ + return MediaWikiServices::getInstance()->getRevisionStore()-> + getFirstRevision( $title )->getTimestamp(); + } + return $title->getEarliestRevTime(); + } + + /** + * @param Title $title + * @return ?int + */ + public static function getFirstRevisionId( Title $title ) : ?int { + if ( class_exists( '\MediaWiki\Revision\RevisionStore' ) && + method_exists( '\MediaWiki\Revision\RevisionStore', 'getFirstRevision' ) ) { + // MW 1.35+ + $revisionRecord = + MediaWikiServices::getInstance()->getRevisionStore()->getFirstRevision( $title ); + if ( $revisionRecord !== null ) { + return $revisionRecord->getId(); + } + } else { + $revision = $title->getFirstRevision(); + if ( $revision !== null ) { + return $revision->getId(); + } + } + return null; + } + + /** + * @param Title $title + * @return ?User + */ + public static function getAuthor( Title $title ) : ?User { + if ( class_exists( '\MediaWiki\Revision\RevisionStore' ) && + method_exists( '\MediaWiki\Revision\RevisionStore', 'getFirstRevision' ) ) { + // MW 1.35+ + $revisionRecord = + MediaWikiServices::getInstance()->getRevisionStore()->getFirstRevision( $title ); + if ( $revisionRecord !== null ) { + return User::newFromId( $revisionRecord->getUser( + \MediaWiki\Revision\RevisionRecord::RAW )->getId() ); + } + } else { + $revision = $title->getFirstRevision( Title::GAID_FOR_UPDATE ); + if ( $revision !== null ) { + return User::newFromId( $revision->getUser() ); + } + } + return null; + } + + /** + * @param WikiPage $wikipage + * @return ?UserIdentity + */ + public static function getLastEditor( WikiPage $wikipage ) : ?UserIdentity { + $revisionStore = MediaWikiServices::getInstance()->getRevisionStore(); + $latestRevision = $revisionStore->getRevisionByTitle( $wikipage->getTitle(), + 0, IDBAccessObject::READ_LATEST ); + if ( $latestRevision !== null ) { + if ( class_exists( '\MediaWiki\Revision\RevisionRecord' ) ) { + return $latestRevision->getUser( \MediaWiki\Revision\RevisionRecord::RAW ); + } else { + return $latestRevision->getUser( \MediaWiki\Storage\RevisionRecord::RAW ); + } + } + return null; + } + + /** + * @param WikiPage $wikipage + * @param Content $content + * @param User $user + * @param int $flags + * @return Status + * @throws MWException + */ + public static function doEditContent( + WikiPage $wikipage, + Content $content, + User $user, + int $flags + ) : Status { + return $wikipage->doEditContent( + $content, + '', + $flags, + false, + $user, + null ); + } + + /** + * @param WikiPage $wikipage + * @param string $reason + * @param User $deleter + * @return Status + * @throws FatalError + * @throws MWException + */ + public static function deDeleteArticle( + WikiPage $wikipage, + string $reason, + User $deleter + ) : Status { + if ( version_compare( MW_VERSION, '1.35', '<' ) ) { + return $wikipage->doDeleteArticleReal( $reason, true ); + } + return $wikipage->doDeleteArticleReal( $reason, $deleter, true ); + } + + /** + * @param int $namespace + * @return int + */ + public static function getSubjectNamespace( int $namespace ) : int { + if ( class_exists( 'NamespaceInfo' ) ) { + // MW 1.34+ + return MediaWikiServices::getInstance()->getNamespaceInfo()->getSubject( $namespace ); + } + return MWNamespace::getSubject( $namespace ); + } + + /** + * @param string $wikitext + * @param WikiPage $wikipage + * @param IContextSource $context + * @return string + */ + public static function parse( + string $wikitext, + WikiPage $wikipage, + IContextSource $context + ) : string { + if ( class_exists( '\ParserFactory' ) ) { + // MW 1.32+ + $parser = MediaWikiServices::getInstance()->getParserFactory()->create(); + } else { + // @phan-suppress-next-line PhanParamTooFew + $parser = new Parser(); + } + $parserOptions = $wikipage->makeParserOptions( $context ); + $parserOptions->setOption( 'enableLimitReport', false ); + return $parser + ->parse( $wikitext, $wikipage->getTitle(), $parserOptions ) + ->getText( [ 'wrapperDivClass' => '' ] ); + } /** - * Shim for compatibility - * @param Title $title to link to - * @param string $display to show - * @return string for link + * @param WikiPage $wikipage + * @return Content */ - public static function link( Title $title, $display ) { - if ( method_exists( 'MediaWikiServices', 'getLinkRenderer' ) ) { - $linkRenderer = MediaWikiServices::getInstance()->getLinkRenderer(); - return $linkRenderer->makeLink( $title, $display ); + public static function getContent( WikiPage $wikipage ) : Content { + if ( class_exists( '\MediaWiki\Revision\RevisionRecord' ) ) { + return $wikipage->getContent( \MediaWiki\Revision\RevisionRecord::RAW ); } - return Linker::link( $title, $display ); + return $wikipage->getContent( \MediaWiki\Storage\RevisionRecord::RAW ); } } diff --git a/CommentStreams/includes/EchoCSPresentationModel.php b/CommentStreams/includes/EchoCSPresentationModel.php index 3dba5cc9..3159672a 100644 --- a/CommentStreams/includes/EchoCSPresentationModel.php +++ b/CommentStreams/includes/EchoCSPresentationModel.php @@ -24,20 +24,20 @@ namespace MediaWiki\Extension\CommentStreams; use EchoEventPresentationModel; +use Message; class EchoCSPresentationModel extends EchoEventPresentationModel { - /** * @inheritDoc */ - public function getIconType() { + public function getIconType() : string { return 'chat'; } /** * @inheritDoc */ - public function getPrimaryLink() { + public function getPrimaryLink() : array { $id = $this->event->getExtraParam( 'comment_id' ); return [ 'url' => $this->event->getTitle()->getFullURL() . '#cs-comment-' . $id, @@ -48,18 +48,9 @@ class EchoCSPresentationModel extends EchoEventPresentationModel { /** * @inheritDoc */ - public function getHeaderMessage() { + public function getHeaderMessage() : Message { $msg = wfMessage( "notification-header-{$this->type}" ); - $msg->params( $this->event->getExtraParam( - 'comment_author_display_name' ) ); - $msg->params( $this->event->getExtraParam( 'comment_title' ) ); - $msg->params( $this->event->getExtraParam( - 'associated_page_display_title' ) ); - $msg->params( $this->event->getExtraParam( - 'comment_author_username' ) ); - $msg->params( $this->event->getExtraParam( - 'comment_wikitext' ) ); - $msg->params( $this->getViewingUserForGender() ); + $this->addMessageParams( $msg ); return $msg; } @@ -68,6 +59,14 @@ class EchoCSPresentationModel extends EchoEventPresentationModel { */ public function getBodyMessage() { $msg = wfMessage( "notification-body-{$this->type}" ); + $this->addMessageParams( $msg ); + return $msg; + } + + /** + * @param Message $msg + */ + private function addMessageParams( Message $msg ) { $msg->params( $this->event->getExtraParam( 'comment_author_display_name' ) ); $msg->params( $this->event->getExtraParam( 'comment_title' ) ); @@ -78,13 +77,12 @@ class EchoCSPresentationModel extends EchoEventPresentationModel { $msg->params( $this->event->getExtraParam( 'comment_wikitext' ) ); $msg->params( $this->getViewingUserForGender() ); - return $msg; } /** * @inheritDoc */ - public function canRender() { + public function canRender() : bool { return $this->event->getTitle() !== null; } } diff --git a/CommentStreams/includes/ServiceWiring.php b/CommentStreams/includes/ServiceWiring.php new file mode 100644 index 00000000..8041d0a0 --- /dev/null +++ b/CommentStreams/includes/ServiceWiring.php @@ -0,0 +1,85 @@ +<?php +/* + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +namespace MediaWiki\Extension\CommentStreams; + +use ExtensionRegistry; +use MediaWiki\MediaWikiServices; + +return [ + 'CommentStreamsHandler' => + static function ( MediaWikiServices $services ) : CommentStreamsHandler { + return new CommentStreamsHandler( + $services->getService( 'CommentStreamsFactory' ), + $services->getService( 'CommentStreamsStore' ), + $services->getService( 'CommentStreamsEchoInterface' ) + ); + }, + 'CommentStreamsStore' => + static function ( MediaWikiServices $services ) : CommentStreamsStore { + return new CommentStreamsStore( + $services->getDBLoadBalancer() + ); + }, + 'CommentStreamsFactory' => + static function ( MediaWikiServices $services ) : CommentStreamsFactory { + $config = $services->getConfigFactory()->makeConfig( 'CommentStreams' ); + if ( class_exists( '\MediaWiki\Config\ServiceOptions' ) ) { + $config = new \MediaWiki\Config\ServiceOptions( + Comment::CONSTRUCTOR_OPTIONS, + $config + ); + } + return new CommentStreamsFactory( + $config, + $services->getService( 'CommentStreamsStore' ), + $services->getService( 'CommentStreamsEchoInterface' ), + $services->getService( 'CommentStreamsSMWInterface' ), + $services->getService( 'CommentStreamsSocialProfileInterface' ), + $services->getLinkRenderer() + ); + }, + 'CommentStreamsEchoInterface' => + static function ( MediaWikiServices $services ) : CommentStreamsEchoInterface { + return new CommentStreamsEchoInterface( + ExtensionRegistry::getInstance() + ); + }, + 'CommentStreamsSMWInterface' => + static function ( MediaWikiServices $services ) : CommentStreamsSMWInterface { + return new CommentStreamsSMWInterface( + ExtensionRegistry::getInstance() + ); + }, + 'CommentStreamsSocialProfileInterface' => + static function ( MediaWikiServices $services ) : CommentStreamsSocialProfileInterface { + $config = $services->getConfigFactory()->makeConfig( 'CommentStreams' ); + if ( class_exists( '\MediaWiki\Config\ServiceOptions' ) ) { + $config = new \MediaWiki\Config\ServiceOptions( + CommentStreamsSocialProfileInterface::CONSTRUCTOR_OPTIONS, + $config + ); + } + return new CommentStreamsSocialProfileInterface( + $config + ); + }, +]; diff --git a/CommentStreams/package-lock.json b/CommentStreams/package-lock.json index a48acfe0..4f6dfbba 100644 --- a/CommentStreams/package-lock.json +++ b/CommentStreams/package-lock.json @@ -2,24 +2,509 @@ "requires": true, "lockfileVersion": 1, "dependencies": { + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/core": { + "version": "7.12.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.12.9.tgz", + "integrity": "sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.12.5", + "@babel/helper-module-transforms": "^7.12.1", + "@babel/helpers": "^7.12.5", + "@babel/parser": "^7.12.7", + "@babel/template": "^7.12.7", + "@babel/traverse": "^7.12.9", + "@babel/types": "^7.12.7", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.19", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.5.tgz", + "integrity": "sha512-m16TQQJ8hPt7E+OS/XVQg/7U184MLXtvuGbCdA7na61vha+ImkyyNM/9DDA0unYCVZn3ZOhng+qz48/KBOT96A==", + "dev": true, + "requires": { + "@babel/types": "^7.12.5", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/helper-function-name": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", + "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", + "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", + "dev": true, + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.7.tgz", + "integrity": "sha512-DCsuPyeWxeHgh1Dus7APn7iza42i/qXqiFPWyBDdOFtvS581JQePsc1F/nD+fHrcswhLlRc2UpYS1NwERxZhHw==", + "dev": true, + "requires": { + "@babel/types": "^7.12.7" + } + }, + "@babel/helper-module-imports": { + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.12.5.tgz", + "integrity": "sha512-SR713Ogqg6++uexFRORf/+nPXMmWIn80TALu0uaFb+iQIUoR7bOC7zBWyzBs5b3tBBJXuyD0cRu1F15GyzjOWA==", + "dev": true, + "requires": { + "@babel/types": "^7.12.5" + } + }, + "@babel/helper-module-transforms": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz", + "integrity": "sha512-QQzehgFAZ2bbISiCpmVGfiGux8YVFXQ0abBic2Envhej22DVXV9nCFaS5hIQbkyo1AdGb+gNME2TSh3hYJVV/w==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.12.1", + "@babel/helper-replace-supers": "^7.12.1", + "@babel/helper-simple-access": "^7.12.1", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/helper-validator-identifier": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.12.1", + "@babel/types": "^7.12.1", + "lodash": "^4.17.19" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.7.tgz", + "integrity": "sha512-I5xc9oSJ2h59OwyUqjv95HRyzxj53DAubUERgQMrpcCEYQyToeHA+NEcUEsVWB4j53RDeskeBJ0SgRAYHDBckw==", + "dev": true, + "requires": { + "@babel/types": "^7.12.7" + } + }, + "@babel/helper-replace-supers": { + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.12.5.tgz", + "integrity": "sha512-5YILoed0ZyIpF4gKcpZitEnXEJ9UoDRki1Ey6xz46rxOzfNMAhVIJMoune1hmPVxh40LRv1+oafz7UsWX+vyWA==", + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.12.1", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/traverse": "^7.12.5", + "@babel/types": "^7.12.5" + } + }, + "@babel/helper-simple-access": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz", + "integrity": "sha512-OxBp7pMrjVewSSC8fXDFrHrBcJATOOFssZwv16F3/6Xtc138GHybBfPbm9kfiqQHKhYQrlamWILwlDCeyMFEaA==", + "dev": true, + "requires": { + "@babel/types": "^7.12.1" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", + "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", + "dev": true, + "requires": { + "@babel/types": "^7.11.0" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "dev": true + }, + "@babel/helpers": { + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.12.5.tgz", + "integrity": "sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA==", + "dev": true, + "requires": { + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.12.5", + "@babel/types": "^7.12.5" + } + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@babel/parser": { + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.12.7.tgz", + "integrity": "sha512-oWR02Ubp4xTLCAqPRiNIuMVgNO5Aif/xpXtabhzW2HWUD47XJsAB4Zd/Rg30+XeQA3juXigV7hlquOTmwqLiwg==", + "dev": true + }, + "@babel/template": { + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.7.tgz", + "integrity": "sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.12.7", + "@babel/types": "^7.12.7" + } + }, + "@babel/traverse": { + "version": "7.12.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.12.9.tgz", + "integrity": "sha512-iX9ajqnLdoU1s1nHt36JDI9KG4k+vmI8WgjK5d+aDTwQbL2fUnzedNedssA645Ede3PM2ma1n8Q4h2ohwXgMXw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.12.5", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/parser": "^7.12.7", + "@babel/types": "^7.12.7", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.19" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.12.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.12.7.tgz", + "integrity": "sha512-MNyI92qZq6jrQkXvtIiykvl4WtoRrVV9MPn+ZfsoEENjiWcBQ3ZSHrkxnJWgWtLX3XXqX5hrSQ+X69wkmesXuQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "@eslint/eslintrc": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.0.tgz", + "integrity": "sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@mdn/browser-compat-data": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-2.0.7.tgz", + "integrity": "sha512-GeeM827DlzFFidn1eKkMBiqXFD2oLsnZbaiGhByPl0vcapsRzUL+t9hDoov1swc9rB2jw64R+ihtzC8qOE9wXw==", + "dev": true, + "requires": { + "extend": "3.0.2" + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", + "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.3", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz", + "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz", + "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.3", + "fastq": "^1.6.0" + } + }, + "@stylelint/postcss-css-in-js": { + "version": "0.37.2", + "resolved": "https://registry.npmjs.org/@stylelint/postcss-css-in-js/-/postcss-css-in-js-0.37.2.tgz", + "integrity": "sha512-nEhsFoJurt8oUmieT8qy4nk81WRHmJynmVwn/Vts08PL9fhgIsMhk1GId5yAN643OzqEEb5S/6At2TZW7pqPDA==", + "dev": true, + "requires": { + "@babel/core": ">=7.9.0" + } + }, + "@stylelint/postcss-markdown": { + "version": "0.36.2", + "resolved": "https://registry.npmjs.org/@stylelint/postcss-markdown/-/postcss-markdown-0.36.2.tgz", + "integrity": "sha512-2kGbqUVJUGE8dM+bMzXG/PYUWKkjLIkRLWNh39OaADkiabDRdw8ATFCgbMz5xdIcvwspPAluSL7uY+ZiTWdWmQ==", + "dev": true, + "requires": { + "remark": "^13.0.0", + "unist-util-find-all-after": "^3.0.2" + } + }, "@types/color-name": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", "dev": true }, - "JSV": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/JSV/-/JSV-4.0.2.tgz", - "integrity": "sha1-0Hf2glVx+CEy+d/67Vh7QCn+/1c=", + "@types/mdast": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.3.tgz", + "integrity": "sha512-SXPBMnFVQg1s00dlMCc/jCdvPqdE4mXaMMCeRlxLDmTAEoegHT53xKtkDnzDTOcmMHUfcjyf36/YYZ6SxRdnsw==", + "dev": true, + "requires": { + "@types/unist": "*" + } + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, + "@types/minimist": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.1.tgz", + "integrity": "sha512-fZQQafSREFyuZcdWFAExYjBiCL7AUCdgsk80iO0q4yihYYdcIiH28CcuPTGFgLOCC8RlW49GSQxdHwZP+I7CNg==", "dev": true }, + "@types/normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==", + "dev": true + }, + "@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "@types/unist": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz", + "integrity": "sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ==", + "dev": true + }, + "JSONStream": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-0.8.4.tgz", + "integrity": "sha1-kWV9/m/4V0gwZhMrRhi2Lo9Ih70=", + "dev": true, + "requires": { + "jsonparse": "0.0.5", + "through": ">=2.2.7 <3" + } + }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true }, + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", + "dev": true + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, "ansi-styles": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", @@ -47,22 +532,10 @@ } } }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "array-differ": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", + "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", "dev": true }, "array-each": { @@ -77,28 +550,55 @@ "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", "dev": true }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "dev": true }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "ast-metadata-inferer": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/ast-metadata-inferer/-/ast-metadata-inferer-0.4.0.tgz", + "integrity": "sha512-tKHdBe8N/Vq2nLAm4YPBVREVZjMux6KrqyPfNQgIbDl0t7HaNSmy8w4OyVHYg/cvyn5BW7o7pVwpjPte89Zhcg==", + "dev": true + }, + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true }, "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", + "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==", "dev": true }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "autoprefixer": { + "version": "9.8.6", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.6.tgz", + "integrity": "sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg==", + "dev": true, + "requires": { + "browserslist": "^4.12.0", + "caniuse-lite": "^1.0.30001109", + "colorette": "^1.2.1", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "postcss": "^7.0.32", + "postcss-value-parser": "^4.1.0" + } + }, + "bail": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz", + "integrity": "sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ==", "dev": true }, "balanced-match": { @@ -107,61 +607,6 @@ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -173,51 +618,70 @@ } }, "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "browserslist": { + "version": "4.16.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", + "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001219", + "colorette": "^1.2.2", + "electron-to-chromium": "^1.3.723", + "escalade": "^3.1.1", + "node-releases": "^1.1.71" }, "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } + "caniuse-lite": { + "version": "1.0.30001228", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001228.tgz", + "integrity": "sha512-QQmLOGJ3DEgokHbMSA8cj2a+geXqmnpyOFT0lhQV6P3/YOJvGDEwoedcwxEQ30gJIwIIunHIicunJ2rzK5gB2A==", + "dev": true + }, + "colorette": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", + "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", + "dev": true } } }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", "dev": true, "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" } }, + "caniuse-lite": { + "version": "1.0.30001164", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001164.tgz", + "integrity": "sha512-G+A/tkf4bu0dSp9+duNiXc7bGds35DioCyC6vgK2m/rjA4Krpy5WeZgZyfH2f0wj2kI6yAWWucyap6oOwmY1mg==", + "dev": true + }, "chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -228,37 +692,42 @@ "supports-color": "^7.1.0" } }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "character-entities": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-1.2.4.tgz", + "integrity": "sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==", + "dev": true + }, + "character-entities-legacy": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz", + "integrity": "sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==", + "dev": true + }, + "character-reference-invalid": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz", + "integrity": "sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==", + "dev": true + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", "dev": true, "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" } }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "clone-regexp": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clone-regexp/-/clone-regexp-2.2.0.tgz", + "integrity": "sha512-beMpP7BOtTipFuW8hrJvREQ2DrRu3BE7by0ZpibtfBA+qfHYvMGTc2Yb1JMYPKg/JUw0CHYvpg796aNTSW9z7Q==", "dev": true, "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" + "is-regexp": "^2.0.0" } }, "color-convert": { @@ -276,16 +745,22 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "colorette": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz", + "integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==", + "dev": true + }, "colors": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", "dev": true }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "comment-parser": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.1.2.tgz", + "integrity": "sha512-AOdq0i8ghZudnYv8RUnHrhTgafUGs61Rdz9jemU5x2lnZwAWyOq7vySo626K59e1fVKH1xSRorJwPVRLSWOoAQ==", "dev": true }, "concat-map": { @@ -294,257 +769,1037 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "core-js": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.10.1.tgz", + "integrity": "sha512-pwCxEXnj27XG47mu7SXAwhLP3L5CrlvCB91ANUkIz40P27kUcvNfSdvyZJ9CLHiVoKSp+TTChMQMSKQEH/IQxA==", "dev": true }, - "dateformat": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", - "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "cosmiconfig": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz", + "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==", "dev": true, "requires": { - "ms": "2.0.0" + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" } }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "dependencies": { + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "css-rule-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/css-rule-stream/-/css-rule-stream-1.1.0.tgz", + "integrity": "sha1-N4bnGYmD2WWibjGVfgkHjLt3BaI=", "dev": true, "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" + "css-tokenize": "^1.0.1", + "duplexer2": "0.0.2", + "ldjson-stream": "^1.2.1", + "through2": "^0.6.3" }, "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "kind-of": "^6.0.0" + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" } }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", "dev": true, "requires": { - "kind-of": "^6.0.0" + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" } + } + } + }, + "css-tokenize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/css-tokenize/-/css-tokenize-1.0.1.tgz", + "integrity": "sha1-RiXLHtohwUOFi3+B1oA8HSb8FL4=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^1.0.33" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true } } }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true + }, + "dateformat": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decamelize-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", + "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", + "dev": true, + "requires": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "dependencies": { + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + } + } + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, "detect-file": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", "dev": true }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } }, - "eventemitter2": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", - "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=", + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "doiuse": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/doiuse/-/doiuse-4.4.0.tgz", + "integrity": "sha512-+RbL+7ECpBzbX+GMnX3PXzc/t+ufvZV/q/ysES5U8i0VexgGKLezQPCVehKwzLH2pIFC0pISfPaSm69CxuEw6w==", + "dev": true, + "requires": { + "browserslist": "^4.14.7", + "caniuse-lite": "^1.0.30001157", + "css-rule-stream": "^1.1.0", + "duplexer2": "0.0.2", + "jsonfilter": "^1.1.2", + "ldjson-stream": "^1.2.1", + "multimatch": "^5.0.0", + "postcss": "^8.1.6", + "source-map": "^0.7.3", + "through2": "^4.0.2", + "yargs": "^16.1.0" + }, + "dependencies": { + "postcss": { + "version": "8.2.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.15.tgz", + "integrity": "sha512-2zO3b26eJD/8rb106Qu2o7Qgg52ND5HPjcyQiK2B98O388h43A448LCslC0dI2P97wCAQRJsFvwTRcXxTKds+Q==", + "dev": true, + "requires": { + "colorette": "^1.2.2", + "nanoid": "^3.1.23", + "source-map": "^0.6.1" + }, + "dependencies": { + "colorette": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", + "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", + "dev": true + }, + "nanoid": { + "version": "3.1.23", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", + "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + } + } + }, + "dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.2.tgz", + "integrity": "sha512-wFwTwCVebUrMgGeAwRL/NhZtHAUyT9n9yg4IMDwf10+6iCMxSkVq9MGCVEH+QZWo1nNidy8kNvwmv4zWHDTqvA==", + "dev": true + }, + "entities": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz", + "integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==", + "dev": true + } + } + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", "dev": true }, - "exit": { + "domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "dev": true, + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "duplexer": { "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", "dev": true }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", "dev": true, "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "readable-stream": "~1.1.9" }, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true } } }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "electron-to-chromium": { + "version": "1.3.737", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.737.tgz", + "integrity": "sha512-P/B84AgUSQXaum7a8m11HUsYL8tj9h/Pt5f7Hg7Ty6bm5DxlFq+e5+ouHUoNQMsKDJ7u4yGfI8mOErCmSH9wyg==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", "dev": true, "requires": { - "homedir-polyfill": "^1.0.1" + "ansi-colors": "^4.1.1" } }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", "dev": true }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.24.0.tgz", + "integrity": "sha512-k9gaHeHiFmGCDQ2rEfvULlSLruz6tgfA8DEn+rY9/oYPFFTlz55mM/Q/Rij1b2Y42jwZiK3lXvNTw6w6TXzcKQ==", "dev": true, "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash": "^4.17.21", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.4", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" }, "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", "dev": true, "requires": { - "is-plain-object": "^2.0.4" + "is-extglob": "^2.1.1" } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true } } }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "eslint-config-wikimedia": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/eslint-config-wikimedia/-/eslint-config-wikimedia-0.20.0.tgz", + "integrity": "sha512-F2dm+S6aCDDb99Fr6KD9L7u1gOK819deG6xAG4EIVaLsHdQhjbcpNUuzUkUmGmpEHIYHqSpwkZ1EvBMc9Pxn+w==", + "dev": true, + "requires": { + "eslint": "^7.23.0", + "eslint-plugin-compat": "^3.9.0", + "eslint-plugin-es": "^4.1.0", + "eslint-plugin-jsdoc": "^32.3.0", + "eslint-plugin-json-es": "^1.5.3", + "eslint-plugin-mediawiki": "^0.2.7", + "eslint-plugin-mocha": "^8.1.0", + "eslint-plugin-no-jquery": "^2.6.0", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-qunit": "^6.0.0", + "eslint-plugin-vue": "^7.8.0", + "eslint-plugin-wdio": "^7.0.0" }, "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "@babel/code-frame": { + "version": "7.12.11", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", + "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", "dev": true, "requires": { - "is-descriptor": "^1.0.0" + "@babel/highlight": "^7.10.4" } }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "ms": "2.1.2" } }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "eslint": { + "version": "7.24.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.24.0.tgz", + "integrity": "sha512-k9gaHeHiFmGCDQ2rEfvULlSLruz6tgfA8DEn+rY9/oYPFFTlz55mM/Q/Rij1b2Y42jwZiK3lXvNTw6w6TXzcKQ==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash": "^4.17.21", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.4", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" } }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "is-extglob": "^2.1.1" } }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "eslint-plugin-compat": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-compat/-/eslint-plugin-compat-3.9.0.tgz", + "integrity": "sha512-lt3l5PHFHVEYSZ5zijcoYvtQJPsBifRiH5N0Et57KwVu7l/yxmHhSG6VJiLMa/lXrg93Qu8049RNQOMn0+yJBg==", + "dev": true, + "requires": { + "@mdn/browser-compat-data": "^2.0.7", + "ast-metadata-inferer": "^0.4.0", + "browserslist": "^4.12.2", + "caniuse-lite": "^1.0.30001166", + "core-js": "^3.6.5", + "find-up": "^4.1.0", + "lodash.memoize": "4.1.2", + "semver": "7.3.2" + }, + "dependencies": { + "caniuse-lite": { + "version": "1.0.30001208", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001208.tgz", + "integrity": "sha512-OE5UE4+nBOro8Dyvv0lfx+SRtfVIOM9uhKqFmJeUbGriqhhStgp1A0OyBpgy3OUF8AhYCT+PVwPC1gMl2ZcQMA==", + "dev": true + } + } + }, + "eslint-plugin-es": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-4.1.0.tgz", + "integrity": "sha512-GILhQTnjYE2WorX5Jyi5i4dz5ALWxBIdQECVQavL6s7cI76IZTDWleTHkxz/QT3kvcs2QlGHvKLYsSlPOlPXnQ==", + "dev": true, + "requires": { + "eslint-utils": "^2.0.0", + "regexpp": "^3.0.0" + } + }, + "eslint-plugin-jsdoc": { + "version": "32.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-32.3.0.tgz", + "integrity": "sha512-zyx7kajDK+tqS1bHuY5sapkad8P8KT0vdd/lE55j47VPG2MeenSYuIY/M/Pvmzq5g0+3JB+P3BJGUXmHxtuKPQ==", + "dev": true, + "requires": { + "comment-parser": "1.1.2", + "debug": "^4.3.1", + "jsdoctypeparser": "^9.0.0", + "lodash": "^4.17.20", + "regextras": "^0.7.1", + "semver": "^7.3.4", + "spdx-expression-parse": "^3.0.1" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "dev": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" } } } }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "eslint-plugin-json-es": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-json-es/-/eslint-plugin-json-es-1.5.3.tgz", + "integrity": "sha512-9wWjwhoN+ipMel70ktkWy0H7jj9sm5OAbAy3N3F3AT0swpIofVsIjDXyjGZJwSzy9tZzDtI/aKIj2WsqMHw2QA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1" + } + }, + "eslint-plugin-mediawiki": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/eslint-plugin-mediawiki/-/eslint-plugin-mediawiki-0.2.7.tgz", + "integrity": "sha512-2ZvPvLEwCIqrJxV1349bdX5Q03c30WccuUMCfB1Gh2IVxbBSrY0gbzOk/gPZeYigVhODt9xoFWUCIz8jwTWfrA==", + "dev": true, + "requires": { + "eslint-plugin-vue": "^7.7.0", + "upath": "^1.2.0" + } + }, + "eslint-plugin-mocha": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-8.1.0.tgz", + "integrity": "sha512-1EgHvXKRl7W3mq3sntZAi5T24agRMyiTPL4bSXe+B4GksYOjAPEWYx+J3eJg4It1l2NMNZJtk0gQyQ6mfiPhQg==", + "dev": true, + "requires": { + "eslint-utils": "^2.1.0", + "ramda": "^0.27.1" + } + }, + "eslint-plugin-no-jquery": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-no-jquery/-/eslint-plugin-no-jquery-2.6.0.tgz", + "integrity": "sha512-xC7pbNHJMdyxqhzcNMRrmC5/tbt1T4KCKXjOqUpKm/CaRryGKS5iWztzWPrL0KwyI3R3ub6goHFmIQS19f+mZA==", + "dev": true + }, + "eslint-plugin-node": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz", + "integrity": "sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" + "eslint-plugin-es": "^3.0.0", + "eslint-utils": "^2.0.0", + "ignore": "^5.1.1", + "minimatch": "^3.0.4", + "resolve": "^1.10.1", + "semver": "^6.1.0" }, "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "eslint-plugin-es": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz", + "integrity": "sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "eslint-utils": "^2.0.0", + "regexpp": "^3.0.0" } + }, + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "eslint-plugin-qunit": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-qunit/-/eslint-plugin-qunit-6.0.0.tgz", + "integrity": "sha512-+R8z2umSTIiWcxmTQ9nGoML8DL0VQJg4C+E9OpJ2KF9QL4WL/FoayROeTG5Z9zhlZ2qqa+9WkZ1YD6mx89io8w==", + "dev": true, + "requires": { + "eslint-utils": "^2.1.0", + "requireindex": "^1.2.0" + } + }, + "eslint-plugin-vue": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-7.9.0.tgz", + "integrity": "sha512-2Q0qQp5+5h+pZvJKCbG1/jCRUYrdgAz5BYKGyTlp2NU8mx09u3Hp7PsH6d5qef6ojuPoCXMnrbbDxeoplihrSw==", + "dev": true, + "requires": { + "eslint-utils": "^2.1.0", + "natural-compare": "^1.4.0", + "semver": "^7.3.2", + "vue-eslint-parser": "^7.6.0" + } + }, + "eslint-plugin-wdio": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-wdio/-/eslint-plugin-wdio-7.4.2.tgz", + "integrity": "sha512-tkISFycJmRFMKsEjetRcAmWSHKJKnw5rKHDxfE7Ob3tF5lbmYlCLfNKH0UwanOpSdulpe52s3K+CBHSd6qUUNQ==", + "dev": true + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true } } }, + "eslint-visitor-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", + "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", + "dev": true + }, + "espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "requires": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "eventemitter2": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", + "integrity": "sha1-j2G3XN4BKy6esoTUVFWDtWQ7Yas=", + "dev": true + }, + "execall": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/execall/-/execall-2.0.0.tgz", + "integrity": "sha512-0FU2hZ5Hh6iQnarpRtQurM/aAvp3RIbfvgLHrcqJYzhXyV2KFruhuChf9NC6waAhiUR7FFtlugkI4p7f2Fqlow==", + "dev": true, + "requires": { + "clone-regexp": "^2.1.0" + } + }, + "exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "dev": true + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-glob": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", + "integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2", + "picomatch": "^2.2.1" + }, + "dependencies": { + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + } + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fastest-levenshtein": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", + "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", + "dev": true + }, + "fastq": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.9.0.tgz", + "integrity": "sha512-i7FVWL8HhVY+CTkwFxkN2mk3h+787ixS5S63eb78diVRc1MCssarHq3W5cj0av7YDSwmaV928RNag+U1etRQ7w==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, "findup-sync": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.3.0.tgz", @@ -588,6 +1843,22 @@ "integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==", "dev": true }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.1.tgz", + "integrity": "sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==", + "dev": true + }, "for-in": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", @@ -603,31 +1874,46 @@ "for-in": "^1.0.1" } }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } - }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-stdin": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", + "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", "dev": true }, "getobject": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/getobject/-/getobject-0.1.0.tgz", - "integrity": "sha1-BHpEl4n6Fg0Bj1SG7ZEyC27HiFw=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/getobject/-/getobject-1.0.0.tgz", + "integrity": "sha512-tbUz6AKKKr2YiMB+fLWIgq5ZeBOobop9YMMAU9dC54/ot2ksMXt3DOFyBuhZw6ptcVszEykgByK20j7W9jHFag==", "dev": true }, "glob": { @@ -644,6 +1930,26 @@ "path-is-absolute": "^1.0.0" } }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + }, + "dependencies": { + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + } + } + }, "global-modules": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", @@ -668,10 +1974,64 @@ "which": "^1.2.14" } }, + "globals": { + "version": "13.6.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.6.0.tgz", + "integrity": "sha512-YFKCX0SiPg7l5oKYCJ2zZGxcXprVXHcSnVuvzrT3oSENQonVLqM5pf9fN5dLGZGyCjhw8TN8Btwe/jKnZ0pjvQ==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + }, + "dependencies": { + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + } + } + }, + "globby": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.1.tgz", + "integrity": "sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + }, + "dependencies": { + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + } + } + }, + "globjoin": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", + "integrity": "sha1-L0SUrIkZ43Z8XLtpHp9GMyQoXUM=", + "dev": true + }, + "gonzales-pe": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/gonzales-pe/-/gonzales-pe-4.3.0.tgz", + "integrity": "sha512-otgSPpUmdWJ43VXyiNgEYE4luzHCL2pz4wQ0OnDluC6Eg4Ko3Vexy/SrSynglw/eR+OhkzmqFCZa/OFa/RgAOQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, "grunt": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.3.0.tgz", - "integrity": "sha512-6ILlMXv11/4cxuhSMfSU+SfvbxrPuqZrAtLN64+tZpQ3DAKfSQPQHRbTjSbdtxfyQhGZPtN0bDZJ/LdCM5WXXA==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/grunt/-/grunt-1.4.0.tgz", + "integrity": "sha512-yRFc0GVCDu9yxqOFzpuXQ2pEdgtLDnFv5Qz54jfIcNnpJ8Z7B7P7kPkT4VMuRvm+N+QOsI8C4v/Q0DSaoj3LgQ==", "dev": true, "requires": { "dateformat": "~3.0.3", @@ -679,10 +2039,10 @@ "exit": "~0.1.2", "findup-sync": "~0.3.0", "glob": "~7.1.6", - "grunt-cli": "~1.3.2", - "grunt-known-options": "~1.1.0", + "grunt-cli": "~1.4.2", + "grunt-known-options": "~1.1.1", "grunt-legacy-log": "~3.0.0", - "grunt-legacy-util": "~2.0.0", + "grunt-legacy-util": "~2.0.1", "iconv-lite": "~0.4.13", "js-yaml": "~3.14.0", "minimatch": "~3.0.4", @@ -692,16 +2052,16 @@ }, "dependencies": { "grunt-cli": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.3.2.tgz", - "integrity": "sha512-8OHDiZZkcptxVXtMfDxJvmN7MVJNE8L/yIcPb4HB7TlyFD1kDvjHrb62uhySsU14wJx9ORMnTuhRMQ40lH/orQ==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/grunt-cli/-/grunt-cli-1.4.2.tgz", + "integrity": "sha512-wsu6BZh7KCnfeaSkDrKIAvOlqGKxNRTZjc8xfZlvxCByQIqUfZ31kh5uHpPnhQ4NdVgvaWaVxa1LUbVU80nACw==", "dev": true, "requires": { - "grunt-known-options": "~1.1.0", + "grunt-known-options": "~1.1.1", "interpret": "~1.1.0", - "liftoff": "~2.5.0", + "liftup": "~3.0.1", "nopt": "~4.0.1", - "v8flags": "~3.1.1" + "v8flags": "~3.2.0" }, "dependencies": { "nopt": { @@ -724,14 +2084,14 @@ "integrity": "sha512-SqPiB6OazWqR8USL0NymtuT5Br3mD9WBBsM1rHC/3wIi2SrZNM6/+j9CIeuEM5oCn+AtO2Y0+rzzFyOdC9afAg==", "dev": true }, - "grunt-jsonlint": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/grunt-jsonlint/-/grunt-jsonlint-1.1.0.tgz", - "integrity": "sha1-ox7pckCu4/NDyiY8Rb1TIGMSfbI=", + "grunt-eslint": { + "version": "23.0.0", + "resolved": "https://registry.npmjs.org/grunt-eslint/-/grunt-eslint-23.0.0.tgz", + "integrity": "sha512-QqHSAiGF08EVD7YlD4OSRWuLRaDvpsRdTptwy9WaxUXE+03mCLVA/lEaR6SHWehF7oUwIqCEjaNONeeeWlB4LQ==", "dev": true, "requires": { - "jsonlint": "1.6.2", - "strip-json-comments": "^2.0.0" + "chalk": "^4.0.0", + "eslint": "^7.0.0" } }, "grunt-known-options": { @@ -763,64 +2123,61 @@ } }, "grunt-legacy-util": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-2.0.0.tgz", - "integrity": "sha512-ZEmYFB44bblwPE2oz3q3ygfF6hseQja9tx8I3UZIwbUik32FMWewA+d1qSFicMFB+8dNXDkh35HcDCWlpRsGlA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/grunt-legacy-util/-/grunt-legacy-util-2.0.1.tgz", + "integrity": "sha512-2bQiD4fzXqX8rhNdXkAywCadeqiPiay0oQny77wA2F3WF4grPJXCvAcyoWUJV+po/b15glGkxuSiQCK299UC2w==", "dev": true, "requires": { - "async": "~1.5.2", - "exit": "~0.1.1", - "getobject": "~0.1.0", + "async": "~3.2.0", + "exit": "~0.1.2", + "getobject": "~1.0.0", "hooker": "~0.2.3", - "lodash": "~4.17.20", + "lodash": "~4.17.21", "underscore.string": "~3.3.5", - "which": "~1.3.0" + "which": "~2.0.2" + }, + "dependencies": { + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } } }, - "has-color": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", - "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "grunt-stylelint": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/grunt-stylelint/-/grunt-stylelint-0.16.0.tgz", + "integrity": "sha512-ullm0h9iCdgPEDq1TNwKL5HteXA4zke6wbYoRtsO32ATCU3zfUXmDN9unhu+joEcdgJKOPcd2+7UhRNXO1rr+w==", "dev": true, "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" + "chalk": "^4.1.0" } }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", "dev": true, "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "function-bind": "^1.1.1" } }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, "homedir-polyfill": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", @@ -836,6 +2193,35 @@ "integrity": "sha1-uDT3I8xKJCqmWWNFnfbZhMXT2Vk=", "dev": true }, + "hosted-git-info": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.8.tgz", + "integrity": "sha512-aXpmwoOhRBrw6X3j0h5RloK4x1OzsxMPyxqIHyNfSe2pypkVTZFpEiRoSipPEPlMrh0HW/XsjkJ5WgnCirpNUw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "html-tags": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz", + "integrity": "sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==", + "dev": true + }, + "htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "dev": true, + "requires": { + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -845,6 +2231,46 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "import-fresh": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.2.tgz", + "integrity": "sha512-cTPNrlvJT6twpYy+YmKUKrTSjWFs3bjYjAhCwm+z4EOCubZxAuO+hHpRN64TqjEaYSHs7tJAE0w1CKMGmsG/lw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "import-lazy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", + "dev": true + }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -862,9 +2288,9 @@ "dev": true }, "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true }, "interpret": { @@ -883,75 +2309,41 @@ "is-windows": "^1.0.1" } }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "is-alphabetical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-1.0.4.tgz", + "integrity": "sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==", "dev": true }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "is-alphanumerical": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz", + "integrity": "sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A==", "dev": true, "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "is-alphabetical": "^1.0.0", + "is-decimal": "^1.0.0" } }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-core-module": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.3.0.tgz", + "integrity": "sha512-xSphU2KG9867tsYdLD4RWQ1VqdFl4HTO9Thf3I/3dLEfr0dbPTWKsuCKrgqMljg4nPE+Gq0VCnzT3gr0CyBmsw==", "dev": true, "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } + "has": "^1.0.3" } }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "is-decimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-1.0.4.tgz", + "integrity": "sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw==", "dev": true }, "is-extglob": { @@ -960,34 +2352,38 @@ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", "dev": true, "requires": { - "is-extglob": "^2.1.0" + "is-extglob": "^2.1.1" } }, + "is-hexadecimal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz", + "integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==", + "dev": true + }, "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true }, "is-plain-object": { "version": "2.0.4", @@ -998,6 +2394,12 @@ "isobject": "^3.0.1" } }, + "is-regexp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-2.1.0.tgz", + "integrity": "sha512-OZ4IlER3zmRIoB9AqNhEggVxqIH4ofDns5nRrPS6yQxXE1TPCUpFznBfRQmQa8uC+pXqjMnukiJBxCisIxiLGA==", + "dev": true + }, "is-relative": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", @@ -1007,6 +2409,12 @@ "is-unc-path": "^1.0.0" } }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, "is-unc-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", @@ -1022,12 +2430,6 @@ "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -1040,6 +2442,12 @@ "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, "js-yaml": { "version": "3.14.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", @@ -1050,58 +2458,258 @@ "esprima": "^4.0.0" } }, - "jsonlint": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/jsonlint/-/jsonlint-1.6.2.tgz", - "integrity": "sha1-VzcEUIX1XrRVxosf9OvAG9UOiDA=", + "jsdoctypeparser": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/jsdoctypeparser/-/jsdoctypeparser-9.0.0.tgz", + "integrity": "sha512-jrTA2jJIL6/DAEILBEh2/w9QxCuwmvNXIry39Ay/HVfhE3o2yVV0U44blYkqdHA/OKloJEqvJy0xU+GSdE2SIw==", + "dev": true + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json5": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", "dev": true, "requires": { - "JSV": ">= 4.0.x", - "nomnom": ">= 1.5.x" + "minimist": "^1.2.5" } }, + "jsonfilter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/jsonfilter/-/jsonfilter-1.1.2.tgz", + "integrity": "sha1-Ie987cdRk4E8dZMulqmL4gW6WhE=", + "dev": true, + "requires": { + "JSONStream": "^0.8.4", + "minimist": "^1.1.0", + "stream-combiner": "^0.2.1", + "through2": "^0.6.3" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + } + } + }, + "jsonparse": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-0.0.5.tgz", + "integrity": "sha1-MwVCrT8KZUZlt3jz6y2an6UHrGQ=", + "dev": true + }, "kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true }, - "liftoff": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", - "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", + "known-css-properties": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.20.0.tgz", + "integrity": "sha512-URvsjaA9ypfreqJ2/ylDr5MUERhJZ+DhguoWRr2xgS5C7aGCalXo+ewL+GixgKBfhT2vuL02nbIgNGqVWgTOYw==", + "dev": true + }, + "ldjson-stream": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ldjson-stream/-/ldjson-stream-1.2.1.tgz", + "integrity": "sha1-kb7O2lrE7SsX5kn7d356v6AYnCs=", "dev": true, "requires": { - "extend": "^3.0.0", - "findup-sync": "^2.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", + "split2": "^0.2.1", + "through2": "^0.6.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + } + } + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "liftup": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/liftup/-/liftup-3.0.1.tgz", + "integrity": "sha512-yRHaiQDizWSzoXk3APcA71eOI/UuhEkNN9DiW2Tt44mhYzX4joFoCZlxsSOF7RyeLlfqzFLQI1ngFq3ggMPhOw==", + "dev": true, + "requires": { + "extend": "^3.0.2", + "findup-sync": "^4.0.0", + "fined": "^1.2.0", + "flagged-respawn": "^1.0.1", "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" + "object.map": "^1.0.1", + "rechoir": "^0.7.0", + "resolve": "^1.19.0" }, "dependencies": { "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-4.0.0.tgz", + "integrity": "sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ==", "dev": true, "requires": { "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", + "is-glob": "^4.0.0", + "micromatch": "^4.0.2", "resolve-dir": "^1.0.1" } + }, + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } } } }, + "lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, "lodash": { - "version": "4.17.20", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", - "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", + "dev": true + }, + "log-symbols": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", + "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", + "dev": true, + "requires": { + "chalk": "^4.0.0" + } + }, + "longest-streak": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-2.0.4.tgz", + "integrity": "sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg==", "dev": true }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, "make-iterator": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", @@ -1117,126 +2725,207 @@ "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", "dev": true }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "map-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.1.0.tgz", + "integrity": "sha512-glc9y00wgtwcDmp7GaE/0b0OnxpNJsVf3ael/An6Fe2Q51LLwN1er6sdomLRzz5h0+yMpiYLhWYF5R7HeqVd4g==", + "dev": true + }, + "mathml-tag-names": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", + "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", + "dev": true + }, + "mdast-util-from-markdown": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-0.8.1.tgz", + "integrity": "sha512-qJXNcFcuCSPqUF0Tb0uYcFDIq67qwB3sxo9RPdf9vG8T90ViKnksFqdB/Coq2a7sTnxL/Ify2y7aIQXDkQFH0w==", "dev": true, "requires": { - "object-visit": "^1.0.0" + "@types/mdast": "^3.0.0", + "mdast-util-to-string": "^1.0.0", + "micromark": "~2.10.0", + "parse-entities": "^2.0.0" } }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" + "mdast-util-to-markdown": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-0.5.4.tgz", + "integrity": "sha512-0jQTkbWYx0HdEA/h++7faebJWr5JyBoBeiRf0u3F4F3QtnyyGaWIsOwo749kRb1ttKrLLr+wRtOkfou9yB0p6A==", + "dev": true, + "requires": { + "@types/unist": "^2.0.0", + "longest-streak": "^2.0.0", + "mdast-util-to-string": "^2.0.0", + "parse-entities": "^2.0.0", + "repeat-string": "^1.0.0", + "zwitch": "^1.0.0" + }, + "dependencies": { + "mdast-util-to-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz", + "integrity": "sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==", + "dev": true + } } }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "mdast-util-to-string": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-1.1.0.tgz", + "integrity": "sha512-jVU0Nr2B9X3MU4tSK7JP1CMkSvOj7X5l/GboG1tKRw52lLF1x2Ju92Ms9tNetCcbfX3hzlM73zYo2NKkWSfF/A==", + "dev": true + }, + "meow": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-8.0.0.tgz", + "integrity": "sha512-nbsTRz2fwniJBFgUkcdISq8y/q9n9VbiHYbfwklFh5V4V2uAcxtKQkDc0yCLPM/kP0d+inZBewn3zJqewHE7kg==", "dev": true, "requires": { - "brace-expansion": "^1.1.7" + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + }, + "dependencies": { + "type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "dev": true + } } }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "micromark": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-2.10.1.tgz", + "integrity": "sha512-fUuVF8sC1X7wsCS29SYQ2ZfIZYbTymp0EYr6sab3idFjigFFjGa5UwoniPlV9tAgntjuapW1t9U+S0yDYeGKHQ==", "dev": true, "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" + "debug": "^4.0.0", + "parse-entities": "^2.0.0" }, "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "dev": true, "requires": { - "is-plain-object": "^2.0.4" + "ms": "2.1.2" } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true } } }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + }, + "dependencies": { + "picomatch": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", + "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==", + "dev": true + } + } + }, + "min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", "dev": true }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", "dev": true, "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" } }, - "nomnom": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz", - "integrity": "sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc=", + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "multimatch": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-5.0.0.tgz", + "integrity": "sha512-ypMKuglUrZUD99Tk2bUQ+xNQj43lPEfAeX2o9cTteAmShXy2VHDJpuwu1o0xqoKCt9jLVAvwyFKdLTPXKAfJyA==", "dev": true, "requires": { - "chalk": "~0.4.0", - "underscore": "~1.6.0" + "@types/minimatch": "^3.0.3", + "array-differ": "^3.0.0", + "array-union": "^2.1.0", + "arrify": "^2.0.1", + "minimatch": "^3.0.4" }, "dependencies": { - "ansi-styles": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", - "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=", + "arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", "dev": true - }, - "chalk": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", - "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", - "dev": true, - "requires": { - "ansi-styles": "~1.0.0", - "has-color": "~0.1.0", - "strip-ansi": "~0.1.0" - } } } }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "node-releases": { + "version": "1.1.72", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.72.tgz", + "integrity": "sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw==", + "dev": true + }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", @@ -1246,45 +2935,35 @@ "abbrev": "1" } }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "normalize-package-data": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.0.tgz", + "integrity": "sha512-6lUjEI0d3v6kFrtgA/lOx4zHCWULXsFNIjHolnZCKCTLA6m/G625cdn3O7eNmT0iD3jfo6HZ9cdImGZwf21prw==", "dev": true, "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "hosted-git-info": "^3.0.6", + "resolve": "^1.17.0", + "semver": "^7.3.2", + "validate-npm-package-license": "^3.0.1" } }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "^3.0.0" - } + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", + "dev": true + }, + "normalize-selector": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/normalize-selector/-/normalize-selector-0.2.0.tgz", + "integrity": "sha1-0LFF62kRicY6eNIB3E/bEpPvDAM=", + "dev": true + }, + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", + "dev": true }, "object.defaults": { "version": "1.1.0", @@ -1326,6 +3005,20 @@ "wrappy": "1" } }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, "os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", @@ -1348,6 +3041,53 @@ "os-tmpdir": "^1.0.0" } }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-entities": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-2.0.0.tgz", + "integrity": "sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ==", + "dev": true, + "requires": { + "character-entities": "^1.0.0", + "character-entities-legacy": "^1.0.0", + "character-reference-invalid": "^1.0.0", + "is-alphanumerical": "^1.0.0", + "is-decimal": "^1.0.0", + "is-hexadecimal": "^1.0.0" + } + }, "parse-filepath": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", @@ -1359,16 +3099,28 @@ "path-root": "^0.1.1" } }, + "parse-json": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz", + "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, "parse-passwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", "dev": true }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true }, "path-is-absolute": { @@ -1377,6 +3129,12 @@ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, "path-parse": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", @@ -1398,43 +3156,366 @@ "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", "dev": true }, - "posix-character-classes": { + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true + }, + "postcss": { + "version": "7.0.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.35.tgz", + "integrity": "sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-html": { + "version": "0.36.0", + "resolved": "https://registry.npmjs.org/postcss-html/-/postcss-html-0.36.0.tgz", + "integrity": "sha512-HeiOxGcuwID0AFsNAL0ox3mW6MHH5cstWN1Z3Y+n6H+g12ih7LHdYxWwEA/QmrebctLjo79xz9ouK3MroHwOJw==", + "dev": true, + "requires": { + "htmlparser2": "^3.10.0" + } + }, + "postcss-less": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-less/-/postcss-less-3.1.4.tgz", + "integrity": "sha512-7TvleQWNM2QLcHqvudt3VYjULVB49uiW6XzEUFmvwHzvsOEF5MwBrIXZDJQvJNFGjJQTzSzZnDoCJ8h/ljyGXA==", + "dev": true, + "requires": { + "postcss": "^7.0.14" + } + }, + "postcss-media-query-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", + "integrity": "sha1-J7Ocb02U+Bsac7j3Y1HGCeXO8kQ=", + "dev": true + }, + "postcss-resolve-nested-selector": { "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz", + "integrity": "sha1-Kcy8fDfe36wwTp//C/FZaz9qDk4=", + "dev": true + }, + "postcss-safe-parser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-4.0.2.tgz", + "integrity": "sha512-Uw6ekxSWNLCPesSv/cmqf2bY/77z11O7jZGPax3ycZMFU/oi2DMH9i89AdHc1tRwFg/arFoEwX0IS3LCUxJh1g==", + "dev": true, + "requires": { + "postcss": "^7.0.26" + } + }, + "postcss-sass": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/postcss-sass/-/postcss-sass-0.4.4.tgz", + "integrity": "sha512-BYxnVYx4mQooOhr+zer0qWbSPYnarAy8ZT7hAQtbxtgVf8gy+LSLT/hHGe35h14/pZDTw1DsxdbrwxBN++H+fg==", + "dev": true, + "requires": { + "gonzales-pe": "^4.3.0", + "postcss": "^7.0.21" + } + }, + "postcss-scss": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-2.1.1.tgz", + "integrity": "sha512-jQmGnj0hSGLd9RscFw9LyuSVAa5Bl1/KBPqG1NQw9w8ND55nY4ZEsdlVuYJvLPpV+y0nwTV5v/4rHPzZRihQbA==", + "dev": true, + "requires": { + "postcss": "^7.0.6" + } + }, + "postcss-selector-parser": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.4.tgz", + "integrity": "sha512-gjMeXBempyInaBqpp8gODmwZ52WaYsVOsfr4L4lDQ7n3ncD6mEyySiDtgzCT+NYC0mmeOLvtsF8iaEf0YT6dBw==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1", + "util-deprecate": "^1.0.2" + } + }, + "postcss-syntax": { + "version": "0.36.2", + "resolved": "https://registry.npmjs.org/postcss-syntax/-/postcss-syntax-0.36.2.tgz", + "integrity": "sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w==", + "dev": true + }, + "postcss-value-parser": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", + "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==", + "dev": true + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "dev": true + }, + "ramda": { + "version": "0.27.1", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.27.1.tgz", + "integrity": "sha512-PgIdVpn5y5Yns8vqb8FzBUEYn98V3xcPgawAkkgj0YJ0qDsnHCiNmZYfOGMgOvoB0eWFLpYbhxUR3mxfDIMvpw==", "dev": true }, + "read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true + } + } + }, + "read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "requires": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.0.tgz", + "integrity": "sha512-ADsDEH2bvbjltXEP+hTIAmeFekTFK0V2BTxMkok6qILyAJEXV0AFfoWcAq4yfll5VdIMd/RVXq0lR+wQi5ZU3Q==", "dev": true, "requires": { - "resolve": "^1.1.6" + "resolve": "^1.9.0" } }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", "dev": true, "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" } }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "regexpp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "dev": true + }, + "regextras": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/regextras/-/regextras-0.7.1.tgz", + "integrity": "sha512-9YXf6xtW+qzQ+hcMQXx95MOvfqXFgsKDZodX3qZB0x2n5Z94ioetIITsBtvJbiOyxa/6s9AtyweBLCdPmPko/w==", "dev": true }, + "remark": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/remark/-/remark-13.0.0.tgz", + "integrity": "sha512-HDz1+IKGtOyWN+QgBiAT0kn+2s6ovOxHyPAFGKVE81VSzJ+mq7RwHFledEvB5F1p4iJvOah/LOKdFuzvRnNLCA==", + "dev": true, + "requires": { + "remark-parse": "^9.0.0", + "remark-stringify": "^9.0.0", + "unified": "^9.1.0" + } + }, + "remark-parse": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-9.0.0.tgz", + "integrity": "sha512-geKatMwSzEXKHuzBNU1z676sGcDcFoChMK38TgdHJNAYfFtsfHDQG7MoJAjs6sgYMqyLduCYWDIWZIxiPeafEw==", + "dev": true, + "requires": { + "mdast-util-from-markdown": "^0.8.0" + } + }, + "remark-stringify": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-9.0.0.tgz", + "integrity": "sha512-8x29DpTbVzEc6Dwb90qhxCtbZ6hmj3BxWWDpMhA+1WM4dOEGH5U5/GFe3Be5Hns5MvPSFAr1e2KSVtKZkK5nUw==", + "dev": true, + "requires": { + "mdast-util-to-markdown": "^0.5.0" + } + }, "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", "dev": true }, + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true + }, + "requireindex": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", + "integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==", + "dev": true + }, "resolve": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", @@ -1454,16 +3535,16 @@ "global-modules": "^1.0.0" } }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true }, "rimraf": { @@ -1475,14 +3556,17 @@ "glob": "^7.1.3" } }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "~0.1.10" - } + "run-parallel": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.10.tgz", + "integrity": "sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw==", + "dev": true + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true }, "safer-buffer": { "version": "2.1.2", @@ -1490,258 +3574,595 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" } }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", "dev": true, "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz", + "integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==", + "dev": true + }, + "specificity": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/specificity/-/specificity-0.4.1.tgz", + "integrity": "sha512-1klA3Gi5PD1Wv9Q0wUoOQN1IWAuPu0D1U03ThXTr0cJ20+/iq2tHSDnK7Kk/0LXJ1ztUB2/1Os0wKmfyNgUQfg==", + "dev": true + }, + "split2": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/split2/-/split2-0.2.1.tgz", + "integrity": "sha1-At2smtwD7Au3jBKC7Aecpuha6QA=", + "dev": true, + "requires": { + "through2": "~0.6.1" }, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" } }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" } } } }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "sprintf-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", + "dev": true + }, + "stream-combiner": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", + "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", + "dev": true, + "requires": { + "duplexer": "~0.1.1", + "through": "~2.3.4" + } + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dev": true, "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" + "safe-buffer": "~5.2.0" }, "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "requires": { + "min-indent": "^1.0.0" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "style-search": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", + "integrity": "sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI=", + "dev": true + }, + "stylelint": { + "version": "13.8.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-13.8.0.tgz", + "integrity": "sha512-iHH3dv3UI23SLDrH4zMQDjLT9/dDIz/IpoFeuNxZmEx86KtfpjDOscxLTFioQyv+2vQjPlRZnK0UoJtfxLICXQ==", + "dev": true, + "requires": { + "@stylelint/postcss-css-in-js": "^0.37.2", + "@stylelint/postcss-markdown": "^0.36.2", + "autoprefixer": "^9.8.6", + "balanced-match": "^1.0.0", + "chalk": "^4.1.0", + "cosmiconfig": "^7.0.0", + "debug": "^4.2.0", + "execall": "^2.0.0", + "fast-glob": "^3.2.4", + "fastest-levenshtein": "^1.0.12", + "file-entry-cache": "^6.0.0", + "get-stdin": "^8.0.0", + "global-modules": "^2.0.0", + "globby": "^11.0.1", + "globjoin": "^0.1.4", + "html-tags": "^3.1.0", + "ignore": "^5.1.8", + "import-lazy": "^4.0.0", + "imurmurhash": "^0.1.4", + "known-css-properties": "^0.20.0", + "lodash": "^4.17.20", + "log-symbols": "^4.0.0", + "mathml-tag-names": "^2.1.3", + "meow": "^8.0.0", + "micromatch": "^4.0.2", + "normalize-selector": "^0.2.0", + "postcss": "^7.0.35", + "postcss-html": "^0.36.0", + "postcss-less": "^3.1.4", + "postcss-media-query-parser": "^0.2.3", + "postcss-resolve-nested-selector": "^0.1.1", + "postcss-safe-parser": "^4.0.2", + "postcss-sass": "^0.4.4", + "postcss-scss": "^2.1.1", + "postcss-selector-parser": "^6.0.4", + "postcss-syntax": "^0.36.2", + "postcss-value-parser": "^4.1.0", + "resolve-from": "^5.0.0", + "slash": "^3.0.0", + "specificity": "^0.4.1", + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "style-search": "^0.1.0", + "sugarss": "^2.0.0", + "svg-tags": "^1.0.0", + "table": "^6.0.3", + "v8-compile-cache": "^2.2.0", + "write-file-atomic": "^3.0.3" + }, + "dependencies": { + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "requires": { - "is-descriptor": "^1.0.0" + "fill-range": "^7.0.1" } }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "ms": "2.1.2" } }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "file-entry-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.0.tgz", + "integrity": "sha512-fqoO76jZ3ZnYrXLDRxBR1YvOvc0k844kcOg40bgsPrE25LAb/PDqTY+ho64Xh2c8ZXgIKldchCFHczG2UVRcWA==", "dev": true, "requires": { - "kind-of": "^6.0.0" + "flat-cache": "^3.0.4" } }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "to-regex-range": "^5.0.1" + } + }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.1.0.tgz", + "integrity": "sha512-tW+UkmtNg/jv9CSofAKvgVcO7c2URjhTdW1ZTkcAritblu8tajiYy7YisnIflEwtKssCtOxpnBRoCB7iap0/TA==", + "dev": true + }, + "global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dev": true, + "requires": { + "global-prefix": "^3.0.0" + } + }, + "global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dev": true, + "requires": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + } + }, + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + } + }, + "table": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/table/-/table-6.0.4.tgz", + "integrity": "sha512-sBT4xRLdALd+NFBvwOz8bw4b15htyythha+q+DVZqy2RS08PPC8O2sZFgJYEY7bJvbCFKccs+WIZ/cd+xxTWCw==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "lodash": "^4.17.20", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" } } } }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "stylelint-config-wikimedia": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/stylelint-config-wikimedia/-/stylelint-config-wikimedia-0.10.3.tgz", + "integrity": "sha512-+n082jsEfX4v+ra5F6RfsEnjG6VymnHc613yJeyQAJtigL/+B5XDduVmtXk5vPZ01s0eXTOzVuK0aJ98ofmkoA==", + "dev": true, + "requires": { + "stylelint": "13.8.0", + "stylelint-no-unsupported-browser-features": "4.1.4" + } + }, + "stylelint-no-unsupported-browser-features": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/stylelint-no-unsupported-browser-features/-/stylelint-no-unsupported-browser-features-4.1.4.tgz", + "integrity": "sha512-GORR+/z4KkWP9SWO4fLmC5WAIjDClShSfwCYTuAB9cT8GE+rtOXeAqw5RyXuN9BLIBAPjeO2W7LFIrWUH8x7FA==", "dev": true, "requires": { - "kind-of": "^3.2.0" + "doiuse": "^4.3.1", + "lodash": "^4.17.15", + "postcss": "^8.1.4" }, "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "postcss": { + "version": "8.2.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.2.15.tgz", + "integrity": "sha512-2zO3b26eJD/8rb106Qu2o7Qgg52ND5HPjcyQiK2B98O388h43A448LCslC0dI2P97wCAQRJsFvwTRcXxTKds+Q==", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "colorette": "^1.2.2", + "nanoid": "^3.1.23", + "source-map": "^0.6.1" + }, + "dependencies": { + "colorette": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", + "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", + "dev": true + }, + "nanoid": { + "version": "3.1.23", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", + "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==", + "dev": true + } } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true } } }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "sugarss": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sugarss/-/sugarss-2.0.0.tgz", + "integrity": "sha512-WfxjozUk0UVA4jm+U1d736AUpzSrNsQcIbyOkoE364GrtWmIrFdk5lksEupgWMD4VaT/0kVx1dobpiDumSgmJQ==", "dev": true, "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" + "postcss": "^7.0.2" } }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { - "extend-shallow": "^3.0.0" + "has-flag": "^4.0.0" } }, - "sprintf-js": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", - "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", + "svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=", "dev": true }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "table": { + "version": "6.0.7", + "resolved": "https://registry.npmjs.org/table/-/table-6.0.7.tgz", + "integrity": "sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g==", "dev": true, "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" + "ajv": "^7.0.2", + "lodash": "^4.17.20", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.0" }, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "ajv": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-7.2.1.tgz", + "integrity": "sha512-+nu0HDv7kNSOua9apAVc979qd932rrZeb3WOvoiD31A/p1mIE5/9bN2027pE2rOPYEdS3UHzsvof4hY+lM9/WQ==", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true } } }, - "strip-ansi": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", - "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=", + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", "dev": true }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", "dev": true, "requires": { - "has-flag": "^4.0.0" + "readable-stream": "3" } }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } + "is-number": "^7.0.0" } }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "trim-newlines": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.0.tgz", + "integrity": "sha512-C4+gOpvmxaSMKuEf9Qc134F1ZuOHVXKRbtEflf4NTtuuJDEIJ9p5PXsalL8SkeRw+qit1Mo+yuvMPAKwWg/1hA==", + "dev": true + }, + "trough": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/trough/-/trough-1.0.5.tgz", + "integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==", + "dev": true + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" + "prelude-ls": "^1.2.1" } }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", "dev": true, "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" + "is-typedarray": "^1.0.0" } }, "unc-path-regex": { @@ -1750,12 +4171,6 @@ "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", "dev": true }, - "underscore": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", - "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=", - "dev": true - }, "underscore.string": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-3.3.5.tgz", @@ -1766,85 +4181,189 @@ "util-deprecate": "^1.0.2" } }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "unified": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.0.tgz", + "integrity": "sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==", "dev": true, "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" + "bail": "^1.0.0", + "extend": "^3.0.0", + "is-buffer": "^2.0.0", + "is-plain-obj": "^2.0.0", + "trough": "^1.0.0", + "vfile": "^4.0.0" }, "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } + "is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "dev": true }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", "dev": true } } }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", "dev": true }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "unist-util-find-all-after": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/unist-util-find-all-after/-/unist-util-find-all-after-3.0.2.tgz", + "integrity": "sha512-xaTC/AGZ0rIM2gM28YVRAFPIZpzbpDtU3dRmp7EXlNVA8ziQc4hY3H7BHXM1J49nEmiqc3svnqMReW+PGqbZKQ==", + "dev": true, + "requires": { + "unist-util-is": "^4.0.0" + } + }, + "unist-util-is": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.0.4.tgz", + "integrity": "sha512-3dF39j/u423v4BBQrk1AQ2Ve1FxY5W3JKwXxVFzBODQ6WEvccguhgp802qQLKSnxPODE6WuRZtV+ohlUg4meBA==", + "dev": true + }, + "unist-util-stringify-position": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz", + "integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==", + "dev": true, + "requires": { + "@types/unist": "^2.0.2" + } + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", "dev": true }, + "uri-js": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", + "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, + "v8-compile-cache": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz", + "integrity": "sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q==", + "dev": true + }, "v8flags": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.3.tgz", - "integrity": "sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", "dev": true, "requires": { "homedir-polyfill": "^1.0.1" } }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "vfile": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-4.2.0.tgz", + "integrity": "sha512-a/alcwCvtuc8OX92rqqo7PflxiCgXRFjdyoGVuYV+qbgCb0GgZJRvIgCD4+U/Kl1yhaRsaTwksF88xbPyGsgpw==", + "dev": true, + "requires": { + "@types/unist": "^2.0.0", + "is-buffer": "^2.0.0", + "replace-ext": "1.0.0", + "unist-util-stringify-position": "^2.0.0", + "vfile-message": "^2.0.0" + }, + "dependencies": { + "is-buffer": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", + "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", + "dev": true + } + } + }, + "vfile-message": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz", + "integrity": "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==", + "dev": true, + "requires": { + "@types/unist": "^2.0.0", + "unist-util-stringify-position": "^2.0.0" + } + }, + "vue-eslint-parser": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.6.0.tgz", + "integrity": "sha512-QXxqH8ZevBrtiZMZK0LpwaMfevQi9UL7lY6Kcp+ogWHC88AuwUPwwCIzkOUc1LR4XsYAt/F9yHXAB/QoD17QXA==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "eslint-scope": "^5.0.0", + "eslint-visitor-keys": "^1.1.0", + "espree": "^6.2.1", + "esquery": "^1.4.0", + "lodash": "^4.17.15" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + }, + "espree": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", + "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", + "dev": true, + "requires": { + "acorn": "^7.1.1", + "acorn-jsx": "^5.2.0", + "eslint-visitor-keys": "^1.1.0" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -1854,11 +4373,91 @@ "isexe": "^2.0.0" } }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true + }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, + "y18n": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz", + "integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yaml": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.0.tgz", + "integrity": "sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==", + "dev": true + }, + "yargs": { + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.1.1.tgz", + "integrity": "sha512-hAD1RcFP/wfgfxgMVswPE+z3tlPFtxG8/yWUrG2i17sTWGCGqWnxKcLTF4cUKDUK8fzokwsmO9H0TDkRbMHy8w==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true + }, + "zwitch": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-1.0.5.tgz", + "integrity": "sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==", + "dev": true } } } diff --git a/CommentStreams/package.json b/CommentStreams/package.json index ec570705..89b54169 100644 --- a/CommentStreams/package.json +++ b/CommentStreams/package.json @@ -4,8 +4,11 @@ "test": "grunt test" }, "devDependencies": { - "grunt": "1.3.0", + "eslint-config-wikimedia": "0.20.0", + "grunt": "1.4.0", "grunt-banana-checker": "0.9.0", - "grunt-jsonlint": "1.1.0" + "grunt-eslint": "23.0.0", + "grunt-stylelint": "0.16.0", + "stylelint-config-wikimedia": "0.10.3" } } diff --git a/CommentStreams/resources/CommentStreams.css b/CommentStreams/resources/CommentStreams.css index 0e1b648e..6311ac4b 100644 --- a/CommentStreams/resources/CommentStreams.css +++ b/CommentStreams/resources/CommentStreams.css @@ -22,12 +22,17 @@ margin-left: 30px; } +.cs-comment-header { + padding-top: 2px; + padding-bottom: 2px; +} + .cs-head-comment > .cs-comment-header { border-top: 1px solid #00a7d8; } .cs-target-comment .cs-comment-header { - border: 2px solid green; + border: 2px solid #0f0; } .cs-expanded .cs-comment-header { @@ -35,7 +40,7 @@ } .cs-collapsed .cs-comment-header { - background-color: #eeeeee; + background-color: #eee; margin-bottom: 10px; } @@ -43,11 +48,6 @@ background-color: #f5faff; } -.cs-comment-header { - padding-top: 2px; - padding-bottom: 2px; -} - .cs-comment-header-left { display: inline-block; vertical-align: middle; @@ -82,7 +82,7 @@ .cs-comment-author-anonymous { font-style: italic; opacity: 0.8; - color: #555555; + color: #555; } .cs-comment-author a { @@ -96,7 +96,7 @@ } .cs-comment-details { - color: #555555; + color: #555; opacity: 0.8; font-size: 12px; padding-right: 5px; @@ -107,13 +107,9 @@ padding-left: 5px; } -.cs-button:hover { - background-color: #8eddf5; -} - .cs-button { background-color: transparent; - border: none; + border: 0; font-family: sans-serif; font-weight: bold; text-decoration: none; @@ -122,6 +118,15 @@ box-shadow: none; } +.cs-button:hover { + background-color: #8eddf5; +} + +.cs-button:disabled { + color: #95a5a6; + opacity: 0.2; +} + .cs-button:enabled:active { opacity: 0.5; } @@ -130,35 +135,30 @@ color: #3ccefa; } -.cs-button:disabled { - color: #95a5a6; - opacity: 0.2; -} - .cs-moderator-button { - color: #ff0000; + color: #f00; } .cs-moderator-button:enabled:hover { - color: #ff5555; + color: #f55; } .cs-toggle-button { - border: none; - border-style: none; + border: 0; } -.cs-vote-upcount, .cs-vote-downcount { - color: #555555; +.cs-vote-upcount, +.cs-vote-downcount { + color: #555; padding-left: 3px; } .cs-link-button { - border: none; - border-style: none; + border: 0; } -#cs-add-button, .cs-reply-button { +#cs-add-button, +.cs-reply-button { font-size: 14px; padding-left: 0; } @@ -178,7 +178,7 @@ border-radius: 2px; border-width: 1px; border-color: #00a7d8; - box-style: content-box; + box-sizing: content-box; -webkit-box-sizing: content-box; width: 80%; min-width: 400px; @@ -200,8 +200,9 @@ font-size: 14px; } -// VisualEditor/VEForAll CSS -.ve-area-wrapper, .ve-ce-documentNode { +/* VisualEditor/VEForAll CSS */ +.ve-area-wrapper, +.ve-ce-documentNode { width: auto !important; } @@ -211,7 +212,6 @@ div.ve-ce-branchNode { border: 1px solid #00a7d8; - background: white; + background: #fff; margin-bottom: 5px; } - diff --git a/CommentStreams/resources/CommentStreams.js b/CommentStreams/resources/CommentStreams.js index 45a2ce5a..1dc0a683 100644 --- a/CommentStreams/resources/CommentStreams.js +++ b/CommentStreams/resources/CommentStreams.js @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2016 The MITRE Corporation * * Permission is hereby granted, free of charge, to any person obtaining a @@ -20,7 +20,7 @@ * DEALINGS IN THE SOFTWARE. */ -var commentstreams_controller = ( function( mw, $ ) { +var commentstreams_controller = ( function () { 'use strict'; return { @@ -33,9 +33,9 @@ var commentstreams_controller = ( function( mw, $ ) { moderatorDelete: false, moderatorFastDelete: false, showLabels: false, - userDisplayName: null, newestStreamsOnTop: false, initiallyCollapsed: false, + isNamespaceEnabled: false, enableVoting: false, enableWatchlist: false, comments: [], @@ -57,9 +57,8 @@ var commentstreams_controller = ( function( mw, $ ) { top: '50%', // Top position relative to parent left: '50%' // Left position relative to parent }, - initialize: function() { - var self = this; - this.baseUrl = window.location.href.split( /[?#]/ )[0]; + initialize: function () { + this.baseUrl = window.location.href.split( /[?#]/ )[ 0 ]; this.imagepath = mw.config.get( 'wgExtensionAssetsPath' ) + '/CommentStreams/images/'; if ( window.location.hash ) { @@ -75,12 +74,11 @@ var commentstreams_controller = ( function( mw, $ ) { this.canComment = config.canComment; this.moderatorEdit = config.moderatorEdit; this.moderatorDelete = config.moderatorDelete; - this.moderatorFastDelete = this.moderatorDelete ? - config.moderatorFastDelete : false; + this.moderatorFastDelete = this.moderatorDelete ? config.moderatorFastDelete : false; this.showLabels = config.showLabels; - this.userDisplayName = config.userDisplayName; this.newestStreamsOnTop = config.newestStreamsOnTop; this.initiallyCollapsed = config.initiallyCollapsed; + this.isNamespaceEnabled = config.isNamespaceEnabled; this.enableVoting = config.enableVoting; this.enableWatchlist = config.enableWatchlist; this.comments = config.comments; @@ -90,68 +88,82 @@ var commentstreams_controller = ( function( mw, $ ) { this.scrollToAnchor( this.targetComment ); } }, - scrollToAnchor: function( id ){ + scrollToAnchor: function ( id ) { var element = $( '#' + id ); if ( element.length ) { - $( 'html,body' ).animate( {scrollTop: element.offset().top},'slow'); + $( 'html,body' ).animate( { scrollTop: element.offset().top }, 'slow' ); } }, - setupDivs: function() { + setupDivs: function () { var self = this; - var mainDiv = $( '#cs-comments' ); - if ( !mainDiv.length ) { - mainDiv = $( '<div>' ).attr( 'id', 'cs-comments' ); + if ( self.isNamespaceEnabled && $( '#cs-comments.cs-comments' ).length === 0 ) { + var mainDiv = $( '<div>' ).attr( 'class', 'cs-comments' ).attr( 'id', 'cs-comments' ); mainDiv.insertAfter( '#catlinks' ); } + $( '.cs-comments' ).each( function () { + var commentDiv = $( this ); - var headerDiv = $( '<div> ').attr( 'id', 'cs-header'); - mainDiv.append( headerDiv ); - - var footerDiv = $( '<div> ').attr( 'id', 'cs-footer'); - mainDiv.append( footerDiv ); - - if ( this.canComment ) { - var addButton = $( '<button>' ) - .attr( { - type: 'button', - id: 'cs-add-button', - title: mw.message( 'commentstreams-buttontext-add' ), - 'data-toggle': 'tooltip' - } ) - .addClass( 'cs-button' ); - var addImage = $( '<img>' ) - .attr( { - title: mw.message( 'commentstreams-buttontooltip-add' ), - src: this.imagepath + 'comment_add.png' - } ); - addButton.append( addImage ); - if ( this.showLabels ) { - var addLabel = $( '<span>' ) - .text( mw.message( 'commentstreams-buttontext-add' ) ) - .addClass( 'cs-comment-button-label' ) - addButton.append( addLabel ); + var headerDiv = $( '<div>' ).attr( 'class', 'cs-header' ); + // For backwards compatibility. Please remove in ver 6.0 + if ( commentDiv.attr( 'id' ) === 'cs-comments' ) { + headerDiv.attr( 'id', 'cs-header' ); } + commentDiv.append( headerDiv ); - if ( this.newestStreamsOnTop ) { - headerDiv.append( addButton ); - } else { - footerDiv.append( addButton ); + var footerDiv = $( '<div>' ).attr( 'class', 'cs-footer' ); + // For backwards compatibility. Please remove in ver 6.0 + if ( commentDiv.attr( 'id' ) === 'cs-comments' ) { + footerDiv.attr( 'id', 'cs-footer' ); } + commentDiv.append( footerDiv ); - addButton.click( function() { - self.showNewCommentStreamBox(); - } ); - } + if ( self.canComment ) { + var addButton = $( '<button>' ) + .attr( { + type: 'button', + class: 'cs-add-button', + title: mw.message( 'commentstreams-buttontext-add' ), + 'data-toggle': 'tooltip' + } ) + .addClass( 'cs-button' ); + // For backwards compatibility. Please remove in ver 6.0 + if ( commentDiv.attr( 'id' ) === 'cs-comments' ) { + addButton.attr( 'id', 'cs-add-button' ); + } + var addImage = $( '<img>' ) + .attr( { + title: mw.message( 'commentstreams-buttontooltip-add' ), + src: self.imagepath + 'comment_add.png' + } ); + addButton.append( addImage ); + if ( self.showLabels ) { + var addLabel = $( '<span>' ) + .text( mw.message( 'commentstreams-buttontext-add' ) ) + .addClass( 'cs-comment-button-label' ); + addButton.append( addLabel ); + } + + if ( self.newestStreamsOnTop ) { + headerDiv.append( addButton ); + } else { + footerDiv.append( addButton ); + } + + addButton.click( function () { + self.showNewCommentStreamBox( this ); + } ); + } + } ); }, - addInitialComments: function() { + addInitialComments: function () { var self = this; var parentIndex; for ( parentIndex in this.comments ) { var parentComment = this.comments[ parentIndex ]; var commenthtml = this.formatComment( parentComment ); var location = $( commenthtml ) - .insertBefore( '#cs-footer' ); + .insertBefore( '#' + parentComment.commentblockid + ' .cs-footer' ); var childIndex; for ( childIndex in parentComment.children ) { var childComment = parentComment.children[ childIndex ]; @@ -162,13 +174,13 @@ var commentstreams_controller = ( function( mw, $ ) { } if ( this.initiallyCollapsed ) { - $( '.cs-stream' ).each( function() { + $( '.cs-stream' ).each( function () { self.collapseStream( $( this ), $( this ) .find( '.cs-toggle-button' ) ); } ); } }, - collapseStream: function( stream, button ) { + collapseStream: function ( stream, button ) { stream.find( '.cs-reply-comment' ).addClass( 'cs-hidden' ); stream.find( '.cs-head-comment .cs-comment-body' ).addClass( 'cs-hidden' ); stream.find( '.cs-stream-footer .cs-reply-button' ).addClass( 'cs-hidden' ); @@ -180,7 +192,7 @@ var commentstreams_controller = ( function( mw, $ ) { src: this.imagepath + 'expand.png' } ); }, - expandStream: function( stream, button ) { + expandStream: function ( stream, button ) { stream.find( '.cs-reply-comment' ).removeClass( 'cs-hidden' ); stream.find( '.cs-head-comment .cs-comment-body' ).removeClass( 'cs-hidden' ); stream.find( '.cs-stream-footer .cs-reply-button' ).removeClass( 'cs-hidden' ); @@ -192,27 +204,27 @@ var commentstreams_controller = ( function( mw, $ ) { src: this.imagepath + 'collapse.png' } ); }, - disableAllButtons: function() { + disableAllButtons: function () { $( '.cs-edit-button' ).prop( 'disabled', true ); $( '.cs-reply-button' ).prop( 'disabled', true ); - $( '#cs-add-button' ).prop( 'disabled', true ); + $( '.cs-add-button' ).prop( 'disabled', true ); $( '.cs-delete-button' ).prop( 'disabled', true ); $( '.cs-toggle-button' ).prop( 'disabled', true ); $( '.cs-link-button' ).prop( 'disabled', true ); $( '.cs-vote-button' ).prop( 'disabled', true ); $( '.cs-watch-button' ).prop( 'disabled', true ); }, - enableAllButtons: function() { + enableAllButtons: function () { $( '.cs-edit-button' ).prop( 'disabled', false ); $( '.cs-reply-button' ).prop( 'disabled', false ); - $( '#cs-add-button' ).prop( 'disabled', false ); + $( '.cs-add-button' ).prop( 'disabled', false ); $( '.cs-delete-button' ).prop( 'disabled', false ); $( '.cs-toggle-button' ).prop( 'disabled', false ); $( '.cs-link-button' ).prop( 'disabled', false ); $( '.cs-vote-button' ).prop( 'disabled', false ); $( '.cs-watch-button' ).prop( 'disabled', false ); }, - formatComment: function( commentData ) { + formatComment: function ( commentData ) { var self = this; var comment = this.formatCommentInner( commentData ); @@ -246,11 +258,11 @@ var commentstreams_controller = ( function( mw, $ ) { if ( this.showLabels ) { var replyLabel = $( '<span>' ) .text( mw.message( 'commentstreams-buttontext-reply' ) ) - .addClass( 'cs-comment-button-label' ) + .addClass( 'cs-comment-button-label' ); replyButton.append( replyLabel ); } streamFooter.append( replyButton ); - replyButton.click( function() { + replyButton.click( function () { var pageId = $( this ).attr( 'data-stream-id' ); self.showNewReplyBox( $( this ), pageId ); } ); @@ -259,7 +271,7 @@ var commentstreams_controller = ( function( mw, $ ) { return comment; }, - formatCommentInner: function( commentData ) { + formatCommentInner: function ( commentData ) { var self = this; var commentHeader = $( '<div>' ) .addClass( 'cs-comment-header' ); @@ -318,11 +330,11 @@ var commentstreams_controller = ( function( mw, $ ) { centerDiv.append( divider ); if ( this.canEdit( commentData ) ) { - centerDiv.append( this.createEditButton( commentData.username) ); + centerDiv.append( this.createEditButton( commentData.username ) ); } if ( this.canDelete( commentData ) ) { - centerDiv.append( this.createDeleteButton( commentData.username) ); + centerDiv.append( this.createDeleteButton( commentData.username ) ); } centerDiv.append( this.createPermalinkButton( commentData.pageid ) ); @@ -332,8 +344,7 @@ var commentstreams_controller = ( function( mw, $ ) { var rightDiv = $( '<div>' ) .addClass( 'cs-comment-header-right' ); - if ( commentData.parentid === null && this.enableWatchlist && - !this.isLoggedIn ) { + if ( commentData.parentid === null && this.enableWatchlist && this.isLoggedIn ) { rightDiv.append( this.createWatchButton( commentData ) ); } @@ -353,7 +364,7 @@ var commentstreams_controller = ( function( mw, $ ) { } ); collapseButton.append( collapseimage ); rightDiv.append( collapseButton ); - collapseButton.click( function() { + collapseButton.click( function () { var stream = $( this ).closest( '.cs-stream' ); if ( stream.hasClass( 'cs-expanded' ) ) { self.collapseStream( stream, this ); @@ -378,11 +389,14 @@ var commentstreams_controller = ( function( mw, $ ) { commentClass = 'cs-head-comment'; } var id = 'cs-comment-' + commentData.pageid; + // The following classes are used here: + // * cs-reply-comment + // * cs-head-comment var comment = $( '<div>' ) .addClass( 'cs-comment' ) .addClass( commentClass ) .attr( { - 'id': id, + id: id, 'data-id': commentData.pageid } ); if ( this.targetComment === id ) { @@ -426,7 +440,7 @@ var commentstreams_controller = ( function( mw, $ ) { windowManager.openWindow( urlDialog ); textInput.select(); }, - createEditButton: function( username ) { + createEditButton: function ( username ) { var self = this; var editButton = $( '<button>' ) .addClass( 'cs-button' ) @@ -444,7 +458,7 @@ var commentstreams_controller = ( function( mw, $ ) { src: this.imagepath + 'comment_moderator_edit.png' } ); editButton - .addClass( 'cs-moderator-button' ) + .addClass( 'cs-moderator-button' ); } else { editimage .attr( { @@ -453,20 +467,20 @@ var commentstreams_controller = ( function( mw, $ ) { } ); } editButton.append( editimage ); - editButton.click( function() { + editButton.click( function () { var comment = $( this ).closest( '.cs-comment' ); var pageId = $( comment ).attr( 'data-id' ); self.editComment( $( comment ), pageId ); } ); return editButton; }, - createDeleteButton: function( username ) { + createDeleteButton: function ( username ) { var self = this; var deleteButton = $( '<button>' ) .addClass( 'cs-button' ) .addClass( 'cs-delete-button' ) .attr( { - type: 'button', + type: 'button', title: mw.message( 'commentstreams-buttontooltip-delete' ), 'data-toggle': 'tooltip' } ); @@ -478,7 +492,7 @@ var commentstreams_controller = ( function( mw, $ ) { src: this.imagepath + 'comment_moderator_delete.png' } ); deleteButton - .addClass( 'cs-moderator-button' ) + .addClass( 'cs-moderator-button' ); } else { deleteimage .attr( { @@ -487,14 +501,14 @@ var commentstreams_controller = ( function( mw, $ ) { } ); } deleteButton.append( deleteimage ); - deleteButton.click( function() { + deleteButton.click( function () { var comment = $( this ).closest( '.cs-comment' ); var pageId = $( comment ).attr( 'data-id' ); self.deleteComment( $( comment ), pageId ); } ); return deleteButton; }, - createPermalinkButton: function( pageid ) { + createPermalinkButton: function ( pageid ) { var self = this; var id = 'cs-comment-' + pageid; var permalinkButton = $( '<button>' ) @@ -504,10 +518,10 @@ var commentstreams_controller = ( function( mw, $ ) { title: mw.message( 'commentstreams-buttontooltip-permalink' ), 'data-toggle': 'tooltip' } ) - .click( function() { + .on( 'click', function () { $( '.cs-target-comment' ) .removeClass( 'cs-target-comment' ); - self.scrollToAnchor( id ) + self.scrollToAnchor( id ); var comment = $( this ).closest( '.cs-comment' ); comment .addClass( 'cs-target-comment' ); @@ -522,12 +536,12 @@ var commentstreams_controller = ( function( mw, $ ) { permalinkButton.append( permalinkimage ); return permalinkButton; }, - createWatchButton: function( commentData ) { + createWatchButton: function ( commentData ) { var self = this; var watchButton = $( '<button>' ) .addClass( 'cs-button' ) .addClass( 'cs-watch-button' ) - .click( function() { + .on( 'click', function () { self.watch( $( this ), commentData.pageid ); } ); var watchimage = $( '<img>' ) @@ -544,12 +558,12 @@ var commentstreams_controller = ( function( mw, $ ) { .attr( { title: mw.message( 'commentstreams-buttontooltip-watch' ), src: this.imagepath + 'notwatching.png' - } ) + } ); } watchButton.append( watchimage ); return watchButton; }, - createVotingButtons: function( commentData ) { + createVotingButtons: function ( commentData ) { var self = this; var upButton; @@ -557,7 +571,7 @@ var commentstreams_controller = ( function( mw, $ ) { upButton = $( '<button>' ) .addClass( 'cs-button' ) .addClass( 'cs-vote-button' ) - .click( function() { + .on( 'click', function () { self.vote( $( this ), commentData.pageid, true, commentData.created_timestamp ); } ); @@ -585,7 +599,7 @@ var commentstreams_controller = ( function( mw, $ ) { downButton = $( '<button>' ) .addClass( 'cs-button' ) .addClass( 'cs-vote-button' ) - .click( function() { + .on( 'click', function () { self.vote( $( this ), commentData.pageid, false, commentData.created_timestamp ); } ); @@ -614,7 +628,7 @@ var commentstreams_controller = ( function( mw, $ ) { votingSpan.append( downButton ); return votingSpan; }, - vote: function( button, pageid, up, created_timestamp ) { + vote: function ( button, pageid, up, created_timestamp ) { var self = this; var votespan = button.closest( '.cs-voting-span' ); @@ -626,30 +640,17 @@ var commentstreams_controller = ( function( mw, $ ) { var downimage = votespan.find( '.cs-vote-downimage' ); var newvote; - var oldvote; if ( up ) { if ( upimage.hasClass( 'cs-vote-enabled' ) ) { newvote = 0; - oldvote = 1; } else { newvote = 1; - if ( downimage.hasClass( 'cs-vote-enabled' ) ) { - oldvote = -1; - } else { - oldvote = 0; - } } } else { if ( downimage.hasClass( 'cs-vote-enabled' ) ) { newvote = 0; - oldvote = -1; } else { newvote = -1; - if ( upimage.hasClass( 'cs-vote-enabled' ) ) { - oldvote = 1; - } else { - oldvote = 0; - } } } @@ -657,9 +658,9 @@ var commentstreams_controller = ( function( mw, $ ) { this.disableAllButtons(); new Spinner( self.spinnerOptions ) .spin( document.getElementById( comment.attr( 'id' ) ) ); - CommentStreamsQuerier.vote( pageid, newvote, function( result ) { + CommentStreamsQuerier.vote( pageid, newvote, function ( result ) { $( '.spinner' ).remove(); - if ( result.error === undefined ) { + if ( result === undefined ) { if ( up ) { if ( upimage.hasClass( 'cs-vote-enabled' ) ) { upimage.attr( 'src', self.imagepath + 'upvote-disabled.png' ); @@ -707,17 +708,17 @@ var commentstreams_controller = ( function( mw, $ ) { } } ); }, - watch: function( button, pageid ) { + watch: function ( button, pageid ) { var self = this; - var image = button.find( '.cs-watch-image'); + var image = button.find( '.cs-watch-image' ); var watchaction = !image.hasClass( 'cs-watch-watching' ); var comment = button.closest( '.cs-comment' ); this.disableAllButtons(); new Spinner( self.spinnerOptions ) .spin( document.getElementById( comment.attr( 'id' ) ) ); - CommentStreamsQuerier.watch( pageid, watchaction, function( result ) { + CommentStreamsQuerier.watch( pageid, watchaction, function ( result ) { $( '.spinner' ).remove(); - if ( result.error === undefined ) { + if ( result === undefined ) { if ( watchaction ) { image .attr( { @@ -739,18 +740,18 @@ var commentstreams_controller = ( function( mw, $ ) { self.enableAllButtons(); } ); }, - adjustCommentOrder: function( stream, votediff, upcount, + adjustCommentOrder: function ( stream, votediff, upcount, created_timestamp ) { var nextSiblings = stream.nextAll( '.cs-stream' ); var first = true; var index; for ( index = 0; index < nextSiblings.length; index++ ) { - var sibling = nextSiblings[index]; + var nextSibling = nextSiblings[ index ]; var nextupcountspan = - $( sibling ).find( '.cs-vote-upcount' ); + $( nextSibling ).find( '.cs-vote-upcount' ); var nextupcount = parseInt( nextupcountspan.text() ); var nextdowncountspan = - $( sibling ).find( '.cs-vote-downcount' ); + $( nextSibling ).find( '.cs-vote-downcount' ); var nextdowncount = parseInt( nextdowncountspan.text() ); var nextvotediff = nextupcount - nextdowncount; if ( nextvotediff > votediff ) { @@ -760,7 +761,7 @@ var commentstreams_controller = ( function( mw, $ ) { // keeping looking } else if ( nextupcount === upcount ) { var nextcreated_timestamp = - $( sibling ).attr( 'data-created-timestamp' ); + $( nextSibling ).attr( 'data-created-timestamp' ); if ( this.newestStreamsOnTop ) { if ( nextcreated_timestamp > created_timestamp ) { // keeping looking @@ -768,7 +769,7 @@ var commentstreams_controller = ( function( mw, $ ) { // check previous siblings break; } else { - this.moveComment( stream, true, $( sibling ) ); + this.moveComment( stream, true, $( nextSibling ) ); return; } } else if ( nextcreated_timestamp < created_timestamp ) { @@ -777,39 +778,39 @@ var commentstreams_controller = ( function( mw, $ ) { // check previous siblings break; } else { - this.moveComment( stream, true, $( sibling ) ); + this.moveComment( stream, true, $( nextSibling ) ); return; } } else if ( first ) { // check previous siblings break; } else { - this.moveComment( stream, true, $( sibling ) ); + this.moveComment( stream, true, $( nextSibling ) ); return; } } else if ( first ) { // check previous siblings break; } else { - this.moveComment( stream, true, $( sibling ) ); + this.moveComment( stream, true, $( nextSibling ) ); return; } first = false; } if ( !first ) { this.moveComment( stream, false, - $( nextSiblings[nextSiblings.length - 1] ) ); + $( nextSiblings[ nextSiblings.length - 1 ] ) ); return; } var prevSiblings = stream.prevAll( '.cs-stream' ); first = true; for ( index = 0; index < prevSiblings.length; index++ ) { - var sibling = prevSiblings[index]; + var prevSibling = prevSiblings[ index ]; var prevupcountspan = - $( sibling ).find( '.cs-vote-upcount' ); + $( prevSibling ).find( '.cs-vote-upcount' ); var prevupcount = parseInt( prevupcountspan.text() ); var prevdowncountspan = - $( sibling ).find( '.cs-vote-downcount' ); + $( prevSibling ).find( '.cs-vote-downcount' ); var prevdowncount = parseInt( prevdowncountspan.text() ); var prevvotediff = prevupcount - prevdowncount; if ( prevvotediff < votediff ) { @@ -819,7 +820,7 @@ var commentstreams_controller = ( function( mw, $ ) { // keeping looking } else if ( prevupcount === upcount ) { var prevcreated_timestamp = - $( sibling ).attr( 'data-created-timestamp' ); + $( prevSibling ).attr( 'data-created-timestamp' ); if ( this.newestStreamsOnTop ) { if ( prevcreated_timestamp < created_timestamp ) { // keeping looking @@ -827,7 +828,7 @@ var commentstreams_controller = ( function( mw, $ ) { // done break; } else { - this.moveComment( stream, false, $( sibling ) ); + this.moveComment( stream, false, $( prevSibling ) ); return; } } else if ( prevcreated_timestamp > created_timestamp ) { @@ -836,36 +837,36 @@ var commentstreams_controller = ( function( mw, $ ) { // done break; } else { - this.moveComment( stream, false, $( sibling ) ); + this.moveComment( stream, false, $( prevSibling ) ); return; } } else if ( first ) { // done break; } else { - this.moveComment( stream, false, $( sibling ) ); + this.moveComment( stream, false, $( prevSibling ) ); return; } } else if ( first ) { // done break; } else { - this.moveComment( stream, false, $( sibling ) ); + this.moveComment( stream, false, $( prevSibling ) ); return; } first = false; } if ( !first ) { this.moveComment( stream, true, - $( prevSiblings[prevSiblings.length - 1] ) ); + $( prevSiblings[ prevSiblings.length - 1 ] ) ); return; } // otherwise, the comment was in the correct place already this.enableAllButtons(); }, - moveComment: function( stream, before, location ) { + moveComment: function ( stream, before, location ) { var self = this; - stream.slideUp( 1000, function() { + stream.slideUp( 1000, function () { stream.detach(); stream.hide(); if ( before ) { @@ -873,19 +874,19 @@ var commentstreams_controller = ( function( mw, $ ) { } else { stream.insertAfter( location ); } - stream.slideDown( 1000, function() { + stream.slideDown( 1000, function () { self.enableAllButtons(); var id = $( this ).find( '.cs-head-comment:first' ).attr( 'id' ); self.scrollToAnchor( id ); } ); } ); }, - createDivider: function() { + createDivider: function () { return $( '<span>' ) .addClass( 'cs-comment-details' ) .text( '|' ); }, - formatEditBox: function( is_stream ) { + formatEditBox: function ( is_stream ) { var commentBox = $( '<div>' ) .addClass( 'cs-edit-box' ) .attr( 'id', 'cs-edit-box' ); @@ -893,11 +894,11 @@ var commentstreams_controller = ( function( mw, $ ) { if ( is_stream ) { var titleField = $( '<input>' ) .attr( { - 'id': 'cs-title-edit-field', - 'type': 'text', - 'placeholder': mw.message( 'commentstreams-title-field-placeholder' ) + id: 'cs-title-edit-field', + type: 'text', + placeholder: mw.message( 'commentstreams-title-field-placeholder' ) } ); - commentBox.append( titleField ); + commentBox.append( titleField ); } else { commentBox.addClass( 'cs-reply-edit-box' ); } @@ -909,9 +910,9 @@ var commentstreams_controller = ( function( mw, $ ) { var bodyField = $( '<textarea>' ) .attr( { - 'id': 'cs-body-edit-field', - 'rows': 10, - 'placeholder': mw.message( 'commentstreams-body-field-placeholder' ) + id: 'cs-body-edit-field', + rows: 10, + placeholder: mw.message( 'commentstreams-body-field-placeholder' ) } ); commentBox.append( bodyField ); @@ -919,8 +920,8 @@ var commentstreams_controller = ( function( mw, $ ) { .addClass( 'cs-button' ) .addClass( 'cs-submit-button' ) .attr( { - 'id': 'cs-submit-button', - 'type': 'button' + id: 'cs-submit-button', + type: 'button' } ); var submitimage = $( '<img>' ) .attr( { @@ -935,8 +936,8 @@ var commentstreams_controller = ( function( mw, $ ) { .addClass( 'cs-button' ) .addClass( 'cs-cancel-button' ) .attr( { - 'id': 'cs-cancel-button', - 'type': 'button' + id: 'cs-cancel-button', + type: 'button' } ); var cancelimage = $( '<img>' ) .attr( { @@ -949,16 +950,16 @@ var commentstreams_controller = ( function( mw, $ ) { return commentBox; }, - showNewCommentStreamBox: function() { + showNewCommentStreamBox: function ( addButton ) { var self = this; var editBox = this.formatEditBox( true ); if ( this.newestStreamsOnTop ) { - $( '#cs-header' ).append( editBox ); + $( addButton ).parent( '.cs-header' ).append( editBox ); $( '#cs-edit-box' ) .hide() .slideDown(); } else { - $( '#cs-footer' ).prepend( editBox ); + $( addButton ).parent( '.cs-footer' ).prepend( editBox ); $( '#cs-edit-box' ) .hide() .slideDown(); @@ -968,10 +969,10 @@ var commentstreams_controller = ( function( mw, $ ) { var editField = $( '#cs-body-edit-field' ); editField.applyVisualEditor(); } - $( '#cs-submit-button' ).click( function() { - self.postComment( null ); + $( '#cs-submit-button' ).on( 'click', function () { + self.postComment( null, $( addButton ).parents( '.cs-comments' ).attr( 'id' ) ); } ); - $( '#cs-cancel-button' ).click( function() { + $( '#cs-cancel-button' ).on( 'click', function () { self.hideEditBox( true ); } ); this.disableAllButtons(); @@ -980,7 +981,7 @@ var commentstreams_controller = ( function( mw, $ ) { titleField.focus(); } }, - showNewReplyBox: function( element, topCommentId ) { + showNewReplyBox: function ( element, topCommentId ) { var self = this; var editBox = this.formatEditBox( false ); $( editBox ) @@ -988,10 +989,10 @@ var commentstreams_controller = ( function( mw, $ ) { .hide() .slideDown(); - $( '#cs-submit-button' ).click( function() { - self.postComment( topCommentId ); + $( '#cs-submit-button' ).on( 'click', function () { + self.postComment( topCommentId, '0' ); } ); - $( '#cs-cancel-button' ).click( function() { + $( '#cs-cancel-button' ).on( 'click', function () { self.hideEditBox( true ); } ); this.disableAllButtons(); @@ -1004,10 +1005,9 @@ var commentstreams_controller = ( function( mw, $ ) { } } }, - hideEditBox: function( animated ) { - var self = this; + hideEditBox: function ( animated ) { if ( animated ) { - $( '#cs-edit-box' ).slideUp( 'normal', function() { + $( '#cs-edit-box' ).slideUp( 'normal', function () { $( '#cs-edit-box' ).remove(); } ); } else { @@ -1015,10 +1015,10 @@ var commentstreams_controller = ( function( mw, $ ) { } this.enableAllButtons(); }, - postComment: function( parentPageId ) { + postComment: function ( parentPageId, commentblockid ) { var self = this; if ( this.isLoggedIn ) { - self.postComment2( parentPageId ); + self.postComment2( parentPageId, commentblockid ); } else { var message_text = mw.message( 'commentstreams-dialog-anonymous-message' ).text(); @@ -1028,7 +1028,7 @@ var commentstreams_controller = ( function( mw, $ ) { mw.message( 'commentstreams-dialog-buttontext-cancel' ).text(); var dialog = new OO.ui.MessageDialog(); var window_manager = new OO.ui.WindowManager(); - $( '#cs-comments' ).append( window_manager.$element ); + $( '.cs-comments' ).append( window_manager.$element ); window_manager.addWindows( [ dialog ] ); window_manager.openWindow( dialog, { message: message_text, @@ -1036,31 +1036,27 @@ var commentstreams_controller = ( function( mw, $ ) { { label: ok_text, action: 'ok' }, { label: cancel_text, flags: 'primary' } ] - } ).then( function ( opened ) { - opened.then( function ( closing, data ) { - if ( data && data.action ) { - if ( data.action === 'ok' ) { - self.postComment2( parentPageId ); - } - } - } ); + } ).closed.then( function ( data ) { + if ( data && data.action && data.action === 'ok' ) { + self.postComment2( parentPageId, commentblockid ); + } } ); } }, - postComment2: function( parentPageId ) { + postComment2: function ( parentPageId, commentblockid ) { var self = this; - if ( $( '#cs-body-edit-field' ).css( 'display' ) == 'none' ) { - self.postCommentFromVE( parentPageId ); + if ( $( '#cs-body-edit-field' ).css( 'display' ) === 'none' ) { + self.postCommentFromVE( parentPageId, commentblockid ); } else { var commentText = $( '#cs-body-edit-field' ).val(); - self.realPostComment( parentPageId, commentText ); + self.realPostComment( parentPageId, commentblockid, commentText ); } }, - postCommentFromVE: function( parentPageId ) { + postCommentFromVE: function ( parentPageId, commentblockid ) { var self = this; var editField = $( '#cs-body-edit-field' ); var veInstances = editField.getVEInstances(); - var curVEEditor = veInstances[veInstances.length - 1]; + var curVEEditor = veInstances[ veInstances.length - 1 ]; new mw.Api().post( { action: 'veforall-parsoid-utils', from: 'html', @@ -1069,20 +1065,20 @@ var commentstreams_controller = ( function( mw, $ ) { title: mw.config.get( 'wgPageName' ).split( /(\\|\/)/g ).pop() } ).then( function ( data ) { var commentText = data[ 'veforall-parsoid-utils' ].content; - self.realPostComment( parentPageId, commentText ); + self.realPostComment( parentPageId, commentblockid, commentText ); } ) - .fail( function ( data ) { - self.reportError( 'commentstreams-ve-conversion-error' ); - } ); + .fail( function () { + self.reportError( 'commentstreams-ve-conversion-error' ); + } ); }, - realPostComment: function( parentPageId, commentText ) { + realPostComment: function ( parentPageId, commentblockid, commentText ) { var self = this; var commentTitle; if ( parentPageId === null ) { var titleField = $( '#cs-title-edit-field' ); if ( titleField !== null ) { - commentTitle = titleField .val(); + commentTitle = titleField.val(); if ( commentTitle === null || commentTitle.trim() === '' ) { this.reportError( 'commentstreams-validation-error-nocommenttitle' ); return; @@ -1100,57 +1096,57 @@ var commentstreams_controller = ( function( mw, $ ) { $( '#cs-submit-button' ).prop( 'disabled', true ); $( '#cs-cancel-button' ).prop( 'disabled', true ); - $( '#cs-edit-box' ).fadeTo( 100, 0.2, function() { + $( '#cs-edit-box' ).fadeTo( 100, 0.2, function () { new Spinner( self.spinnerOptions ) .spin( document.getElementById( 'cs-edit-box' ) ); var associatedPageId = mw.config.get( 'wgArticleId' ); CommentStreamsQuerier.postComment( commentTitle, commentText, - associatedPageId, parentPageId, function( result ) { - $( '.spinner' ).remove(); - if ( result.error === undefined ) { - var comment = self.formatComment( result ); - if ( parentPageId ) { - if ( !self.moderatorFastDelete ) { - var deleteSpan = $( '#cs-edit-box' ) + associatedPageId, parentPageId, commentblockid, function ( result ) { + $( '.spinner' ).remove(); + if ( result.error === undefined ) { + var comment = self.formatComment( result ); + if ( parentPageId ) { + if ( !self.moderatorFastDelete ) { + var deleteSpan = $( '#cs-edit-box' ) + .closest( '.cs-stream' ) + .find( '.cs-head-comment' ) + .find( '.cs-comment-header' ) + .find( '.cs-delete-button' ); + deleteSpan.remove(); + } + var location = $( '#cs-edit-box' ) .closest( '.cs-stream' ) - .find( '.cs-head-comment' ) - .find( '.cs-comment-header' ) - .find( '.cs-delete-button' ); - deleteSpan.remove(); - } - var location = $( '#cs-edit-box' ) - .closest( '.cs-stream' ) - .find( '.cs-stream-footer' ); - self.hideEditBox( false ); - comment.insertBefore( $( location ) ) - .hide() - .slideDown(); - } else { - self.hideEditBox( false ); - if ( self.newestStreamsOnTop ) { - comment.insertAfter( '#cs-header' ) + .find( '.cs-stream-footer' ); + self.hideEditBox( false ); + comment.insertBefore( $( location ) ) .hide() .slideDown(); } else { - comment.insertBefore( '#cs-footer' ) - .hide() - .slideDown(); + self.hideEditBox( false ); + if ( self.newestStreamsOnTop ) { + comment.insertAfter( '#' + commentblockid + ' .cs-header' ) + .hide() + .slideDown(); + } else { + comment.insertBefore( '#' + commentblockid + ' .cs-footer' ) + .hide() + .slideDown(); + } + self.adjustCommentOrder( comment, 0, 0, + result.created_timestamp ); } - self.adjustCommentOrder( comment, 0, 0, - result.created_timestamp ); + } else { + self.reportError( result.error ); + $( '#cs-edit-box' ).fadeTo( 0.2, 100, function () { + $( '#cs-submit-button' ).prop( 'disabled', false ); + $( '#cs-cancel-button' ).prop( 'disabled', false ); + } ); } - } else { - self.reportError( result.error ); - $( '#cs-edit-box').fadeTo( 0.2, 100, function() { - $( '#cs-submit-button' ).prop( 'disabled', false ); - $( '#cs-cancel-button' ).prop( 'disabled', false ); - } ); - } - } ); + } ); } ); }, - deleteComment: function( element, pageId ) { + deleteComment: function ( element, pageId ) { var self = this; var message_text = mw.message( 'commentstreams-dialog-delete-message' ).text(); @@ -1160,7 +1156,7 @@ var commentstreams_controller = ( function( mw, $ ) { mw.message( 'commentstreams-dialog-buttontext-no' ).text(); var dialog = new OO.ui.MessageDialog(); var window_manager = new OO.ui.WindowManager(); - $( '#cs-comments' ).append( window_manager.$element ); + $( '.cs-comments' ).append( window_manager.$element ); window_manager.addWindows( [ dialog ] ); window_manager.openWindow( dialog, { message: message_text, @@ -1168,48 +1164,49 @@ var commentstreams_controller = ( function( mw, $ ) { { label: yes_text, action: 'yes' }, { label: no_text, flags: 'primary' } ] - } ).then( function ( opened ) { - opened.then( function ( closing, data ) { - if ( data && data.action ) { - if ( data.action === 'yes' ) { - self.realDeleteComment( element, pageId ); - } - } - } ); + } ).closed.then( function ( data ) { + if ( data && data.action && data.action === 'yes' ) { + self.realDeleteComment( element, pageId ); + } } ); }, - realDeleteComment: function( element, pageId ) { + realDeleteComment: function ( element, pageId ) { var self = this; this.disableAllButtons(); - element.fadeTo( 100, 0.2, function() { + var parentId = element + .closest( '.cs-stream' ) + .find( '.cs-head-comment' ) + .attr( 'data-id' ); + var fadeElement = element; + if ( parentId === pageId && self.moderatorFastDelete ) { + fadeElement = element.closest( '.cs-stream' ); + } + fadeElement.fadeTo( 100, 0.2, function () { new Spinner( self.spinnerOptions ) .spin( document.getElementById( element.attr( 'id' ) ) ); - CommentStreamsQuerier.deleteComment( pageId, function( result ) { + CommentStreamsQuerier.deleteComment( pageId, function ( result ) { $( '.spinner' ).remove(); - if ( result.error === undefined || + if ( result === undefined || result.error === 'commentstreams-api-error-commentnotfound' ) { if ( element.hasClass( 'cs-head-comment' ) ) { element.closest( '.cs-stream' ) - .slideUp( 'normal', function() { + .slideUp( 'normal', function () { element.closest( '.cs-stream' ).remove(); self.enableAllButtons(); } ); } else { - var parentId = element - .closest( '.cs-stream' ) - .find( '.cs-head-comment' ) - .attr( 'data-id' ); - CommentStreamsQuerier.queryComment( parentId, function( result ) { - if ( result.error === undefined && self.canDelete( result ) && + CommentStreamsQuerier.queryComment( parentId, function ( queryResult ) { + if ( queryResult.error === undefined && + self.canDelete( queryResult ) && !self.moderatorFastDelete ) { - self.createDeleteButton( result.username ) - .insertAfter ( element + self.createDeleteButton( queryResult.username ) + .insertAfter( element .closest( '.cs-stream' ) .find( '.cs-head-comment' ) .find( '.cs-comment-header' ) .find( '.cs-edit-button' ) ); } - element.slideUp( 'normal', function() { + element.slideUp( 'normal', function () { element.remove(); self.enableAllButtons(); } ); @@ -1217,20 +1214,20 @@ var commentstreams_controller = ( function( mw, $ ) { } } else { self.reportError( result.error ); - element.fadeTo( 0.2, 100, function() { + fadeElement.fadeTo( 0.2, 100, function () { self.enableAllButtons(); } ); } } ); } ); }, - editComment: function( element, pageId ) { + editComment: function ( element, pageId ) { var self = this; this.disableAllButtons(); - element.fadeTo( 100, 0.2, function() { + element.fadeTo( 100, 0.2, function () { new Spinner( self.spinnerOptions ) .spin( document.getElementById( element.attr( 'id' ) ) ); - CommentStreamsQuerier.queryComment( pageId, function( result ) { + CommentStreamsQuerier.queryComment( pageId, function ( result ) { $( '.spinner' ).remove(); if ( result.error === undefined ) { @@ -1254,17 +1251,17 @@ var commentstreams_controller = ( function( mw, $ ) { editField.applyVisualEditor(); } - $( '#cs-cancel-button' ).click( function() { - commentBox.slideUp( 'normal', function() { - element.fadeTo( 0.2, 100, function() { + $( '#cs-cancel-button' ).on( 'click', function () { + commentBox.slideUp( 'normal', function () { + element.fadeTo( 0.2, 100, function () { commentBox.remove(); self.enableAllButtons(); } ); } ); } ); - $( '#cs-submit-button' ).click( function() { - if ( $( '#cs-body-edit-field' ).css( 'display' ) == 'none' ) { + $( '#cs-submit-button' ).on( 'click', function () { + if ( $( '#cs-body-edit-field' ).css( 'display' ) === 'none' ) { self.editCommentFromVE( element, commentBox, pageId ); } else { var commentText = $( '#cs-body-edit-field' ).val(); @@ -1277,34 +1274,36 @@ var commentstreams_controller = ( function( mw, $ ) { .closest( '.cs-stream' ) .find( '.cs-head-comment' ) .attr( 'data-id' ); - CommentStreamsQuerier.queryComment( parentId, function( result ) { - if ( result.error === undefined && - self.canDelete( result ) && - !self.moderatorFastDelete ) { - self.createDeleteButton( result.username ) - .insertAfter ( element - .closest( '.cs-stream' ) - .find( '.cs-head-comment' ) - .find( '.cs-comment-header' ) - .find( '.cs-edit-button' ) ); + CommentStreamsQuerier.queryComment( parentId, function ( queryResult ) { + if ( queryResult.error === undefined ) { + if ( self.canDelete( queryResult ) && !self.moderatorFastDelete ) { + self.createDeleteButton( queryResult.username ) + .insertAfter( element + .closest( '.cs-stream' ) + .find( '.cs-head-comment' ) + .find( '.cs-comment-header' ) + .find( '.cs-edit-button' ) ); + } + } else { + self.reportError( queryResult.error ); } element.remove(); self.enableAllButtons(); } ); } else { self.reportError( result.error ); - element.fadeTo( 0.2, 100, function() { + element.fadeTo( 0.2, 100, function () { self.enableAllButtons(); } ); } } ); } ); }, - editCommentFromVE: function( element, commentBox, pageId ) { + editCommentFromVE: function ( element, commentBox, pageId ) { var self = this; var editField = $( '#cs-body-edit-field' ); var veInstances = editField.getVEInstances(); - var curVEEditor = veInstances[veInstances.length - 1]; + var curVEEditor = veInstances[ veInstances.length - 1 ]; new mw.Api().post( { action: 'veforall-parsoid-utils', from: 'html', @@ -1315,14 +1314,15 @@ var commentstreams_controller = ( function( mw, $ ) { var commentText = data[ 'veforall-parsoid-utils' ].content; self.realEditComment( element, commentBox, pageId, commentText ); } ) - .fail( function ( data ) { - self.reportError( 'commentstreams-ve-conversion-error' ); - } ); + .fail( function () { + self.reportError( 'commentstreams-ve-conversion-error' ); + } ); }, - realEditComment: function( element, commentBox, pageId, commentText ) { + realEditComment: function ( element, commentBox, pageId, commentText ) { var self = this; + var commentTitle = null; if ( element.hasClass( 'cs-head-comment' ) ) { - var commentTitle = $( '#cs-title-edit-field' ).val(); + commentTitle = $( '#cs-title-edit-field' ).val(); if ( commentTitle === null || commentTitle.trim() === '' ) { self.reportError( 'commentstreams-validation-error-nocommenttitle' ); @@ -1339,58 +1339,63 @@ var commentstreams_controller = ( function( mw, $ ) { $( '#cs-submit-button' ).prop( 'disabled', true ); $( '#cs-cancel-button' ).prop( 'disabled', true ); - commentBox.fadeTo( 100, 0.2, function() { + commentBox.fadeTo( 100, 0.2, function () { new Spinner( self.spinnerOptions ) .spin( document.getElementById( 'cs-edit-box' ) ); CommentStreamsQuerier.editComment( commentTitle, commentText, - pageId, function( result ) { - $( '.spinner' ).remove(); - if ( result.error === undefined ) { - var comment = self.formatCommentInner( result ); - if ( element.closest( '.cs-stream' ).hasClass( 'cs-collapsed' ) ) { - comment.find( '.cs-comment-body' ).addClass( 'cs-hidden' ); - } - commentBox.slideUp( 'normal', function() { - comment.insertAfter( commentBox ); - commentBox.remove(); - element.remove(); - self.enableAllButtons(); - } ); - } else if ( result.error === 'commentstreams-api-error-commentnotfound' ) { - self.reportError( result.error ); - var parentId = element - .closest( '.cs-stream' ) - .find( '.cs-head-comment' ) - .attr( 'data-id' ); - CommentStreamsQuerier.queryComment( parentId, function( result ) { - if ( result.error === undefined && - self.canDelete( result ) && - !self.moderatorFastDelete ) { - self.createDeleteButton( result.username ) - .insertAfter ( element - .closest( '.cs-stream' ) - .find( '.cs-head-comment' ) - .find( '.cs-comment-header' ) - .find( '.cs-edit-button' ) ); + pageId, function ( result ) { + $( '.spinner' ).remove(); + if ( result.error === undefined ) { + var comment = self.formatCommentInner( result ); + if ( element.closest( '.cs-stream' ).hasClass( 'cs-collapsed' ) ) { + comment.find( '.cs-comment-body' ).addClass( 'cs-hidden' ); } - commentBox.slideUp( 'normal', function() { + commentBox.slideUp( 'normal', function () { + comment.insertAfter( commentBox ); commentBox.remove(); element.remove(); self.enableAllButtons(); } ); - } ); - } else { - self.reportError( result.error ); - commentBox.fadeTo( 0.2, 100, function() { - $( '#cs-submit-button' ).prop( 'disabled', false ); - $( '#cs-cancel-button' ).prop( 'disabled', false ); - } ); - } - } ); + } else if ( result.error === 'commentstreams-api-error-commentnotfound' ) { + self.reportError( result.error ); + var parentId = element + .closest( '.cs-stream' ) + .find( '.cs-head-comment' ) + .attr( 'data-id' ); + CommentStreamsQuerier.queryComment( parentId, function ( queryResult ) { + if ( queryResult.error === undefined ) { + if ( + self.canDelete( queryResult ) && + !self.moderatorFastDelete + ) { + self.createDeleteButton( queryResult.usernam ) + .insertAfter( element + .closest( '.cs-stream' ) + .find( '.cs-head-comment' ) + .find( '.cs-comment-header' ) + .find( '.cs-edit-button' ) ); + } + } else { + self.reportError( queryResult.error ); + } + commentBox.slideUp( 'normal', function () { + commentBox.remove(); + element.remove(); + self.enableAllButtons(); + } ); + } ); + } else { + self.reportError( result.error ); + commentBox.fadeTo( 0.2, 100, function () { + $( '#cs-submit-button' ).prop( 'disabled', false ); + $( '#cs-cancel-button' ).prop( 'disabled', false ); + } ); + } + } ); } ); }, - canEdit: function( comment ) { + canEdit: function ( comment ) { var username = comment.username; if ( this.isLoggedIn && ( mw.config.get( 'wgUserName' ) === username || this.moderatorEdit ) ) { @@ -1398,7 +1403,7 @@ var commentstreams_controller = ( function( mw, $ ) { } return false; }, - canDelete: function( comment ) { + canDelete: function ( comment ) { var username = comment.username; if ( this.isLoggedIn && ( mw.config.get( 'wgUserName' ) === username || this.moderatorDelete ) && @@ -1407,12 +1412,17 @@ var commentstreams_controller = ( function( mw, $ ) { } return false; }, - reportError: function( message ) { - var message_text = mw.message( message ).text(); + reportError: function ( message ) { + /* eslint-disable mediawiki/msg-doc */ + var message_text = message; + var mwmessage = mw.message( message ); + if ( mwmessage.exists() ) { + message_text = mwmessage.text(); + } var ok_text = mw.message( 'commentstreams-dialog-buttontext-ok' ).text(); var dialog = new OO.ui.MessageDialog(); var window_manager = new OO.ui.WindowManager(); - $( '#cs-comments' ).append( window_manager.$element ); + $( '.cs-comments' ).append( window_manager.$element ); window_manager.addWindows( [ dialog ] ); window_manager.openWindow( dialog, { message: message_text, @@ -1424,15 +1434,17 @@ var commentstreams_controller = ( function( mw, $ ) { } ); } }; -}( mediaWiki, jQuery ) ); +}() ); window.CommentStreamsController = commentstreams_controller; -( function( mw, $ ) { +( function () { + 'use strict'; + $( document ) - .ready( function() { + .ready( function () { if ( mw.config.exists( 'CommentStreams' ) ) { window.CommentStreamsController.initialize(); } } ); -}( mediaWiki, jQuery ) ); +}() ); diff --git a/CommentStreams/resources/CommentStreamsAllComments.css b/CommentStreams/resources/CommentStreamsAllComments.css index e39ea4bc..4aca1479 100644 --- a/CommentStreams/resources/CommentStreamsAllComments.css +++ b/CommentStreams/resources/CommentStreamsAllComments.css @@ -1,9 +1,6 @@ .csall-message { background-color: #ddd; - padding-top: 5px; - padding-bottom: 5px; - padding-left: 10px; - padding-right: 10px; + padding: 5px 10px 5px 10px; } .csall-wikitable { @@ -20,11 +17,11 @@ .csall-button { font-size: 1em; - padding:5px 15px; - margin:5px 5px; - background:#ccc; - border:0 none; - cursor:pointer; + padding: 5px 15px; + margin: 5px 5px; + background: #ccc; + border: 0 none; + cursor: pointer; -webkit-border-radius: 5px; border-radius: 5px; } diff --git a/CommentStreams/resources/CommentStreamsQuerier.js b/CommentStreams/resources/CommentStreamsQuerier.js index 84d92403..bcb83755 100644 --- a/CommentStreams/resources/CommentStreamsQuerier.js +++ b/CommentStreams/resources/CommentStreamsQuerier.js @@ -20,45 +20,51 @@ * DEALINGS IN THE SOFTWARE. */ -var commentstreams_querier = ( function( mw ) { +var commentstreams_querier = ( function () { + 'use strict'; + return { - queryComment: function( pageid, reply ) { + queryComment: function ( pageid, reply ) { var self = this; var api = new mw.Api(); api.get( { - action: 'csQueryComment', - pageid: pageid - } ) - .done( function( data ) { - reply( data.csQueryComment ); + action: 'csquerycomment', + pageid: pageid + } ) + .done( function ( data ) { + if ( data.csquerycomment === undefined ) { + self.reportError( 'invalid', reply ); + } + reply( data.csquerycomment ); } ) - .fail( function( data ) { - self.reportError( data, reply ); + .fail( function ( code, error ) { + self.reportError( error, reply ); } ); }, - deleteComment: function( pageid, reply ) { + deleteComment: function ( pageid, reply ) { var self = this; var api = new mw.Api(); api.post( { - action: 'csDeleteComment', - pageid: pageid, - token: mw.user.tokens.get( 'csrfToken' ) - } ) - .done( function( data ) { - reply( data ); + action: 'csdeletecomment', + pageid: pageid, + token: mw.user.tokens.get( 'csrfToken' ) + } ) + .done( function () { + reply(); } ) - .fail( function( data ) { - self.reportError( data, reply ); + .fail( function ( code, error ) { + self.reportError( error, reply ); } ); }, - postComment: function( commenttitle, wikitext, associatedid, parentid, + postComment: function ( commenttitle, wikitext, associatedid, parentid, commentblockid, reply ) { var self = this; var api = new mw.Api(); var data = { - action: 'csPostComment', + action: 'cspostcomment', wikitext: wikitext, associatedid: associatedid, + commentblockid: commentblockid, token: mw.user.tokens.get( 'csrfToken' ) }; if ( commenttitle !== null ) { @@ -68,83 +74,99 @@ var commentstreams_querier = ( function( mw ) { data.parentid = parentid; } api.post( - data - ) - .done( function( data ) { - reply( data.csPostComment ); + data + ) + .done( function ( postData ) { + if ( postData.cspostcomment === undefined ) { + self.reportError( 'invalid', reply ); + } + self.queryComment( postData.cspostcomment, reply ); } ) - .fail( function( data ) { - self.reportError( data, reply ); + .fail( function ( code, error ) { + self.reportError( error, reply ); } ); }, - editComment: function( commenttitle, wikitext, pageid, reply ) { + editComment: function ( commenttitle, wikitext, pageid, reply ) { var self = this; var api = new mw.Api(); - api.post( { - action: 'csEditComment', - pageid: pageid, - commenttitle: commenttitle, - wikitext: wikitext, - token: mw.user.tokens.get( 'csrfToken' ) - } ) - .done( function( data ) { - reply( data.csEditComment ); + var data = { + action: 'cseditcomment', + pageid: pageid, + wikitext: wikitext, + token: mw.user.tokens.get( 'csrfToken' ) + }; + if ( commenttitle ) { + data.commenttitle = commenttitle; + } + api.post( + data + ) + .done( function () { + self.queryComment( pageid, reply ); } ) - .fail( function( data ) { - self.reportError( data, reply ); + .fail( function ( code, error ) { + self.reportError( error, reply ); } ); }, - vote: function( pageid, vote, reply ) { + vote: function ( pageid, vote, reply ) { var self = this; var api = new mw.Api(); api.post( { - action: 'csVote', - pageid: pageid, - vote: vote, - token: mw.user.tokens.get( 'csrfToken' ) - } ) - .done( function( data ) { - reply( data.csVote ); + action: 'csvote', + pageid: pageid, + vote: vote, + token: mw.user.tokens.get( 'csrfToken' ) + } ) + .done( function () { + reply(); } ) - .fail( function( data ) { - self.reportError( data, reply ); + .fail( function ( code, error ) { + self.reportError( error, reply ); } ); }, - watch: function( pageid, action, reply ) { + watch: function ( pageid, action, reply ) { var self = this; var api = new mw.Api(); api.post( { - action: action ? 'csWatch' : 'csUnwatch', - pageid: pageid, - token: mw.user.tokens.get( 'csrfToken' ) - } ) - .done( function( data ) { - if ( action ) { - reply( data.csWatch ); - } else { - reply( data.csUnwatch ); - } + action: action ? 'cswatch' : 'csunwatch', + pageid: pageid, + token: mw.user.tokens.get( 'csrfToken' ) + } ) + .done( function () { + reply(); } ) - .fail( function( data ) { - self.reportError( data, reply ); + .fail( function ( code, error ) { + self.reportError( error, reply ); } ); }, - reportError: function( data, reply ) { - if ( data === 'nosuchpageid' ) { + reportError: function ( error, reply ) { + if ( + error === 'invalid' || + error.error === undefined || + error.error.code === undefined || + error.error[ '*' ] === undefined + ) { + reply( { + error: 'commentstreams-api-error-invalid' + } ); + } else if ( error.error.code === 'nosuchpageid' ) { reply( { - 'error': 'commentstreams-api-error-commentnotfound' + error: 'commentstreams-api-error-commentnotfound' } ); - } else if ( data === 'badtoken' ) { + } else if ( error.error.code === 'badtoken' ) { reply( { - 'error': 'commentstreams-api-error-notloggedin' + error: 'commentstreams-api-error-notloggedin' } ); } else { + // These types of errors should never happen, but in the case of install errors, + // syntax errors during development, or conflicting extensions, they could happen. + // Since there is no other good way of debugging them, they will be displayed. reply( { - 'error': data + error: error.error[ '*' ] } ); } } }; -}( mediaWiki ) ); +}() ); window.CommentStreamsQuerier = commentstreams_querier; diff --git a/CommentStreams/sql/addCommentId.sql b/CommentStreams/sql/addCommentId.sql new file mode 100644 index 00000000..5087c2ee --- /dev/null +++ b/CommentStreams/sql/addCommentId.sql @@ -0,0 +1 @@ +ALTER TABLE /*_*/cs_comment_data ADD cst_id varchar(50) DEFAULT "cs-comments"; diff --git a/CommentStreams/sql/commentData.sql b/CommentStreams/sql/commentData.sql index d8d26d73..cde12f59 100644 --- a/CommentStreams/sql/commentData.sql +++ b/CommentStreams/sql/commentData.sql @@ -4,5 +4,6 @@ cst_page_id int(10) unsigned, cst_assoc_page_id int(10) unsigned, cst_parent_page_id int(10) unsigned, cst_comment_title varbinary(255), +cst_id varchar(50) DEFAULT "cs-comments", PRIMARY KEY (cst_page_id) ); |