diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index ef6e90b2..00000000 --- a/.editorconfig +++ /dev/null @@ -1,32 +0,0 @@ -# editorconfig tool configuration -# see http://editorconfig.org for docs - -root = true - -[*] -charset = utf-8 -end_of_line = lf -indent_style = tab -trim_trailing_whitespace = true -insert_final_newline = true -quote_type = single -max_line_length = off - -[*.js] -quote_type = double -ij_javascript_use_double_quotes = true - -[*.yml] -indent_style = space -indent_size = 2 - -[*.xml] -indent_style = space -indent_size = 2 - -[*.json] -indent_style = space -indent_size = 2 - -[composer.json] -indent_size = 4 diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 4be1c918..00000000 --- a/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -# Disable LF normalization for all files -* -text \ No newline at end of file diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 0d32de00..00000000 --- a/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -favicon.* -.htconfig.php -\#* -*.log -*.out -*.version* -favicon.* -*~ - -#ignore reports, should be generted with every build -report/ - -#ignore config files from eclipse, we don't want IDE files in our repository -.project -.buildpath -.externalToolBuilders -.settings -#ignore OSX .DS_Store files -.DS_Store - -/nbproject/ - -#ignore smarty cache -/view/smarty3/compiled/ diff --git a/.tx/config b/.tx/config deleted file mode 100644 index 8542c680..00000000 --- a/.tx/config +++ /dev/null @@ -1,399 +0,0 @@ -[main] -host = https://api.transifex.com - -[o:Friendica:p:friendica:r:addon_advancedcontentfilter_messagespo] -file_filter = advancedcontentfilter/lang//messages.po -source_file = advancedcontentfilter/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_blackout_messagespo] -file_filter = blackout/lang//messages.po -source_file = blackout/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_blockem_messagespo] -file_filter = blockem/lang//messages.po -source_file = blockem/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_blogger_messagespo] -file_filter = blogger/lang//messages.po -source_file = blogger/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_buffer_messagespo] -file_filter = buffer/lang//messages.po -source_file = buffer/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_buglink_messagespo] -file_filter = buglink/lang//messages.po -source_file = buglink/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_catavatar_messagespo] -file_filter = catavatar/lang//messages.po -source_file = catavatar/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_cookienotice_messagespo] -file_filter = cookienotice/lang//messages.po -source_file = cookienotice/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_curweather_messagespo] -file_filter = curweather/lang//messages.po -source_file = curweather/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_diaspora_messagespo] -file_filter = diaspora/lang//messages.po -source_file = diaspora/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_dwpost_messagespo] -file_filter = dwpost/lang//messages.po -source_file = dwpost/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_forumdirectory_messagespo] -file_filter = forumdirectory/lang//messages.po -source_file = forumdirectory/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_fromapp_messagespo] -file_filter = fromapp/lang//messages.po -source_file = fromapp/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_fromgplus_messagespo] -file_filter = fromgplus/lang//messages.po -source_file = fromgplus/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_geonames_messagespo] -file_filter = geonames/lang//messages.po -source_file = geonames/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_gnot_messagespo] -file_filter = gnot/lang//messages.po -source_file = gnot/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_gravatar_messagespo] -file_filter = gravatar/lang//messages.po -source_file = gravatar/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_group_text_messagespo] -file_filter = group_text/lang//messages.po -source_file = group_text/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_ifttt_messagespo] -file_filter = ifttt/lang//messages.po -source_file = ifttt/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_ijpost_messagespo] -file_filter = ijpost/lang//messages.po -source_file = ijpost/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_impressum_messagespo] -file_filter = impressum/lang//messages.po -source_file = impressum/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_infiniteimprobabilitydrive_messagespo] -file_filter = infiniteimprobabilitydrive/lang//messages.po -source_file = infiniteimprobabilitydrive/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_irc_messagespo] -file_filter = irc/lang//messages.po -source_file = irc/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_jappixmini_messagespo] -file_filter = jappixmini/lang//messages.po -source_file = jappixmini/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_js_upload_messagespo] -file_filter = js_upload/lang//messages.po -source_file = js_upload/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_krynn_messagespo] -file_filter = krynn/lang//messages.po -source_file = krynn/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_langfilter_messagespo] -file_filter = langfilter/lang//messages.po -source_file = langfilter/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_libertree_messagespo] -file_filter = libertree/lang//messages.po -source_file = libertree/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_libravatar_messagespo] -file_filter = libravatar/lang//messages.po -source_file = libravatar/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_ljpost_messagespo] -file_filter = ljpost/lang//messages.po -source_file = ljpost/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_mailstream_messagespo] -file_filter = mailstream/lang//messages.po -source_file = mailstream/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_mathjax_messagespo] -file_filter = mathjax/lang//messages.po -source_file = mathjax/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_membersince_messagespo] -file_filter = membersince/lang//messages.po -source_file = membersince/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_morechoice_messagespo] -file_filter = morechoice/lang//messages.po -source_file = morechoice/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_morepokes_messagespo] -file_filter = morepokes/lang//messages.po -source_file = morepokes/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_newmemberwidget_messagespo] -file_filter = newmemberwidget/lang//messages.po -source_file = newmemberwidget/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_notifyall_messagespo] -file_filter = notifyall/lang//messages.po -source_file = notifyall/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_notimeline_messagespo] -file_filter = notimeline/lang//messages.po -source_file = notimeline/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_nsfw_messagespo] -file_filter = nsfw/lang//messages.po -source_file = nsfw/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_numfriends_messagespo] -file_filter = numfriends/lang//messages.po -source_file = numfriends/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_openstreetmap_messagespo] -file_filter = openstreetmap/lang//messages.po -source_file = openstreetmap/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_pageheader_messagespo] -file_filter = pageheader/lang//messages.po -source_file = pageheader/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_piwik_messagespo] -file_filter = piwik/lang//messages.po -source_file = piwik/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_planets_messagespo] -file_filter = planets/lang//messages.po -source_file = planets/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_public_server_messagespo] -file_filter = public_server/lang//messages.po -source_file = public_server/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_pumpio_messagespo] -file_filter = pumpio/lang//messages.po -source_file = pumpio/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_qcomment_messagespo] -file_filter = qcomment/lang//messages.po -source_file = qcomment/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_randplace_messagespo] -file_filter = randplace/lang//messages.po -source_file = randplace/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_remote_permissions_messagespo] -file_filter = remote_permissions/lang//messages.po -source_file = remote_permissions/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_rendertime_messagespo] -file_filter = rendertime/lang//messages.po -source_file = rendertime/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_securemail_messagespo] -file_filter = securemail/lang//messages.po -source_file = securemail/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_showmore_messagespo] -file_filter = showmore/lang//messages.po -source_file = showmore/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_smileybutton_messagespo] -file_filter = smileybutton/lang//messages.po -source_file = smileybutton/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_startpage_messagespo] -file_filter = startpage/lang//messages.po -source_file = startpage/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_statusnet_messagespo] -file_filter = statusnet/lang//messages.po -source_file = statusnet/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_superblock_messagespo] -file_filter = superblock/lang//messages.po -source_file = superblock/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_testdrive_messagespo] -file_filter = testdrive/lang//messages.po -source_file = testdrive/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_tictac_messagespo] -file_filter = tictac/lang//messages.po -source_file = tictac/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_tumblr_messagespo] -file_filter = tumblr/lang//messages.po -source_file = tumblr/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_twitter_messagespo] -file_filter = twitter/lang//messages.po -source_file = twitter/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_viewsrc_messagespo] -file_filter = viewsrc/lang//messages.po -source_file = viewsrc/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_webrtc_messagespo] -file_filter = webrtc/lang//messages.po -source_file = webrtc/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_widgets_messagespo] -file_filter = widgets/lang//messages.po -source_file = widgets/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_windowsphonepush_messagespo] -file_filter = windowsphonepush/lang//messages.po -source_file = windowsphonepush/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_wppost_messagespo] -file_filter = wppost/lang//messages.po -source_file = wppost/lang/C/messages.po -source_lang = en -type = PO - -[o:Friendica:p:friendica:r:addon_xmpp_messagespo] -file_filter = xmpp/lang//messages.po -source_file = xmpp/lang/C/messages.po -source_lang = en -type = PO - diff --git a/.woodpecker/.code_standards_check.yml b/.woodpecker/.code_standards_check.yml deleted file mode 100644 index 60a1bd2a..00000000 --- a/.woodpecker/.code_standards_check.yml +++ /dev/null @@ -1,76 +0,0 @@ -skip_clone: true - -steps: - clone_friendica_base: - image: alpine/git - commands: - - git config --global user.email "no-reply@friendi.ca" - - git config --global user.name "Friendica" - - git config --global --add safe.directory $CI_WORKSPACE - - git clone https://github.com/friendica/friendica.git . - - git checkout $CI_COMMIT_BRANCH - when: - event: pull_request - clone_friendica_addon: - image: alpine/git - commands: - - git config --global user.email "no-reply@friendi.ca" - - git config --global user.name "Friendica" - - git clone $CI_REPO_CLONE_URL addon - - cd addon/ - - git checkout $CI_COMMIT_BRANCH - - git fetch origin $CI_COMMIT_REF - - git merge $CI_COMMIT_SHA - when: - event: pull_request - restore_cache: - image: meltwater/drone-cache:dev - settings: - backend: "filesystem" - restore: true - cache_key: '{{ .Repo.Name }}_phpcs_{{ arch }}_{{ os }}' - archive_format: "gzip" - mount: - - '.composer' - volumes: - - /tmp/drone-cache:/tmp/cache - when: - event: pull_request - composer_install: - image: composer - commands: - - export COMPOSER_HOME=.composer - - ./bin/composer.phar run cs:install - when: - event: pull_request - rebuild_cache: - image: meltwater/drone-cache:dev - settings: - backend: "filesystem" - rebuild: true - cache_key: '{{ .Repo.Name }}_phpcs_{{ arch }}_{{ os }}' - archive_format: "gzip" - mount: - - '.composer' - volumes: - - /tmp/drone-cache:/tmp/cache - when: - event: pull_request - phpstan: - image: friendicaci/php8.3:php8.3.3 - commands: - - ./bin/composer.phar run phpstan; - check: - image: friendicaci/php-cs - commands: - - cd addon/ - - if [ ! -z "$${CI_COMMIT_PULL_REQUEST}" ]; then - git fetch --no-tags origin ${CI_COMMIT_TARGET_BRANCH}; - export CHANGED_FILES="$(git diff --name-status $(git merge-base FETCH_HEAD origin/${CI_COMMIT_TARGET_BRANCH})..${CI_COMMIT_SHA} | grep ^A | cut -f2 | sed -e "s/^/addon\\//")"; - else - export CHANGED_FILES="$(git diff --name-status ${CI_COMMIT_SHA} | grep ^A | cut -f2 | sed -e "s/^/addon\\//")"; - fi - - cd ../ - - /check-php-cs.sh - when: - event: pull_request diff --git a/.woodpecker/.continuous-deployment.yml b/.woodpecker/.continuous-deployment.yml deleted file mode 100644 index 6b41deae..00000000 --- a/.woodpecker/.continuous-deployment.yml +++ /dev/null @@ -1,115 +0,0 @@ -# This prevents executing this pipeline at other servers than ci.friendi.ca -labels: - location: friendica - type: releaser - -skip_clone: true - -steps: - clone_friendica_base: - image: alpine/git - commands: - - git config --global user.email "no-reply@friendi.ca" - - git config --global user.name "Friendica" - - git config --global --add safe.directory $CI_WORKSPACE - - git clone https://github.com/friendica/friendica.git . - - git checkout $CI_COMMIT_BRANCH - when: - repo: friendica/friendica-addons - branch: [ develop, '*-rc' ] - event: push - clone_friendica_addon: - image: alpine/git - commands: - - git config --global user.email "no-reply@friendi.ca" - - git config --global user.name "Friendica" - - git clone $CI_REPO_CLONE_URL addon - - cd addon/ - - git checkout $CI_COMMIT_BRANCH - - git fetch origin $CI_COMMIT_REF - - git merge $CI_COMMIT_SHA - when: - repo: friendica/friendica-addons - branch: [ develop, '*-rc' ] - event: push - restore_cache: - image: meltwater/drone-cache:dev - settings: - backend: "filesystem" - restore: true - cache_key: "{{ .Repo.Name }}_php7.4_{{ arch }}_{{ os }}" - archive_format: "gzip" - mount: - - '.composer' - volumes: - - /tmp/drone-cache:/tmp/cache - when: - repo: friendica/friendica-addons - branch: [ develop, '*-rc' ] - event: push - composer_install: - image: friendicaci/php8.2:php8.2.16 - commands: - - export COMPOSER_HOME=.composer - - composer validate - - composer install --no-dev --optimize-autoloader - volumes: - - /etc/hosts:/etc/hosts - when: - repo: friendica/friendica-addons - branch: [ develop, '*-rc' ] - event: push - create_artifacts: - image: debian - commands: - - apt-get update - - apt-get install bzip2 - - mkdir ./build - - export VERSION="$(cat VERSION)" - - export RELEASE="friendica-addons-$VERSION" - - export ARTIFACT="$RELEASE.tar.gz" - - tar - --exclude='.tx' - --exclude='.git' - --exclude='.editorconfig' - --exclude='.gitattributes' - --exclude='.gitignore' - --exclude='.woodpecker' - --exclude='**/*/messages.po' - -cvzf ./build/$ARTIFACT addon/ - - cd ./build - - sha256sum "$ARTIFACT" > "$ARTIFACT.sum256" - - chmod 664 ./* - - ls -lh - - cat "$ARTIFACT.sum256" - - sha256sum "$ARTIFACT" - when: - repo: friendica/friendica-addons - branch: [ develop, '*-rc' ] - event: push - sign_artifacts: - image: plugins/gpgsign - settings: - key: - from_secret: gpg_key - passphrase: - from_secret: gpg_password - files: - - build/* - exclude: - - build/*.sum256 - detach_sign: true - when: - repo: friendica/friendica-addons - branch: [ develop, '*-rc' ] - event: push - publish_artifacts: - image: alpine - commands: - - cp -fr build/* /tmp/friendica_files/ - volumes: - - files:/tmp/friendica_files - when: - repo: friendica/friendica-addons - branch: [ develop, '*-rc' ] - event: push diff --git a/.woodpecker/.messages.po_check.yml b/.woodpecker/.messages.po_check.yml deleted file mode 100644 index e0239dcd..00000000 --- a/.woodpecker/.messages.po_check.yml +++ /dev/null @@ -1,40 +0,0 @@ -skip_clone: true - -steps: - clone_friendica_base: - image: alpine/git - commands: - - git config --global user.email "no-reply@friendi.ca" - - git config --global user.name "Friendica" - - git config --global --add safe.directory $CI_WORKSPACE - - git clone https://github.com/friendica/friendica.git . - - git checkout $CI_COMMIT_BRANCH - when: - event: pull_request - clone_friendica_addon: - image: alpine/git - commands: - - git config --global user.email "no-reply@friendi.ca" - - git config --global user.name "Friendica" - - git clone $CI_REPO_CLONE_URL addon - - cd addon/ - - git checkout $CI_COMMIT_BRANCH - - git fetch origin $CI_COMMIT_REF - - git merge $CI_COMMIT_SHA - when: - event: pull_request - build_xgettext: - image: friendicaci/transifex - commands: - - /xgettext-addon.sh - when: - event: pull_request - check: - image: friendicaci/transifex - commands: - - /check-addons.sh - when: - event: pull_request - -branches: - exclude: [ stable ] diff --git a/.woodpecker/.phpunit.yml b/.woodpecker/.phpunit.yml deleted file mode 100644 index 8b840f80..00000000 --- a/.woodpecker/.phpunit.yml +++ /dev/null @@ -1,118 +0,0 @@ -matrix: - include: - - PHP_MAJOR_VERSION: 7.4 - PHP_VERSION: 7.4.33 - - PHP_MAJOR_VERSION: 8.0 - PHP_VERSION: 8.0.30 - - PHP_MAJOR_VERSION: 8.1 - PHP_VERSION: 8.1.27 - - PHP_MAJOR_VERSION: 8.2 - PHP_VERSION: 8.2.16 - - PHP_MAJOR_VERSION: 8.3 - PHP_VERSION: 8.3.3 - -# This forces PHP Unit executions at the "opensocial" labeled location (because of much more power...) -labels: - location: opensocial - -skip_clone: true - -steps: - clone_friendica_base: - image: alpine/git - commands: - - git config --global user.email "no-reply@friendi.ca" - - git config --global user.name "Friendica" - - git config --global --add safe.directory $CI_WORKSPACE - - git clone https://github.com/friendica/friendica.git . - - git checkout $CI_COMMIT_BRANCH - clone_friendica_addon: - image: alpine/git - commands: - - git config --global user.email "no-reply@friendi.ca" - - git config --global user.name "Friendica" - - git clone $CI_REPO_CLONE_URL addon - - cd addon/ - - git checkout $CI_COMMIT_BRANCH - - git fetch origin $CI_COMMIT_REF - - git merge $CI_COMMIT_SHA - restore_cache: - image: meltwater/drone-cache:dev - settings: - backend: "filesystem" - restore: true - cache_key: "{{ .Repo.Name }}_php${PHP_MAJOR_VERSION}_{{ arch }}_{{ os }}" - archive_format: "gzip" - mount: - - '.composer' - volumes: - - /tmp/drone-cache:/tmp/cache - composer_install: - image: friendicaci/php${PHP_MAJOR_VERSION}:php${PHP_VERSION} - commands: - - export COMPOSER_HOME=.composer - - ./bin/composer.phar validate - - ./bin/composer.phar install --prefer-dist - volumes: - - /etc/hosts:/etc/hosts - rebuild_cache: - image: meltwater/drone-cache:dev - settings: - backend: "filesystem" - rebuild: true - cache_key: "{{ .Repo.Name }}_php${PHP_MAJOR_VERSION}_{{ arch }}_{{ os }}" - archive_format: "gzip" - mount: - - '.composer' - volumes: - - /tmp/drone-cache:/tmp/cache - test: - image: friendicaci/php${PHP_MAJOR_VERSION}:php${PHP_VERSION} - environment: - MYSQL_HOST: "mariadb" - MYSQL_PORT: "3306" - MYSQL_DATABASE: "test" - MYSQL_PASSWORD: "test" - MYSQL_USER: "test" - REDIS_HOST: "redis" - MEMCACHED_HOST: "memcached" - MEMCACHE_HOST: "memcached" - commands: - - cp config/local-sample.config.php config/local.config.php - - if ! bin/wait-for-connection $MYSQL_HOST $MYSQL_PORT 300; then echo "[ERROR] Waited 300 seconds, no response" >&2; exit 1; fi - - mysql -h$MYSQL_HOST -P$MYSQL_PORT -p$MYSQL_PASSWORD -u$MYSQL_USER $MYSQL_DATABASE < database.sql - - if [ "${PHP_MAJOR_VERSION}" = "8.2" -a "${CI_REPO}" = "friendica/friendica-addons" ]; then - phpenmod xdebug; - export XDEBUG_MODE=coverage; - phpunit --configuration tests/phpunit-addons.xml --coverage-clover clover.xml; - else - phpunit --configuration tests/phpunit-addons.xml; - fi - codecov: - image: friendicaci/codecov - when: - matrix: - PHP_MAJOR_VERSION: 8.2 - PHP_VERSION: 8.2.16 - repo: - - friendica/friendica-addons - commands: - - codecov -R '.' -Z -f 'clover.xml' - environment: - CODECOV_TOKEN: - from_secret: codecov-token - -services: - mariadb: - image: mariadb:latest - environment: - MYSQL_ALLOW_EMPTY_PASSWORD: "true" - MYSQL_DATABASE: "test" - MYSQL_PASSWORD: "test" - MYSQL_USER: "test" - - memcached: - image: memcached - - redis: - image: redis diff --git a/.woodpecker/.releaser.yml b/.woodpecker/.releaser.yml deleted file mode 100644 index 2d880a6b..00000000 --- a/.woodpecker/.releaser.yml +++ /dev/null @@ -1,108 +0,0 @@ -# This prevents executing this pipeline at other servers than ci.friendi.ca -labels: - location: friendica - type: releaser - -skip_clone: true - -steps: - clone_friendica_base: - image: alpine/git - commands: - - git config --global user.email "no-reply@friendi.ca" - - git config --global user.name "Friendica" - - git config --global --add safe.directory $CI_WORKSPACE - - git clone https://github.com/friendica/friendica.git . - - git checkout $CI_COMMIT_BRANCH - when: - repo: friendica/friendica-addons - event: tag - clone_friendica_addon: - image: alpine/git - commands: - - git config --global user.email "no-reply@friendi.ca" - - git config --global user.name "Friendica" - - git clone $CI_REPO_CLONE_URL addon - - cd addon/ - - git checkout $CI_COMMIT_BRANCH - - git fetch origin $CI_COMMIT_REF - - git merge $CI_COMMIT_SHA - when: - repo: friendica/friendica-addons - event: tag - restore_cache: - image: meltwater/drone-cache:dev - settings: - backend: "filesystem" - restore: true - cache_key: "{{ .Repo.Name }}_php7.4_{{ arch }}_{{ os }}" - archive_format: "gzip" - mount: - - '.composer' - volumes: - - /tmp/drone-cache:/tmp/cache - when: - repo: friendica/friendica-addons - event: tag - composer_install: - image: friendicaci/php8.2:php8.2.16 - commands: - - export COMPOSER_HOME=.composer - - composer validate - - composer install --no-dev --optimize-autoloader - when: - repo: friendica/friendica-addons - event: tag - volumes: - - /etc/hosts:/etc/hosts - create_artifacts: - image: debian - commands: - - apt-get update - - apt-get install bzip2 - - mkdir ./build - - export VERSION="$(cat VERSION)" - - export RELEASE="friendica-addons-$VERSION" - - export ARTIFACT="$RELEASE.tar.gz" - - tar - --exclude='.tx' - --exclude='.git' - --exclude='.editorconfig' - --exclude='.gitattributes' - --exclude='.gitignore' - --exclude='.woodpecker' - --exclude='**/*/messages.po' - -cvzf ./build/$ARTIFACT addon/ - - cd ./build - - sha256sum "$ARTIFACT" > "$ARTIFACT.sum256" - - chmod 664 ./* - - ls -lh - - cat "$ARTIFACT.sum256" - - sha256sum "$ARTIFACT" - when: - repo: friendica/friendica-addons - event: tag - sign_artifacts: - image: plugins/gpgsign - settings: - key: - from_secret: gpg_key - passphrase: - from_secret: gpg_password - files: - - build/* - exclude: - - build/*.sum256 - detach_sign: true - when: - repo: friendica/friendica-addons - event: tag - publish_artifacts: - image: alpine - commands: - - cp -fr build/* /tmp/friendica_files/ - volumes: - - files:/tmp/friendica_files - when: - repo: friendica/friendica-addons - event: tag diff --git a/INSTALL.txt b/INSTALL.txt deleted file mode 100644 index 37998583..00000000 --- a/INSTALL.txt +++ /dev/null @@ -1,18 +0,0 @@ -********************* -* Install Using Git * -********************* - -To install all addons using git, cd into your top level Friendica directory and - - git clone https://github.com/friendica/friendica-addons.git addon - -This will clone the entire repository in a directory called addon. They can now be activated in the addons section of your admin panel. - -******************** -* Install Manually * -******************** - -1. Download the archive (Download ZIP button) containing the addons. -2. Unzip the contents of the archive to your harddrive. -3. Upload the extracted directory and all it's contents to /path/to/friendica/addon. You will need to create the addon directory if this is the first addon you have installed. -4. Activate the addon in the addons section of your admin panel. diff --git a/Makefile b/Makefile new file mode 100755 index 00000000..8dd9f543 --- /dev/null +++ b/Makefile @@ -0,0 +1,4 @@ + +all: + @./buildtgz + diff --git a/README.md b/README.md deleted file mode 100644 index 6a3202bb..00000000 --- a/README.md +++ /dev/null @@ -1,29 +0,0 @@ -Addons for Friendica -==================== - -This repository is a collection of addons for the [Friendica Social Communications Server](https://github.com/friendica/friendica). -You can add these addons to the /addon directory of your Friendica installation do extend the functionality of your node. - -After uploading the addons to your server, you need to activate the desired addons in the Admin panel. Addons not activated have no effect on your node. - -## Issues - -Please report any issues you have with addons of Friendica from this repository in [the main issue tracker of the project](https://github.com/friendica/friendica/issues). - -## Connectors - -Among these addons there are also the [connectors](https://github.com/friendica/friendica/blob/stable/doc/Connectors.md) for various other networks (e.g. Twitter, pump.io, Google+) that are needed for communication when the protocol is not supported by Friendica core (DFRN, OStatus and Diaspora). - -For communication with contacts in networks supporting those (e.g. GNU social, Diaspora and red#matrix) you just need to access the page configuration in the Admin panel and enable them. For networks where communication is only possible the API access to a remote account, you need to activate the fitting connectors. - -## Development - -The addon interface of Friendica is very flexible and powerful, so if you are missing functionality, your chances are high it may be added with an addon. -See the [documentation](https://github.com/friendica/friendica/blob/stable/doc/Addons.md) for more information on the addon development. - -## Translation - -Addons can be translated like any other part of Friendica. -Translation for addons is done at [the Transifex Friendica page](https://www.transifex.com/Friendica/friendica/dashboard/). - -Read more about the workflow in the [Friendica translation documentation](https://github.com/friendica/friendica/blob/stable/doc/translations.md#addon). diff --git a/advancedcontentfilter/LICENSE b/advancedcontentfilter/LICENSE deleted file mode 100644 index e877cc1c..00000000 --- a/advancedcontentfilter/LICENSE +++ /dev/null @@ -1,24 +0,0 @@ -Copyright (c) 2011-2018 Hypolite Petovan -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the distribution. - * Neither the name of Friendica nor the names of its contributors - may be used to endorse or promote products derived from this software - without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL FRIENDICA BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE -OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/advancedcontentfilter/README.md b/advancedcontentfilter/README.md deleted file mode 100644 index de16d6f2..00000000 --- a/advancedcontentfilter/README.md +++ /dev/null @@ -1,11 +0,0 @@ -Advanced Content Filter -======================= - -Main author Hypolite Petovan. - - -## License - -The _Advanced Content Filter_ addon is licensed under the [3-clause BSD license][2] see the LICENSE file in the addons directory. - -[1]: http://opensource.org/licenses/BSD-3-Clause diff --git a/advancedcontentfilter/advancedcontentfilter.js b/advancedcontentfilter/advancedcontentfilter.js deleted file mode 100644 index a8fc1c65..00000000 --- a/advancedcontentfilter/advancedcontentfilter.js +++ /dev/null @@ -1,132 +0,0 @@ -$.ajaxSetup({headers: {'X-CSRF-Token': csrfToken}}); - -$.extend({ - ajaxJSON: function(method, url, data) { - return $.ajax({ - type: method.toUpperCase(), - url: url, - data: JSON.stringify(data), - contentType: 'application/json; charset=utf-8', - dataType: 'json' - }); - } -}); - -new Vue({ - el: '#rules', - - data: { - showModal: false, - errorMessage: '', - editedIndex: null, - rule: {id: '', name: '', expression: '', created: ''}, - rules: existingRules || [], - itemUrl: '', - itemJson: '', - currentTheme: currentTheme, - messages: messages, - }, - - watch: { - showModal: function () { - if (this.showModal) { - $(this.$refs.vuemodal).modal('show'); - } else { - $(this.$refs.vuemodal).modal('hide'); - } - } - }, - - methods: { - resetForm: function() { - this.rule = {id: '', name: '', expression: '', created: ''}; - this.showModal = false; - this.editedIndex = null; - }, - - addRule: function () { - if (this.rule.name.trim()) { - this.errorMessage = ''; - - var self = this; - $.ajaxJSON('post', '/advancedcontentfilter/api/rules', this.rule) - .then(function (responseJSON) { - self.rules.push(responseJSON.rule); - self.resetForm(); - }, function (response) { - self.errorMessage = response.responseJSON.exception[0].message; - }); - } - }, - - editRule: function (rule) { - this.editedIndex = this.rules.indexOf(rule); - this.rule = Object.assign({}, rule); - this.showModal = true; - }, - - saveRule: function (rule) { - this.errorMessage = ''; - - var self = this; - $.ajaxJSON('put', '/advancedcontentfilter/api/rules/' + rule.id, rule) - .then(function () { - self.rules[self.editedIndex] = rule; - self.resetForm(); - }, function (response) { - self.errorMessage = response.responseJSON.exception[0].message; - }); - }, - - toggleActive: function (rule) { - var previousValue = this.rules[this.rules.indexOf(rule)].active; - var newValue = Math.abs(parseInt(rule.active) - 1); - - this.rules[this.rules.indexOf(rule)].active = newValue; - - var self = this; - $.ajaxJSON('put', '/advancedcontentfilter/api/rules/' + rule.id, {'active': newValue}) - .fail(function (response) { - self.rules[self.rules.indexOf(rule)].active = previousValue; - console.log(response.responseJSON.message); - }); - }, - - deleteRule: function (rule) { - if (confirm('Are you sure you want to delete this rule?')) { - var self = this; - $.ajaxJSON('delete', '/advancedcontentfilter/api/rules/' + rule.id) - .then(function () { - self.rules.splice(self.rules.indexOf(rule), 1); - }, function (response) { - console.log(response.responseJSON.message); - }); - } - }, - - showVariables: function () { - var urlParts = this.itemUrl.split('/'); - var guid = urlParts[urlParts.length - 1]; - - this.itemJson = ''; - - var self = this; - $.ajaxJSON('get', '/advancedcontentfilter/api/variables/' + guid) - .then(function (responseJSON) { - self.itemJson = responseJSON.variables; - }, function (response) { - self.itemJson = response.responseJSON.message; - }); - - return false; - } - }, - - // These render functions have been compiled from templates/advancedcontentfilter.vue, check this file out for instructions - render: function () { - with(this){return _c('div',{attrs:{"id":"rules"}},[_c('p',[_c('a',{attrs:{"href":"settings/addons"}},[_v("🔙 "+_s(messages.backtosettings))])]),_c('h1',[_v(_s(messages.title)+" "),_c('a',{staticClass:"btn btn-default btn-sm",attrs:{"href":"advancedcontentfilter/help","title":messages.help}},[_c('i',{staticClass:"fa fa-question fa-2x",attrs:{"aria-hidden":"true"}})])]),_c('div',[_v(_s(messages.intro))]),_c('h2',[_v(_s(messages.your_rules)+" "),_c('button',{staticClass:"btn btn-primary btn-sm",attrs:{"title":messages.add_a_rule},on:{"click":function($event){showModal = true}}},[_c('i',{staticClass:"fa fa-plus fa-2x",attrs:{"aria-hidden":"true"}})])]),(rules.length === 0)?_c('div',{},[_v(_s(messages.no_rules))]):_e(),_c('ul',{staticClass:"list-group"},_l((rules),function(rule){return _c('li',{staticClass:"list-group-item"},[_c('p',{staticClass:"pull-right"},[(parseInt(rule.active))?_c('button',{staticClass:"btn btn-xs btn-primary",attrs:{"type":"button","aria-label":messages.disable_this_rule,"title":messages.disable_this_rule},on:{"click":function($event){toggleActive(rule)}}},[_c('i',{staticClass:"fa fa-toggle-on",attrs:{"aria-hidden":"true"}}),_v(" "+_s(messages.enabled))]):_c('button',{staticClass:"btn btn-xs btn-default",attrs:{"type":"button","aria-label":messages.enable_this_rule,"title":messages.enable_this_rule},on:{"click":function($event){toggleActive(rule)}}},[_c('i',{staticClass:"fa fa-toggle-off",attrs:{"aria-hidden":"true"}}),_v(" "+_s(messages.disabled))]),_v(" "),_c('button',{staticClass:"btn btn-xs btn-primary",attrs:{"type":"button","aria-label":messages.edit_this_rule,"title":messages.edit_this_rule},on:{"click":function($event){editRule(rule)}}},[_c('i',{staticClass:"fa fa-pencil",attrs:{"aria-hidden":"true"}})]),_v(" "),_c('button',{staticClass:"btn btn-xs btn-default",attrs:{"type":"button","aria-label":messages.delete_this_rule,"title":messages.delete_this_rule},on:{"click":function($event){deleteRule(rule)}}},[_c('i',{staticClass:"fa fa-trash-o",attrs:{"aria-hidden":"true"}})])]),_c('h3',{staticClass:"list-group-item-heading"},[_v(_s(messages.rule)+" #"+_s(rule.id)+": "+_s(rule.name))]),(rule.expression)?_c('pre',{staticClass:"list-group-item-text"},[_v(_s(rule.expression))]):_e()])})),_c('div',{ref:"vuemodal",staticClass:"modal fade",attrs:{"tabindex":"-1","role":"dialog"}},[_c('div',{staticClass:"modal-dialog",attrs:{"role":"document"}},[_c('div',{staticClass:"modal-content"},[_c('div',{staticClass:"modal-header"},[(currentTheme === 'frio')?_c('button',{staticClass:"close",attrs:{"type":"button","data-dismiss":"modal","aria-label":messages.close},on:{"click":function($event){showModal = false}}},[_c('span',{attrs:{"aria-hidden":"true"}},[_v("×")])]):_e(),(rule.id)?_c('h3',[_v(_s(messages.edit_the_rule)+" \""+_s(rule.name)+"\"")]):_e(),(!rule.id)?_c('h3',[_v(_s(messages.add_a_rule))]):_e()]),_c('div',{staticClass:"modal-body"},[_c('form',[(errorMessage)?_c('div',{staticClass:"alert alert-danger",attrs:{"role":"alert"}},[_v(_s(errorMessage))]):_e(),_c('div',{staticClass:"form-group"},[_c('input',{directives:[{name:"model",rawName:"v-model",value:(rule.name),expression:"rule.name"}],staticClass:"form-control",attrs:{"placeholder":messages.rule_name},domProps:{"value":(rule.name)},on:{"input":function($event){if($event.target.composing)return;$set(rule, "name", $event.target.value)}}})]),_c('div',{staticClass:"form-group"},[_c('input',{directives:[{name:"model",rawName:"v-model",value:(rule.expression),expression:"rule.expression"}],staticClass:"form-control",attrs:{"placeholder":messages.rule_expression},domProps:{"value":(rule.expression)},on:{"input":function($event){if($event.target.composing)return;$set(rule, "expression", $event.target.value)}}})])])]),_c('div',{staticClass:"modal-footer"},[_c('button',{staticClass:"btn btn-default",attrs:{"type":"button","data-dismiss":"modal","aria-label":"Close"},on:{"click":function($event){resetForm()}}},[_v(_s(messages.cancel))]),(rule.id)?_c('button',{staticClass:"btn btn-primary",attrs:{"slot":"button","type":"button"},on:{"click":function($event){saveRule(rule)}},slot:"button"},[_v(_s(messages.save_this_rule))]):_e(),(!rule.id)?_c('button',{staticClass:"btn btn-primary",attrs:{"slot":"button","type":"button"},on:{"click":function($event){addRule()}},slot:"button"},[_v(_s(messages.add_a_rule))]):_e()])])])]),_c('form',{staticClass:"form-inline",on:{"submit":function($event){$event.preventDefault();showVariables()}}},[_c('fieldset',[_c('legend',[_v("Show post variables")]),_c('div',{staticClass:"form-group",staticStyle:{"width":"50%"}},[_c('label',{staticClass:"sr-only",attrs:{"for":"itemUrl"}},[_v("Post URL or item guid")]),_c('input',{directives:[{name:"model",rawName:"v-model",value:(itemUrl),expression:"itemUrl"}],staticClass:"form-control",staticStyle:{"width":"100%"},attrs:{"id":"itemUrl","placeholder":"Post URL or item guid"},domProps:{"value":(itemUrl)},on:{"input":function($event){if($event.target.composing)return;itemUrl=$event.target.value}}})]),_c('button',{staticClass:"btn btn-primary",attrs:{"type":"submit"}},[_v("Show Variables")])])]),_c('pre',{},[_v(_s(itemJson))])])} - }, - - staticRenderFns: [ - ], -}); diff --git a/advancedcontentfilter/advancedcontentfilter.php b/advancedcontentfilter/advancedcontentfilter.php deleted file mode 100644 index aeeff77c..00000000 --- a/advancedcontentfilter/advancedcontentfilter.php +++ /dev/null @@ -1,485 +0,0 @@ - - * Maintainer: Hypolite Petovan - * - * Copyright (c) 2018 Hypolite Petovan - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * * copyright notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the distribution. - * * Neither the name of Friendica nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL FRIENDICA BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -use Friendica\BaseModule; -use Friendica\Content\Text\Markdown; -use Friendica\Core\Hook; -use Friendica\Core\Renderer; -use Friendica\Database\DBA; -use Friendica\Database\DBStructure; -use Friendica\DI; -use Friendica\Model\Post; -use Friendica\Model\Tag; -use Friendica\Model\User; -use Friendica\Module\Security\Login; -use Friendica\Network\HTTPException; -use Friendica\Util\DateTimeFormat; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\ServerRequestInterface; -use Symfony\Component\ExpressionLanguage; - -require_once __DIR__ . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php'; - -function advancedcontentfilter_install() -{ - Hook::register('dbstructure_definition' , __FILE__, 'advancedcontentfilter_dbstructure_definition'); - Hook::register('prepare_body_content_filter', __FILE__, 'advancedcontentfilter_prepare_body_content_filter'); - Hook::register('addon_settings' , __FILE__, 'advancedcontentfilter_addon_settings'); - - Hook::add('dbstructure_definition' , __FILE__, 'advancedcontentfilter_dbstructure_definition'); - DBStructure::performUpdate(); - - DI::logger()->notice('installed advancedcontentfilter'); -} - -/* - * Hooks - */ - -function advancedcontentfilter_dbstructure_definition(&$database) -{ - $database['advancedcontentfilter_rules'] = [ - 'comment' => 'Advancedcontentfilter addon rules', - 'fields' => [ - 'id' => ['type' => 'int unsigned', 'not null' => '1', 'extra' => 'auto_increment', 'primary' => '1', 'comment' => 'Auto incremented rule id'], - 'uid' => ['type' => 'int unsigned', 'not null' => '1', 'comment' => 'Owner user id'], - 'name' => ['type' => 'varchar(255)', 'not null' => '1', 'comment' => 'Rule name'], - 'expression' => ['type' => 'mediumtext' , 'not null' => '1', 'comment' => 'Expression text'], - 'serialized' => ['type' => 'mediumtext' , 'not null' => '1', 'comment' => 'Serialized parsed expression'], - 'active' => ['type' => 'boolean' , 'not null' => '1', 'default' => '1', 'comment' => 'Whether the rule is active or not'], - 'created' => ['type' => 'datetime' , 'not null' => '1', 'default' => DBA::NULL_DATETIME, 'comment' => 'Creation date'], - ], - 'indexes' => [ - 'PRIMARY' => ['id'], - 'uid_active' => ['uid', 'active'], - ] - ]; -} - -/** - * @param array $item Prepared by either Model\Item::prepareBody or advancedcontentfilter_prepare_item_row - * @return array - */ -function advancedcontentfilter_get_filter_fields(array $item) -{ - $vars = []; - - // Convert the language JSON text into a filterable format - if (!empty($item['language']) && ($languages = json_decode($item['language'], true))) { - foreach ($languages as $key => $value) { - $vars['language_' . strtolower($key)] = $value; - } - } - - foreach ($item as $key => $value) { - $vars[str_replace('-', '_', $key)] = $value; - } - - ksort($vars); - - return $vars; -} - -function advancedcontentfilter_prepare_body_content_filter(&$hook_data) -{ - static $expressionLanguage; - - if (is_null($expressionLanguage)) { - $expressionLanguage = new ExpressionLanguage\ExpressionLanguage(); - } - - if (!DI::userSession()->getLocalUserId()) { - return; - } - - $vars = advancedcontentfilter_get_filter_fields($hook_data['item']); - - $rules = DI::cache()->get('rules_' . DI::userSession()->getLocalUserId()); - if (!isset($rules)) { - $rules = DBA::toArray(DBA::select( - 'advancedcontentfilter_rules', - ['name', 'expression', 'serialized'], - ['uid' => DI::userSession()->getLocalUserId(), 'active' => true] - )); - - DI::cache()->set('rules_' . DI::userSession()->getLocalUserId(), $rules); - } - - if ($rules) { - foreach($rules as $rule) { - try { - $serializedParsedExpression = new ExpressionLanguage\SerializedParsedExpression( - $rule['expression'], - $rule['serialized'] - ); - - // The error suppression operator is used because of potentially broken user-supplied regular expressions - $found = (bool) @$expressionLanguage->evaluate($serializedParsedExpression, $vars); - } catch (Exception $e) { - $found = false; - } - - if ($found) { - $hook_data['filter_reasons'][] = DI::l10n()->t('Filtered by rule: %s', $rule['name']); - break; - } - } - } -} - - -function advancedcontentfilter_addon_settings(array &$data) -{ - if (!DI::userSession()->getLocalUserId()) { - return; - } - - $data = [ - 'addon' => 'advancedcontentfilter', - 'title' => DI::l10n()->t('Advanced Content Filter'), - 'href' => 'advancedcontentfilter', - ]; -} - -/* - * Module - */ - -/** - * This is a statement rather than an actual function definition. The simple - * existence of this method is checked to figure out if the addon offers a - * module. - */ -function advancedcontentfilter_module() {} - -function advancedcontentfilter_init() -{ - if (DI::args()->getArgc() > 1 && DI::args()->getArgv()[1] == 'api') { - $slim = \Slim\Factory\AppFactory::create(); - - /** - * The routing middleware should be added before the ErrorMiddleware - * Otherwise exceptions thrown from it will not be handled - */ - $slim->addRoutingMiddleware(); - - $slim->addErrorMiddleware(true, true, true, DI::logger()); - - // register routes - $slim->group('/advancedcontentfilter/api', function (\Slim\Routing\RouteCollectorProxy $app) { - $app->group('/rules', function (\Slim\Routing\RouteCollectorProxy $app) { - $app->get('', 'advancedcontentfilter_get_rules'); - $app->post('', 'advancedcontentfilter_post_rules'); - - $app->get('/{id}', 'advancedcontentfilter_get_rules_id'); - $app->put('/{id}', 'advancedcontentfilter_put_rules_id'); - $app->delete('/{id}', 'advancedcontentfilter_delete_rules_id'); - }); - - $app->group('/variables', function (\Slim\Routing\RouteCollectorProxy $app) { - $app->get('/{guid}', 'advancedcontentfilter_get_variables_guid'); - }); - }); - - $slim->run(); - - exit; - } -} - -function advancedcontentfilter_content() -{ - if (!DI::userSession()->getLocalUserId()) { - return Login::form('/' . implode('/', DI::args()->getArgv())); - } - - if (DI::args()->getArgc() > 1 && DI::args()->getArgv()[1] == 'help') { - $user = User::getById(DI::userSession()->getLocalUserId()); - - $lang = $user['language']; - - $default_dir = 'addon/advancedcontentfilter/doc/'; - $help_file = 'advancedcontentfilter.md'; - $help_path = $default_dir . $help_file; - if (file_exists($default_dir . $lang . '/' . $help_file)) { - $help_path = $default_dir . $lang . '/' . $help_file; - } - - $content = file_get_contents($help_path); - - $html = Markdown::convert($content, false); - - $html = str_replace('code>', 'key>', $html); - - return $html; - } else { - $t = Renderer::getMarkupTemplate('settings.tpl', 'addon/advancedcontentfilter/'); - return Renderer::replaceMacros($t, [ - '$messages' => [ - 'backtosettings' => DI::l10n()->t('Back to Addon Settings'), - 'title' => DI::l10n()->t('Advanced Content Filter'), - 'add_a_rule' => DI::l10n()->t('Add a Rule'), - 'help' => DI::l10n()->t('Help'), - 'intro' => DI::l10n()->t('Add and manage your personal content filter rules in this screen. Rules have a name and an arbitrary expression that will be matched against post data. For a complete reference of the available operations and variables, check the help page.'), - 'your_rules' => DI::l10n()->t('Your rules'), - 'no_rules' => DI::l10n()->t('You have no rules yet! Start adding one by clicking on the button above next to the title.'), - 'disabled' => DI::l10n()->t('Disabled'), - 'enabled' => DI::l10n()->t('Enabled'), - 'disable_this_rule' => DI::l10n()->t('Disable this rule'), - 'enable_this_rule' => DI::l10n()->t('Enable this rule'), - 'edit_this_rule' => DI::l10n()->t('Edit this rule'), - 'edit_the_rule' => DI::l10n()->t('Edit the rule'), - 'save_this_rule' => DI::l10n()->t('Save this rule'), - 'delete_this_rule' => DI::l10n()->t('Delete this rule'), - 'rule' => DI::l10n()->t('Rule'), - 'close' => DI::l10n()->t('Close'), - 'addtitle' => DI::l10n()->t('Add new rule'), - 'rule_name' => DI::l10n()->t('Rule Name'), - 'rule_expression' => DI::l10n()->t('Rule Expression'), - 'cancel' => DI::l10n()->t('Cancel'), - ], - '$current_theme' => DI::appHelper()->getCurrentTheme(), - '$rules' => DBA::toArray(DBA::select('advancedcontentfilter_rules', [], ['uid' => DI::userSession()->getLocalUserId()])), - '$form_security_token' => BaseModule::getFormSecurityToken() - ]); - } -} - -/* - * Common functions - */ -function advancedcontentfilter_build_fields($data) -{ - $fields = []; - - if (!empty($data['name'])) { - $fields['name'] = $data['name']; - } - - if (!empty($data['expression'])) { - // Using a dummy item to validate the field existence - $condition = ["(`uid` = ? OR `uid` = 0)", DI::userSession()->getLocalUserId()]; - $params = ['order' => ['uid' => true]]; - $item_row = Post::selectFirstForUser(DI::userSession()->getLocalUserId(), [], $condition, $params); - - if (!DBA::isResult($item_row)) { - throw new HTTPException\NotFoundException(DI::l10n()->t('This addon requires this node having at least one post')); - } - - $expressionLanguage = new ExpressionLanguage\ExpressionLanguage(); - $parsedExpression = $expressionLanguage->parse( - $data['expression'], - array_keys(advancedcontentfilter_get_filter_fields(advancedcontentfilter_prepare_item_row($item_row))) - ); - - $serialized = serialize($parsedExpression->getNodes()); - - $fields['expression'] = $data['expression']; - $fields['serialized'] = $serialized; - } - - if (isset($data['active'])) { - $fields['active'] = intval($data['active']); - } else { - $fields['active'] = 1; - } - - return $fields; -} - -/* - * API - */ - -function advancedcontentfilter_get_rules(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface -{ - if (!DI::userSession()->getLocalUserId()) { - throw new HTTPException\UnauthorizedException(DI::l10n()->t('You must be logged in to use this method')); - } - - $rules = DBA::toArray(DBA::select('advancedcontentfilter_rules', [], ['uid' => DI::userSession()->getLocalUserId()])); - - $response->getBody()->write(json_encode($rules)); - return $response->withHeader('Content-Type', 'application/json'); -} - -function advancedcontentfilter_get_rules_id(ServerRequestInterface $request, ResponseInterface $response, $args) -{ - if (!DI::userSession()->getLocalUserId()) { - throw new HTTPException\UnauthorizedException(DI::l10n()->t('You must be logged in to use this method')); - } - - $rule = DBA::selectFirst('advancedcontentfilter_rules', [], ['id' => $args['id'], 'uid' => DI::userSession()->getLocalUserId()]); - - $response->getBody()->write(json_encode($rule)); - return $response->withHeader('Content-Type', 'application/json'); -} - -function advancedcontentfilter_post_rules(ServerRequestInterface $request, ResponseInterface $response) -{ - if (!DI::userSession()->getLocalUserId()) { - throw new HTTPException\UnauthorizedException(DI::l10n()->t('You must be logged in to use this method')); - } - - if (!BaseModule::checkFormSecurityToken()) { - throw new HTTPException\BadRequestException(DI::l10n()->t('Invalid form security token, please refresh the page.')); - } - - $data = json_decode($request->getBody(), true); - - try { - $fields = advancedcontentfilter_build_fields($data); - } catch (Exception $e) { - throw new HTTPException\BadRequestException($e->getMessage(), $e); - } - - if (empty($fields['name']) || empty($fields['expression'])) { - throw new HTTPException\BadRequestException(DI::l10n()->t('The rule name and expression are required.')); - } - - $fields['uid'] = DI::userSession()->getLocalUserId(); - $fields['created'] = DateTimeFormat::utcNow(); - - if (!DBA::insert('advancedcontentfilter_rules', $fields)) { - throw new HTTPException\ServiceUnavailableException(DBA::errorMessage()); - } - - $rule = DBA::selectFirst('advancedcontentfilter_rules', [], ['id' => DBA::lastInsertId()]); - - DI::cache()->delete('rules_' . DI::userSession()->getLocalUserId()); - - $response->getBody()->write(json_encode(['message' => DI::l10n()->t('Rule successfully added'), 'rule' => $rule])); - return $response->withHeader('Content-Type', 'application/json'); -} - -function advancedcontentfilter_put_rules_id(ServerRequestInterface $request, ResponseInterface $response, $args) -{ - if (!DI::userSession()->getLocalUserId()) { - throw new HTTPException\UnauthorizedException(DI::l10n()->t('You must be logged in to use this method')); - } - - if (!BaseModule::checkFormSecurityToken()) { - throw new HTTPException\BadRequestException(DI::l10n()->t('Invalid form security token, please refresh the page.')); - } - - if (!DBA::exists('advancedcontentfilter_rules', ['id' => $args['id'], 'uid' => DI::userSession()->getLocalUserId()])) { - throw new HTTPException\NotFoundException(DI::l10n()->t('Rule doesn\'t exist or doesn\'t belong to you.')); - } - - $data = json_decode($request->getBody(), true); - - try { - $fields = advancedcontentfilter_build_fields($data); - } catch (Exception $e) { - throw new HTTPException\BadRequestException($e->getMessage(), $e); - } - - if (!DBA::update('advancedcontentfilter_rules', $fields, ['id' => $args['id']])) { - throw new HTTPException\ServiceUnavailableException(DBA::errorMessage()); - } - - DI::cache()->delete('rules_' . DI::userSession()->getLocalUserId()); - - $response->getBody()->write(json_encode(['message' => DI::l10n()->t('Rule successfully updated')])); - return $response->withHeader('Content-Type', 'application/json'); -} - -function advancedcontentfilter_delete_rules_id(ServerRequestInterface $request, ResponseInterface $response, $args) -{ - if (!DI::userSession()->getLocalUserId()) { - throw new HTTPException\UnauthorizedException(DI::l10n()->t('You must be logged in to use this method')); - } - - if (!BaseModule::checkFormSecurityToken()) { - throw new HTTPException\BadRequestException(DI::l10n()->t('Invalid form security token, please refresh the page.')); - } - - if (!DBA::exists('advancedcontentfilter_rules', ['id' => $args['id'], 'uid' => DI::userSession()->getLocalUserId()])) { - throw new HTTPException\NotFoundException(DI::l10n()->t('Rule doesn\'t exist or doesn\'t belong to you.')); - } - - if (!DBA::delete('advancedcontentfilter_rules', ['id' => $args['id']])) { - throw new HTTPException\ServiceUnavailableException(DBA::errorMessage()); - } - - DI::cache()->delete('rules_' . DI::userSession()->getLocalUserId()); - - $response->getBody()->write(json_encode(['message' => DI::l10n()->t('Rule successfully deleted')])); - return $response->withHeader('Content-Type', 'application/json'); -} - -function advancedcontentfilter_get_variables_guid(ServerRequestInterface $request, ResponseInterface $response, $args) -{ - if (!DI::userSession()->getLocalUserId()) { - throw new HTTPException\UnauthorizedException(DI::l10n()->t('You must be logged in to use this method')); - } - - if (!isset($args['guid'])) { - throw new HTTPException\BadRequestException(DI::l10n()->t('Missing argument: guid.')); - } - - $condition = ["`guid` = ? AND (`uid` = ? OR `uid` = 0)", $args['guid'], DI::userSession()->getLocalUserId()]; - $params = ['order' => ['uid' => true]]; - $item_row = Post::selectFirstForUser(DI::userSession()->getLocalUserId(), [], $condition, $params); - - if (!DBA::isResult($item_row)) { - throw new HTTPException\NotFoundException(DI::l10n()->t('Unknown post with guid: %s', $args['guid'])); - } - - $return = advancedcontentfilter_get_filter_fields(advancedcontentfilter_prepare_item_row($item_row)); - - $response->getBody()->write(json_encode(['variables' => str_replace('\\\'', '\'', var_export($return, true))])); - return $response->withHeader('Content-Type', 'application/json'); -} - -/** - * This mimimcs the processing performed in Model\Item::prepareBody - * - * @param array $item_row - * @return array - * @throws HTTPException\InternalServerErrorException - * @throws ImagickException - */ -function advancedcontentfilter_prepare_item_row(array $item_row): array -{ - $tags = Tag::populateFromItem($item_row); - - $item_row['tags'] = $tags['tags']; - $item_row['hashtags'] = $tags['hashtags']; - $item_row['mentions'] = $tags['mentions']; - $item_row['attachments'] = DI::postMediaRepository()->splitAttachments($item_row['uri-id']); - - return $item_row; -} diff --git a/advancedcontentfilter/asset/vue/dist/vue.js b/advancedcontentfilter/asset/vue/dist/vue.js deleted file mode 100644 index 04bcb375..00000000 --- a/advancedcontentfilter/asset/vue/dist/vue.js +++ /dev/null @@ -1,11894 +0,0 @@ -/*! - * Vue.js v2.7.13 - * (c) 2014-2022 Evan You - * Released under the MIT License. - */ -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : - typeof define === 'function' && define.amd ? define(factory) : - (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Vue = factory()); -})(this, (function () { 'use strict'; - - var emptyObject = Object.freeze({}); - var isArray = Array.isArray; - // These helpers produce better VM code in JS engines due to their - // explicitness and function inlining. - function isUndef(v) { - return v === undefined || v === null; - } - function isDef(v) { - return v !== undefined && v !== null; - } - function isTrue(v) { - return v === true; - } - function isFalse(v) { - return v === false; - } - /** - * Check if value is primitive. - */ - function isPrimitive(value) { - return (typeof value === 'string' || - typeof value === 'number' || - // $flow-disable-line - typeof value === 'symbol' || - typeof value === 'boolean'); - } - function isFunction(value) { - return typeof value === 'function'; - } - /** - * Quick object check - this is primarily used to tell - * objects from primitive values when we know the value - * is a JSON-compliant type. - */ - function isObject(obj) { - return obj !== null && typeof obj === 'object'; - } - /** - * Get the raw type string of a value, e.g., [object Object]. - */ - var _toString = Object.prototype.toString; - function toRawType(value) { - return _toString.call(value).slice(8, -1); - } - /** - * Strict object type check. Only returns true - * for plain JavaScript objects. - */ - function isPlainObject(obj) { - return _toString.call(obj) === '[object Object]'; - } - function isRegExp(v) { - return _toString.call(v) === '[object RegExp]'; - } - /** - * Check if val is a valid array index. - */ - function isValidArrayIndex(val) { - var n = parseFloat(String(val)); - return n >= 0 && Math.floor(n) === n && isFinite(val); - } - function isPromise(val) { - return (isDef(val) && - typeof val.then === 'function' && - typeof val.catch === 'function'); - } - /** - * Convert a value to a string that is actually rendered. - */ - function toString(val) { - return val == null - ? '' - : Array.isArray(val) || (isPlainObject(val) && val.toString === _toString) - ? JSON.stringify(val, null, 2) - : String(val); - } - /** - * Convert an input value to a number for persistence. - * If the conversion fails, return original string. - */ - function toNumber(val) { - var n = parseFloat(val); - return isNaN(n) ? val : n; - } - /** - * Make a map and return a function for checking if a key - * is in that map. - */ - function makeMap(str, expectsLowerCase) { - var map = Object.create(null); - var list = str.split(','); - for (var i = 0; i < list.length; i++) { - map[list[i]] = true; - } - return expectsLowerCase ? function (val) { return map[val.toLowerCase()]; } : function (val) { return map[val]; }; - } - /** - * Check if a tag is a built-in tag. - */ - var isBuiltInTag = makeMap('slot,component', true); - /** - * Check if an attribute is a reserved attribute. - */ - var isReservedAttribute = makeMap('key,ref,slot,slot-scope,is'); - /** - * Remove an item from an array. - */ - function remove$2(arr, item) { - var len = arr.length; - if (len) { - // fast path for the only / last item - if (item === arr[len - 1]) { - arr.length = len - 1; - return; - } - var index = arr.indexOf(item); - if (index > -1) { - return arr.splice(index, 1); - } - } - } - /** - * Check whether an object has the property. - */ - var hasOwnProperty = Object.prototype.hasOwnProperty; - function hasOwn(obj, key) { - return hasOwnProperty.call(obj, key); - } - /** - * Create a cached version of a pure function. - */ - function cached(fn) { - var cache = Object.create(null); - return function cachedFn(str) { - var hit = cache[str]; - return hit || (cache[str] = fn(str)); - }; - } - /** - * Camelize a hyphen-delimited string. - */ - var camelizeRE = /-(\w)/g; - var camelize = cached(function (str) { - return str.replace(camelizeRE, function (_, c) { return (c ? c.toUpperCase() : ''); }); - }); - /** - * Capitalize a string. - */ - var capitalize = cached(function (str) { - return str.charAt(0).toUpperCase() + str.slice(1); - }); - /** - * Hyphenate a camelCase string. - */ - var hyphenateRE = /\B([A-Z])/g; - var hyphenate = cached(function (str) { - return str.replace(hyphenateRE, '-$1').toLowerCase(); - }); - /** - * Simple bind polyfill for environments that do not support it, - * e.g., PhantomJS 1.x. Technically, we don't need this anymore - * since native bind is now performant enough in most browsers. - * But removing it would mean breaking code that was able to run in - * PhantomJS 1.x, so this must be kept for backward compatibility. - */ - /* istanbul ignore next */ - function polyfillBind(fn, ctx) { - function boundFn(a) { - var l = arguments.length; - return l - ? l > 1 - ? fn.apply(ctx, arguments) - : fn.call(ctx, a) - : fn.call(ctx); - } - boundFn._length = fn.length; - return boundFn; - } - function nativeBind(fn, ctx) { - return fn.bind(ctx); - } - // @ts-expect-error bind cannot be `undefined` - var bind$1 = Function.prototype.bind ? nativeBind : polyfillBind; - /** - * Convert an Array-like object to a real Array. - */ - function toArray(list, start) { - start = start || 0; - var i = list.length - start; - var ret = new Array(i); - while (i--) { - ret[i] = list[i + start]; - } - return ret; - } - /** - * Mix properties into target object. - */ - function extend(to, _from) { - for (var key in _from) { - to[key] = _from[key]; - } - return to; - } - /** - * Merge an Array of Objects into a single Object. - */ - function toObject(arr) { - var res = {}; - for (var i = 0; i < arr.length; i++) { - if (arr[i]) { - extend(res, arr[i]); - } - } - return res; - } - /* eslint-disable no-unused-vars */ - /** - * Perform no operation. - * Stubbing args to make Flow happy without leaving useless transpiled code - * with ...rest (https://flow.org/blog/2017/05/07/Strict-Function-Call-Arity/). - */ - function noop(a, b, c) { } - /** - * Always return false. - */ - var no = function (a, b, c) { return false; }; - /* eslint-enable no-unused-vars */ - /** - * Return the same value. - */ - var identity = function (_) { return _; }; - /** - * Generate a string containing static keys from compiler modules. - */ - function genStaticKeys$1(modules) { - return modules - .reduce(function (keys, m) { - return keys.concat(m.staticKeys || []); - }, []) - .join(','); - } - /** - * Check if two values are loosely equal - that is, - * if they are plain objects, do they have the same shape? - */ - function looseEqual(a, b) { - if (a === b) - return true; - var isObjectA = isObject(a); - var isObjectB = isObject(b); - if (isObjectA && isObjectB) { - try { - var isArrayA = Array.isArray(a); - var isArrayB = Array.isArray(b); - if (isArrayA && isArrayB) { - return (a.length === b.length && - a.every(function (e, i) { - return looseEqual(e, b[i]); - })); - } - else if (a instanceof Date && b instanceof Date) { - return a.getTime() === b.getTime(); - } - else if (!isArrayA && !isArrayB) { - var keysA = Object.keys(a); - var keysB = Object.keys(b); - return (keysA.length === keysB.length && - keysA.every(function (key) { - return looseEqual(a[key], b[key]); - })); - } - else { - /* istanbul ignore next */ - return false; - } - } - catch (e) { - /* istanbul ignore next */ - return false; - } - } - else if (!isObjectA && !isObjectB) { - return String(a) === String(b); - } - else { - return false; - } - } - /** - * Return the first index at which a loosely equal value can be - * found in the array (if value is a plain object, the array must - * contain an object of the same shape), or -1 if it is not present. - */ - function looseIndexOf(arr, val) { - for (var i = 0; i < arr.length; i++) { - if (looseEqual(arr[i], val)) - return i; - } - return -1; - } - /** - * Ensure a function is called only once. - */ - function once(fn) { - var called = false; - return function () { - if (!called) { - called = true; - fn.apply(this, arguments); - } - }; - } - // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is#polyfill - function hasChanged(x, y) { - if (x === y) { - return x === 0 && 1 / x !== 1 / y; - } - else { - return x === x || y === y; - } - } - - var SSR_ATTR = 'data-server-rendered'; - var ASSET_TYPES = ['component', 'directive', 'filter']; - var LIFECYCLE_HOOKS = [ - 'beforeCreate', - 'created', - 'beforeMount', - 'mounted', - 'beforeUpdate', - 'updated', - 'beforeDestroy', - 'destroyed', - 'activated', - 'deactivated', - 'errorCaptured', - 'serverPrefetch', - 'renderTracked', - 'renderTriggered' - ]; - - var config = { - /** - * Option merge strategies (used in core/util/options) - */ - // $flow-disable-line - optionMergeStrategies: Object.create(null), - /** - * Whether to suppress warnings. - */ - silent: false, - /** - * Show production mode tip message on boot? - */ - productionTip: true, - /** - * Whether to enable devtools - */ - devtools: true, - /** - * Whether to record perf - */ - performance: false, - /** - * Error handler for watcher errors - */ - errorHandler: null, - /** - * Warn handler for watcher warns - */ - warnHandler: null, - /** - * Ignore certain custom elements - */ - ignoredElements: [], - /** - * Custom user key aliases for v-on - */ - // $flow-disable-line - keyCodes: Object.create(null), - /** - * Check if a tag is reserved so that it cannot be registered as a - * component. This is platform-dependent and may be overwritten. - */ - isReservedTag: no, - /** - * Check if an attribute is reserved so that it cannot be used as a component - * prop. This is platform-dependent and may be overwritten. - */ - isReservedAttr: no, - /** - * Check if a tag is an unknown element. - * Platform-dependent. - */ - isUnknownElement: no, - /** - * Get the namespace of an element - */ - getTagNamespace: noop, - /** - * Parse the real tag name for the specific platform. - */ - parsePlatformTagName: identity, - /** - * Check if an attribute must be bound using property, e.g. value - * Platform-dependent. - */ - mustUseProp: no, - /** - * Perform updates asynchronously. Intended to be used by Vue Test Utils - * This will significantly reduce performance if set to false. - */ - async: true, - /** - * Exposed for legacy reasons - */ - _lifecycleHooks: LIFECYCLE_HOOKS - }; - - /** - * unicode letters used for parsing html tags, component names and property paths. - * using https://www.w3.org/TR/html53/semantics-scripting.html#potentialcustomelementname - * skipping \u10000-\uEFFFF due to it freezing up PhantomJS - */ - var unicodeRegExp = /a-zA-Z\u00B7\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u037D\u037F-\u1FFF\u200C-\u200D\u203F-\u2040\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD/; - /** - * Check if a string starts with $ or _ - */ - function isReserved(str) { - var c = (str + '').charCodeAt(0); - return c === 0x24 || c === 0x5f; - } - /** - * Define a property. - */ - function def(obj, key, val, enumerable) { - Object.defineProperty(obj, key, { - value: val, - enumerable: !!enumerable, - writable: true, - configurable: true - }); - } - /** - * Parse simple path. - */ - var bailRE = new RegExp("[^".concat(unicodeRegExp.source, ".$_\\d]")); - function parsePath(path) { - if (bailRE.test(path)) { - return; - } - var segments = path.split('.'); - return function (obj) { - for (var i = 0; i < segments.length; i++) { - if (!obj) - return; - obj = obj[segments[i]]; - } - return obj; - }; - } - - // can we use __proto__? - var hasProto = '__proto__' in {}; - // Browser environment sniffing - var inBrowser = typeof window !== 'undefined'; - var UA = inBrowser && window.navigator.userAgent.toLowerCase(); - var isIE = UA && /msie|trident/.test(UA); - var isIE9 = UA && UA.indexOf('msie 9.0') > 0; - var isEdge = UA && UA.indexOf('edge/') > 0; - UA && UA.indexOf('android') > 0; - var isIOS = UA && /iphone|ipad|ipod|ios/.test(UA); - UA && /chrome\/\d+/.test(UA) && !isEdge; - UA && /phantomjs/.test(UA); - var isFF = UA && UA.match(/firefox\/(\d+)/); - // Firefox has a "watch" function on Object.prototype... - // @ts-expect-error firebox support - var nativeWatch = {}.watch; - var supportsPassive = false; - if (inBrowser) { - try { - var opts = {}; - Object.defineProperty(opts, 'passive', { - get: function () { - /* istanbul ignore next */ - supportsPassive = true; - } - }); // https://github.com/facebook/flow/issues/285 - window.addEventListener('test-passive', null, opts); - } - catch (e) { } - } - // this needs to be lazy-evaled because vue may be required before - // vue-server-renderer can set VUE_ENV - var _isServer; - var isServerRendering = function () { - if (_isServer === undefined) { - /* istanbul ignore if */ - if (!inBrowser && typeof global !== 'undefined') { - // detect presence of vue-server-renderer and avoid - // Webpack shimming the process - _isServer = - global['process'] && global['process'].env.VUE_ENV === 'server'; - } - else { - _isServer = false; - } - } - return _isServer; - }; - // detect devtools - var devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__; - /* istanbul ignore next */ - function isNative(Ctor) { - return typeof Ctor === 'function' && /native code/.test(Ctor.toString()); - } - var hasSymbol = typeof Symbol !== 'undefined' && - isNative(Symbol) && - typeof Reflect !== 'undefined' && - isNative(Reflect.ownKeys); - var _Set; // $flow-disable-line - /* istanbul ignore if */ if (typeof Set !== 'undefined' && isNative(Set)) { - // use native Set when available. - _Set = Set; - } - else { - // a non-standard Set polyfill that only works with primitive keys. - _Set = /** @class */ (function () { - function Set() { - this.set = Object.create(null); - } - Set.prototype.has = function (key) { - return this.set[key] === true; - }; - Set.prototype.add = function (key) { - this.set[key] = true; - }; - Set.prototype.clear = function () { - this.set = Object.create(null); - }; - return Set; - }()); - } - - var currentInstance = null; - /** - * This is exposed for compatibility with v3 (e.g. some functions in VueUse - * relies on it). Do not use this internally, just use `currentInstance`. - * - * @internal this function needs manual type declaration because it relies - * on previously manually authored types from Vue 2 - */ - function getCurrentInstance() { - return currentInstance && { proxy: currentInstance }; - } - /** - * @internal - */ - function setCurrentInstance(vm) { - if (vm === void 0) { vm = null; } - if (!vm) - currentInstance && currentInstance._scope.off(); - currentInstance = vm; - vm && vm._scope.on(); - } - - /** - * @internal - */ - var VNode = /** @class */ (function () { - function VNode(tag, data, children, text, elm, context, componentOptions, asyncFactory) { - this.tag = tag; - this.data = data; - this.children = children; - this.text = text; - this.elm = elm; - this.ns = undefined; - this.context = context; - this.fnContext = undefined; - this.fnOptions = undefined; - this.fnScopeId = undefined; - this.key = data && data.key; - this.componentOptions = componentOptions; - this.componentInstance = undefined; - this.parent = undefined; - this.raw = false; - this.isStatic = false; - this.isRootInsert = true; - this.isComment = false; - this.isCloned = false; - this.isOnce = false; - this.asyncFactory = asyncFactory; - this.asyncMeta = undefined; - this.isAsyncPlaceholder = false; - } - Object.defineProperty(VNode.prototype, "child", { - // DEPRECATED: alias for componentInstance for backwards compat. - /* istanbul ignore next */ - get: function () { - return this.componentInstance; - }, - enumerable: false, - configurable: true - }); - return VNode; - }()); - var createEmptyVNode = function (text) { - if (text === void 0) { text = ''; } - var node = new VNode(); - node.text = text; - node.isComment = true; - return node; - }; - function createTextVNode(val) { - return new VNode(undefined, undefined, undefined, String(val)); - } - // optimized shallow clone - // used for static nodes and slot nodes because they may be reused across - // multiple renders, cloning them avoids errors when DOM manipulations rely - // on their elm reference. - function cloneVNode(vnode) { - var cloned = new VNode(vnode.tag, vnode.data, - // #7975 - // clone children array to avoid mutating original in case of cloning - // a child. - vnode.children && vnode.children.slice(), vnode.text, vnode.elm, vnode.context, vnode.componentOptions, vnode.asyncFactory); - cloned.ns = vnode.ns; - cloned.isStatic = vnode.isStatic; - cloned.key = vnode.key; - cloned.isComment = vnode.isComment; - cloned.fnContext = vnode.fnContext; - cloned.fnOptions = vnode.fnOptions; - cloned.fnScopeId = vnode.fnScopeId; - cloned.asyncMeta = vnode.asyncMeta; - cloned.isCloned = true; - return cloned; - } - - /* not type checking this file because flow doesn't play well with Proxy */ - var initProxy; - { - var allowedGlobals_1 = makeMap('Infinity,undefined,NaN,isFinite,isNaN,' + - 'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' + - 'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,BigInt,' + - 'require' // for Webpack/Browserify - ); - var warnNonPresent_1 = function (target, key) { - warn$2("Property or method \"".concat(key, "\" is not defined on the instance but ") + - 'referenced during render. Make sure that this property is reactive, ' + - 'either in the data option, or for class-based components, by ' + - 'initializing the property. ' + - 'See: https://v2.vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.', target); - }; - var warnReservedPrefix_1 = function (target, key) { - warn$2("Property \"".concat(key, "\" must be accessed with \"$data.").concat(key, "\" because ") + - 'properties starting with "$" or "_" are not proxied in the Vue instance to ' + - 'prevent conflicts with Vue internals. ' + - 'See: https://v2.vuejs.org/v2/api/#data', target); - }; - var hasProxy_1 = typeof Proxy !== 'undefined' && isNative(Proxy); - if (hasProxy_1) { - var isBuiltInModifier_1 = makeMap('stop,prevent,self,ctrl,shift,alt,meta,exact'); - config.keyCodes = new Proxy(config.keyCodes, { - set: function (target, key, value) { - if (isBuiltInModifier_1(key)) { - warn$2("Avoid overwriting built-in modifier in config.keyCodes: .".concat(key)); - return false; - } - else { - target[key] = value; - return true; - } - } - }); - } - var hasHandler_1 = { - has: function (target, key) { - var has = key in target; - var isAllowed = allowedGlobals_1(key) || - (typeof key === 'string' && - key.charAt(0) === '_' && - !(key in target.$data)); - if (!has && !isAllowed) { - if (key in target.$data) - warnReservedPrefix_1(target, key); - else - warnNonPresent_1(target, key); - } - return has || !isAllowed; - } - }; - var getHandler_1 = { - get: function (target, key) { - if (typeof key === 'string' && !(key in target)) { - if (key in target.$data) - warnReservedPrefix_1(target, key); - else - warnNonPresent_1(target, key); - } - return target[key]; - } - }; - initProxy = function initProxy(vm) { - if (hasProxy_1) { - // determine which proxy handler to use - var options = vm.$options; - var handlers = options.render && options.render._withStripped ? getHandler_1 : hasHandler_1; - vm._renderProxy = new Proxy(vm, handlers); - } - else { - vm._renderProxy = vm; - } - }; - } - - /****************************************************************************** - Copyright (c) Microsoft Corporation. - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH - REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, - INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - PERFORMANCE OF THIS SOFTWARE. - ***************************************************************************** */ - - var __assign = function() { - __assign = Object.assign || function __assign(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; - } - return t; - }; - return __assign.apply(this, arguments); - }; - - var uid$2 = 0; - var pendingCleanupDeps = []; - var cleanupDeps = function () { - for (var i = 0; i < pendingCleanupDeps.length; i++) { - var dep = pendingCleanupDeps[i]; - dep.subs = dep.subs.filter(function (s) { return s; }); - dep._pending = false; - } - pendingCleanupDeps.length = 0; - }; - /** - * A dep is an observable that can have multiple - * directives subscribing to it. - * @internal - */ - var Dep = /** @class */ (function () { - function Dep() { - // pending subs cleanup - this._pending = false; - this.id = uid$2++; - this.subs = []; - } - Dep.prototype.addSub = function (sub) { - this.subs.push(sub); - }; - Dep.prototype.removeSub = function (sub) { - // #12696 deps with massive amount of subscribers are extremely slow to - // clean up in Chromium - // to workaround this, we unset the sub for now, and clear them on - // next scheduler flush. - this.subs[this.subs.indexOf(sub)] = null; - if (!this._pending) { - this._pending = true; - pendingCleanupDeps.push(this); - } - }; - Dep.prototype.depend = function (info) { - if (Dep.target) { - Dep.target.addDep(this); - if (info && Dep.target.onTrack) { - Dep.target.onTrack(__assign({ effect: Dep.target }, info)); - } - } - }; - Dep.prototype.notify = function (info) { - // stabilize the subscriber list first - var subs = this.subs.filter(function (s) { return s; }); - if (!config.async) { - // subs aren't sorted in scheduler if not running async - // we need to sort them now to make sure they fire in correct - // order - subs.sort(function (a, b) { return a.id - b.id; }); - } - for (var i = 0, l = subs.length; i < l; i++) { - var sub = subs[i]; - if (info) { - sub.onTrigger && - sub.onTrigger(__assign({ effect: subs[i] }, info)); - } - sub.update(); - } - }; - return Dep; - }()); - // The current target watcher being evaluated. - // This is globally unique because only one watcher - // can be evaluated at a time. - Dep.target = null; - var targetStack = []; - function pushTarget(target) { - targetStack.push(target); - Dep.target = target; - } - function popTarget() { - targetStack.pop(); - Dep.target = targetStack[targetStack.length - 1]; - } - - /* - * not type checking this file because flow doesn't play well with - * dynamically accessing methods on Array prototype - */ - var arrayProto = Array.prototype; - var arrayMethods = Object.create(arrayProto); - var methodsToPatch = [ - 'push', - 'pop', - 'shift', - 'unshift', - 'splice', - 'sort', - 'reverse' - ]; - /** - * Intercept mutating methods and emit events - */ - methodsToPatch.forEach(function (method) { - // cache original method - var original = arrayProto[method]; - def(arrayMethods, method, function mutator() { - var args = []; - for (var _i = 0; _i < arguments.length; _i++) { - args[_i] = arguments[_i]; - } - var result = original.apply(this, args); - var ob = this.__ob__; - var inserted; - switch (method) { - case 'push': - case 'unshift': - inserted = args; - break; - case 'splice': - inserted = args.slice(2); - break; - } - if (inserted) - ob.observeArray(inserted); - // notify change - { - ob.dep.notify({ - type: "array mutation" /* TriggerOpTypes.ARRAY_MUTATION */, - target: this, - key: method - }); - } - return result; - }); - }); - - var rawMap = new WeakMap(); - function reactive(target) { - makeReactive(target, false); - return target; - } - /** - * Return a shallowly-reactive copy of the original object, where only the root - * level properties are reactive. It also does not auto-unwrap refs (even at the - * root level). - */ - function shallowReactive(target) { - makeReactive(target, true); - def(target, "__v_isShallow" /* ReactiveFlags.IS_SHALLOW */, true); - return target; - } - function makeReactive(target, shallow) { - // if trying to observe a readonly proxy, return the readonly version. - if (!isReadonly(target)) { - { - if (isArray(target)) { - warn$2("Avoid using Array as root value for ".concat(shallow ? "shallowReactive()" : "reactive()", " as it cannot be tracked in watch() or watchEffect(). Use ").concat(shallow ? "shallowRef()" : "ref()", " instead. This is a Vue-2-only limitation.")); - } - var existingOb = target && target.__ob__; - if (existingOb && existingOb.shallow !== shallow) { - warn$2("Target is already a ".concat(existingOb.shallow ? "" : "non-", "shallow reactive object, and cannot be converted to ").concat(shallow ? "" : "non-", "shallow.")); - } - } - var ob = observe(target, shallow, isServerRendering() /* ssr mock reactivity */); - if (!ob) { - if (target == null || isPrimitive(target)) { - warn$2("value cannot be made reactive: ".concat(String(target))); - } - if (isCollectionType(target)) { - warn$2("Vue 2 does not support reactive collection types such as Map or Set."); - } - } - } - } - function isReactive(value) { - if (isReadonly(value)) { - return isReactive(value["__v_raw" /* ReactiveFlags.RAW */]); - } - return !!(value && value.__ob__); - } - function isShallow(value) { - return !!(value && value.__v_isShallow); - } - function isReadonly(value) { - return !!(value && value.__v_isReadonly); - } - function isProxy(value) { - return isReactive(value) || isReadonly(value); - } - function toRaw(observed) { - var raw = observed && observed["__v_raw" /* ReactiveFlags.RAW */]; - return raw ? toRaw(raw) : observed; - } - function markRaw(value) { - if (isObject(value)) { - rawMap.set(value, true); - } - return value; - } - /** - * @internal - */ - function isCollectionType(value) { - var type = toRawType(value); - return (type === 'Map' || type === 'WeakMap' || type === 'Set' || type === 'WeakSet'); - } - - var arrayKeys = Object.getOwnPropertyNames(arrayMethods); - var NO_INIITIAL_VALUE = {}; - /** - * In some cases we may want to disable observation inside a component's - * update computation. - */ - var shouldObserve = true; - function toggleObserving(value) { - shouldObserve = value; - } - // ssr mock dep - var mockDep = { - notify: noop, - depend: noop, - addSub: noop, - removeSub: noop - }; - /** - * Observer class that is attached to each observed - * object. Once attached, the observer converts the target - * object's property keys into getter/setters that - * collect dependencies and dispatch updates. - */ - var Observer = /** @class */ (function () { - function Observer(value, shallow, mock) { - if (shallow === void 0) { shallow = false; } - if (mock === void 0) { mock = false; } - this.value = value; - this.shallow = shallow; - this.mock = mock; - // this.value = value - this.dep = mock ? mockDep : new Dep(); - this.vmCount = 0; - def(value, '__ob__', this); - if (isArray(value)) { - if (!mock) { - if (hasProto) { - value.__proto__ = arrayMethods; - /* eslint-enable no-proto */ - } - else { - for (var i = 0, l = arrayKeys.length; i < l; i++) { - var key = arrayKeys[i]; - def(value, key, arrayMethods[key]); - } - } - } - if (!shallow) { - this.observeArray(value); - } - } - else { - /** - * Walk through all properties and convert them into - * getter/setters. This method should only be called when - * value type is Object. - */ - var keys = Object.keys(value); - for (var i = 0; i < keys.length; i++) { - var key = keys[i]; - defineReactive(value, key, NO_INIITIAL_VALUE, undefined, shallow, mock); - } - } - } - /** - * Observe a list of Array items. - */ - Observer.prototype.observeArray = function (value) { - for (var i = 0, l = value.length; i < l; i++) { - observe(value[i], false, this.mock); - } - }; - return Observer; - }()); - // helpers - /** - * Attempt to create an observer instance for a value, - * returns the new observer if successfully observed, - * or the existing observer if the value already has one. - */ - function observe(value, shallow, ssrMockReactivity) { - if (value && hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) { - return value.__ob__; - } - if (shouldObserve && - (ssrMockReactivity || !isServerRendering()) && - (isArray(value) || isPlainObject(value)) && - Object.isExtensible(value) && - !value.__v_skip /* ReactiveFlags.SKIP */ && - !rawMap.has(value) && - !isRef(value) && - !(value instanceof VNode)) { - return new Observer(value, shallow, ssrMockReactivity); - } - } - /** - * Define a reactive property on an Object. - */ - function defineReactive(obj, key, val, customSetter, shallow, mock) { - var dep = new Dep(); - var property = Object.getOwnPropertyDescriptor(obj, key); - if (property && property.configurable === false) { - return; - } - // cater for pre-defined getter/setters - var getter = property && property.get; - var setter = property && property.set; - if ((!getter || setter) && - (val === NO_INIITIAL_VALUE || arguments.length === 2)) { - val = obj[key]; - } - var childOb = !shallow && observe(val, false, mock); - Object.defineProperty(obj, key, { - enumerable: true, - configurable: true, - get: function reactiveGetter() { - var value = getter ? getter.call(obj) : val; - if (Dep.target) { - { - dep.depend({ - target: obj, - type: "get" /* TrackOpTypes.GET */, - key: key - }); - } - if (childOb) { - childOb.dep.depend(); - if (isArray(value)) { - dependArray(value); - } - } - } - return isRef(value) && !shallow ? value.value : value; - }, - set: function reactiveSetter(newVal) { - var value = getter ? getter.call(obj) : val; - if (!hasChanged(value, newVal)) { - return; - } - if (customSetter) { - customSetter(); - } - if (setter) { - setter.call(obj, newVal); - } - else if (getter) { - // #7981: for accessor properties without setter - return; - } - else if (!shallow && isRef(value) && !isRef(newVal)) { - value.value = newVal; - return; - } - else { - val = newVal; - } - childOb = !shallow && observe(newVal, false, mock); - { - dep.notify({ - type: "set" /* TriggerOpTypes.SET */, - target: obj, - key: key, - newValue: newVal, - oldValue: value - }); - } - } - }); - return dep; - } - function set(target, key, val) { - if ((isUndef(target) || isPrimitive(target))) { - warn$2("Cannot set reactive property on undefined, null, or primitive value: ".concat(target)); - } - if (isReadonly(target)) { - warn$2("Set operation on key \"".concat(key, "\" failed: target is readonly.")); - return; - } - var ob = target.__ob__; - if (isArray(target) && isValidArrayIndex(key)) { - target.length = Math.max(target.length, key); - target.splice(key, 1, val); - // when mocking for SSR, array methods are not hijacked - if (ob && !ob.shallow && ob.mock) { - observe(val, false, true); - } - return val; - } - if (key in target && !(key in Object.prototype)) { - target[key] = val; - return val; - } - if (target._isVue || (ob && ob.vmCount)) { - warn$2('Avoid adding reactive properties to a Vue instance or its root $data ' + - 'at runtime - declare it upfront in the data option.'); - return val; - } - if (!ob) { - target[key] = val; - return val; - } - defineReactive(ob.value, key, val, undefined, ob.shallow, ob.mock); - { - ob.dep.notify({ - type: "add" /* TriggerOpTypes.ADD */, - target: target, - key: key, - newValue: val, - oldValue: undefined - }); - } - return val; - } - function del(target, key) { - if ((isUndef(target) || isPrimitive(target))) { - warn$2("Cannot delete reactive property on undefined, null, or primitive value: ".concat(target)); - } - if (isArray(target) && isValidArrayIndex(key)) { - target.splice(key, 1); - return; - } - var ob = target.__ob__; - if (target._isVue || (ob && ob.vmCount)) { - warn$2('Avoid deleting properties on a Vue instance or its root $data ' + - '- just set it to null.'); - return; - } - if (isReadonly(target)) { - warn$2("Delete operation on key \"".concat(key, "\" failed: target is readonly.")); - return; - } - if (!hasOwn(target, key)) { - return; - } - delete target[key]; - if (!ob) { - return; - } - { - ob.dep.notify({ - type: "delete" /* TriggerOpTypes.DELETE */, - target: target, - key: key - }); - } - } - /** - * Collect dependencies on array elements when the array is touched, since - * we cannot intercept array element access like property getters. - */ - function dependArray(value) { - for (var e = void 0, i = 0, l = value.length; i < l; i++) { - e = value[i]; - if (e && e.__ob__) { - e.__ob__.dep.depend(); - } - if (isArray(e)) { - dependArray(e); - } - } - } - - /** - * @internal - */ - var RefFlag = "__v_isRef"; - function isRef(r) { - return !!(r && r.__v_isRef === true); - } - function ref$1(value) { - return createRef(value, false); - } - function shallowRef(value) { - return createRef(value, true); - } - function createRef(rawValue, shallow) { - if (isRef(rawValue)) { - return rawValue; - } - var ref = {}; - def(ref, RefFlag, true); - def(ref, "__v_isShallow" /* ReactiveFlags.IS_SHALLOW */, shallow); - def(ref, 'dep', defineReactive(ref, 'value', rawValue, null, shallow, isServerRendering())); - return ref; - } - function triggerRef(ref) { - if (!ref.dep) { - warn$2("received object is not a triggerable ref."); - } - { - ref.dep && - ref.dep.notify({ - type: "set" /* TriggerOpTypes.SET */, - target: ref, - key: 'value' - }); - } - } - function unref(ref) { - return isRef(ref) ? ref.value : ref; - } - function proxyRefs(objectWithRefs) { - if (isReactive(objectWithRefs)) { - return objectWithRefs; - } - var proxy = {}; - var keys = Object.keys(objectWithRefs); - for (var i = 0; i < keys.length; i++) { - proxyWithRefUnwrap(proxy, objectWithRefs, keys[i]); - } - return proxy; - } - function proxyWithRefUnwrap(target, source, key) { - Object.defineProperty(target, key, { - enumerable: true, - configurable: true, - get: function () { - var val = source[key]; - if (isRef(val)) { - return val.value; - } - else { - var ob = val && val.__ob__; - if (ob) - ob.dep.depend(); - return val; - } - }, - set: function (value) { - var oldValue = source[key]; - if (isRef(oldValue) && !isRef(value)) { - oldValue.value = value; - } - else { - source[key] = value; - } - } - }); - } - function customRef(factory) { - var dep = new Dep(); - var _a = factory(function () { - { - dep.depend({ - target: ref, - type: "get" /* TrackOpTypes.GET */, - key: 'value' - }); - } - }, function () { - { - dep.notify({ - target: ref, - type: "set" /* TriggerOpTypes.SET */, - key: 'value' - }); - } - }), get = _a.get, set = _a.set; - var ref = { - get value() { - return get(); - }, - set value(newVal) { - set(newVal); - } - }; - def(ref, RefFlag, true); - return ref; - } - function toRefs(object) { - if (!isReactive(object)) { - warn$2("toRefs() expects a reactive object but received a plain one."); - } - var ret = isArray(object) ? new Array(object.length) : {}; - for (var key in object) { - ret[key] = toRef(object, key); - } - return ret; - } - function toRef(object, key, defaultValue) { - var val = object[key]; - if (isRef(val)) { - return val; - } - var ref = { - get value() { - var val = object[key]; - return val === undefined ? defaultValue : val; - }, - set value(newVal) { - object[key] = newVal; - } - }; - def(ref, RefFlag, true); - return ref; - } - - var rawToReadonlyMap = new WeakMap(); - var rawToShallowReadonlyMap = new WeakMap(); - function readonly(target) { - return createReadonly(target, false); - } - function createReadonly(target, shallow) { - if (!isPlainObject(target)) { - { - if (isArray(target)) { - warn$2("Vue 2 does not support readonly arrays."); - } - else if (isCollectionType(target)) { - warn$2("Vue 2 does not support readonly collection types such as Map or Set."); - } - else { - warn$2("value cannot be made readonly: ".concat(typeof target)); - } - } - return target; - } - // already a readonly object - if (isReadonly(target)) { - return target; - } - // already has a readonly proxy - var map = shallow ? rawToShallowReadonlyMap : rawToReadonlyMap; - var existingProxy = map.get(target); - if (existingProxy) { - return existingProxy; - } - var proxy = Object.create(Object.getPrototypeOf(target)); - map.set(target, proxy); - def(proxy, "__v_isReadonly" /* ReactiveFlags.IS_READONLY */, true); - def(proxy, "__v_raw" /* ReactiveFlags.RAW */, target); - if (isRef(target)) { - def(proxy, RefFlag, true); - } - if (shallow || isShallow(target)) { - def(proxy, "__v_isShallow" /* ReactiveFlags.IS_SHALLOW */, true); - } - var keys = Object.keys(target); - for (var i = 0; i < keys.length; i++) { - defineReadonlyProperty(proxy, target, keys[i], shallow); - } - return proxy; - } - function defineReadonlyProperty(proxy, target, key, shallow) { - Object.defineProperty(proxy, key, { - enumerable: true, - configurable: true, - get: function () { - var val = target[key]; - return shallow || !isPlainObject(val) ? val : readonly(val); - }, - set: function () { - warn$2("Set operation on key \"".concat(key, "\" failed: target is readonly.")); - } - }); - } - /** - * Returns a reactive-copy of the original object, where only the root level - * properties are readonly, and does NOT unwrap refs nor recursively convert - * returned properties. - * This is used for creating the props proxy object for stateful components. - */ - function shallowReadonly(target) { - return createReadonly(target, true); - } - - function computed(getterOrOptions, debugOptions) { - var getter; - var setter; - var onlyGetter = isFunction(getterOrOptions); - if (onlyGetter) { - getter = getterOrOptions; - setter = function () { - warn$2('Write operation failed: computed value is readonly'); - } - ; - } - else { - getter = getterOrOptions.get; - setter = getterOrOptions.set; - } - var watcher = isServerRendering() - ? null - : new Watcher(currentInstance, getter, noop, { lazy: true }); - if (watcher && debugOptions) { - watcher.onTrack = debugOptions.onTrack; - watcher.onTrigger = debugOptions.onTrigger; - } - var ref = { - // some libs rely on the presence effect for checking computed refs - // from normal refs, but the implementation doesn't matter - effect: watcher, - get value() { - if (watcher) { - if (watcher.dirty) { - watcher.evaluate(); - } - if (Dep.target) { - if (Dep.target.onTrack) { - Dep.target.onTrack({ - effect: Dep.target, - target: ref, - type: "get" /* TrackOpTypes.GET */, - key: 'value' - }); - } - watcher.depend(); - } - return watcher.value; - } - else { - return getter(); - } - }, - set value(newVal) { - setter(newVal); - } - }; - def(ref, RefFlag, true); - def(ref, "__v_isReadonly" /* ReactiveFlags.IS_READONLY */, onlyGetter); - return ref; - } - - var mark; - var measure; - { - var perf_1 = inBrowser && window.performance; - /* istanbul ignore if */ - if (perf_1 && - // @ts-ignore - perf_1.mark && - // @ts-ignore - perf_1.measure && - // @ts-ignore - perf_1.clearMarks && - // @ts-ignore - perf_1.clearMeasures) { - mark = function (tag) { return perf_1.mark(tag); }; - measure = function (name, startTag, endTag) { - perf_1.measure(name, startTag, endTag); - perf_1.clearMarks(startTag); - perf_1.clearMarks(endTag); - // perf.clearMeasures(name) - }; - } - } - - var normalizeEvent = cached(function (name) { - var passive = name.charAt(0) === '&'; - name = passive ? name.slice(1) : name; - var once = name.charAt(0) === '~'; // Prefixed last, checked first - name = once ? name.slice(1) : name; - var capture = name.charAt(0) === '!'; - name = capture ? name.slice(1) : name; - return { - name: name, - once: once, - capture: capture, - passive: passive - }; - }); - function createFnInvoker(fns, vm) { - function invoker() { - var fns = invoker.fns; - if (isArray(fns)) { - var cloned = fns.slice(); - for (var i = 0; i < cloned.length; i++) { - invokeWithErrorHandling(cloned[i], null, arguments, vm, "v-on handler"); - } - } - else { - // return handler return value for single handlers - return invokeWithErrorHandling(fns, null, arguments, vm, "v-on handler"); - } - } - invoker.fns = fns; - return invoker; - } - function updateListeners(on, oldOn, add, remove, createOnceHandler, vm) { - var name, cur, old, event; - for (name in on) { - cur = on[name]; - old = oldOn[name]; - event = normalizeEvent(name); - if (isUndef(cur)) { - warn$2("Invalid handler for event \"".concat(event.name, "\": got ") + String(cur), vm); - } - else if (isUndef(old)) { - if (isUndef(cur.fns)) { - cur = on[name] = createFnInvoker(cur, vm); - } - if (isTrue(event.once)) { - cur = on[name] = createOnceHandler(event.name, cur, event.capture); - } - add(event.name, cur, event.capture, event.passive, event.params); - } - else if (cur !== old) { - old.fns = cur; - on[name] = old; - } - } - for (name in oldOn) { - if (isUndef(on[name])) { - event = normalizeEvent(name); - remove(event.name, oldOn[name], event.capture); - } - } - } - - function mergeVNodeHook(def, hookKey, hook) { - if (def instanceof VNode) { - def = def.data.hook || (def.data.hook = {}); - } - var invoker; - var oldHook = def[hookKey]; - function wrappedHook() { - hook.apply(this, arguments); - // important: remove merged hook to ensure it's called only once - // and prevent memory leak - remove$2(invoker.fns, wrappedHook); - } - if (isUndef(oldHook)) { - // no existing hook - invoker = createFnInvoker([wrappedHook]); - } - else { - /* istanbul ignore if */ - if (isDef(oldHook.fns) && isTrue(oldHook.merged)) { - // already a merged invoker - invoker = oldHook; - invoker.fns.push(wrappedHook); - } - else { - // existing plain hook - invoker = createFnInvoker([oldHook, wrappedHook]); - } - } - invoker.merged = true; - def[hookKey] = invoker; - } - - function extractPropsFromVNodeData(data, Ctor, tag) { - // we are only extracting raw values here. - // validation and default values are handled in the child - // component itself. - var propOptions = Ctor.options.props; - if (isUndef(propOptions)) { - return; - } - var res = {}; - var attrs = data.attrs, props = data.props; - if (isDef(attrs) || isDef(props)) { - for (var key in propOptions) { - var altKey = hyphenate(key); - { - var keyInLowerCase = key.toLowerCase(); - if (key !== keyInLowerCase && attrs && hasOwn(attrs, keyInLowerCase)) { - tip("Prop \"".concat(keyInLowerCase, "\" is passed to component ") + - "".concat(formatComponentName( - // @ts-expect-error tag is string - tag || Ctor), ", but the declared prop name is") + - " \"".concat(key, "\". ") + - "Note that HTML attributes are case-insensitive and camelCased " + - "props need to use their kebab-case equivalents when using in-DOM " + - "templates. You should probably use \"".concat(altKey, "\" instead of \"").concat(key, "\".")); - } - } - checkProp(res, props, key, altKey, true) || - checkProp(res, attrs, key, altKey, false); - } - } - return res; - } - function checkProp(res, hash, key, altKey, preserve) { - if (isDef(hash)) { - if (hasOwn(hash, key)) { - res[key] = hash[key]; - if (!preserve) { - delete hash[key]; - } - return true; - } - else if (hasOwn(hash, altKey)) { - res[key] = hash[altKey]; - if (!preserve) { - delete hash[altKey]; - } - return true; - } - } - return false; - } - - // The template compiler attempts to minimize the need for normalization by - // statically analyzing the template at compile time. - // - // For plain HTML markup, normalization can be completely skipped because the - // generated render function is guaranteed to return Array. There are - // two cases where extra normalization is needed: - // 1. When the children contains components - because a functional component - // may return an Array instead of a single root. In this case, just a simple - // normalization is needed - if any child is an Array, we flatten the whole - // thing with Array.prototype.concat. It is guaranteed to be only 1-level deep - // because functional components already normalize their own children. - function simpleNormalizeChildren(children) { - for (var i = 0; i < children.length; i++) { - if (isArray(children[i])) { - return Array.prototype.concat.apply([], children); - } - } - return children; - } - // 2. When the children contains constructs that always generated nested Arrays, - // e.g.