diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000..39b18dbc
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,18 @@
+root = true
+
+[*]
+indent_style = space
+indent_size = 4
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.js]
+quote_type = double
+
+[*.css]
+indent_size = 2
+
+[*.html]
+indent_size = 2
diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 00000000..7c6b5bc7
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,11 @@
+# Dependencies
+node_modules/
+
+# Build output
+dist/
+
+# Documentation
+docs/
+
+# Third-party libraries
+src/scripts/libs/
\ No newline at end of file
diff --git a/.eslintrc.js b/.eslintrc.js
new file mode 100644
index 00000000..1e5283dd
--- /dev/null
+++ b/.eslintrc.js
@@ -0,0 +1,172 @@
+module.exports = {
+ env: {
+ browser: true,
+ es2021: true,
+ amd: true, // Add AMD environment for RequireJS
+ },
+ extends: ["eslint:recommended"],
+ parserOptions: {
+ ecmaVersion: 2021,
+ sourceType: "module",
+ },
+ globals: {
+ // Application globals
+ app: true,
+ bg: true,
+ tabID: true,
+
+ // WebExtension API globals
+ browser: "readonly", // Firefox WebExtensions API
+ chrome: "readonly", // Chrome Extensions API
+
+ // Module system
+ define: false,
+ require: false,
+ requirejs: false,
+
+ // Browser APIs
+ requestAnimationFrame: true,
+ URL: true,
+ HTMLCollection: true,
+ fetch: "readonly",
+ localStorage: "readonly",
+ sessionStorage: "readonly",
+ indexedDB: "readonly",
+ Notification: "readonly",
+ WebSocket: "readonly",
+
+ // WebExtension specific globals
+ Blob: "readonly",
+ FileReader: "readonly",
+
+ // Firefox specific
+ InstallTrigger: "readonly",
+
+ // Extension messaging
+ runtime: "readonly",
+
+ // Common WebExtension APIs
+ tabs: "readonly",
+ storage: "readonly",
+ contextMenus: "readonly",
+ webRequest: "readonly",
+ permissions: "readonly",
+ i18n: "readonly",
+
+ // Background process globals
+ sourceToFocus: true,
+ Source: true,
+ Item: true,
+ Folder: true,
+ settings: true,
+ info: true,
+ sources: true,
+ items: true,
+ folders: true,
+ loaded: true,
+ toolbars: true,
+ loader: true,
+ valueToBoolean: true,
+ getBoolean: true,
+ getElementBoolean: true,
+ getElementSetting: true,
+ fetchAll: true,
+ fetchOne: true,
+ reloadExt: true,
+ appStarted: true,
+ parsedData: true,
+
+ // Libraries
+ $: true,
+ jQuery: true,
+ _: true,
+ Backbone: true,
+ BB: true,
+
+ // AMD modules that might be used globally
+ RSSParser: true,
+ Favicon: true,
+ Animation: true,
+ Locale: true,
+ dateUtils: true,
+ escapeHtml: true,
+ stripTags: true,
+
+ // Models and collections
+ Settings: true,
+ Info: true,
+ Sources: true,
+ Items: true,
+ Folders: true,
+ Toolbars: true,
+ Loader: true,
+ Special: true,
+
+ // Views and layouts
+ Layout: true,
+ ArticlesLayout: true,
+ ContentLayout: true,
+ FeedsLayout: true,
+
+ // Allow console for debugging
+ console: true,
+ },
+ rules: {
+ // Disable all formatting rules
+ indent: "off",
+ "linebreak-style": "off",
+ quotes: "off",
+ semi: "off",
+ "comma-dangle": "off",
+ "max-len": "off",
+ "brace-style": "off",
+ "space-before-function-paren": "off",
+ "space-before-blocks": "off",
+ "keyword-spacing": "off",
+ "object-curly-spacing": "off",
+ "array-bracket-spacing": "off",
+ "computed-property-spacing": "off",
+ "space-in-parens": "off",
+ "comma-spacing": "off",
+ "no-trailing-spaces": "off",
+ "eol-last": "off",
+
+ // Keep logical/semantic rules
+ "no-unused-vars": "warn",
+ curly: "error",
+ eqeqeq: "error",
+ "no-empty": "error",
+
+ // Browser-specific rules
+ "no-alert": "off", // Allow alert, confirm, and prompt
+ "no-console": "off", // Allow console for extension debugging
+
+ // Rules for messy codebase
+ "no-undef": "warn", // Warn instead of error for undefined variables
+ "no-global-assign": "warn", // Warn instead of error for global reassignments
+ "no-useless-escape": "warn", // Warn instead of error for unnecessary escape characters
+ },
+ // Allow globals to be declared via comments
+ noInlineConfig: false,
+ overrides: [
+ {
+ // For AMD modules
+ files: ["src/scripts/**/*.js"],
+ env: {
+ amd: true,
+ },
+ globals: {
+ define: "readonly",
+ require: "readonly",
+ },
+ },
+ {
+ // For background process
+ files: ["src/scripts/bgprocess/**/*.js"],
+ globals: {
+ browser: "readonly",
+ chrome: "readonly",
+ },
+ },
+ ],
+};
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..08852963
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,32 @@
+# Dependencies
+node_modules/
+npm-debug.log
+yarn-error.log
+yarn-debug.log
+package-lock.json
+
+# Build output
+dist/
+*.zip
+
+# IDE and editor files
+.idea/
+.vscode/
+*.sublime-project
+*.sublime-workspace
+.DS_Store
+Thumbs.db
+
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# Documentation
+docs/
+
+# Temporary files
+.tmp/
+.temp/
diff --git a/.jshintignore b/.jshintignore
new file mode 100644
index 00000000..04afcfb2
--- /dev/null
+++ b/.jshintignore
@@ -0,0 +1,3 @@
+node_modules/*
+dist/*
+docs/*
diff --git a/.jshintrc b/.jshintrc
new file mode 100644
index 00000000..9a13b998
--- /dev/null
+++ b/.jshintrc
@@ -0,0 +1,39 @@
+{
+ "curly": true,
+ "eqnull": true,
+ "eqeqeq": true,
+ "immed": true,
+ "newcap": true,
+ "noarg": true,
+ "sub": true,
+ "undef": true,
+ "browser": true,
+ "devel": true,
+ "boss": true,
+ "forin": true,
+ "noempty": true,
+ "unused": true,
+ "trailing": true,
+ "supernew": true,
+ "onevar": false,
+ "funcscope": true,
+ "maxdepth": 5,
+ "quotmark": "single",
+ "-W030": true,
+ "-W117": true,
+ "-W089": true,
+ "esversion": 8,
+ "futurehostile": true,
+ "globals": {
+ "app": true,
+ "bg": true,
+ "tabID": true,
+ "chrome": false,
+ "define": false,
+ "require": false,
+ "requirejs": false,
+ "requestAnimationFrame": true,
+ "URL": true,
+ "HTMLCollection": true
+ }
+}
diff --git a/BUILD.md b/BUILD.md
new file mode 100644
index 00000000..dfe5229a
--- /dev/null
+++ b/BUILD.md
@@ -0,0 +1,97 @@
+# Smart-RSS Build System
+
+This document explains the build system for Smart-RSS.
+
+## Overview
+
+The build system has been simplified from a Grunt-based system to a plain Node.js script. The script provides the same functionality as the previous Grunt-based system but with a simpler implementation.
+
+## Requirements
+
+- Node.js (v12 or higher recommended)
+- npm
+
+## Installation
+
+```bash
+npm install
+```
+
+## Usage
+
+You can use the build system in two ways:
+
+### 1. Using npm scripts
+
+```bash
+# Copy files from src to dist and strip comments
+npm run prepare
+
+# Prepare and create zip package
+npm run package
+
+# Bump version, commit, prepare, and create zip package (patch version)
+npm run release
+
+# Bump minor version, commit, prepare, and create zip package
+npm run release:minor
+
+# Bump major version, commit, prepare, and create zip package
+npm run release:major
+
+# Watch for changes in src directory
+npm run watch
+
+# Bump version number (patch by default)
+npm run bump-version
+```
+
+### 2. Using the build script directly
+
+```bash
+# Copy files from src to dist and strip comments
+node build.js prepare
+
+# Prepare and create zip package
+node build.js package
+
+# Bump version, commit, prepare, and create zip package
+node build.js release [patch|minor|major]
+
+# Watch for changes in src directory
+node build.js watch
+
+# Bump version number
+node build.js bump-version [patch|minor|major]
+```
+
+## Features
+
+- **prepare**: Copies files from src to dist and strips comments from JS files
+- **package**: Prepares files and creates a zip package
+- **release**: Bumps version, commits changes, prepares files, and creates a zip package
+- **watch**: Watches for changes in the src directory and automatically runs prepare
+- **bump-version**: Bumps the version number in manifest.json
+
+## Migrating from Grunt
+
+The new build system provides the same functionality as the previous Grunt-based system. If you were using Grunt tasks, here's how they map to the new system:
+
+| Grunt Task | New Command |
+| --------------------- | -------------------------------------------------------- |
+| `grunt prepare` | `npm run prepare` or `node build.js prepare` |
+| `grunt package` | `npm run package` or `node build.js package` |
+| `grunt release` | `npm run release` or `node build.js release` |
+| `grunt release:minor` | `npm run release:minor` or `node build.js release minor` |
+| `grunt release:major` | `npm run release:major` or `node build.js release major` |
+| `grunt watch` | `npm run watch` or `node build.js watch` |
+| `grunt bump-version` | `npm run bump-version` or `node build.js bump-version` |
+
+## Why the Change?
+
+The new build system:
+
+1. Reduces dependencies (no Grunt and related plugins)
+2. Simplifies the build process
+3. Makes it easier to understand and modify
+4. Provides the same functionality in a more straightforward way
diff --git a/Gruntfile.js b/Gruntfile.js
deleted file mode 100644
index b7296a21..00000000
--- a/Gruntfile.js
+++ /dev/null
@@ -1,177 +0,0 @@
-module.exports = function(grunt) {
-
- // Project configuration.
- grunt.initConfig({
- pkg: grunt.file.readJSON('package.json'),
-
-
- jshint: {
- options: {
- curly: false, // true: force { }
- eqnull: true, // true: enable something == null
- eqeqeq: false, // true: force ===
- immed: true, // true: immidiatly invocated fns has to be in ()
- newcap: true, // true: construcotr has to have firt letter uppercased
- noarg: true, // true: no arguments.caller and arguments.callee
- sub: true, // true: no warning about a['something'] if a.something can be used
- undef: true, // true: can't use undeclared vars
- browser: true, // true: set window object and other stuff as globals
- devel: true, // true: set alert,confirm,console,... as globals
- boss: true, // true: allow assigments in conditions and return statements
- forin: true, // true: hasOwnProperty has to be in all for..in cycles
- noempty: true, // true: no empty blocks
- unused: true, // true: warn about unused vars
- trailing: true, // true: no trailing whitespaces
- supernew: true, // true: enable 'new Constructor' instead of 'new Constructor()'
- onevar: false, // true: only one var per fn
- funcscope: false, // false: no 'var' in blocks
- maxdepth: 5, // max nesting depth
- quotmark: 'single', // single: force '
- '-W041': true, // don't warn about something == false/true
- '-W117': true, // don't warn about not defined vars until I refactorize bg.js
- globals: {
- app: true,
- bg: true,
- tabID: true,
- chrome: false,
- define: false,
- require: false,
-
- /* browser globals not recognized by browser or devel options */
- requestAnimationFrame: true,
- URL: true,
- HTMLCollection: true
- }
- },
- all: ['scripts/app/**/*.js', 'scripts/bgprocess/**/*.js']
- },
-
- requirejs: {
- app: {
- options: {
- name: '../main',
- baseUrl: 'scripts/app',
- generateSourceMaps: true,
- preserveLicenseComments: false,
- optimize: 'uglify2',
- waitSeconds: 0,
- paths: {
- jquery: '../libs/jquery.min',
- underscore: '../libs/underscore.min',
- backbone: '../libs/backbone.min',
- text: '../text',
- i18n: '../i18n',
- domReady: '../domReady'
- },
- shim: {
- jquery: {
- exports: '$'
- },
- backbone: {
- deps: ['underscore', 'jquery'],
- exports: 'Backbone'
- },
- underscore: {
- exports: '_'
- }
- },
- excludeShallow: ['modules/Locale', 'jquery', 'underscore', 'backbone'],
- out: 'scripts/main-compiled.js'
- }
- },
- bg: {
- options: {
- name: '../bgprocess',
- baseUrl: 'scripts/bgprocess',
- generateSourceMaps: true,
- preserveLicenseComments: false,
- optimize: 'uglify2',
- waitSeconds: 0,
- paths: {
- jquery: '../libs/jquery.min',
- underscore: '../libs/underscore.min',
- backbone: '../libs/backbone.min',
- text: '../text',
- i18n: '../i18n',
- md5: '../libs/md5',
- domReady: '../domReady',
- backboneDB: '../libs/backbone.indexDB'
- },
- shim: {
- jquery: {
- exports: '$'
- },
- backboneDB: {
- deps: ['backbone']
- },
- backbone: {
- deps: ['underscore', 'jquery'],
- exports: 'Backbone'
- },
- underscore: {
- exports: '_'
- },
- md5: {
- exports: 'CryptoJS'
- }
- },
- excludeShallow: ['jquery', 'underscore', 'backbone', 'backboneDB'],
- out: 'scripts/bgprocess-compiled.js'
- }
- }
- },
-
- stylus: {
- compile: {
- options: {
- compress: false,
- //imports: ['nib']
- },
- files: {
- //'styles/options-compiled.css': 'options.styl', // 1:1 compile
- 'styles/main-compiled.css': [
- 'styles/global.styl',
- 'styles/feeds.styl',
- 'styles/articles.styl',
- 'styles/content.styl'
- ]
- }
- }
- },
- watch: {
- scripts: {
- files: ['styles/*.styl'],
- tasks: ['stylus'],
- options: {
- spawn: false,
- interrupt: true,
- events: ['all']
- },
- },
- },
- yuidoc: {
- compile: {
- name: '<%= pkg.name %>',
- description: '<%= pkg.description %>',
- version: '<%= pkg.version %>',
- url: '<%= pkg.homepage %>',
- options: {
- paths: ['scripts'],
- /*themedir: 'path/to/custom/theme/',*/
- outdir: 'docs/'
- }
- }
- }
- });
-
-
- grunt.loadNpmTasks('grunt-contrib-jshint');
- grunt.loadNpmTasks('grunt-contrib-requirejs');
- grunt.loadNpmTasks('grunt-contrib-stylus');
- grunt.loadNpmTasks('grunt-contrib-watch');
- grunt.loadNpmTasks('grunt-contrib-yuidoc');
-
- // Default task(s).
- grunt.registerTask('default', ['jshint']);
- grunt.registerTask('rjs', ['requirejs:app', 'requirejs:bg']);
-};
\ No newline at end of file
diff --git a/README.md b/README.md
index ca326978..03b66d3a 100644
--- a/README.md
+++ b/README.md
@@ -1,82 +1,99 @@
-# Smart RSS extension
-
-Translations are in scripts/nls/*.js
-
-For technical bug reports use issues here on GitHub
-
-For bugs from user perspective use commments on:
-http://blog.martinkadlec.eu/post/501-smart-rss-final-v10
-
-## For developers
-
-If you are interested in improving Smart RSS then there are few tips to get started.
-
-First of all you will need several command line tools:
-
-- Git (obviously) - http://msysgit.github.io
-- Node.JS & npm - http://nodejs.org
-- Grunt-cli - http://gruntjs.com/getting-started (npm install -g grunt-cli)
-- Mocha - http://visionmedia.github.io/mocha/ (npm install -g mocha) - for in-app integration tests I load mocha from cdn, but if you want to create out-of-app unit tests you will want to install this.
-
-To setup your Smart RSS project open your console, go to your projects folders and type:
-```
-git clone git@github.com:BS-Harou/Smart-RSS.git smartrss
-cd smartrss
-npm install
-```
-
-You should also create .gitignore file including at least:
-```
-node_modules/*
-docs/*
-*.map
-*-compiled.js
-*.sublime-*
-```
-(\*.sublime-\* only if you use sublime text projects)
-
-To check for jshint errors:
-```
-grunt jshint
-```
-
-To compile stylus files to css:
-```
-grunt stylus
-```
-
-You can also use watch task that will automatically compile your stylus files on change:
-```
-grunt watch
-```
-
-To generate source documentaion in ./docs run:
-```
-grunt yuidoc
-```
-
-In dev. builds you can run integration tests by pressing shift+insert directly in smart rss tab.
-
-When you are done editing the code you should compile all the js files:
-```
-grunt rjs
-```
-
-
-and then switch to "publish" branch (that will make index.html (bgprocess) and rss.tml (app) use the compiled files instead of loading all the files separately) and rebase it.
-```
-git checkout publish
-git rebase master
-```
-
-Then you can use Opera to make extenion out of it. Opera will automatically ignore all files and folders beggining with "." like ".git", but you might want to remove some other files too (like sublime text projects files). You have to do this manually or use some script that will do this for you. I have a script to do this but it is not yet ready to get published. In future it might work like this:
-
-```
-grunt build
-```
-
-
-Then don't forget to switch back to master banch
-```
-git checkout master
-```
\ No newline at end of file
+# Smart RSS extension
+
+## Now officially unmaintained, I _may_ fix some critical issue if any is found within few following weeks, but then I'll archive this repo. Feel free to fork and continue development as you wish
+
+Originally developed for Opera 15+ by BS-Harou (Martin Kadlec)
+
+Translations are in scripts/nls/\*.js
+
+For technical bug reports use issues here on GitHub
+
+## For users
+
+Extension is available in following repositories:
+
+#### AMO: https://addons.mozilla.org/firefox/addon/smart-rss-reader/
+
+~#### Chrome Web Store: https://chrome.google.com/webstore/detail/eggggihfcaabljfpjiiaohloefmgejic/~
+
+If you encounter issue with a specific feed for best results please back up and include current state of that feed in your report, this will be helpful in case the feed changes before I get to check it, thanks in advance
+
+
+## For developers
+
+If you are interested in improving Smart RSS then there are few tips to get started.
+
+First of all you will need several command line tools:
+
+- Git
+- Node.JS (v12 or higher recommended) & npm
+
+To setup your Smart RSS project open your console, go to your projects folders and type:
+
+```
+git clone git@github.com:zakius/Smart-RSS.git smartrss
+cd smartrss
+npm install
+```
+
+Sometimes you may encounter texts ending with `*` or `!` in app, first ones are fallbacks to English text when used locale lacks the needed one and the latter are actual keys displayed when even English text is missing, feel free to submit PR's to fill them. If you change wording or punctuation somewhere please comment that line (using GitHub interface) with reasoning like common conventions or special punctuation rules in given language.
+
+### Code Quality
+
+The project uses a clear separation of concerns for code quality:
+
+- **ESLint** checks for logical and semantic issues (potential bugs, unused variables, etc.)
+- **EditorConfig** handles all formatting concerns (indentation, line endings, quotes, etc.)
+
+This separation ensures that ESLint focuses on code correctness while EditorConfig manages consistent formatting across different editors and IDEs.
+
+To lint your code:
+
+```
+npm run lint
+```
+
+This will check your code for:
+
+- Syntax errors and potential bugs
+- Logical issues and best practices
+- Browser extension-specific concerns
+
+### Build System
+
+The build system has been simplified to a plain Node.js script. You can use npm scripts to run the build tasks:
+
+```bash
+# Copy files from src to dist and strip comments
+npm run prepare
+
+# Prepare and create zip package
+npm run package
+
+# Bump version, commit, prepare, and create zip package (patch version)
+npm run release
+
+# Bump minor version, commit, prepare, and create zip package
+npm run release:minor
+
+# Bump major version, commit, prepare, and create zip package
+npm run release:major
+
+# Watch for changes in src directory
+npm run watch
+
+# Bump version number (patch by default)
+npm run bump-version
+```
+
+Or you can use the build script directly:
+
+```bash
+node build.js prepare
+node build.js package
+node build.js release [patch|minor|major]
+node build.js watch
+node build.js bump-version [patch|minor|major]
+```
+
+For more details about the build system, see [BUILD.md](BUILD.md).
diff --git a/_config.yml b/_config.yml
new file mode 100644
index 00000000..c4192631
--- /dev/null
+++ b/_config.yml
@@ -0,0 +1 @@
+theme: jekyll-theme-cayman
\ No newline at end of file
diff --git a/build.js b/build.js
new file mode 100755
index 00000000..062dd5bc
--- /dev/null
+++ b/build.js
@@ -0,0 +1,228 @@
+#!/usr/bin/env node
+
+const { join, dirname, relative } = require("path");
+const {
+ readdirSync,
+ lstatSync,
+ copyFileSync,
+ mkdirSync,
+ existsSync,
+ readFileSync,
+ writeFileSync,
+} = require("fs");
+const { execSync } = require("child_process");
+const semver = require("semver");
+const AdmZip = require("adm-zip");
+
+// Utility functions
+const scan = (dir) => {
+ const filesList = [];
+ readdirSync(dir).forEach((file) => {
+ if (file[0] === ".") {
+ return;
+ }
+ const filePath = join(dir, file);
+
+ if (lstatSync(filePath).isDirectory()) {
+ filesList.push(...scan(filePath));
+ return;
+ }
+ filesList.push(filePath);
+ });
+ return filesList;
+};
+
+const ensureDirectoryExists = (dirPath) => {
+ if (!existsSync(dirPath)) {
+ mkdirSync(dirPath, { recursive: true });
+ }
+};
+
+// Main functions
+const bumpVersion = (level = "patch") => {
+ console.log(`Bumping version (${level})...`);
+ const manifestPath = join(__dirname, "src/manifest.json");
+ const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
+ manifest.version = semver.inc(manifest.version, level);
+ writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
+ console.log(`Version bumped to ${manifest.version}`);
+ return manifest.version;
+};
+
+const commit = (level = "patch") => {
+ console.log("Committing changes...");
+ try {
+ execSync("git add *", { stdio: "inherit" });
+ execSync(`git commit -m "auto version bump: ${level}"`, {
+ stdio: "inherit",
+ });
+ console.log("Changes committed");
+ return true;
+ } catch (error) {
+ console.error("Git commit failed:", error.message);
+ return false;
+ }
+};
+
+const copyFiles = () => {
+ console.log("Copying files from src to dist...");
+ const srcDir = join(__dirname, "src");
+ const distDir = join(__dirname, "dist");
+
+ // Ensure dist directory exists
+ ensureDirectoryExists(distDir);
+
+ // Get all files from src
+ const srcFiles = scan(srcDir);
+
+ // Copy each file to dist, preserving directory structure
+ srcFiles.forEach((srcFile) => {
+ const relativePath = relative(srcDir, srcFile);
+ const destFile = join(distDir, relativePath);
+ const destDir = dirname(destFile);
+
+ ensureDirectoryExists(destDir);
+ copyFileSync(srcFile, destFile);
+ });
+
+ console.log("Files copied");
+};
+
+const stripComments = () => {
+ console.log("Stripping comments from JS files...");
+ const root = join(__dirname, "dist");
+ const filesList = scan(root);
+
+ const multilineComment = /^[\t\s]*\/\*\*?[^!][\s\S]*?\*\/[\r\n]/gm;
+ const specialComments = /^[\t\s]*\/\*!\*?[^!][\s\S]*?\*\/[\r\n]/gm;
+ const singleLineComment = /^[\t\s]*(\/\/)[^\n\r]*[\n\r]/gm;
+
+ filesList.forEach((filePath) => {
+ if (!filePath.endsWith(".js")) {
+ return;
+ }
+ const contents = readFileSync(filePath, "utf8")
+ .replace(multilineComment, "")
+ .replace(singleLineComment, "")
+ .replace(specialComments, "");
+
+ writeFileSync(filePath, contents);
+ });
+
+ console.log("Comments stripped");
+};
+
+const zipPackage = () => {
+ console.log("Creating zip package...");
+ const root = join(__dirname, "dist");
+ const manifestPath = join(root, "manifest.json");
+ const filesList = scan(root);
+ const version = JSON.parse(readFileSync(manifestPath, "utf8")).version;
+
+ const zipFile = new AdmZip();
+
+ filesList.forEach((file) => {
+ // Get the directory relative to the root, or empty string if it's at the root
+ const relativePath =
+ dirname(file) === root ? "" : relative(root, dirname(file));
+ zipFile.addLocalFile(file, relativePath);
+ });
+
+ const zipPath = join(__dirname, "dist", `SmartRSS_v${version}.zip`);
+ zipFile.writeZip(zipPath);
+ console.log(`Zip package created: ${zipPath}`);
+};
+
+const watch = () => {
+ console.log("Watching for changes in src directory...");
+ const chokidar = require("chokidar");
+
+ chokidar
+ .watch(join(__dirname, "src"), {
+ ignored: /(^|[\/\\])\../,
+ persistent: true,
+ })
+ .on("change", (path) => {
+ console.log(`File ${path} has been changed`);
+ prepare();
+ });
+
+ console.log("Watching for changes. Press Ctrl+C to stop.");
+};
+
+// Combined tasks
+const prepare = () => {
+ copyFiles();
+ stripComments();
+};
+
+const packageTask = () => {
+ prepare();
+ zipPackage();
+};
+
+const release = (level = "patch") => {
+ if (!["major", "minor", "patch"].includes(level)) {
+ console.error("Wrong update level, aborting");
+ return false;
+ }
+
+ bumpVersion(level);
+ commit(level);
+ copyFiles();
+ stripComments();
+ zipPackage();
+};
+
+// Command line interface
+const printUsage = () => {
+ console.log(`
+Usage: node build.js [command] [options]
+
+Commands:
+ prepare Copy files from src to dist and strip comments
+ package Prepare and create zip package
+ release [level] Bump version, commit, prepare, and create zip package
+ level can be: patch, minor, major (default: patch)
+ watch Watch for changes in src directory
+ bump-version [level] Bump version number
+ level can be: patch, minor, major (default: patch)
+
+Examples:
+ node build.js prepare
+ node build.js release minor
+ node build.js watch
+`);
+};
+
+// Main
+const args = process.argv.slice(2);
+const command = args[0];
+const option = args[1];
+
+if (!command) {
+ printUsage();
+ process.exit(0);
+}
+
+switch (command) {
+ case "prepare":
+ prepare();
+ break;
+ case "package":
+ packageTask();
+ break;
+ case "release":
+ release(option || "patch");
+ break;
+ case "watch":
+ watch();
+ break;
+ case "bump-version":
+ bumpVersion(option || "patch");
+ break;
+ default:
+ console.error(`Unknown command: ${command}`);
+ printUsage();
+ process.exit(1);
+}
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 00000000..9daeafb9
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1 @@
+test
diff --git a/index.html b/index.html
deleted file mode 100644
index 1500c6ba..00000000
--- a/index.html
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
- Smart RSS - background process
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/manifest.json b/manifest.json
deleted file mode 100644
index 14a2fa92..00000000
--- a/manifest.json
+++ /dev/null
@@ -1,40 +0,0 @@
-{
- "name": "Smart RSS",
- "developer": {
- "name": "BS-Harou (Martin Kadlec)",
- "url": "http://blog.martinkadlec.eu/"
- },
- "description": "RSS Reader for Opera 15+!",
- "manifest_version": 2,
- "version": "2.0",
- "background": {
- "page": "index.html"
- },
- "web_accessible_resources": ["libs/jquery.min.js", "libs/underscore.min.js", "libs/backbone.min.js", "libs/backbone.indexDB.js", "images/icon16_v2.png"],
- "permissions": ["https://*/*", "storage", "unlimitedStorage", "alarms", "tabs", "contextMenus", "http://*/*"],
- "content_security_policy": "script-src 'self' 'unsafe-eval' https://cdnjs.cloudflare.com/ajax/libs/mocha/ https://raw.github.com/chaijs/chai/master/; object-src 'unsafe-eval';",
- "browser_action": {
- "default_title": "Smart RSS",
- "default_icon": {
- "19": "images/reload_anim_1.png"
- }
- },
- "options_page": "options.html",
- "icons": {
- "19": "images/icon19-arrow-orange.png",
- "48": "images/48-inverted-round.png",
- "64": "images/64-inverted-round.png",
- "96": "images/96-inverted-round.png",
- "128": "images/128-inverted-round.png"
- },
- "commands": {
- "_execute_browser_action": {
- "suggested_key": {
- "windows": "Ctrl+Shift+R",
- "mac": "Command+Shift+R",
- "chromeos": "Ctrl+Shift+R",
- "linux": "Ctrl+Shift+R"
- }
- }
- }
-}
\ No newline at end of file
diff --git a/options.html b/options.html
deleted file mode 100644
index 2a034ff4..00000000
--- a/options.html
+++ /dev/null
@@ -1,286 +0,0 @@
-
-
-
-
- Smart RSS - Options
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 00000000..0666f008
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,2416 @@
+{
+ "name": "smartrss",
+ "version": "2.0.0",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "smartrss",
+ "version": "2.0.0",
+ "license": "MIT",
+ "devDependencies": {
+ "@types/firefox-webext-browser": "^120.0.4",
+ "adm-zip": "^0.5.16",
+ "chokidar": "^3.5.3",
+ "eslint": "^8.57.1",
+ "md5-file": "^5.0.0",
+ "semver": "^7.7.1"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz",
+ "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.12.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
+ "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
+ "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^9.6.0",
+ "globals": "^13.19.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/js": {
+ "version": "8.57.1",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz",
+ "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@humanwhocodes/config-array": {
+ "version": "0.13.0",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
+ "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==",
+ "deprecated": "Use @eslint/config-array instead",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@humanwhocodes/object-schema": "^2.0.3",
+ "debug": "^4.3.1",
+ "minimatch": "^3.0.5"
+ },
+ "engines": {
+ "node": ">=10.10.0"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/object-schema": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
+ "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
+ "deprecated": "Use @eslint/object-schema instead",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@types/firefox-webext-browser": {
+ "version": "120.0.4",
+ "resolved": "https://registry.npmjs.org/@types/firefox-webext-browser/-/firefox-webext-browser-120.0.4.tgz",
+ "integrity": "sha512-lBrpf08xhiZBigrtdQfUaqX1UauwZ+skbFiL8u2Tdra/rklkKadYmIzTwkNZSWtuZ7OKpFqbE2HHfDoFqvZf6w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@ungap/structured-clone": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz",
+ "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/acorn": {
+ "version": "8.14.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
+ "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/adm-zip": {
+ "version": "0.5.16",
+ "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.16.tgz",
+ "integrity": "sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true,
+ "license": "Python-2.0"
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/binary-extensions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
+ "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
+ "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
+ "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "8.57.1",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz",
+ "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==",
+ "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.6.1",
+ "@eslint/eslintrc": "^2.1.4",
+ "@eslint/js": "8.57.1",
+ "@humanwhocodes/config-array": "^0.13.0",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@nodelib/fs.walk": "^1.2.8",
+ "@ungap/structured-clone": "^1.2.0",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "doctrine": "^3.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.2.2",
+ "eslint-visitor-keys": "^3.4.3",
+ "espree": "^9.6.1",
+ "esquery": "^1.4.2",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "globals": "^13.19.0",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "is-path-inside": "^3.0.3",
+ "js-yaml": "^4.1.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3",
+ "strip-ansi": "^6.0.1",
+ "text-table": "^0.2.0"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
+ "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/espree": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
+ "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "acorn": "^8.9.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
+ "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fastq": {
+ "version": "1.19.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz",
+ "integrity": "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flat-cache": "^3.0.4"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
+ "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.3",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
+ "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "deprecated": "Glob versions prior to v9 are no longer supported",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/globals": {
+ "version": "13.24.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
+ "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/graphemer": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
+ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ignore": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+ "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-path-inside": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/md5-file": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/md5-file/-/md5-file-5.0.0.tgz",
+ "integrity": "sha512-xbEFXCYVWrSx/gEKS1VPlg84h/4L20znVIulKw6kMfmBUAZNAnF00eczz9ICMl+/hjQGo5KSXRxbL/47X3rmMw==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "md5-file": "cli.js"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
+ "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "deprecated": "Rimraf versions prior to v4 are no longer supported",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
+ "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true,
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ }
+ },
+ "dependencies": {
+ "@eslint-community/eslint-utils": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz",
+ "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==",
+ "dev": true,
+ "requires": {
+ "eslint-visitor-keys": "^3.4.3"
+ }
+ },
+ "@eslint-community/regexpp": {
+ "version": "4.12.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
+ "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
+ "dev": true
+ },
+ "@eslint/eslintrc": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
+ "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
+ "dev": true,
+ "requires": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^9.6.0",
+ "globals": "^13.19.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ }
+ },
+ "@eslint/js": {
+ "version": "8.57.1",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz",
+ "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==",
+ "dev": true
+ },
+ "@humanwhocodes/config-array": {
+ "version": "0.13.0",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
+ "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==",
+ "dev": true,
+ "requires": {
+ "@humanwhocodes/object-schema": "^2.0.3",
+ "debug": "^4.3.1",
+ "minimatch": "^3.0.5"
+ }
+ },
+ "@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true
+ },
+ "@humanwhocodes/object-schema": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
+ "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
+ "dev": true
+ },
+ "@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ }
+ },
+ "@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true
+ },
+ "@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "requires": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ }
+ },
+ "@types/firefox-webext-browser": {
+ "version": "120.0.4",
+ "resolved": "https://registry.npmjs.org/@types/firefox-webext-browser/-/firefox-webext-browser-120.0.4.tgz",
+ "integrity": "sha512-lBrpf08xhiZBigrtdQfUaqX1UauwZ+skbFiL8u2Tdra/rklkKadYmIzTwkNZSWtuZ7OKpFqbE2HHfDoFqvZf6w==",
+ "dev": true
+ },
+ "@ungap/structured-clone": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz",
+ "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==",
+ "dev": true
+ },
+ "acorn": {
+ "version": "8.14.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
+ "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
+ "dev": true
+ },
+ "acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "requires": {}
+ },
+ "adm-zip": {
+ "version": "0.5.16",
+ "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.16.tgz",
+ "integrity": "sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==",
+ "dev": true
+ },
+ "ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true
+ },
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dev": true,
+ "requires": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ }
+ },
+ "argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true
+ },
+ "balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "binary-extensions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
+ "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
+ "dev": true
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "dev": true,
+ "requires": {
+ "fill-range": "^7.1.1"
+ }
+ },
+ "callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true
+ },
+ "chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "chokidar": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
+ "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
+ "dev": true,
+ "requires": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "fsevents": "~2.3.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true
+ },
+ "cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ }
+ },
+ "debug": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
+ "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.3"
+ }
+ },
+ "deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true
+ },
+ "doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "requires": {
+ "esutils": "^2.0.2"
+ }
+ },
+ "escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true
+ },
+ "eslint": {
+ "version": "8.57.1",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz",
+ "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==",
+ "dev": true,
+ "requires": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.6.1",
+ "@eslint/eslintrc": "^2.1.4",
+ "@eslint/js": "8.57.1",
+ "@humanwhocodes/config-array": "^0.13.0",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@nodelib/fs.walk": "^1.2.8",
+ "@ungap/structured-clone": "^1.2.0",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "doctrine": "^3.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.2.2",
+ "eslint-visitor-keys": "^3.4.3",
+ "espree": "^9.6.1",
+ "esquery": "^1.4.2",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "globals": "^13.19.0",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "is-path-inside": "^3.0.3",
+ "js-yaml": "^4.1.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3",
+ "strip-ansi": "^6.0.1",
+ "text-table": "^0.2.0"
+ },
+ "dependencies": {
+ "glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.3"
+ }
+ }
+ }
+ },
+ "eslint-scope": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
+ "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
+ "dev": true,
+ "requires": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ }
+ },
+ "eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true
+ },
+ "espree": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
+ "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
+ "dev": true,
+ "requires": {
+ "acorn": "^8.9.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.4.1"
+ }
+ },
+ "esquery": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
+ "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
+ "dev": true,
+ "requires": {
+ "estraverse": "^5.1.0"
+ }
+ },
+ "esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "requires": {
+ "estraverse": "^5.2.0"
+ }
+ },
+ "estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true
+ },
+ "esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true
+ },
+ "fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true
+ },
+ "fastq": {
+ "version": "1.19.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz",
+ "integrity": "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==",
+ "dev": true,
+ "requires": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "requires": {
+ "flat-cache": "^3.0.4"
+ }
+ },
+ "fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "dev": true,
+ "requires": {
+ "to-regex-range": "^5.0.1"
+ }
+ },
+ "find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ }
+ },
+ "flat-cache": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
+ "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
+ "dev": true,
+ "requires": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.3",
+ "rimraf": "^3.0.2"
+ }
+ },
+ "flatted": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
+ "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
+ "dev": true
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true
+ },
+ "fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "optional": true
+ },
+ "glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ },
+ "globals": {
+ "version": "13.24.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
+ "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
+ "dev": true,
+ "requires": {
+ "type-fest": "^0.20.2"
+ }
+ },
+ "graphemer": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
+ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "ignore": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "dev": true
+ },
+ "import-fresh": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+ "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+ "dev": true,
+ "requires": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ }
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "dev": true,
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dev": true,
+ "requires": {
+ "binary-extensions": "^2.0.0"
+ }
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true
+ },
+ "is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true
+ },
+ "is-path-inside": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+ "dev": true
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true
+ },
+ "js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "requires": {
+ "argparse": "^2.0.1"
+ }
+ },
+ "json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true
+ },
+ "keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "requires": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ }
+ },
+ "locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^5.0.0"
+ }
+ },
+ "lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true
+ },
+ "md5-file": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/md5-file/-/md5-file-5.0.0.tgz",
+ "integrity": "sha512-xbEFXCYVWrSx/gEKS1VPlg84h/4L20znVIulKw6kMfmBUAZNAnF00eczz9ICMl+/hjQGo5KSXRxbL/47X3rmMw==",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true
+ },
+ "natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true
+ },
+ "normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "optionator": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
+ "dev": true,
+ "requires": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.5"
+ }
+ },
+ "p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "requires": {
+ "yocto-queue": "^0.1.0"
+ }
+ },
+ "p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^3.0.2"
+ }
+ },
+ "parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "requires": {
+ "callsites": "^3.0.0"
+ }
+ },
+ "path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true
+ },
+ "path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true
+ },
+ "picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true
+ },
+ "prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true
+ },
+ "punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "dev": true
+ },
+ "queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true
+ },
+ "readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dev": true,
+ "requires": {
+ "picomatch": "^2.2.1"
+ }
+ },
+ "resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true
+ },
+ "reusify": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
+ "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
+ "dev": true
+ },
+ "rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "requires": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "semver": {
+ "version": "7.7.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
+ "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
+ "dev": true
+ },
+ "shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^3.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true
+ },
+ "strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "requires": {
+ "ansi-regex": "^5.0.1"
+ }
+ },
+ "strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ },
+ "text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true
+ },
+ "to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "requires": {
+ "is-number": "^7.0.0"
+ }
+ },
+ "type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "requires": {
+ "prelude-ls": "^1.2.1"
+ }
+ },
+ "type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true
+ },
+ "uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "requires": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true
+ },
+ "yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true
+ }
+ }
+}
diff --git a/package.json b/package.json
index 2b533bbe..41b6f5c2 100644
--- a/package.json
+++ b/package.json
@@ -1,29 +1,41 @@
{
- "name": "smartrss",
- "version": "2.0.0",
- "description": "RSS Reader for Opera 15+",
- "homepage": "http://blog.martinkadlec.eu/post/501-smart-rss-final-v10",
- "dependencies": {},
- "devDependencies": {
- "grunt": ">=0.4.1",
- "grunt-contrib-jshint": ">=0.6.4",
- "grunt-contrib-requirejs": ">=0.4.1",
- "grunt-contrib-stylus": ">=0.8.0",
- "grunt-contrib-watch": ">=0.5.3",
- "grunt-contrib-yuidoc": "~0.5.0",
- "ncp": "~0.4.2"
- },
- "scripts": {
- "test": "echo \"Error: no test specified\" && exit 1"
- },
- "repository": {
- "type": "git",
- "url": "git://github.com/BS-Harou/Smart-RSS.git"
- },
- "author": "Martin Kadlec",
- "license": "BSD-2-Clause",
- "bugs": {
- "url": "https://github.com/BS-Harou/Smart-RSS/issues"
- },
- "engine": "node >= 0.10.0"
+ "name": "smartrss",
+ "version": "2.0.0",
+ "description": "RSS Reader",
+ "homepage": "https://github.com/zakius/Smart-RSS",
+ "devDependencies": {
+ "@types/firefox-webext-browser": "^120.0.4",
+ "adm-zip": "^0.5.16",
+ "chokidar": "^3.5.3",
+ "eslint": "^8.57.1",
+ "md5-file": "^5.0.0",
+ "semver": "^7.7.1"
+ },
+ "scripts": {
+ "prepare": "node build.js prepare",
+ "package": "node build.js package",
+ "release": "node build.js release",
+ "release:minor": "node build.js release minor",
+ "release:major": "node build.js release major",
+ "watch": "node build.js watch",
+ "bump-version": "node build.js bump-version",
+ "lint": "eslint src/"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/zakius/Smart-RSS.git"
+ },
+ "author": "zakius",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/zakius/Smart-RSS/issues"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "browserslist": [
+ "last 2 Firefox versions",
+ "last 2 Chrome versions"
+ ],
+ "private": true
}
diff --git a/rss.html b/rss.html
deleted file mode 100644
index 176cdb2e..00000000
--- a/rss.html
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
- Smart RSS
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/rss_content.html b/rss_content.html
deleted file mode 100644
index 03022066..00000000
--- a/rss_content.html
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/scripts/app/app.js b/scripts/app/app.js
deleted file mode 100644
index 084a33e7..00000000
--- a/scripts/app/app.js
+++ /dev/null
@@ -1,186 +0,0 @@
-/**
- * @module App
- */
-define([
- 'controllers/comm',
- 'layouts/Layout', 'jquery', 'domReady!', 'collections/Actions', 'layouts/FeedsLayout', 'layouts/ArticlesLayout',
- 'layouts/ContentLayout', 'staticdb/shortcuts', 'modules/Locale', 'views/ReportView', 'preps/all'
-],
-function (comm, Layout, $, doc, Actions, FeedsLayout, ArticlesLayout, ContentLayout, shortcuts, Locale, ReportView) {
-
- document.documentElement.style.fontSize = bg.settings.get('uiFontSize') + '%';
-
- var templates = $('script[type="text/template"]');
- templates.each(function(i, el) {
- el.innerHTML = Locale.translateHTML(el.innerHTML);
- });
-
- document.addEventListener('contextmenu', function(e) {
- if (!e.target.matchesSelector('#region-content header, #region-content header *')) {
- e.preventDefault();
- }
- });
-
- var app = window.app = new (Layout.extend({
- el: 'body',
- fixURL: function(url) {
- if (url.search(/[a-z]+:\/\//) == -1) {
- url = 'http://' + url;
- }
- return url;
- },
- events: {
- 'mousedown': 'handleMouseDown',
- 'click #panel-toggle': 'handleClickToggle'
- },
- initialize: function() {
- this.actions = new Actions();
-
- window.addEventListener('blur', function(e) {
- this.hideContextMenus();
- //$('.focused').removeClass('focused');
-
- if (e.target instanceof window.Window) {
- comm.trigger('stop-blur');
- }
-
- }.bind(this));
-
- bg.settings.on('change:layout', this.handleLayoutChange, this);
- bg.settings.on('change:panelToggled', this.handleToggleChange, this);
- bg.sources.on('clear-events', this.handleClearEvents, this);
-
- if (bg.settings.get('enablePanelToggle')) {
- $('#panel-toggle').css('display', 'block');
- }
-
- if (bg.settings.get('thickFrameBorders')) {
- this.$el.addClass('thick-borders');
- }
- },
- handleClearEvents: function(id) {
- if (window == null || id == tabID) {
- bg.settings.off('change:layout', this.handleLayoutChange, this);
- bg.settings.off('change:panelToggled', this.handleToggleChange, this);
- bg.sources.off('clear-events', this.handleClearEvents, this);
- }
- },
- handleLayoutChange: function() {
- if (bg.settings.get('layout') == 'vertical') {
- this.layoutToVertical();
- this.articles.enableResizing(bg.settings.get('layout'), bg.settings.get('posC'));
- } else {
- this.layoutToHorizontal();
- this.articles.enableResizing(bg.settings.get('layout'), bg.settings.get('posB'));
- }
- },
- layoutToVertical: function() {
- $('.regions .regions').addClass('vertical');
- },
- layoutToHorizontal: function() {
- $('.regions .regions').removeClass('vertical');
- },
-
- /**
- * Saves the panel toggle state (panel visible/hidden)
- * @method handleClickToggle
- */
- handleClickToggle: function() {
- bg.settings.save('panelToggled', !bg.settings.get('panelToggled'));
- },
-
- /**
- * Shows/hides the panel
- * @method handleToggleChange
- */
- handleToggleChange: function() {
- this.feeds.$el.toggleClass('hidden', !bg.settings.get('panelToggled'));
- $('#panel-toggle').toggleClass('toggled', bg.settings.get('panelToggled'));
-
- if (!bg.settings.get('panelToggled')) {
- this.feeds.disableResizing();
- } else {
- this.feeds.enableResizing('horizontal', bg.settings.get('posA'));
- }
- },
- handleMouseDown: function(e) {
- if (!e.target.matchesSelector('.context-menu, .context-menu *, .overlay, .overlay *')) {
- this.hideContextMenus();
- }
- },
- hideContextMenus: function() {
- comm.trigger('hide-overlays', { blur: true });
- },
- focusLayout: function(e) {
- this.setFocus(e.currentTarget.getAttribute('name'));
- },
- start: function() {
- this.attach('feeds', new FeedsLayout);
- this.attach('articles', new ArticlesLayout);
- this.attach('content', new ContentLayout);
-
-
- this.handleToggleChange();
-
- this.trigger('start');
- this.trigger('start:after');
-
- setTimeout(function(that) {
- $('body').removeClass('loading');
- that.setFocus('articles');
- that.handleLayoutChange();
-
- }, 0, this);
- },
- report: function() {
- var report = new ReportView();
- document.body.appendChild(report.render().el);
- },
- handleKeyDown: function(e) {
- var ac = document.activeElement;
- if (ac && (ac.tagName == 'INPUT' || ac.tagName == 'TEXTAREA')) {
- return;
- }
-
- var str = '';
- if (e.ctrlKey) str += 'ctrl+';
- if (e.shiftKey) str += 'shift+';
-
- if (e.keyCode > 46 && e.keyCode < 91) {
- str += String.fromCharCode(e.keyCode).toLowerCase();
- } else if (e.keyCode in shortcuts.keys) {
- str += shortcuts.keys[e.keyCode];
- } else {
- return;
- }
-
- var focus = document.activeElement.getAttribute('name');
-
- if (focus && focus in shortcuts) {
- if (str in shortcuts[focus]) {
- app.actions.execute( shortcuts[focus][str], e);
- e.preventDefault();
- return;
- }
- }
-
- if (str in shortcuts.global) {
- app.actions.execute( shortcuts.global[str], e);
- e.preventDefault();
- }
- }
- }));
-
- // Prevent context-menu when alt is pressed
- document.addEventListener('keyup', function(e) {
- if (e.keyCode == 18) {
- e.preventDefault();
- }
- });
-
-
- document.addEventListener('keydown', app.handleKeyDown);
-
-
- return app;
-});
\ No newline at end of file
diff --git a/scripts/app/collections/Actions.js b/scripts/app/collections/Actions.js
deleted file mode 100644
index f3657d1b..00000000
--- a/scripts/app/collections/Actions.js
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
- * @module App
- * @submodule collections/Actions
- */
-define(['backbone', 'models/Action', 'staticdb/actions'], function (BB, Action, db) {
-
- /**
- * Collection of executable actions. Actions are usually executed by shorcuts, buttons or context menus.
- * @class Actions
- * @constructor
- * @extends Backbone.Collection
- */
- var Actions = BB.Collection.extend({
- model: Action,
-
- /**
- * @method initialize
- */
- initialize: function() {
- Object.keys(db).forEach(function(region) {
- Object.keys(db[region]).forEach(function(name) {
- var c = db[region][name];
- this.add({ name: region + ':' + name, fn: c.fn, icon: c.icon, title: c.title });
- }, this);
- }, this);
- },
-
- /**
- * Executes given action
- * @method execute
- * @param action {string|models/Action}
- */
- execute: function(action) {
- if (typeof action == 'string') action = this.get(action);
- if (!action) {
- console.log('Action "' + action + '" does not exists');
- return false;
- }
- var args = [].slice.call(arguments);
- args.shift();
- action.get('fn').apply(app, args);
- return true;
- }
- });
-
- return Actions;
-});
\ No newline at end of file
diff --git a/scripts/app/collections/Groups.js b/scripts/app/collections/Groups.js
deleted file mode 100644
index 7dca4419..00000000
--- a/scripts/app/collections/Groups.js
+++ /dev/null
@@ -1,18 +0,0 @@
-/**
- * @module App
- * @submodule collections/Groups
- */
-define(['backbone', 'models/Group'], function(BB, Group) {
-
- /**
- * Collection of date groups
- * @class Groups
- * @constructor
- * @extends Backbone.Collection
- */
- var Groups = BB.Collection.extend({
- model: Group
- });
-
- return Groups;
-});
\ No newline at end of file
diff --git a/scripts/app/collections/MenuCollection.js b/scripts/app/collections/MenuCollection.js
deleted file mode 100644
index 09fb3fae..00000000
--- a/scripts/app/collections/MenuCollection.js
+++ /dev/null
@@ -1,18 +0,0 @@
-/**
- * @module App
- * @submodule collections/MenuCollection
- */
-define(['backbone', 'models/MenuItem'], function(BB, MenuItem) {
-
- /**
- * Each ContextMenu has its own MenuCollection instance
- * @class MenuCollection
- * @constructor
- * @extends Backbone.Collection
- */
- var MenuCollection = BB.Collection.extend({
- model: MenuItem
- });
-
- return MenuCollection;
-});
\ No newline at end of file
diff --git a/scripts/app/collections/ToolbarItems.js b/scripts/app/collections/ToolbarItems.js
deleted file mode 100644
index 4a659810..00000000
--- a/scripts/app/collections/ToolbarItems.js
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- * @module App
- * @submodule collections/ToolbarItems
- */
-define(['backbone', 'models/ToolbarButton'], function (BB, ToolbarButton) {
-
- /**
- * Each ToolbarView has its own ToolbarItems instance
- * @class ToolbarItems
- * @constructor
- * @extends Backbone.Collection
- */
- var ToolbarItems = BB.Collection.extend({
- model: ToolbarButton,
-
- comparator: function(tbItem1, tbItem2) {
- if (!tbItem1.view || !tbItem2.view) return 0;
- var r1 = tbItem1.view.el.getBoundingClientRect();
- var r2 = tbItem2.view.el.getBoundingClientRect();
-
- return r1.left > r2.left ? 1 : -1;
- }
- });
-
- return ToolbarItems;
-});
\ No newline at end of file
diff --git a/scripts/app/factories/ToolbarItemsFactory.js b/scripts/app/factories/ToolbarItemsFactory.js
deleted file mode 100644
index f8c0300e..00000000
--- a/scripts/app/factories/ToolbarItemsFactory.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
- * Factory for making instances of toolbar items
- * @module App
- * @submodule factories/ToolbarItemsFactory
- */
-define([
- 'views/ToolbarButtonView', 'views/ToolbarDynamicSpaceView', 'views/ToolbarSearchView'
-],
-function (ToolbarButtonView, ToolbarDynamicSpaceView, ToolbarSearchView) {
-
- var ToolbarItemsFactory = {
- /**
- * Returns instance of toolbar item
- * @method create
- * @param name {string}
- * @param itemModel {Object}
- * @returns ToolbarDynamicSpaceView|ToolbarSearchView|ToolbarButtonView
- */
- create: function(name, itemModel) {
- if (name == 'dynamicSpace') {
- return new ToolbarDynamicSpaceView({ model: itemModel });
- } else if (name == 'search') {
- return new ToolbarSearchView({ model: itemModel });
- } else {
- return new ToolbarButtonView({ model: itemModel });
- }
- }
- };
-
-
- return ToolbarItemsFactory;
-});
\ No newline at end of file
diff --git a/scripts/app/helpers/escapeHtml.js b/scripts/app/helpers/escapeHtml.js
deleted file mode 100644
index cb1c1f6d..00000000
--- a/scripts/app/helpers/escapeHtml.js
+++ /dev/null
@@ -1,28 +0,0 @@
-/**
- * Escapes following characters: &, <, >, ", '
- * @module App
- * @submodule helpers/escapeHtml
- * @param string {String} String with html to be escaped
- */
-define([], function() {
- var entityMap = {
- '&': '&',
- '<': '<',
- '>': '>',
- '"': '"',
- '\'': '''
- };
-
- var escapeHtml = function(str) {
- str = String(str).replace(/[&<>"']/gm, function (s) {
- return entityMap[s];
- });
- str = str.replace(/\s/, function(f) {
- if (f == ' ') return ' ';
- return '';
- });
- return str;
- };
-
- return escapeHtml;
-});
\ No newline at end of file
diff --git a/scripts/app/helpers/formatDate.js b/scripts/app/helpers/formatDate.js
deleted file mode 100644
index dfefd97f..00000000
--- a/scripts/app/helpers/formatDate.js
+++ /dev/null
@@ -1,91 +0,0 @@
-/**
- * Returns formatted date string
- * @module App
- * @submodule helpers/formatDate
- * @param date {Integer|Date} Date to be formated
- * @param formatString {String} String consisting of special characters
- * @example formatDate(new Date, 'YYYY-MM-DD hh:mm');
- */
-define([], function() {
- var formatDate = (function() {
- var that;
- var addZero = function(num) {
- if (num < 10) num = '0' + num;
- return num;
- };
- var na = function(n, z) {
- return n % z;
- };
- var getDOY = function() {
- var dt = new Date(that);
- dt.setHours(0, 0, 0);
- var onejan = new Date(dt.getFullYear(), 0, 1);
- return Math.ceil((dt - onejan) / 86400000);
- };
- var getWOY = function() {
- var dt = new Date(that);
- dt.setHours(0, 0, 0);
- dt.setDate(dt.getDate() + 4 - (dt.getDay() || 7));
- var onejan = new Date(dt.getFullYear(), 0, 1);
- return Math.ceil((((dt - onejan) / 86400000) + onejan.getDay() + 1) / 7);
- };
- var dateVal = function(all, found) {
- switch (found) {
- case 'DD':
- return addZero(that.getDate());
- case 'D':
- return that.getDate();
- case 'MM':
- return addZero(that.getMonth() + 1);
- case 'M':
- return that.getMonth() + 1;
- case 'YYYY':
- return that.getFullYear();
- case 'YY':
- return that.getFullYear().toString().substr(2, 2);
- case 'hh':
- return addZero(that.getHours());
- case 'h':
- return that.getHours();
- case 'HH':
- return addZero(na(that.getHours(), 12));
- case 'H':
- return na(that.getHours(), 12);
- case 'mm':
- return addZero(that.getMinutes());
- case 'm':
- return that.getMinutes();
- case 'ss':
- return addZero(that.getSeconds());
- case 's':
- return that.getSeconds();
- case 'u':
- return that.getMilliseconds();
- case 'U':
- return that.getTime();
- case 'T':
- return that.getTime() - that.getTimezoneOffset() * 60000;
- case 'W':
- return that.getDay();
- case 'y':
- return getDOY();
- case 'w':
- return getWOY();
- case 'G':
- return that.getTimezoneOffset();
- case 'a':
- return that.getHours() > 12 ? 'PM' : 'AM';
- default:
- return '';
- }
- };
- return function(date, str) {
- if (!(date instanceof Date)) date = new Date(date);
- that = date;
- str = str.replace(/(DD|D|MM|M|YYYY|YY|hh|h|HH|H|mm|m|ss|s|u|U|W|y|w|G|a|T)/g, dateVal);
- return str;
- };
- }());
-
- return formatDate;
-});
\ No newline at end of file
diff --git a/scripts/app/helpers/getWOY.js b/scripts/app/helpers/getWOY.js
deleted file mode 100644
index 39984822..00000000
--- a/scripts/app/helpers/getWOY.js
+++ /dev/null
@@ -1,16 +0,0 @@
-/**
- * Get week of year
- * @module App
- * @submodule helpers/getWOY
- * @param date {string|Date} Get the week based on this date
- */
-define([], function() {
- var getWOY = function(pdate) {
- pdate = new Date(pdate);
- pdate.setHours(0, 0, 0);
- pdate.setDate(pdate.getDate() + 4 - (pdate.getDay() || 7));
- var onejan = new Date(pdate.getFullYear(), 0, 1);
- return Math.ceil((((pdate - onejan) / 86400000) + onejan.getDay() + 1) / 7);
- };
- return getWOY;
-});
\ No newline at end of file
diff --git a/scripts/app/helpers/unixutc.js b/scripts/app/helpers/unixutc.js
deleted file mode 100644
index 11a8b209..00000000
--- a/scripts/app/helpers/unixutc.js
+++ /dev/null
@@ -1,13 +0,0 @@
-/**
- * Get unix time with added/substracted UTC hours
- * @module App
- * @submodule helpers/unixutc
- * @param date {string|Date} Get the week based on this date
- */
-define([], function() {
- var _unixutcoff = (new Date).getTimezoneOffset() * 60000;
- var unixutc = function(date) {
- return date.getTime() - _unixutcoff;
- };
- return unixutc;
-});
\ No newline at end of file
diff --git a/scripts/app/instances/contextMenus.js b/scripts/app/instances/contextMenus.js
deleted file mode 100644
index 5f1caece..00000000
--- a/scripts/app/instances/contextMenus.js
+++ /dev/null
@@ -1,243 +0,0 @@
-define([
- 'backbone', 'views/ContextMenu', 'modules/Locale', 'views/feedList'
-],
-function(BB, ContextMenu, Locale) {
- var sourceContextMenu = new ContextMenu([
- {
- title: Locale.c.UPDATE,
- icon: 'reload.png',
- action: function() {
- app.actions.execute('feeds:update');
- //bg.downloadOne(sourceContextMenu.currentSource);
- }
- },
- {
- title: Locale.c.MARK_ALL_AS_READ,
- icon: 'read.png',
- action: function() {
- app.actions.execute('feeds:mark');
- }
- },
- {
- title: Locale.c.DELETE,
- icon: 'delete.png',
- action: function() {
- app.actions.execute('feeds:delete');
- }
- },
- {
- title: 'Refetch', /**** Localization needed****/
- icon: 'save.png',
- action: function() {
- app.actions.execute('feeds:refetch');
- }
- },
- {
- title: Locale.c.PROPERTIES,
- icon: 'properties.png',
- action: function() {
- app.actions.execute('feeds:showProperties');
- }
- }
- ]);
-
- var trashContextMenu = new ContextMenu([
- {
- title: Locale.c.MARK_ALL_AS_READ,
- icon: 'read.png',
- action: function() {
- bg.items.where({ trashed: true, deleted: false }).forEach(function(item) {
- if (item.get('unread') == true) {
- item.save({
- unread: false,
- visited: true
- });
- }
- });
- }
- },
- {
- title: Locale.c.EMPTY_TRASH,
- icon: 'delete.png',
- action: function() {
- if (confirm(Locale.c.REALLY_EMPTY_TRASH)) {
- bg.items.where({ trashed: true, deleted: false }).forEach(function(item) {
- item.markAsDeleted();
- });
- }
- }
- }
- ]);
-
- var allFeedsContextMenu = new ContextMenu([
- {
- title: Locale.c.UPDATE_ALL,
- icon: 'reload.png',
- action: function() {
- app.actions.execute('feeds:updateAll');
- }
- },
- {
- title: Locale.c.MARK_ALL_AS_READ,
- icon: 'read.png',
- action: function() {
- if (confirm(Locale.c.MARK_ALL_QUESTION)) {
- bg.items.forEach(function(item) {
- item.save({ unread: false, visited: true });
- });
- }
- }
- },
- {
- title: Locale.c.DELETE_ALL_ARTICLES,
- icon: 'delete.png',
- action: function() {
- if (confirm(Locale.c.DELETE_ALL_Q)) {
- bg.items.forEach(function(item) {
- if (item.get('deleted') == true) return;
- item.markAsDeleted();
- });
- }
- }
- }
- ]);
-
- var folderContextMenu = new ContextMenu([
- {
- title: Locale.c.UPDATE,
- icon: 'reload.png',
- action: function() {
- app.actions.execute('feeds:update');
- }
- },
- {
- title: Locale.c.MARK_ALL_AS_READ,
- icon: 'read.png',
- action: function() {
- app.actions.execute('feeds:mark');
- }
- },
- {
- title: Locale.c.DELETE,
- icon: 'delete.png',
- action: function() {
- app.actions.execute('feeds:delete');
- }
- },
- {
- title: Locale.c.PROPERTIES,
- icon: 'properties.png',
- action: function() {
- app.actions.execute('feeds:showProperties');
- }
- }
- /*{
- title: Locale.c.RENAME,
- action: function() {
- var feedList = require('views/feedList');
- var newTitle = prompt(Locale.c.FOLDER_NAME + ': ', feedList.selectedItems[0].model.get('title'));
- if (!newTitle) return;
-
- feedList.selectedItems[0].model.save({ title: newTitle });
- }
- }*/
- ]);
-
- var itemsContextMenu = new ContextMenu([
- {
- title: Locale.c.NEXT_UNREAD + ' (H)',
- icon: 'forward.png',
- action: function() {
- app.actions.execute('articles:nextUnread');
- }
- },
- {
- title: Locale.c.PREV_UNREAD + ' (Y)',
- icon: 'back.png',
- action: function() {
- app.actions.execute('articles:prevUnread');
- }
- },
- {
- title: Locale.c.MARK_AS_READ + ' (K)',
- icon: 'read.png',
- action: function() {
- app.actions.execute('articles:mark');
- }
- },
- {
- title: Locale.c.MARK_AND_NEXT_UNREAD + ' (G)',
- icon: 'find_next.png',
- action: function() {
- app.actions.execute('articles:markAndNextUnread');
- }
- },
- {
- title: Locale.c.MARK_AND_PREV_UNREAD + ' (T)',
- icon: 'find_previous.png',
- action: function() {
- app.actions.execute('articles:markAndPrevUnread');
- }
- },
- {
- title: Locale.c.FULL_ARTICLE,
- icon: 'full_article.png',
- action: function(e) {
- app.actions.execute('articles:fullArticle', e);
- }
- },
- {
- title: Locale.c.PIN + ' (P)',
- icon: 'pinsource_context.png',
- action: function() {
- app.actions.execute('articles:pin');
- }
- },
- {
- title: Locale.c.DELETE + ' (D)',
- icon: 'delete.png',
- action: function(e) {
- app.actions.execute('articles:delete', e);
- }
- },
- {
- title: Locale.c.UNDELETE + ' (N)',
- id: 'context-undelete',
- icon: 'undelete.png',
- action: function() {
- app.actions.execute('articles:undelete');
- }
- }
- ]);
-
- var contextMenus = new (BB.View.extend({
- list: {},
- initialize: function() {
- this.list = {
- source: sourceContextMenu,
- trash: trashContextMenu,
- folder: folderContextMenu,
- allFeeds: allFeedsContextMenu,
- items: itemsContextMenu
- };
- },
- get: function(name) {
- if (name in this.list) {
- return this.list[name];
- }
- return null;
- },
- hideAll: function() {
- Object.keys(this.list).forEach(function(item) {
- this.list[item].hide();
- }, this);
- },
- areActive: function() {
- return Object.keys(this.list).some(function(item) {
- return !!this.list[item].el.parentNode;
- }, this);
- }
- }));
-
- return contextMenus;
-});
\ No newline at end of file
diff --git a/scripts/app/instances/specials.js b/scripts/app/instances/specials.js
deleted file mode 100644
index d296b873..00000000
--- a/scripts/app/instances/specials.js
+++ /dev/null
@@ -1,52 +0,0 @@
-define([
- 'backbone', 'models/Special', 'instances/contextMenus', 'modules/Locale', 'views/feedList'
-],
-function(BB, Special, contextMenus, Locale) {
-
- var specials = {
- trash: new Special({
- title: Locale.c.TRASH,
- icon: 'trashsource.png',
- filter: { trashed: true, deleted: false },
- position: 'bottom',
- name: 'trash',
- onReady: function() {
- this.contextMenu = contextMenus.get('trash');
- this.el.addEventListener('dragover', function(e) {
- e.preventDefault();
- });
- this.el.addEventListener('drop', function(e) {
- e.preventDefault();
- var ids = JSON.parse(e.dataTransfer.getData('text/plain') || '[]') || [];
- ids.forEach(function(id) {
- var item = bg.items.findWhere({ id: id });
- if (item && !item.get('trashed')) {
- item.save({
- trashed: true
- });
- }
- });
- });
- }
- }),
- allFeeds: new Special({
- title: Locale.c.ALL_FEEDS,
- icon: 'icon16_v2.png',
- filter: { trashed: false },
- position: 'top',
- name: 'all-feeds',
- onReady: function() {
- this.contextMenu = contextMenus.get('allFeeds');
- }
- }),
- pinned: new Special({
- title: Locale.c.PINNED,
- icon: 'pinsource.png',
- filter: { trashed: false, pinned: true },
- position: 'bottom',
- name: 'pinned'
- })
- };
-
- return specials;
-});
\ No newline at end of file
diff --git a/scripts/app/layouts/ArticlesLayout.js b/scripts/app/layouts/ArticlesLayout.js
deleted file mode 100644
index 59561cf9..00000000
--- a/scripts/app/layouts/ArticlesLayout.js
+++ /dev/null
@@ -1,97 +0,0 @@
-/**
- * @module App
- * @submodule layouts/ArticlesLayout
- */
-define([
- 'jquery', 'layouts/Layout', 'views/ToolbarView', 'views/articleList',
- 'mixins/resizable', 'controllers/comm', 'domReady!'
-],
-function ($, Layout, ToolbarView, articleList, resizable, comm) {
-
- var toolbar = bg.toolbars.findWhere({ region: 'articles' });
-
- /**
- * Articles layout view
- * @class ArticlesLayout
- * @constructor
- * @extends Layout
- */
- var ArticlesLayout = Layout.extend({
- el: '#region-articles',
- events: {
- 'keydown': 'handleKeyDown',
- 'mousedown': 'handleMouseDown'
- },
- initialize: function() {
- this.el.view = this;
-
- this.on('attach', function() {
- this.attach('toolbar', new ToolbarView({ model: toolbar }) );
- this.attach('articleList', articleList );
- });
-
- this.$el.on('focus', function() {
- $(this).addClass('focused');
- clearTimeout(blurTimeout);
- });
-
- var focus = true;
- var blurTimeout;
-
- comm.on('stop-blur', function() {
- focus = false;
- });
-
- this.$el.on('blur', function(e) {
- blurTimeout = setTimeout(function() {
- if (focus && !e.relatedTarget) {
- this.focus();
- return;
- }
- $(this).removeClass('focused');
- focus = true;
- }.bind(this), 0);
- });
-
-
- this.on('resize:after', this.handleResizeAfter);
- this.on('resize', this.handleResize);
- this.on('resize:enabled', this.handleResize);
-
- },
- /**
- * Saves the new layout size
- * @triggered after resize
- * @method handleResizeAfter
- */
- handleResizeAfter: function() {
- if (bg.settings.get('layout') == 'horizontal') {
- var wid = this.el.offsetWidth;
- bg.settings.save({ posB: wid });
- } else {
- var hei = this.el.offsetHeight;
- bg.settings.save({ posC:hei });
- }
- },
- /**
- * Changes layout to one/two line according to width
- * @triggered while resizing
- * @method handleResize
- */
- handleResize: function() {
- if (bg.settings.get('lines') == 'auto') {
- var oneRem = parseFloat(getComputedStyle(document.documentElement).fontSize);
- if (this.el.offsetWidth > 37 * oneRem) {
- this.articleList.$el.addClass('lines-one-line');
- } else {
- this.articleList.$el.removeClass('lines-one-line');
- }
- }
- }
-
- });
-
- ArticlesLayout = ArticlesLayout.extend(resizable);
-
- return ArticlesLayout;
-});
\ No newline at end of file
diff --git a/scripts/app/layouts/ContentLayout.js b/scripts/app/layouts/ContentLayout.js
deleted file mode 100644
index 1b04060e..00000000
--- a/scripts/app/layouts/ContentLayout.js
+++ /dev/null
@@ -1,82 +0,0 @@
-/**
- * @module App
- * @submodule layouts/ContentLayout
- */
-define([
- 'jquery', 'layouts/Layout', 'views/ToolbarView', 'views/contentView', 'views/SandboxView',
- 'views/OverlayView', 'views/LogView', 'controllers/comm', 'domReady!'
-],
-function ($, Layout, ToolbarView, contentView, SandboxView, OverlayView, LogView, comm) {
-
- var toolbar = bg.toolbars.findWhere({ region: 'content' });
-
- /**
- * Content layout view
- * @class ContentLayout
- * @constructor
- * @extends Layout
- */
- var ContentLayout = Layout.extend({
-
- /**
- * View element
- * @property el
- * @default #region-content
- * @type HTMLElement
- */
- el: '#region-content',
-
- /**
- * @method initialize
- */
- initialize: function() {
- this.on('attach', function() {
-
- this.attach('toolbar', new ToolbarView({ model: toolbar }) );
- this.attach('content', contentView );
- this.attach('sandbox', new SandboxView() );
- this.attach('log', new LogView() );
- this.attach('overlay', new OverlayView() );
-
- this.listenTo(comm, 'hide-overlays', this.hideOverlay);
- });
-
- this.$el.on('focus', function() {
- $(this).addClass('focused');
- clearTimeout(blurTimeout);
- });
-
- var focus = true;
- var blurTimeout;
-
- comm.on('stop-blur', function() {
- focus = false;
- });
-
- this.$el.on('blur', function(e) {
- blurTimeout = setTimeout(function() {
- if (focus && !e.relatedTarget) {
- this.focus();
- return;
- }
- $(this).removeClass('focused');
- focus = true;
- }.bind(this), 0);
- });
-
- },
-
- /**
- * Hides config overlay
- * @method hideOverlay
- */
- hideOverlay: function() {
- if (this.overlay.isVisible()) {
- this.overlay.hide();
- }
- }
-
- });
-
- return ContentLayout;
-});
\ No newline at end of file
diff --git a/scripts/app/layouts/FeedsLayout.js b/scripts/app/layouts/FeedsLayout.js
deleted file mode 100644
index 7750f3c0..00000000
--- a/scripts/app/layouts/FeedsLayout.js
+++ /dev/null
@@ -1,87 +0,0 @@
-/**
- * @module App
- * @submodule layouts/FeedsLayout
- */
-define([
- 'jquery', 'layouts/Layout', 'views/ToolbarView', 'views/feedList',
- 'instances/contextMenus', 'views/Properties', 'mixins/resizable', 'views/IndicatorView',
- 'controllers/comm', 'domReady!'
-],
-function ($, Layout, ToolbarView, feedList, contextMenus, Properties, resizable, IndicatorView, comm) {
-
- var toolbar = bg.toolbars.findWhere({ region: 'feeds' });
-
- /**
- * Feeds layout view
- * @class FeedsLayout
- * @constructor
- * @extends Layout
- */
- var FeedsLayout = Layout.extend({
- /**
- * View element
- * @property el
- * @default #region-feeds
- * @type HTMLElement
- */
- el: '#region-feeds',
-
- /**
- * @method initialize
- */
- initialize: function() {
-
- this.on('attach', function() {
- this.attach('toolbar', new ToolbarView({ model: toolbar }) );
- this.attach('properties', new Properties);
- this.attach('feedList', feedList);
- this.attach('indicator', new IndicatorView);
- });
-
- this.el.view = this;
-
- this.$el.on('focus', function() {
- $(this).addClass('focused');
- clearTimeout(blurTimeout);
- });
-
- var focus = true;
- var blurTimeout;
-
- comm.on('stop-blur', function() {
- focus = false;
- });
-
- this.$el.on('blur', function(e) {
- blurTimeout = setTimeout(function() {
- if (focus && !e.relatedTarget) {
- this.focus();
- return;
- }
- $(this).removeClass('focused');
- focus = true;
- }.bind(this), 0);
- });
-
- this.on('resize:after', this.handleResize);
- //window.addEventListener('resize', this.handleResize.bind(this));
-
- this.enableResizing('horizontal', bg.settings.get('posA'));
- },
-
- /**
- * Saves layout size
- * @method handleResize
- */
- handleResize: function() {
- if (bg.settings.get('panelToggled')) {
- var wid = this.el.offsetWidth;
- bg.settings.save({ posA: wid });
- }
- }
- });
-
- FeedsLayout = FeedsLayout.extend(resizable);
-
- return FeedsLayout;
-});
\ No newline at end of file
diff --git a/scripts/app/layouts/Layout.js b/scripts/app/layouts/Layout.js
deleted file mode 100644
index 297998a2..00000000
--- a/scripts/app/layouts/Layout.js
+++ /dev/null
@@ -1,51 +0,0 @@
-/**
- * @module App
- * @submodule layouts/Layout
- */
-define(['backbone'], function(BB) {
-
- /**
- * Layout abstract class
- * @class Layout
- * @constructor
- * @extends Backbone.View
- */
- var Layout = BB.View.extend({
-
- /**
- * Gives focus to layout region element
- * @method setFocus
- * @param name {String} Name of the region
- */
- setFocus: function(name) {
- if (!name || !this[name]) return;
- this[name].el.focus();
- },
-
- /**
- * Appends new region to layout.
- * If existing name is used, the old region is replaced with the new region
- * and 'close' event is triggered on the old region
- * @method attach
- * @param name {String} Name of the region
- * @param view {Backbone.View} Backbone view to be the attached region
- */
- attach: function(name, view) {
- var old = this[name];
-
- this[name] = view;
- if (!view.el.parentNode) {
- if (old && old instanceof BB.View) {
- old.$el.replaceWith(view.el);
- old.trigger('close');
- } else {
- this.$el.append(view.el);
- }
- }
- view.trigger('attach');
- if (!this.focus) this.setFocus(name);
- }
- });
-
- return Layout;
-});
\ No newline at end of file
diff --git a/scripts/app/mixins/resizable.js b/scripts/app/mixins/resizable.js
deleted file mode 100644
index 512e0c67..00000000
--- a/scripts/app/mixins/resizable.js
+++ /dev/null
@@ -1,138 +0,0 @@
-define(['jquery'], function($) {
-
- var els = [];
-
- var resizeWidth = bg.settings.get('thickFrameBorders') ? 10 : 6;
-
- function handleMouseDown(e) {
- this.resizing = true;
- e.preventDefault();
- $('iframe').css('pointer-events', 'none');
- this.trigger('resize:before');
- }
-
- function handleMouseMove(e) {
- if (this.resizing) {
- var toLeft = bg.settings.get('thickFrameBorders') ? 5 : 1;
- e.preventDefault();
- if (this.layout == 'vertical') {
- setPosition.call(this, e.clientY);
- this.$el.css('flex-basis', Math.abs(e.clientY - this.el.offsetTop + toLeft) );
- } else {
- setPosition.call(this, e.clientX);
- this.$el.css('flex-basis', Math.abs(e.clientX - this.el.offsetLeft + toLeft) );
- }
-
- this.trigger('resize');
- }
- }
-
- function handleMouseUp() {
- if (!this.resizing) return;
- $('iframe').css('pointer-events', 'auto');
- this.resizing = false;
- for (var i=0; i= this.el.offsetHeight) {
- return false;
- }
- return true;
- },
- handleSelectableMouseDown: function(e) {
- //e.currentTarget.view.handleMouseDown(e);
- var item = e.currentTarget.view;
- if (this.selectedItems.length > 1 && item.$el.hasClass('selected') && !e.ctrlKey && !e.shiftKey) {
- this.selectFlag = true;
- return;
- }
- // used to be just { shiftKey: e.shiftKey, ctrlKey: e.ctrlKey } instead of 'e'
- this.select(item, e);
- },
- handleSelectableMouseUp: function(e) {
- var item = e.currentTarget.view;
- if (e.which == 1 && this.selectedItems.length > 1 && this.selectFlag) {
- this.select(item, e);
- this.selectFlag = false;
- }
- }
-
-};
-});
\ No newline at end of file
diff --git a/scripts/app/models/Action.js b/scripts/app/models/Action.js
deleted file mode 100644
index b33a15a8..00000000
--- a/scripts/app/models/Action.js
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
- * @module App
- * @submodule models/Action
- */
-define(['backbone'], function (BB) {
-
- /**
- * Executable action. Actions are usually executed by shorcuts, buttons or context menus.
- * @class Action
- * @constructor
- * @extends Backbone.Model
- */
- var Action = BB.Model.extend({
- /**
- * @property idAttribute
- * @type String
- * @default name
- */
- idAttribute: 'name',
- defaults: {
- /**
- * @attribute name
- * @type String
- * @default global:default
- */
- name: 'global:default',
-
- /**
- * Function to be called when action is executed
- * @attribute fn
- * @type function
- */
- fn: function() {
- return function() {};
- },
-
- /**
- * @attribute icon
- * @type String
- * @default unknown.png
- */
- icon: 'unknown.png',
-
- /**
- * @attribute title
- * @type String
- * @default ''
- */
- title: ''
- }
- });
-
- return Action;
-});
\ No newline at end of file
diff --git a/scripts/app/models/Group.js b/scripts/app/models/Group.js
deleted file mode 100644
index 3ebcab0a..00000000
--- a/scripts/app/models/Group.js
+++ /dev/null
@@ -1,116 +0,0 @@
-/**
- * @module App
- * @submodule models/Group
- */
-define(['backbone', 'helpers/unixutc', 'helpers/getWOY', 'modules/Locale'], function(BB, unixutc, getWOY, Locale) {
-
- /**
- * Date group model
- * @class Group
- * @constructor
- * @extends Backbone.Model
- */
- var Group = BB.Model.extend({
- defaults: {
- /**
- * Title of the date group (Today, Yesterday, 2012, ...)
- * @attribute title
- * @type String
- * @default ''
- */
- title: '',
-
- /**
- * End date of date group (yesterdays date is midnight between yesterday and today) in unix time
- * @attribute date
- * @type Integer
- * @default 0
- */
- date: 0
- },
- idAttribute: 'date'
- });
-
- /**
- * Gets date group attributes of given date
- * @method getGroup
- * @static
- * @param date {Integer|Date}
- * @return {Object} Object contaning title & date attributes
- */
- Group.getGroup = (function() {
- var days = ['SUNDAY', 'MONDAY', 'TUESDAY', 'WEDNESDAY', 'THURSDAY', 'FRIDAY', 'SATURDAY'];
- var months = ['JANUARY', 'FEBRUARY', 'MARCH', 'APRIL', 'MAY', 'JUNE', 'JULY', 'AUGUST', 'SEPTEMBER', 'OCTOBER', 'NOVEMBER', 'DECEMBER'];
- var dc = null;
- var todayMidnight = null;
- var dct = null;
-
-
- return function(date) {
- var dt = new Date(date);
- dc = dc || new Date();
-
-
- var dtt = parseInt(unixutc(dt) / 86400000, 10);
- dct = dct || parseInt(unixutc(dc) / 86400000, 10);
-
- if (!todayMidnight) {
- todayMidnight = new Date(dc);
- todayMidnight.setHours(0,0,0,0);
- setTimeout(function() {
- todayMidnight = null;
- dc = null;
- dct = null;
- }, 10000);
- }
-
- var itemMidnight = new Date(dt);
- itemMidnight.setHours(0,0,0,0);
-
- var group;
- var dtwoy, dcwoy;
-
- if (dtt >= dct) {
- group = {
- title: Locale.c.TODAY.toUpperCase(),
- date: todayMidnight.getTime() + 86400000 * 5000 // 5000 = make sure "today" is the first element in list
- };
- } else if (dtt + 1 == dct) {
- group = {
- title: Locale.c.YESTERDAY.toUpperCase(),
- date: todayMidnight.getTime()
- };
- } else if ((dtwoy = getWOY(dt)) == (dcwoy = getWOY(dc)) && dtt + 7 >= dct) {
- group = {
- title: Locale.c[days[dt.getDay()]].toUpperCase(),
- date: itemMidnight.getTime() + 86400000
- };
- } else if (dtwoy + 1 == dcwoy && dtt + 14 >= dct) {
- group = {
- title: Locale.c.LAST_WEEK.toUpperCase(),
- date: todayMidnight.getTime() - 86400000 * ( ((todayMidnight.getDay() || 7) - 1) || 1)
- };
- } else if (dt.getMonth() == dc.getMonth() && dt.getFullYear() == dc.getFullYear()) {
- group = {
- title: Locale.c.EARLIER_THIS_MONTH.toUpperCase(),
- date: todayMidnight.getTime() - 86400000 * ((todayMidnight.getDay() || 7) - 1) - 7 * 86400000
- };
- } else if (dt.getFullYear() == dc.getFullYear() ) {
- group = {
- title: Locale.c[months[dt.getMonth()]].toUpperCase(),
- date: (new Date(dt.getFullYear(), dt.getMonth() + 1, 1)).getTime()
- };
- } else {
- group = {
- title: dt.getFullYear(),
- date: (new Date(dt.getFullYear() + 1, 0, 1)).getTime()
- };
- }
-
- return group;
-
- };
- })();
-
- return Group;
-});
\ No newline at end of file
diff --git a/scripts/app/models/MenuItem.js b/scripts/app/models/MenuItem.js
deleted file mode 100644
index 605ff880..00000000
--- a/scripts/app/models/MenuItem.js
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * @module App
- * @submodule models/MenuItem
- */
-define(['backbone'], function(BB) {
-
- /**
- * Context menu item
- * @class MenuItem
- * @constructor
- * @extends Backbone.Model
- */
- var MenuItem = BB.Model.extend({
- defaults: {
-
- /**
- * @attribute title
- * @type String
- * @default ''
- */
- 'title': '',
-
- /**
- * Function to be called when user selects this item
- * @attribute action
- * @type function
- * @default null
- */
- 'action': null
- }
- });
-
- return MenuItem;
-});
\ No newline at end of file
diff --git a/scripts/app/models/Special.js b/scripts/app/models/Special.js
deleted file mode 100644
index 7d89eb69..00000000
--- a/scripts/app/models/Special.js
+++ /dev/null
@@ -1,65 +0,0 @@
-/**
- * @module App
- * @submodule models/Special
- */
-define(['backbone'], function(BB) {
- /**
- * Model for special items in feed list like all-feeds, pinned and trash
- * @class Special
- * @constructor
- * @extends Backbone.Model
- */
- var Special = BB.Model.extend({
- defaults: {
- /**
- * Visible title of special. Chnages with localization.
- * @attribute title
- * @type String
- * @default All feeds
- */
- title: 'All feeds',
-
- /**
- * @attribute icon
- * @type String
- * @default icon16_v2.png
- */
- icon: 'icon16_v2.png',
-
- /**
- * Name of the special. It is always the same for one special.
- * @attribute name
- * @type String
- * @default ''
- */
- name: '',
-
- /**
- * Filter used in 'where' function of items collection
- * @attribute filter
- * @type Object
- * @default {}
- * @example { unread: true, trashed: false }
- */
- filter: {},
-
- /**
- * Should the special be above or below feed sources?
- * @attribute position
- * @type String
- * @default top
- */
- position: 'top',
-
- /**
- * Function to be called when specials view is initialized
- * @attribute onReady
- * @type function
- * @default null
- */
- onReady: null
- }
- });
-
- return Special;
-});
\ No newline at end of file
diff --git a/scripts/app/models/ToolbarButton.js b/scripts/app/models/ToolbarButton.js
deleted file mode 100644
index 90622e53..00000000
--- a/scripts/app/models/ToolbarButton.js
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * @module App
- * @submodule models/ToolbarButton
- */
-define(['backbone'], function (BB) {
-
- /**
- * Button model for toolbars
- * @class ToolbarButton
- * @constructor
- * @extends Backbone.Model
- */
- var ToolbarButton = BB.Model.extend({
- defaults: {
-
- /**
- * @attribute actionName
- * @type String
- * @default global:default
- */
- actionName: 'global:default',
-
- /**
- * Is button aligned to left or right?
- * @attribute position
- * @type String
- * @default left
- */
- position: 'left'
- }
- });
-
- return ToolbarButton;
-});
\ No newline at end of file
diff --git a/scripts/app/modules/Locale.js b/scripts/app/modules/Locale.js
deleted file mode 100644
index fec5a5d0..00000000
--- a/scripts/app/modules/Locale.js
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
- * @module App
- * @submodule modules/Locale
- */
-var nl = bg.settings.get('lang') || 'en';
-define(['../../nls/' + nl, '../../nls/en'], function (lang, en) {
-
- /**
- * String localization
- * @class Locale
- * @constructor
- * @extends Object
- */
- var Locale = {
- get c() {
- return lang || en;
- },
- translate: function(str) {
- str = String(str);
- if (lang) return lang[str];
- if (en) return en[str];
- return str;
- },
- translateHTML: function(content) {
- return String(content).replace(/\{\{(\w+)\}\}/gm, function(all, str) {
- return lang[str] || en[str] || str;
- });
- }
- };
-
- return Locale;
-
-});
\ No newline at end of file
diff --git a/scripts/app/preps/all.js b/scripts/app/preps/all.js
deleted file mode 100644
index 0d465c33..00000000
--- a/scripts/app/preps/all.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/**
- * Loads all preps as dependencies
- * @module App
- * @submodule preps/extendNative
- */
-define(['preps/extendNative'], function() {
- return true;
-});
\ No newline at end of file
diff --git a/scripts/app/preps/extendNative.js b/scripts/app/preps/extendNative.js
deleted file mode 100644
index 742db561..00000000
--- a/scripts/app/preps/extendNative.js
+++ /dev/null
@@ -1,95 +0,0 @@
-/**
- * Extends prototypes of native objects with various methods.
- * Removes prefixes for some nonstandard fucntions.
- * @module App
- * @submodule preps/extendNative
- */
-define([], function() {
-
- /**
- * Set or get last array item
- * @method last
- * @extends Array
- * @param value {Any} Value to set - optional
- * @return {Any} Last item of array, null if array is empty
- */
- Array.prototype.last = function(val) {
- if (!this.length) return null;
- if (val) this[this.length - 1] = val;
- return this[this.length - 1];
- };
-
- /**
- * Set or get first array item
- * @method last
- * @extends Array
- * @param value {Any} Value to set - optional
- * @return {Any} First item of array, null if array is empty
- */
- Array.prototype.first = function(val) {
- if (!this.length) return null;
- if (val) this[0] = val;
- return this[0];
- };
-
- /**
- * Get index of element in HTMLCollection (used by eg. Element#children)
- * @method indexOf
- * @extends HTMLCollection
- * @param element {HTMLElement} Element fo find index of
- * @return {Any} First item of array, null if array is empty
- */
- HTMLCollection.prototype.indexOf = Array.prototype.indexOf;
-
- window.requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame;
-
- if (!Element.prototype.hasOwnProperty('matchesSelector')) {
- Element.prototype.matchesSelector = Element.prototype.webkitMatchesSelector;
- }
-
- /**
- * Git first next sibling that matches given selector
- * @method findNext
- * @extends Element
- * @param query {String} CSS selector
- * @return {HTMLELement|null} Found element
- */
- Element.prototype.findNext = function(query) {
- var cur = this;
- while (cur = cur.nextElementSibling) {
- if (cur.matchesSelector(query)) {
- return cur;
- }
- }
- return null;
- };
-
- /**
- * Git first previous sibling that matches given selector
- * @method findPrev
- * @extends Element
- * @param query {String} CSS selector
- * @return {HTMLELement|null} Found element
- */
- Element.prototype.findPrev = function(query) {
- var cur = this;
- while (cur = cur.previousElementSibling) {
- if (cur.matchesSelector(query)) {
- return cur;
- }
- }
- return null;
- };
-
- /**
- * Escapes regexp characters in string
- * @method escape
- * @extends RegExp
- * @static
- * @param text {String} String to be escaped
- * @return {String} Escaped string
- */
- RegExp.escape = function(str) {
- return String(str).replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
- };
-});
\ No newline at end of file
diff --git a/scripts/app/staticdb/actions.js b/scripts/app/staticdb/actions.js
deleted file mode 100644
index 26b59c54..00000000
--- a/scripts/app/staticdb/actions.js
+++ /dev/null
@@ -1,723 +0,0 @@
-define(['jquery', 'underscore', 'helpers/stripTags', 'modules/Locale', 'controllers/comm'], function($, _, stripTags, Locale, comm) {
-
-return {
- global: {
- default: {
- title: 'Unknown',
- fn: function() {
- alert('no action');
- }
- },
- hideOverlays: {
- title: 'Hide Overlays',
- fn: function() {
- comm.trigger('hide-overlays');
- }
- },
- runTests: {
- title: 'Run tests (dev dependencies needed)',
- fn: function() {
- require(['../runtests']);
- }
- },
- openOptions: {
- title: 'Options',
- icon: 'options.png',
- fn: function() {
- window.open('options.html');
- }
- },
- report: {
- title: 'Report a problem',
- icon: 'report.png',
- fn: function() {
- app.report();
- }
- }
- },
- feeds: {
- updateAll: {
- icon: 'reload.png',
- title: Locale.c.UPDATE_ALL,
- fn: function() {
- bg.loader.downloadAll(true);
- }
- },
- update: {
- icon: 'reload.png',
- title: Locale.c.UPDATE,
- fn: function() {
- var s = require('views/feedList').selectedItems;
- if (s.length) {
- bg.loader.download(_.pluck(s, 'model'));
- }
- }
- },
- stopUpdate: {
- icon: 'stop.png',
- title: 'Stop updating feeds',
- fn: function() {
- bg.loader.abortDownloading();
- }
- },
- mark: {
- icon: 'read.png',
- title: Locale.c.MARK_ALL_AS_READ,
- fn: function() {
- var s = require('views/feedList').getSelectedFeeds();
- if (!s.length) return;
-
- bg.items.forEach(function(item) {
- if (item.get('unread') == true && s.indexOf(item.getSource()) >= 0) {
- item.save({
- unread: false,
- visited: true
- });
- }
- });
-
- s.forEach(function(source) {
- if (source.get('hasNew')) {
- source.save({ hasNew: false });
- }
- });
-
- }
- },
- refetch: {
- title: 'Refetch', /****localization needed****/
- fn: function() {
- var s = require('views/feedList').getSelectedFeeds();
- if (!s.length) return;
-
- s.forEach(function(source) {
- bg.items.where({ sourceID: source.get('id') }).forEach(function(item) {
- item.destroy();
- });
- });
-
- app.actions.execute('feeds:update');
-
- }
- },
- delete: {
- icon: 'delete.png',
- title: Locale.c.DELETE,
- fn: function() {
- if (!confirm(Locale.c.REALLY_DELETE)) return;
-
- var feeds = require('views/feedList').getSelectedFeeds();
- var folders = require('views/feedList').getSelectedFolders();
-
- feeds.forEach(function(feed) {
- feed.destroy();
- });
-
- folders.forEach(function(folder) {
- folder.destroy();
- });
- }
- },
- showProperties: {
- icon: 'properties.png',
- title: Locale.c.PROPERTIES,
- fn: function() {
- var properties = app.feeds.properties;
-
- var feedList = require('views/feedList');
-
- var feeds = feedList.getSelectedFeeds();
- var folders = feedList.getSelectedFolders();
-
- if (feedList.selectedItems.length == 1 && folders.length == 1) {
- properties.show(folders[0]);
- } else if (!folders.length && feeds.length == 1) {
- properties.show(feeds[0]);
- } else if (feeds.length > 0) {
- properties.show(feeds);
- }
-
- }
- },
- addSource: {
- icon: 'add.png',
- title: Locale.c.ADD_RSS_SOURCE,
- fn: function() {
- var url = (prompt(Locale.c.RSS_FEED_URL) || '').trim();
- if (!url) return;
-
- var folderID = 0;
- var list = require('views/feedList');
- if (list.selectedItems.length && list.selectedItems[0].$el.hasClass('folder')) {
- var fid = list.selectedItems[0].model.get('id');
- // make sure source is not added to folder which is not in db
- if (bg.folders.get(fid)) {
- folderID = fid;
- }
- }
-
- url = app.fixURL(url);
- var duplicate = bg.sources.findWhere({ url: url });
-
- if (!duplicate) {
- var newFeed = bg.sources.create({
- title: url,
- url: url,
- updateEvery: 180,
- folderID: folderID
- }, { wait: true });
- app.trigger('focus-feed', newFeed.get('id'));
- } else {
- app.trigger('focus-feed', duplicate.get('id'));
- }
- }
- },
- addFolder: {
- icon: 'add_folder.png',
- title: Locale.c.NEW_FOLDER,
- fn: function() {
- var title = (prompt(Locale.c.FOLDER_NAME + ': ') || '').trim();
- if (!title) return;
-
- bg.folders.create({
- title: title
- }, { wait: true });
- }
- },
- focus: {
- title: 'Focus feeds',
- fn: function() {
- app.setFocus('feeds');
- }
- },
- selectNext: {
- title: 'Select next',
- fn: function(e) {
- require('views/feedList').selectNext(e);
- }
- },
- selectPrevious: {
- title: 'Select previous',
- fn: function(e) {
- require('views/feedList').selectPrev(e);
- }
- },
- closeFolders: {
- title: 'Close folders',
- fn: function(e) {
- var folders = $('.folder.opened');
- if (!folders.length) return;
- folders.each(function(i, folder) {
- if (folder.view) {
- folder.view.handleClickArrow(e);
- }
- });
- }
- },
- openFolders: {
- title: 'Open folders',
- fn: function(e) {
- var folders = $('.folder:not(.opened)');
- if (!folders.length) return;
- folders.each(function(i, folder) {
- if (folder.view) {
- folder.view.handleClickArrow(e);
- }
- });
- }
- },
- toggleFolder: {
- title: 'Toggle folder',
- fn: function(e) {
- e = e || {};
- var cs = require('views/feedList').selectedItems;
- if (cs.length && cs[0].$el.hasClass('folder')) {
- cs[0].handleClickArrow(e);
- }
- }
- },
- showArticles: {
- title: 'Show articles',
- fn: function(e) {
- e = e || {};
- var t = e.target || {};
- var feedList = require('views/feedList');
- var feeds = feedList.getSelectedFeeds();
- var ids = _.pluck(feeds, 'id');
- var special = $('.special.selected').get(0);
- if (special) special = special.view.model;
-
- app.trigger('select:' + feedList.el.id, {
- action: 'new-select',
- feeds: ids,
- // _.extend is important, because otherwise it would be sent by reference
- filter: special ? _.extend({}, special.get('filter')) : null,
- name: special ? special.get('name') : null,
- unreadOnly: !!e.altKey || t.className == 'source-counter'
- });
-
-
- if (special && special.get('name') == 'all-feeds') {
- bg.sources.forEach(function(source) {
- if (source.get('hasNew')) {
- source.save({ hasNew: false });
- }
- });
-
- } else if (ids.length) {
- bg.sources.forEach(function(source) {
- if (source.get('hasNew') && ids.indexOf(source.id) >= 0) {
- source.save({ hasNew: false });
- }
- });
- }
- }
- },
- showAndFocusArticles: {
- title: 'Show and focus articles',
- fn: function(e) {
- e = e || {};
- var cs = require('views/feedList').selectedItems;
- if (cs.length) {
- app.actions.execute('feeds:showArticles', e);
- app.actions.execute('articles:focus');
- }
- }
- }
- },
- articles: {
- mark: {
- icon: 'read.png',
- title: Locale.c.MARK_AS_READ,
- fn: function() {
- require('views/articleList').changeUnreadState();
- }
- },
- update: {
- icon: 'reload.png',
- title: Locale.c.UPDATE,
- fn: function() {
- var list = require('views/articleList');
- if (list.currentData.feeds.length) {
- list.currentData.feeds.forEach(function(id) {
- bg.loader.downloadOne(bg.sources.get(id));
- });
- } else {
- bg.loader.downloadAll(true); // true = force
- }
- }
- },
- delete: {
- icon: 'delete.png',
- title: Locale.c.DELETE,
- fn: function(e) {
- var list = require('views/articleList');
- if (list.currentData.name == 'trash' || e.shiftKey) {
- list.destroyBatch(list.selectedItems, list.removeItemCompletely);
- } else {
- list.destroyBatch(list.selectedItems, list.removeItem);
- }
- }
- },
- undelete: {
- icon: 'undelete.png',
- title: Locale.c.UNDELETE,
- fn: function() {
- var articleList = require('views/articleList');
- if (!articleList.selectedItems || !articleList.selectedItems.length || articleList.currentData.name != 'trash') return;
- articleList.destroyBatch(articleList.selectedItems, articleList.undeleteItem);
- }
- },
- selectNext: {
- fn: function(e) {
- require('views/articleList').selectNext(e);
- }
- },
- selectPrevious: {
- fn: function(e) {
- require('views/articleList').selectPrev(e);
- }
- },
- search: {
- title: Locale.c.SEARCH_TIP,
- fn: function(e) {
- e = e || { currentTarget: $('input[type=search]').get(0) };
- var str = e.currentTarget.value || '';
- var list = require('views/articleList');
- if (str == '') {
- $('.date-group').css('display', 'block');
- } else {
- $('.date-group').css('display', 'none');
- }
-
- var searchInContent = false;
- if (str[0] && str[0] == ':') {
- str = str.replace(/^:/, '', str);
- searchInContent = true;
- }
- var rg = new RegExp(RegExp.escape(str), 'i');
- list.views.some(function(view) {
- if (!view.model) return true;
- if (rg.test(view.model.get('title')) || rg.test(view.model.get('author')) || (searchInContent && rg.test(view.model.get('content')) )) {
- view.$el.removeClass('invisible');
- } else {
- view.$el.addClass('invisible');
- }
- });
-
- list.redraw();
-
- list.restartSelection();
- }
- },
- focusSearch: {
- title: 'Focus Search',
- fn: function() {
- $('input[type=search]').focus();
- }
- },
- focus: {
- title: 'Focus Articles',
- fn: function() {
- app.setFocus('articles');
- }
- },
- fullArticle: {
- title: Locale.c.FULL_ARTICLE,
- icon: 'full_article.png',
- fn: function(e) {
- var articleList = app.articles.articleList;
- if (!articleList.selectedItems || !articleList.selectedItems.length) return;
- if (articleList.selectedItems.length > 10 && bg.settings.get('askOnOpening')) {
- if (!confirm('Do you really want to open ' + articleList.selectedItems.length + ' articles?')) {
- return;
- }
- }
- articleList.selectedItems.forEach(function(item) {
- chrome.tabs.create({ url: stripTags(item.model.get('url')), active: !e.shiftKey });
- });
- }
- },
- oneFullArticle: {
- title: 'One full article',
- fn: function(e) {
- e = e || {};
- var articleList = app.articles.articleList;
- var view;
- if ('currentTarget' in e) {
- view = e.currentTarget.view;
- } else {
- if (!articleList.selectedItems || !articleList.selectedItems.length) return;
- view = articleList.selectedItems[0];
- }
- if (view.model) {
- chrome.tabs.create({ url: stripTags(view.model.get('url')), active: !e.shiftKey });
- }
- }
- },
- markAndNextUnread: {
- title: Locale.c.MARK_AND_NEXT_UNREAD,
- icon: 'find_next.png',
- fn: function() {
- require('views/articleList').changeUnreadState({ onlyToRead: true });
- require('views/articleList').selectNext({ selectUnread: true });
- }
- },
- markAndPrevUnread: {
- title: Locale.c.MARK_AND_PREV_UNREAD,
- icon: 'find_previous.png',
- fn: function() {
- require('views/articleList').changeUnreadState({ onlyToRead: true });
- require('views/articleList').selectPrev({ selectUnread: true });
- }
- },
- nextUnread: {
- title: Locale.c.NEXT_UNREAD,
- icon: 'forward.png',
- fn: function() {
- require('views/articleList').selectNext({ selectUnread: true });
- }
- },
- prevUnread: {
- title: Locale.c.PREV_UNREAD,
- icon: 'back.png',
- fn: function() {
- require('views/articleList').selectPrev({ selectUnread: true });
- }
- },
- markAllAsRead: {
- title: Locale.c.MARK_ALL_AS_READ,
- icon: 'read.png',
- fn: function() {
- var articleList = require('views/articleList');
- var f = articleList.currentData.feeds;
- var filter = articleList.currentData.filter;
- if (f.length) {
- (filter ? bg.items.where(articleList.currentData.filter) : bg.items).forEach(function(item) {
- if (item.get('unread') == true && f.indexOf(item.get('sourceID')) >= 0) {
- item.save({ unread: false, visited: true });
- }
- });
- } else if (articleList.currentData.name == 'all-feeds') {
- if (confirm(Locale.c.MARK_ALL_QUESTION)) {
- bg.items.forEach(function(item) {
- if (item.get('unread') == true) {
- item.save({ unread: false, visited: true });
- }
- });
- }
- } else if (articleList.currentData.filter) {
- bg.items.where(articleList.specialFilter).forEach(function(item) {
- item.save({ unread: false, visited: true });
- });
- }
- }
- },
- selectAll: {
- title: 'Select All',
- fn: function() {
- var articleList = require('views/articleList');
- articleList.$el.find('.selected').removeClass('selected');
- articleList.selectedItems = [];
-
- articleList.$el.find('.item:not(.invisible)').each(function(i, item) {
- item.view.$el.addClass('selected');
- articleList.selectedItems.push(item.view);
- });
-
- articleList.$el.find('.last-selected').removeClass('last-selected');
- articleList.$el.find('.item:not(.invisible):last').addClass('last-selected');
- }
- },
- pin: {
- title: Locale.c.PIN,
- icon: 'pinsource_context.png',
- fn: function() {
- var articleList = require('views/articleList');
- if (!articleList.selectedItems || !articleList.selectedItems.length) return;
- var val = !articleList.selectedItems[0].model.get('pinned');
- articleList.selectedItems.forEach(function(item) {
- item.model.save({ pinned: val });
- });
- }
- },
- spaceThrough: {
- title: 'Space Through',
- fn: function() {
- var articleList = require('views/articleList');
- if (!articleList.selectedItems || !articleList.selectedItems.length) return;
- app.trigger('space-pressed');
- }
- },
- pageUp: {
- title: 'Page up',
- fn: function() {
- var el = require('views/articleList').el;
- el.scrollByPages(-1);
- }
- },
- pageDown: {
- title: 'Page down',
- fn: function() {
- var el = require('views/articleList').el;
- el.scrollByPages(1);
- }
- },
- scrollToBottom: {
- title: 'Scroll to bottom',
- fn: function() {
- var el = require('views/articleList').el;
- el.scrollTop = el.scrollHeight;
- }
- },
- scrollToTop: {
- title: 'Scroll to top',
- fn: function() {
- var el = require('views/articleList').el;
- el.scrollTop = 0;
- }
- },
- download: {
- title: Locale.c.DOWNLOAD,
- icon: 'save.png',
- fn: function() {
- var contentView = require('views/contentView');
- var articleList = require('views/articleList');
- if (!articleList.selectedItems.length) {
- app.actions.execute('content:download');
- return;
- }
- var tpl = contentView.downloadTemplate;
-
- var list = {};
- list.articles = articleList.selectedItems.map(function(itemView) {
- var attrs = Object.create(itemView.model.attributes);
- attrs.date = contentView.getFormatedDate(attrs.date);
- return attrs;
- });
-
- var blob = new Blob([ tpl(list) ], { type: 'text\/html' });
- var reader = new FileReader();
- reader.readAsDataURL(blob);
- reader.onload = function() {
- window.open(this.result.replace('data:text/html;', 'data:text/html;charset=utf-8;'));
- };
- /*var url = URL.createObjectURL(blob);
- window.open(url);
- setTimeout(function() {
- URL.revokeObjectURL(url);
- }, 30000);*/
- }
- }
- },
- content: {
- download: {
- title: Locale.c.DOWNLOAD,
- icon: 'save.png',
- fn: function() {
- var contentView = require('views/contentView');
- if (!contentView.model) return;
- var tpl = contentView.downloadTemplate;
- var attrs = Object.create(contentView.model.attributes);
- attrs.date = contentView.getFormatedDate(attrs.date);
- var list = { articles: [attrs] };
- var blob = new Blob([ tpl(list) ], { type: 'text\/html' });
- var reader = new FileReader();
- reader.readAsDataURL(blob);
- reader.onload = function() {
- window.open(this.result.replace('data:text/html;', 'data:text/html;charset=utf-8;'));
- };
- /*var url = URL.createObjectURL(blob);
- window.open(url);
- setTimeout(function() {
- URL.revokeObjectURL(url);
- }, 30000);*/
- }
- },
- print: {
- title: Locale.c.PRINT,
- icon: 'print.png',
- fn: function() {
- var contentView = require('views/contentView');
- if (!contentView.model) return;
- window.print();
- }
- },
- mark: {
- title: Locale.c.MARK_AS_READ,
- icon: 'read.png',
- fn: function() {
- var contentView = require('views/contentView');
- if (!contentView.model) return;
- contentView.model.save({
- unread: !contentView.model.get('unread'),
- visited: true
- });
- }
- },
- delete: {
- title: Locale.c.DELETE,
- icon: 'delete.png',
- fn: function(e) {
- var contentView = require('views/contentView');
- if (!contentView.model) return;
-
- askRmPinned = bg.settings.get('askRmPinned')
- if (e.shiftKey) {
- if (contentView.model.get('pinned') && askRmPinned && askRmPinned != 'none') {
- var conf = confirm(Locale.c.PIN_QUESTION_A + contentView.model.escape('title') + Locale.c.PIN_QUESTION_B);
- if (!conf) {
- return;
- }
- }
-
- contentView.model.markAsDeleted();
- } else {
- if (contentView.model.get('pinned') && askRmPinned == 'all') {
- var conf = confirm(Locale.c.PIN_QUESTION_A + contentView.model.escape('title') + Locale.c.PIN_QUESTION_B);
- if (!conf) {
- return;
- }
- }
-
- contentView.model.save({
- trashed: true,
- visited: true
- });
- }
- }
- },
- showConfig: {
- title: Locale.c.SETTINGS,
- icon: 'config.png',
- fn: function() {
- app.content.overlay.show();
- }
- },
- focus: {
- title: 'Focus Article',
- fn: function() {
- app.setFocus('content');
- }
- },
- focusSandbox: {
- title: 'Focus Article',
- fn: function() {
- app.content.sandbox.el.focus();
- }
- },
- scrollDown: {
- title: 'Scroll down',
- fn: function() {
- var cw = $('iframe').get(0).contentWindow;
- cw.scrollBy(0, 40);
- }
- },
- scrollUp: {
- title: 'Scroll up',
- fn: function() {
- var cw = $('iframe').get(0).contentWindow;
- cw.scrollBy(0, -40);
- }
- },
- spaceThrough: {
- title: 'Space trough',
- fn: function() {
- require('views/contentView').handleSpace();
- }
- },
- pageUp: {
- title: 'Page up',
- fn: function() {
- var cw = $('iframe').get(0).contentWindow;
- var d = $('iframe').get(0).contentWindow.document;
- cw.scrollBy(0, -d.documentElement.clientHeight * 0.85);
- }
- },
- pageDown: {
- title: 'Page down',
- fn: function() {
- var cw = $('iframe').get(0).contentWindow;
- var d = $('iframe').get(0).contentWindow.document;
- cw.scrollBy(0, d.documentElement.clientHeight * 0.85);
- }
- },
- scrollToBottom: {
- title: 'Scroll to bottom',
- fn: function() {
- var cw = $('iframe').get(0).contentWindow;
- var d = $('iframe').get(0).contentWindow.document;
- cw.scrollTo(0, d.documentElement.offsetHeight);
- }
- },
- scrollToTop: {
- title: 'Scroll to top',
- fn: function() {
- var cw = $('iframe').get(0).contentWindow;
- cw.scrollTo(0, 0);
- }
- }
- }
-
-}; // end actions object
-}); // end define function
\ No newline at end of file
diff --git a/scripts/app/staticdb/shortcuts.js b/scripts/app/staticdb/shortcuts.js
deleted file mode 100644
index 94ec8d85..00000000
--- a/scripts/app/staticdb/shortcuts.js
+++ /dev/null
@@ -1,118 +0,0 @@
-define({
- global: {
- 'shift+1': 'feeds:focus',
- 'shift+2': 'articles:focus',
- 'shift+3': 'content:focus',
- 'shift+4': 'content:focusSandbox',
- 'esc': 'global:hideOverlays',
- 'shift+insert': 'global:runTests'
- },
- feeds: {
- 'up': 'feeds:selectPrevious',
- 'down': 'feeds:selectNext',
- 'u': 'feeds:selectPrevious',
- 'j': 'feeds:selectNext',
-
- 'ctrl+left': 'feeds:closeFolders',
- 'ctrl+right': 'feeds:openFolders',
- 'left': 'feeds:toggleFolder',
- 'right': 'feeds:showArticles',
- 'enter': 'feeds:showAndFocusArticles',
-
- 'shift+j': 'feeds:selectNext',
- 'shift+down': 'feeds:selectNext',
- 'shift+u': 'feeds:selectPrevious',
- 'shift+up': 'feeds:selectPrevious',
- },
- articles: {
- 'd': 'articles:delete',
- 'del': 'articles:delete',
- 'shift+d': 'articles:delete',
- 'shift+del': 'articles:delete',
- 'ctrl+f': 'articles:focusSearch',
- 'shift+enter': 'articles:fullArticle',
- 'enter': 'articles:fullArticle',
- 'k': 'articles:mark',
- 'j': 'articles:selectNext',
- 'down': 'articles:selectNext',
- 'u': 'articles:selectPrevious',
- 'up': 'articles:selectPrevious',
-
- 'shift+j': 'articles:selectNext',
- 'shift+down': 'articles:selectNext',
- 'shift+u': 'articles:selectPrevious',
- 'shift+up': 'articles:selectPrevious',
-
- 'g': 'articles:markAndNextUnread',
- 't': 'articles:markAndPrevUnread',
- 'h': 'articles:nextUnread',
- 'y': 'articles:prevUnread',
- 'z': 'articles:prevUnread',
-
- 'ctrl+shift+a': 'articles:markAllAsRead',
- 'ctrl+a': 'articles:selectAll',
- 'p': 'articles:pin',
- 'n': 'articles:undelete',
- 'space': 'articles:spaceThrough',
- 'r': 'articles:update',
-
- 'pgup': 'articles:pageUp',
- 'pgdown': 'articles:pageDown',
- 'end': 'articles:scrollToBottom',
- 'home': 'articles:scrollToTop'
- },
- content: {
- 'up': 'content:scrollUp',
- 'down': 'content:scrollDown',
- 'space': 'content:spaceThrough',
- 'pgup': 'content:pageUp',
- 'pgdown': 'content:pageDown',
- 'end': 'content:scrollToBottom',
- 'home': 'content:scrollToTop',
- 'del': 'content:delete',
- 'd': 'content:delete',
- 'k': 'content:mark',
-
- 'g': 'articles:markAndNextUnread',
- 't': 'articles:markAndPrevUnread',
- 'h': 'articles:nextUnread',
- 'y': 'articles:prevUnread',
- 'z': 'articles:prevUnread',
- 'j': 'articles:selectNext',
- 'u': 'articles:selectPrevious'
- },
- sandbox: {
- 'del': 'content:delete',
- 'd': 'content:delete',
- 'k': 'content:mark',
- 'space': 'content:spaceThrough',
-
- 'g': 'articles:markAndNextUnread',
- 't': 'articles:markAndPrevUnread',
- 'h': 'articles:nextUnread',
- 'y': 'articles:prevUnread',
- 'z': 'articles:prevUnread',
- 'j': 'articles:selectNext',
- 'u': 'articles:selectPrevious'
- },
- keys: {
- 8: 'backspace',
- 9: 'tab',
- 13: 'enter',
- //16: 'shift',
- //17: 'ctrl',
- 20: 'capslock',
- 27: 'esc',
- 32: 'space',
- 33: 'pgup',
- 34: 'pgdown',
- 35: 'end',
- 36: 'home',
- 37: 'left',
- 38: 'up',
- 39: 'right',
- 40: 'down',
- 45: 'insert',
- 46: 'del'
- }
-});
diff --git a/scripts/app/templates/download.html b/scripts/app/templates/download.html
deleted file mode 100644
index 3a5c2da5..00000000
--- a/scripts/app/templates/download.html
+++ /dev/null
@@ -1,62 +0,0 @@
-
-
-
-
-
- <%- (articles[0] ? articles[0].title : 'Feed') %>
-
-
-
- <% for (var i=0; i
-
-
-
<%= articles[i].content %>
-
- <% } %>
-
-
-
diff --git a/scripts/app/templates/folder.html b/scripts/app/templates/folder.html
deleted file mode 100644
index 8819e4ea..00000000
--- a/scripts/app/templates/folder.html
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-<%- title %>
-<% if (count > 0) { %>
- <%- count %>
-<% } %>
\ No newline at end of file
diff --git a/scripts/app/templates/header.html b/scripts/app/templates/header.html
deleted file mode 100644
index db1d009d..00000000
--- a/scripts/app/templates/header.html
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
<%- author %>
-
<%= date %>
-
>
-
\ No newline at end of file
diff --git a/scripts/app/templates/item.html b/scripts/app/templates/item.html
deleted file mode 100644
index c8e23b31..00000000
--- a/scripts/app/templates/item.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<%= title %>
-
-<%- author %>
-<%- date %>
\ No newline at end of file
diff --git a/scripts/app/templates/log.html b/scripts/app/templates/log.html
deleted file mode 100644
index a3b9ecf9..00000000
--- a/scripts/app/templates/log.html
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
diff --git a/scripts/app/templates/overlay.html b/scripts/app/templates/overlay.html
deleted file mode 100644
index 99edf209..00000000
--- a/scripts/app/templates/overlay.html
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-{{OPTIONS}}
\ No newline at end of file
diff --git a/scripts/app/templates/properties.html b/scripts/app/templates/properties.html
deleted file mode 100644
index 367f7f9e..00000000
--- a/scripts/app/templates/properties.html
+++ /dev/null
@@ -1,52 +0,0 @@
-<% if (typeof title != 'undefined') { %>
-
-<% } %>
-
-<% if (typeof url != 'undefined') { %>
-
-<% } %>
-
-
-
-<% if (typeof url != 'undefined') { %>
-{{MORE}}
-
-
-
-
-<% } %>
-
-
-
-<% if (typeof url != 'undefined') { %>
-
-<% } %>
-
-
\ No newline at end of file
diff --git a/scripts/app/templates/report.html b/scripts/app/templates/report.html
deleted file mode 100644
index 637bebaa..00000000
--- a/scripts/app/templates/report.html
+++ /dev/null
@@ -1,19 +0,0 @@
-
\ No newline at end of file
diff --git a/scripts/app/templates/source.html b/scripts/app/templates/source.html
deleted file mode 100644
index ebbb181b..00000000
--- a/scripts/app/templates/source.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<% if (typeof isLoading == 'undefined' || !isLoading) { %>
-
-<% } else { %>
-
-<% } %>
-
-<%- title %>
-<% if (count > 0) { %>
- <%- count %>
-<% } %>
\ No newline at end of file
diff --git a/scripts/app/templates/special.html b/scripts/app/templates/special.html
deleted file mode 100644
index c46bbe87..00000000
--- a/scripts/app/templates/special.html
+++ /dev/null
@@ -1,5 +0,0 @@
-
-<%- title %>
-<% if (typeof count != 'undefined' && count > 0) { %>
- <%- count %>
-<% } %>
\ No newline at end of file
diff --git a/scripts/app/views/ContextMenu.js b/scripts/app/views/ContextMenu.js
deleted file mode 100644
index 6f0fbb93..00000000
--- a/scripts/app/views/ContextMenu.js
+++ /dev/null
@@ -1,120 +0,0 @@
-/**
- * @module App
- * @submodule views/ContextMenu
- */
-define([
- 'backbone', 'jquery', 'collections/MenuCollection', 'views/MenuItemView', 'controllers/comm'
-],
-function(BB, $, MenuCollection, MenuItemView, comm) {
-
- /**
- * Context menu view
- * @class ContextMenu
- * @constructor
- * @extends Backbone.View
- */
- var ContextMenu = BB.View.extend({
-
- /**
- * Tag name of content view element
- * @property tagName
- * @default 'div'
- * @type String
- */
- tagName: 'div',
-
- /**
- * Class name of content view element
- * @property className
- * @default 'context-menu'
- * @type String
- */
- className: 'context-menu',
-
- /**
- * Backbone collection of all context menu items
- * @property menuCollection
- * @default 'context-menu'
- * @type collections/MenuCollection
- */
- menuCollection: null,
-
- /**
- * Adds one context menu item
- * @method addItem
- * @param item {models/MenuItem} New menu item
- */
- addItem: function(item) {
- var v = new MenuItemView({
- model: item
- });
- v.contextMenu = this;
- this.$el.append(v.render().$el);
- },
-
- /**
- * Adds multiple context menu items
- * @method addItems
- * @param items {Array|MenuCollection} List of models to add
- */
- addItems: function(items) {
- items.forEach(function(item) {
- this.addItem(item);
- }, this);
- },
-
- /**
- * Renders the context menu (nothing is happening in the render method right now)
- * @method render
- * @chainable
- */
- render: function() {
- return this;
- },
-
- /**
- * Hides the context menu
- * @method hide
- * @triggered when 'hide-overlays' comm message is sent
- */
- hide: function() {
- if (this.$el.css('display') == 'block') {
- this.$el.css('display', 'none');
- }
- },
-
- /**
- * Called when new instance is created
- * @method initialize
- * @param mc {collections/MenuCollection} Menu collection for this context menu
- */
- initialize: function(mc) {
- this.el.view = this;
- this.menuCollection = new MenuCollection(mc);
- this.addItems(this.menuCollection);
- $('body').append(this.render().$el);
-
- this.listenTo(comm, 'hide-overlays', this.hide);
- },
-
- /**
- * Displays the context menu and moves it to given position
- * @method show
- * @param x {Number} x-coordinate
- * @param y {Number} y-coordinate
- */
- show: function(x, y) {
- if (x + this.$el.width() + 4 > document.body.offsetWidth) {
- x = document.body.offsetWidth - this.$el.width() - 8;
- }
- if (y + this.$el.height() + 4 > document.body.offsetHeight) {
- y = document.body.offsetHeight - this.$el.height() - 8;
- }
- this.$el.css('top', y + 'px');
- this.$el.css('left', x + 'px');
- this.$el.css('display', 'block');
- }
- });
-
- return ContextMenu;
-});
\ No newline at end of file
diff --git a/scripts/app/views/FolderView.js b/scripts/app/views/FolderView.js
deleted file mode 100644
index f018221b..00000000
--- a/scripts/app/views/FolderView.js
+++ /dev/null
@@ -1,217 +0,0 @@
-/**
- * @module App
- * @submodule views/FolderView
- */
-define([
- 'backbone', 'jquery', 'underscore', 'views/TopView', 'instances/contextMenus', 'text!templates/folder.html'
-],
-function(BB, $, _, TopView, contextMenus, tplFolder) {
-
- /**
- * View for Folder in feed list
- * @class FolderView
- * @constructor
- * @extends views/TopView
- */
- var FolderView = TopView.extend({
-
- /**
- * Set CSS classnames
- * @property className
- * @default 'list-item folder'
- * @type String
- */
- className: 'list-item folder',
-
- /**
- * Folder view template
- * @property template
- * @default ./templates/folder.html
- * @type Function
- */
- template: _.template(tplFolder),
-
- /**
- * Reference to view/feedList instance. It should be replaced with require('views/feedList')
- * @property list
- * @default null
- * @type Backbone.View
- */
- list: null,
- events: {
- 'dblclick': 'handleDoubleClick',
- /*'mouseup': 'handleMouseUp',
- 'click': 'handleMouseDown',*/
- 'click .folder-arrow': 'handleClickArrow'
- },
-
- /**
- * Opens/closes folder by calling handleClickArrow method
- * @method handleDoubleClick
- * @triggered on double click on the folder
- * @param event {MouseEvent}
- */
- handleDoubleClick: function(e) {
- this.handleClickArrow(e);
- },
-
- /**
- * Shows context menu for folder
- * @method showContextMenu
- * @triggered on right mouse click
- * @param event {MouseEvent}
- */
- showContextMenu: function(e) {
- if (!this.$el.hasClass('selected')) {
- this.list.select(this, e);
- }
- contextMenus.get('folder').currentSource = this.model;
- contextMenus.get('folder').show(e.clientX, e.clientY);
- },
-
- /**
- * Initializations (*constructor*)
- * @method initialize
- * @param opt {Object} I don't use it, but it is automatically passed by Backbone
- * @param list {Backbone.View} Reference to feedList
- */
- initialize: function(opt, list) {
- this.list = list;
- this.el.view = this;
-
- this.model.on('destroy', this.handleModelDestroy, this);
- this.model.on('change', this.render, this);
- this.model.on('change:title', this.handleChangeTitle, this);
- bg.sources.on('clear-events', this.handleClearEvents, this);
-
- this.el.dataset.id = this.model.get('id');
- },
-
- /**
- * Places folder to its right place after renaming
- * @method handleChangeTitle
- * @triggered when title of folder is changed
- */
- handleChangeTitle: function() {
- var folderViews = $('.folder').toArray();
- if (folderViews.length) {
- this.list.insertBefore(this.render(), folderViews);
- } else if ($('.special:first').length) {
- this.render().$el.insertAfter($('.special:first'));
- }
-
- var that = this;
-
- var feedsInFolder = $('[data-in-folder="' + this.model.get('id') + '"');
-
- feedsInFolder.each(function(i, el) {
- el.parentNode.removeChild(el);
- });
-
- feedsInFolder.each(function(i, el) {
- that.list.placeSource(el.view);
- });
-
- },
-
- /**
- * If the tab is closed, it will remove all events binded to bgprocess
- * @method handleClearEvents
- * @triggered when bgprocesses triggers clear-events event
- * @param id {Number} ID of closed tab
- */
- handleClearEvents: function(id) {
- if (window == null || id == tabID) {
- this.clearEvents();
- }
- },
-
- /**
- * Removes all events binded to bgprocess
- * @method clearEvents
- */
- clearEvents: function() {
- this.model.off('destroy', this.handleModelDestroy, this);
- this.model.off('change', this.render, this);
- this.model.off('change:title', this.handleChangeTitle, this);
- bg.sources.off('clear-events', this.handleClearEvents, this);
- },
-
- /**
- * If the folder model is removed from DB/Backbone then remove it from DOM as well
- * @method handleModelDestroy
- * @triggered When model is removed from DB/Backbone
- * @param id {Number} ID of closed tab
- */
- handleModelDestroy: function() {
- this.list.destroySource(this);
- },
-
- /**
- * If user clicks on folder arrow then show/hide its content
- * @method handleClickArrow
- * @triggered Left click on folder arrow
- * @param e {MouseEvent}
- */
- handleClickArrow: function(e) {
- this.model.save('opened', !this.model.get('opened'));
- $('.source[data-in-folder=' + this.model.get('id') + ']').toggleClass('invisible', !this.model.get('opened'));
- e.stopPropagation();
- },
-
- /**
- * Reference to requestAnimationFrame frame. It is used to prevent multiple render calls in one frame
- * @property renderInterval
- * @type String|Number
- */
- renderInterval: 'first-time',
-
- /**
- * Sets renderInterval to render folder view
- * @method render
- */
- render: function() {
- if (this.renderInterval == 'first-time') return this.realRender();
- if (this.renderInterval) return this;
-
- var that = this;
- this.renderInterval = requestAnimationFrame(function() {
- that.realRender();
- });
- return this;
- },
-
- /**
- * Renders folder view
- * @method realRender
- */
- realRender: function() {
- this.$el.toggleClass('has-unread', !!this.model.get('count'));
-
- var data = Object.create(this.model.attributes);
- this.$el.toggleClass('opened', this.model.get('opened'));
- this.$el.html(this.template(data));
-
- this.setTitle(this.model.get('count'), this.model.get('countAll'));
-
- this.renderInterval = null;
-
- return this;
- },
-
- /**
- * Data to send to middle column (list of articles) when folder is selected
- * @method render
- * @param e {MouseEvent}
- */
- getSelectData: function(e) {
- return {
- action: 'new-folder-select',
- value: this.model.id,
- unreadOnly: !!e.altKey
- };
- }
- });
-
- return FolderView;
-});
\ No newline at end of file
diff --git a/scripts/app/views/GroupView.js b/scripts/app/views/GroupView.js
deleted file mode 100644
index ee43175a..00000000
--- a/scripts/app/views/GroupView.js
+++ /dev/null
@@ -1,78 +0,0 @@
-/**
- * @module App
- * @submodule views/GroupView
- */
-define(['backbone'], function(BB) {
-
- /**
- * View for Date Groups in list of articles
- * @class GroupView
- * @constructor
- * @extends Backbone.View
- */
- var GroupView = BB.View.extend({
-
- /**
- * Tag name of date group element
- * @property tagName
- * @default 'div'
- * @type String
- */
- tagName: 'div',
-
- /**
- * Class name of date group element
- * @property className
- * @default 'date-group'
- * @type String
- */
- className: 'date-group',
-
- /**
- * Initializations (*constructor*)
- * @method initialize
- * @param model {models/Group} Date group model
- * @param groups {Backbone.View} Reference to collection of groups
- */
- initialize: function(model, groups) {
- this.el.view = this;
- this.listenTo(groups, 'reset', this.handleReset);
- this.listenTo(groups, 'remove', this.handleRemove);
- },
-
- /**
- * Renders date group view
- * @method render
- */
- render: function() {
- this.$el.html(this.model.get('title'));
- return this;
- },
-
- /**
- * If date group model is removed from collection of groups remove the DOM object
- * @method handleRemove
- * @triggered when any date group is removed from list of groups
- * @param model {models/Group} Model removed from list of groups
- */
- handleRemove: function(model) {
- if (model == this.model) {
- this.handleReset();
- }
- },
-
- /**
- * If the reset model (that removes all models from collection) is called, removed DOM object of this date group
- * and stop listening to any events of group collection.
- * @method handleRemove
- * @triggered when on reset
- * @param model {models/Group} Model removed from list of groups
- */
- handleReset: function() {
- this.stopListening();
- this.$el.remove();
- }
- });
-
- return GroupView;
-});
\ No newline at end of file
diff --git a/scripts/app/views/IndicatorView.js b/scripts/app/views/IndicatorView.js
deleted file mode 100644
index f52c8149..00000000
--- a/scripts/app/views/IndicatorView.js
+++ /dev/null
@@ -1,101 +0,0 @@
-/**
- * @module App
- * @submodule views/IndicatorView
- */
-define(['backbone', 'modules/Locale', 'text!templates/indicator.html'], function(BB, Locale, tplIndicator) {
-
- /**
- * Feeds update indicator view
- * @class IndicatorView
- * @constructor
- * @extends Backbone.View
- */
- var IndicatorView = BB.View.extend({
- /**
- * Indicator element id
- * @property id
- * @default indicator
- */
- id: 'indicator',
-
- /**
- * Article item view template
- * @property template
- * @default ./templates/item.html
- * @type Function
- */
- template: _.template(tplIndicator),
-
- events: {
- 'click #indicator-stop': 'handleButtonStop'
- },
-
- /**
- * @method initialize
- */
- initialize: function() {
- this.$el.html(this.template());
- bg.loader.on('change:loading', this.handleLoadingChange, this);
- bg.loader.on('change:loaded', this.render, this);
- bg.loader.on('change:maxSources', this.render, this);
- bg.sources.on('clear-events', this.handleClearEvents, this);
-
- this.handleLoadingChange();
- },
-
- /**
- * Clears bg events it listens to
- * @method handleClearEvents
- * @param id {Integer} ID of the closed tab
- */
- handleClearEvents: function(id) {
- if (window == null || id == tabID) {
- bg.loader.off('change:loading', this.handleLoadingChange, this);
- bg.loader.off('change:loaded', this.render, this);
- bg.loader.off('change:maxSources', this.render, this);
- bg.sources.off('clear-events', this.handleClearEvents, this);
- }
- },
-
- /**
- * Stops updating feeds
- * @method handleButtonStop
- * @triggered when user clicks on stop button
- */
- handleButtonStop: function() {
- app.actions.execute('feeds:stopUpdate');
- },
-
- /**
- * Hides/shows indicator according to loading flag
- * @method handleLoadingChange
- */
- handleLoadingChange: function() {
- var that = this;
- if (bg.loader.get('loading') == true) {
- this.render();
- this.$el.addClass('indicator-visible');
- } else {
- setTimeout(function() {
- that.$el.removeClass('indicator-visible');
- }, 500);
- }
- },
-
- /**
- * Renders the indicator (gradient/text)
- * @method render
- * @chainable
- */
- render: function() {
- var l = bg.loader;
- if (l.get('maxSources') == 0) return;
- var perc = Math.round(l.get('loaded') * 100 / l.get('maxSources'));
- this.$el.find('#indicator-progress').css('background', 'linear-gradient(to right, #c5c5c5 ' + perc + '%, #eee ' + perc + '%)');
- this.$el.find('#indicator-progress').html(Locale.c.UPDATING_FEEDS + ' (' + l.get('loaded') + '/' + l.get('maxSources') + ')');
- return this;
- }
- });
-
- return IndicatorView;
-});
\ No newline at end of file
diff --git a/scripts/app/views/ItemView.js b/scripts/app/views/ItemView.js
deleted file mode 100644
index 01ed2eca..00000000
--- a/scripts/app/views/ItemView.js
+++ /dev/null
@@ -1,269 +0,0 @@
-/**
- * @module App
- * @submodule views/ItemView
- */
-define([
- 'backbone', 'jquery', 'underscore', 'helpers/formatDate', 'instances/contextMenus', 'helpers/stripTags', 'text!templates/item.html'
-], function(BB, $, _, formatDate, contextMenus, stripTags, tplItem) {
-
- /**
- * View of one article item in article list
- * @class ItemView
- * @constructor
- * @extends Backbone.View
- */
- var ItemView = BB.View.extend({
-
- /**
- * Tag name of article item element
- * @property tagName
- * @default 'div'
- * @type String
- */
- tagName: 'div',
-
- /**
- * Class name of article item element
- * @property className
- * @default 'item'
- * @type String
- */
- className: 'item',
-
- /**
- * Article item view template
- * @property template
- * @default ./templates/item.html
- * @type Function
- */
- template: _.template(tplItem),
-
- /**
- * Reference to view/articleList instance. It should be replaced with require('views/articleList')
- * @property list
- * @default null
- * @type Backbone.View
- */
- list: null,
-
- /**
- * Initializations (*constructor*)
- * @method initialize
- * @param opt {Object} I don't use it, but it is automatically passed by Backbone
- * @param list {Backbone.View} Reference to articleList
- */
- initialize: function(opt, list) {
- this.list = list;
- this.el.setAttribute('draggable', 'true');
- this.el.view = this;
- this.setEvents();
- },
-
- /**
- * Set events that are binded to bgprocess
- * @method setEvents
- */
- setEvents: function() {
- this.model.on('change', this.handleModelChange, this);
- this.model.on('destroy', this.handleModelDestroy, this);
- bg.sources.on('clear-events', this.handleClearEvents, this);
- },
-
- /**
- * Swaps models of view.
- * It reuses already created DOM when changing selected feeds/folders.
- * @method swapModel
- * @param newModel {Item} Item model to be used
- */
- swapModel: function(newModel) {
- if (this.model == newModel) {
- this.prerender();
- return;
- }
- if (this.model) {
- this.clearEvents();
- }
- this.model = newModel;
- this.setEvents();
- this.prerender();
- },
-
- /**
- * Indiciates whether the item was prerendered (true) or already fully-rendered (false).
- * When prerendered, only the classNames are set without any text content.
- * Prerendering is used for not-visible items in the list.
- * @property prerendered
- * @default false
- * @type Boolean
- */
- prerendered: false,
-
- /**
- * Prerenders view. (More info on prerenderer property).
- * @method prerender
- */
- prerender: function() {
- this.prerendered = true;
- this.list.viewsToRender.push(this);
- this.el.className = this.model.get('unread') ? 'item unread' : 'item';
- },
-
- /**
- * Removes item content without removing the actuall DOM and Backbone view.
- * When changing selected feed with _m_ items to another feed with _n_ items where n= parseInt(formatDate(Date.now(), 'T') / 86400000, 10)) {
- date = formatDate(new Date(date), timeFormat);
- } else if ((new Date(date)).getFullYear() == (new Date()).getFullYear() ) {
- date = formatDate(new Date(date), pickedFormat.replace(/\/?YYYY(?!-)/, ''));
- } else {
- date = formatDate(new Date(date), pickedFormat);
- }
- }
-
- return date;
- },
-
- /**
- * Shows context menu on right click
- * @method handleMouseUp
- * @triggered on mouse up + condition for right click only
- * @param event {MouseEvent}
- */
- handleMouseUp: function(e) {
- if (e.which == 3) {
- this.showContextMenu(e);
- }
- },
-
- /**
- * Shows context menu for article item
- * @method showContextMenu
- * @param event {MouseEvent}
- */
- showContextMenu: function(e) {
- if (!this.$el.hasClass('selected')) {
- this.list.select(this, e);
- }
- contextMenus.get('items').currentSource = this.model;
- contextMenus.get('items').show(e.clientX, e.clientY);
- },
-
- /**
- * When model is changed rerender it or remove it from DOM (depending on what is changed)
- * @method handleModelChange
- * @triggered when model is changed
- */
- handleModelChange: function() {
- if (this.model.get('deleted') || (this.list.currentData.name != 'trash' && this.model.get('trashed')) ) {
- this.list.destroyItem(this);
- } else {
- this.render();
- }
- },
-
- /**
- * When model is removed from DB/Backbone remove it from DOM as well
- * @method handleModelDestroy
- * @triggered when model is destroyed
- */
- handleModelDestroy: function() {
- this.list.destroyItem(this);
- },
-
- /**
- * Changes pin state (true/false)
- * @method when user clicked on pin button in article item
- * @triggered when model is destroyed
- */
- handleClickPin: function(e) {
- e.stopPropagation();
- this.model.save({ pinned: !this.model.get('pinned') });
- }
- });
-
- return ItemView;
-});
\ No newline at end of file
diff --git a/scripts/app/views/LogView.js b/scripts/app/views/LogView.js
deleted file mode 100644
index 764d73a0..00000000
--- a/scripts/app/views/LogView.js
+++ /dev/null
@@ -1,84 +0,0 @@
-/**
- * @module App
- * @submodule views/LogView
- */
-define([
- 'backbone', 'underscore', 'jquery', 'helpers/formatDate', 'text!templates/log.html'
-], function(BB, _, $, formatDate, tplLog) {
-
- /**
- * View in bottom right corner used for bgprocess error logs and integration tests
- * @class LogView
- * @constructor
- * @extends Backbone.View
- */
- var LogView = BB.View.extend({
-
- /**
- * Tag name of the view
- * @property tagName
- * @default 'footer'
- * @type String
- */
- tagName: 'footer',
- events: {
- 'click #button-hide-log': 'hide'
- },
-
- template: _.template(tplLog),
-
- /**
- * Initializations of events and template.
- * Underscore template function has to be created in constructor as the HTML is not yet avalable on Protoype creation.
- * @method initialize
- */
- initialize: function() {
- this.$el.html(this.template({}));
-
- bg.logs.on('add', this.addItem, this);
- bg.sources.on('clear-events', this.handleClearEvents, this);
- },
-
- /**
- * If the tab is closed, it will remove all events binded to bgprocess
- * @method handleClearEvents
- * @triggered when bgprocesses triggers clear-events event
- * @param id {Number} ID of closed tab
- */
- handleClearEvents: function(id) {
- if (window == null || id == tabID) {
- bg.logs.off('add', this.addItem, this);
- bg.sources.off('clear-events', this.handleClearEvents, this);
- }
- },
-
- /**
- * Adds DOM element for the newly added model
- * @method addItem
- * @triggered when new model is added to log collection
- * @param model {Backbone.Model}
- */
- addItem: function(model) {
- this.show();
- $('' + formatDate(new Date, 'hh:mm:ss') + ': ' + model.get('message') + '
').insertAfter(this.$el.find('#button-hide-log'));
- },
-
- /**
- * Show the Log view element (display: block)
- * @method show
- */
- show: function() {
- this.$el.css('display', 'block');
- },
-
- /**
- * Hide the Log view element (display: none)
- * @method hide
- */
- hide: function() {
- this.$el.css('display', 'none');
- }
- });
-
- return LogView;
-});
\ No newline at end of file
diff --git a/scripts/app/views/MenuItemView.js b/scripts/app/views/MenuItemView.js
deleted file mode 100644
index 415e1c50..00000000
--- a/scripts/app/views/MenuItemView.js
+++ /dev/null
@@ -1,31 +0,0 @@
-define(['backbone'], function(BB) {
- var MenuItemView = BB.View.extend({
- tagName: 'div',
- className: 'context-menu-item',
- contextMenu: null,
- events: {
- 'click': 'handleClick'
- },
- initialize: function() {
- if (this.model.id) {
- this.el.id = this.model.id;
- }
- },
- render: function() {
- if (this.model.get('icon')) {
- this.$el.css('background', 'url(/images/' + this.model.get('icon') + ') no-repeat left center');
- }
- this.$el.html(this.model.get('title'));
- return this;
- },
- handleClick: function(e) {
- var action = this.model.get('action');
- if (action && typeof action == 'function') {
- action(e, app.feeds.feedList);
- this.contextMenu.hide();
- }
- }
- });
-
- return MenuItemView;
-});
\ No newline at end of file
diff --git a/scripts/app/views/OverlayView.js b/scripts/app/views/OverlayView.js
deleted file mode 100644
index bc6c916d..00000000
--- a/scripts/app/views/OverlayView.js
+++ /dev/null
@@ -1,59 +0,0 @@
-define([
- 'backbone', 'underscore', 'jquery', 'text!templates/overlay.html', 'modules/Locale'
-],
-function(BB, _, $, tplOverlay, Locale) {
- var OverlayView = BB.View.extend({
- tagName: 'div',
- className: 'overlay',
- template: _.template(Locale.translateHTML(tplOverlay)),
- events: {
- 'click #config-layout input[type=image]': 'handleLayoutChange',
- 'change select': 'handleSelectChange',
- },
- initialize: function() {
-
- window.addEventListener('blur', this.hide.bind(this));
- window.addEventListener('resize', this.hide.bind(this));
- },
- render: function() {
- this.$el.html(this.template({}));
- var layout = bg.settings.get('layout');
- if (layout == 'vertical') {
- $('#config-layout input[value=horizontal]').attr('src', '/images/layout_horizontal.png');
- $('#config-layout input[value=vertical]').attr('src', '/images/layout_vertical_selected.png');
- } else {
- $('#config-layout input[value=horizontal]').attr('src', '/images/layout_horizontal_selected.png');
- $('#config-layout input[value=vertical]').attr('src', '/images/layout_vertical.png');
- }
- this.$el.find('#config-lines').val(bg.settings.get('lines'));
- this.$el.find('#config-sort-order').val(bg.settings.get('sortOrder'));
- this.$el.find('#config-sort-order2').val(bg.settings.get('sortOrder2'));
- this.$el.find('#config-sort-by').val(bg.settings.get('sortBy'));
- this.$el.find('#config-sort-by2').val(bg.settings.get('sortBy2'));
- return this;
- },
- handleSelectChange: function(e) {
- bg.settings.save(e.currentTarget.dataset.name, e.currentTarget.value);
- },
- handleLayoutChange: function(e) {
- var layout = e.currentTarget.value;
- bg.settings.save('layout', layout);
- this.hide();
- },
- hide: function() {
- this.$el.css('display', 'none');
- },
- show: function() {
- var config = $('[data-action="content:showConfig"]');
- if (config.length) {
- this.el.style.top = config.offset().top + config.height() + 5 + 'px';
- }
- this.render().$el.css('display', 'block');
- },
- isVisible: function() {
- return this.$el.css('display') == 'block';
- }
- });
-
-return OverlayView;
-});
\ No newline at end of file
diff --git a/scripts/app/views/Properties.js b/scripts/app/views/Properties.js
deleted file mode 100644
index 5b48b559..00000000
--- a/scripts/app/views/Properties.js
+++ /dev/null
@@ -1,161 +0,0 @@
-define([
- 'backbone', 'jquery', 'underscore', 'text!templates/properties.html', 'modules/Locale'
-],
-function(BB, $, _, tplProperties, Locale) {
-
- var Properties = BB.View.extend({
- id: 'properties',
- current: null,
- template: _.template(Locale.translateHTML(tplProperties)),
- events: {
- 'click button' : 'handleClick',
- 'keydown button' : 'handleKeyDown',
- 'click #advanced-switch' : 'handleSwitchClick',
- },
- handleClick: function(e) {
- var t = e.currentTarget;
- if (t.id == 'prop-cancel') {
- this.hide();
- } else if (t.id == 'prop-ok') {
- this.saveData();
- }
- },
- saveData: function() {
- if (!this.current) {
- this.hide();
- return;
- }
-
- var updateEvery, autoremove;
-
- if (this.current instanceof bg.Source) {
- /* encrypt the password */
- this.current.setPass($('#prop-password').val());
-
- this.current.save({
- title: $('#prop-title').val(),
- url: app.fixURL($('#prop-url').val()),
- username: $('#prop-username').val(),
- updateEvery: parseFloat($('#prop-update-every').val()),
- autoremove: parseFloat($('#prop-autoremove').val(), 10),
- });
- } else if (this.current instanceof bg.Folder) {
- this.current.save({
- title: $('#prop-title').val()
- });
-
- var sourcesInFolder = bg.sources.where({ folderID: this.current.id });
-
- updateEvery = parseFloat($('#prop-update-every').val());
- if (updateEvery >= 0) {
- sourcesInFolder.forEach(function(source) {
- source.save({ updateEvery: updateEvery });
- });
- }
-
- autoremove = parseFloat($('#prop-autoremove').val());
- if (autoremove >= 0) {
- sourcesInFolder.forEach(function(source) {
- source.save({ autoremove: autoremove });
- });
- }
- } else if (Array.isArray(this.current)) {
- updateEvery = parseFloat($('#prop-update-every').val());
- if (updateEvery >= 0) {
- this.current.forEach(function(source) {
- source.save({ updateEvery: updateEvery });
- });
- }
-
- autoremove = parseFloat($('#prop-autoremove').val());
- if (autoremove >= 0) {
- this.current.forEach(function(source) {
- source.save({ autoremove: autoremove });
- });
- }
- }
-
- this.hide();
-
- },
- handleKeyDown: function(e) {
- if (e.keyCode == 13) {
- this.handleClick(e);
- }
- },
- render: function() {
- if (!this.current) return;
-
- if (this.current instanceof bg.Source) {
- /* decrypt password */
- var attrs = this.current.toJSON();
- attrs.password = this.current.getPass();
-
- this.$el.html(this.template(attrs));
-
- if (this.current.get('updateEvery')) {
- $('#prop-update-every').val(this.current.get('updateEvery'));
- }
-
- if (this.current.get('autoremove')) {
- $('#prop-autoremove').val(this.current.get('autoremove'));
- }
- } else {
- var isFolder = this.current instanceof bg.Folder;
- var listOfSources = isFolder ? bg.sources.where({ folderID: this.current.id }) : this.current;
-
- var params = { updateEveryDiffers: 0, autoremoveDiffers: 0, firstUpdate: 0, firstAutoremove: 0 };
-
- /**
- * Test if all selected feeds has the same properteies or if tehy are mixed
- */
-
- if (listOfSources.length) {
- params.firstUpdate = listOfSources[0].get('updateEvery');
- params.updateEveryDiffers = listOfSources.some(function(c) {
- if (params.firstUpdate != c.get('updateEvery')) return true;
- });
-
- params.firstAutoremove = listOfSources[0].get('autoremove');
- params.autoremoveDiffers = listOfSources.some(function(c) {
- if (params.firstAutoremove != c.get('autoremove')) return true;
- });
- }
-
- /**
- * Create HTML
- */
-
- if (isFolder) {
- this.$el.html(this.template( _.extend(params, this.current.attributes) ));
- } else {
- this.$el.html(this.template( params ));
- }
-
- /**
- * Set