feat: update analytics so to meet IABv2 requirements
- https://iabtechlab.com/wp-content/uploads/2017/12/Podcast_Measurement_v2-Dec-20-2017.pdf - no IP address is ever stored on the server. Only aggregate data is stored in the dababase. - rolling 24-hour window - castopod does not do pre-load - IP Blacklisting https://github.com/client9/ipcat - user-agent Filtering https://github.com/opawg/user-agents - ignores 2 bytes range "Range: 0-1" (performed by official Apple iOS Podcast app) - in case of partial content, adds up all requests to check >1mn was downloaded - identifying Uniques is done with a combination of IP Address and User Agent - add AMcharts - add some graphs - add regions to analytics - add ipcat blacklist - enhance useragents performances - add filesize and header size in order to calculate 1mn downloads - update publisher ID3 field - update castopod icon - add disclaimer and warning import form translation - update docs/setup-development.md closes #10
|
|
@ -39,13 +39,11 @@ bundle_app:
|
|||
script:
|
||||
# build all assets for views
|
||||
- npm run build
|
||||
# download GeoLite2-Country and opawg/user-agents archives and extract them to writable/uploads
|
||||
- wget -c "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-Country&license_key=$MAXMIND_LICENCE_KEY&suffix=tar.gz" -O - | tar -xz -C ./writable/uploads/
|
||||
- wget -c "https://github.com/opawg/user-agents/archive/master.tar.gz" -O - | tar -xz -C ./writable/uploads/
|
||||
# download GeoLite2-City archive and extract it to writable/uploads
|
||||
- wget -c "https://download.maxmind.com/app/geoip_download?edition_id=GeoLite2-City&license_key=$MAXMIND_LICENCE_KEY&suffix=tar.gz" -O - | tar -xz -C ./writable/uploads/
|
||||
|
||||
# rename extracted archives' folders
|
||||
- mv ./writable/uploads/GeoLite2-Country* ./writable/uploads/GeoLite2-Country
|
||||
- mv ./writable/uploads/user-agents* ./writable/uploads/user-agents
|
||||
- mv ./writable/uploads/GeoLite2-City* ./writable/uploads/GeoLite2-City
|
||||
|
||||
# create bundle folder: uses .rsync-filter (-F) file to copy only needed files
|
||||
- rsync -avF --progress . ./bundle
|
||||
|
|
|
|||
|
|
@ -12,16 +12,20 @@ PHP Dependencies:
|
|||
- [commonmark](https://commonmark.thephpleague.com/) ([BSD 3-Clause "New" or "Revised" License](https://github.com/thephpleague/commonmark/blob/latest/LICENSE))
|
||||
- [phpdotenv](https://github.com/vlucas/phpdotenv) ([ BSD-3-Clause License ](https://github.com/vlucas/phpdotenv/blob/master/LICENSE))
|
||||
- [HTML To Markdown for PHP](https://github.com/thephpleague/html-to-markdown) ([MIT License](https://github.com/thephpleague/html-to-markdown/blob/master/LICENSE))
|
||||
- [podlibre/user-agents-php](https://github.com/podlibre/user-agents-php) ([MIT License](https://github.com/podlibre/user-agents-php/blob/main/LICENSE))
|
||||
- [podlibre/ipcat](https://github.com/podlibre/ipcat) ([GNU General Public License v3.0](https://github.com/podlibre/ipcat/blob/master/LICENSE))
|
||||
|
||||
Javascript dependencies:
|
||||
|
||||
- [rollup](https://rollupjs.org/) ([MIT License](https://github.com/rollup/rollup/blob/master/LICENSE.md))
|
||||
- [tailwindcss](https://tailwindcss.com/) ([MIT License](https://github.com/tailwindcss/tailwindcss/blob/master/LICENSE))
|
||||
- [ProseMirror](https://prosemirror.net/) ([MIT License](https://github.com/ProseMirror/prosemirror/blob/master/LICENSE))
|
||||
- [D3: Data-Driven Documents](https://d3js.org) ([BSD 3-Clause "New" or "Revised" License](https://github.com/d3/d3/blob/master/LICENSE))
|
||||
- [amCharts 4](https://github.com/amcharts/amcharts4) ([Free amCharts license](https://github.com/amcharts/amcharts4/blob/master/dist/script/LICENSE))
|
||||
- [Choices.js](https://joshuajohnson.co.uk/Choices/) ([MIT License](https://github.com/jshjohnson/Choices/blob/master/LICENSE))
|
||||
|
||||
Other:
|
||||
|
||||
- [RemixIcon](https://remixicon.com/) ([Apache License 2.0](https://github.com/Remix-Design/RemixIcon/blob/master/License))
|
||||
- [User agent list](https://github.com/opawg/user-agents) ([by Open Podcast Analytics Working Group](https://github.com/opawg)) ([MIT license](https://github.com/opawg/user-agents/blob/master/LICENSE))
|
||||
- [OPAWG/User agent list](https://github.com/opawg/user-agents) ([by Open Podcast Analytics Working Group](https://github.com/opawg)) ([MIT license](https://github.com/opawg/user-agents/blob/master/LICENSE))
|
||||
- [client9/ipcat](https://github.com/client9/ipcat) ([GNU General Public License v3.0](https://github.com/client9/ipcat/blob/master/LICENSE))
|
||||
- [GeoLite2 City](https://dev.maxmind.com/geoip/geoip2/geolite2/) ([Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)](https://www.maxmind.com/en/geolite2/eula))
|
||||
|
|
|
|||
|
|
@ -53,10 +53,14 @@ $routes->group(config('App')->installGateway, function ($routes) {
|
|||
]);
|
||||
});
|
||||
|
||||
// Route for podcast audio file analytics (/stats/podcast_id/episode_id/podcast_folder/filename.mp3)
|
||||
$routes->add('stats/(:num)/(:num)/(:any)', 'Analytics::hit/$1/$2/$3', [
|
||||
'as' => 'analytics_hit',
|
||||
]);
|
||||
// Route for podcast audio file analytics (/audio/podcast_id/episode_id/bytes_threshold/filesize/podcast_folder/filename.mp3)
|
||||
$routes->add(
|
||||
'audio/(:num)/(:num)/(:num)/(:num)/(:any)',
|
||||
'Analytics::hit/$1/$2/$3/$4/$5',
|
||||
[
|
||||
'as' => 'analytics_hit',
|
||||
]
|
||||
);
|
||||
|
||||
// Show the Unknown UserAgents
|
||||
$routes->get('.well-known/unknown-useragents', 'UnknownUserAgents');
|
||||
|
|
@ -113,6 +117,26 @@ $routes->group(
|
|||
'as' => 'podcast-delete',
|
||||
'filter' => 'permission:podcasts-delete',
|
||||
]);
|
||||
$routes->get('analytics', 'Podcast::analytics/$1', [
|
||||
'as' => 'podcast-analytics',
|
||||
'filter' => 'permission:podcasts-view,podcast-view',
|
||||
]);
|
||||
$routes->get(
|
||||
'analytics-data/(:segment)/(:segment)',
|
||||
'AnalyticsData::getData/$1/$2/$3',
|
||||
[
|
||||
'as' => 'analytics-data',
|
||||
'filter' => 'permission:podcasts-view,podcast-view',
|
||||
]
|
||||
);
|
||||
$routes->get(
|
||||
'analytics-data/(:segment)/(:segment)/(:num)',
|
||||
'AnalyticsData::getData/$1/$2/$3/$4',
|
||||
[
|
||||
'as' => 'analytics-filtered-data',
|
||||
'filter' => 'permission:podcasts-view,podcast-view',
|
||||
]
|
||||
);
|
||||
|
||||
// Podcast episodes
|
||||
$routes->group('episodes', function ($routes) {
|
||||
|
|
|
|||
69
app/Controllers/Admin/AnalyticsData.php
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @copyright 2020 Podlibre
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
||||
* @link https://castopod.org/
|
||||
*/
|
||||
|
||||
namespace App\Controllers\Admin;
|
||||
|
||||
use App\Models\PodcastModel;
|
||||
use App\Models\EpisodeModel;
|
||||
|
||||
class AnalyticsData extends BaseController
|
||||
{
|
||||
/**
|
||||
* @var \App\Entities\Podcast|null
|
||||
*/
|
||||
protected $podcast;
|
||||
protected $className;
|
||||
protected $methodName;
|
||||
protected $episode;
|
||||
|
||||
public function _remap($method, ...$params)
|
||||
{
|
||||
if (count($params) > 2) {
|
||||
if (!($this->podcast = (new PodcastModel())->find($params[0]))) {
|
||||
throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound(
|
||||
'Podcast not found: ' . $params[0]
|
||||
);
|
||||
}
|
||||
$this->className = '\App\Models\Analytics' . $params[1] . 'Model';
|
||||
$this->methodName = 'getData' . $params[2];
|
||||
if (count($params) > 3) {
|
||||
if (
|
||||
!($this->episode = (new EpisodeModel())
|
||||
->where([
|
||||
'podcast_id' => $this->podcast->id,
|
||||
'id' => $params[3],
|
||||
])
|
||||
->first())
|
||||
) {
|
||||
throw \CodeIgniter\Exceptions\PageNotFoundException::forPageNotFound(
|
||||
'Episode not found: ' . $params[3]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->$method();
|
||||
}
|
||||
public function getData()
|
||||
{
|
||||
$analytics_model = new $this->className();
|
||||
$methodName = $this->methodName;
|
||||
if ($this->episode) {
|
||||
return $this->response->setJSON(
|
||||
$analytics_model->$methodName(
|
||||
$this->podcast->id,
|
||||
$this->episode->id
|
||||
)
|
||||
);
|
||||
} else {
|
||||
return $this->response->setJSON(
|
||||
$analytics_model->$methodName($this->podcast->id)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -58,6 +58,14 @@ class Podcast extends BaseController
|
|||
return view('admin/podcast/view', $data);
|
||||
}
|
||||
|
||||
public function analytics()
|
||||
{
|
||||
$data = ['podcast' => $this->podcast];
|
||||
|
||||
replace_breadcrumb_params([0 => $this->podcast->title]);
|
||||
return view('admin/podcast/analytics', $data);
|
||||
}
|
||||
|
||||
public function create()
|
||||
{
|
||||
helper(['form', 'misc']);
|
||||
|
|
@ -204,7 +212,9 @@ class Podcast extends BaseController
|
|||
$podcast = new \App\Entities\Podcast([
|
||||
'name' => $this->request->getPost('name'),
|
||||
'imported_feed_url' => $this->request->getPost('imported_feed_url'),
|
||||
|
||||
'new_feed_url' => base_url(
|
||||
route_to('podcast_feed', $this->request->getPost('name'))
|
||||
),
|
||||
'title' => $feed->channel[0]->title,
|
||||
'description' => $feed->channel[0]->description,
|
||||
'image' => download_file($nsItunes->image->attributes()),
|
||||
|
|
@ -214,7 +224,9 @@ class Podcast extends BaseController
|
|||
? null
|
||||
: (in_array($nsItunes->explicit, ['yes', 'true'])
|
||||
? 'explicit'
|
||||
: null),
|
||||
: (in_array($nsItunes->explicit, ['no', 'false'])
|
||||
? 'clean'
|
||||
: null)),
|
||||
'owner_name' => $nsItunes->owner->name,
|
||||
'owner_email' => $nsItunes->owner->email,
|
||||
'publisher' => $nsItunes->author,
|
||||
|
|
@ -302,11 +314,13 @@ class Podcast extends BaseController
|
|||
'image' => empty($nsItunes->image->attributes())
|
||||
? null
|
||||
: download_file($nsItunes->image->attributes()),
|
||||
'explicit' => $nsItunes->explicit
|
||||
? (in_array($nsItunes->explicit, ['yes', 'true'])
|
||||
'parental_advisory' => empty($nsItunes->explicit)
|
||||
? null
|
||||
: (in_array($nsItunes->explicit, ['yes', 'true'])
|
||||
? 'explicit'
|
||||
: null)
|
||||
: null,
|
||||
: (in_array($nsItunes->explicit, ['no', 'false'])
|
||||
? 'clean'
|
||||
: null)),
|
||||
'number' =>
|
||||
$this->request->getPost('force_renumber') === 'yes'
|
||||
? $itemNumber
|
||||
|
|
|
|||
|
|
@ -40,16 +40,22 @@ class Analytics extends Controller
|
|||
// E.g.:
|
||||
// $this->session = \Config\Services::session();
|
||||
|
||||
set_user_session_country();
|
||||
set_user_session_deny_list_ip();
|
||||
set_user_session_location();
|
||||
set_user_session_player();
|
||||
}
|
||||
|
||||
// Add one hit to this episode:
|
||||
public function hit($p_podcastId, $p_episodeId, ...$filename)
|
||||
{
|
||||
public function hit(
|
||||
$podcastId,
|
||||
$episodeId,
|
||||
$bytesThreshold,
|
||||
$fileSize,
|
||||
...$filename
|
||||
) {
|
||||
helper('media');
|
||||
|
||||
podcast_hit($p_podcastId, $p_episodeId);
|
||||
podcast_hit($podcastId, $episodeId, $bytesThreshold, $fileSize);
|
||||
return redirect()->to(media_url(implode('/', $filename)));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,9 +45,10 @@ class BaseController extends Controller
|
|||
// E.g.:
|
||||
// $this->session = \Config\Services::session();
|
||||
|
||||
set_user_session_country();
|
||||
set_user_session_deny_list_ip();
|
||||
set_user_session_browser();
|
||||
set_user_session_referer();
|
||||
set_user_session_entry_page();
|
||||
}
|
||||
|
||||
protected static function triggerWebpageHit($podcastId)
|
||||
|
|
|
|||
|
|
@ -110,6 +110,13 @@ class AddPodcasts extends Migration
|
|||
'The RSS feed URL if this podcast was imported, NULL otherwise.',
|
||||
'null' => true,
|
||||
],
|
||||
'new_feed_url' => [
|
||||
'type' => 'VARCHAR',
|
||||
'constraint' => 1024,
|
||||
'comment' =>
|
||||
'The RSS new feed URL if this podcast is moving out, NULL otherwise.',
|
||||
'null' => true,
|
||||
],
|
||||
'created_at' => [
|
||||
'type' => 'TIMESTAMP',
|
||||
],
|
||||
|
|
|
|||
|
|
@ -61,6 +61,12 @@ class AddEpisodes extends Migration
|
|||
'unsigned' => true,
|
||||
'comment' => 'File size in bytes',
|
||||
],
|
||||
'enclosure_headersize' => [
|
||||
'type' => 'INT',
|
||||
'constraint' => 10,
|
||||
'unsigned' => true,
|
||||
'comment' => 'Header size in bytes',
|
||||
],
|
||||
'description' => [
|
||||
'type' => 'TEXT',
|
||||
'null' => true,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Class AddAnalyticsPodcastsByCountry
|
||||
* Creates analytics_podcasts_by_country table in database
|
||||
* @copyright 2020 Podlibre
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
||||
* @link https://castopod.org/
|
||||
*/
|
||||
|
||||
namespace App\Database\Migrations;
|
||||
|
||||
use CodeIgniter\Database\Migration;
|
||||
|
||||
class AddAnalyticsPodcasts extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
$this->forge->addField([
|
||||
'podcast_id' => [
|
||||
'type' => 'BIGINT',
|
||||
'constraint' => 20,
|
||||
'unsigned' => true,
|
||||
],
|
||||
'date' => [
|
||||
'type' => 'date',
|
||||
],
|
||||
'hits' => [
|
||||
'type' => 'INT',
|
||||
'constraint' => 10,
|
||||
'default' => 1,
|
||||
],
|
||||
]);
|
||||
$this->forge->addPrimaryKey(['podcast_id', 'date']);
|
||||
$this->forge->addField(
|
||||
'`created_at` timestamp NOT NULL DEFAULT current_timestamp()'
|
||||
);
|
||||
$this->forge->addField(
|
||||
'`updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp()'
|
||||
);
|
||||
$this->forge->addForeignKey('podcast_id', 'podcasts', 'id');
|
||||
$this->forge->createTable('analytics_podcasts');
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
$this->forge->dropTable('analytics_podcasts');
|
||||
}
|
||||
}
|
||||
|
|
@ -12,34 +12,28 @@ namespace App\Database\Migrations;
|
|||
|
||||
use CodeIgniter\Database\Migration;
|
||||
|
||||
class AddAnalyticsEpisodesByCountry extends Migration
|
||||
class AddAnalyticsPodcastsByEpisode extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
$this->forge->addField([
|
||||
'id' => [
|
||||
'type' => 'BIGINT',
|
||||
'constraint' => 20,
|
||||
'unsigned' => true,
|
||||
'auto_increment' => true,
|
||||
],
|
||||
'podcast_id' => [
|
||||
'type' => 'BIGINT',
|
||||
'constraint' => 20,
|
||||
'unsigned' => true,
|
||||
],
|
||||
'date' => [
|
||||
'type' => 'date',
|
||||
],
|
||||
'episode_id' => [
|
||||
'type' => 'BIGINT',
|
||||
'constraint' => 20,
|
||||
'unsigned' => true,
|
||||
],
|
||||
'country_code' => [
|
||||
'type' => 'VARCHAR',
|
||||
'constraint' => 3,
|
||||
'comment' => 'ISO 3166-1 code.',
|
||||
],
|
||||
'date' => [
|
||||
'type' => 'date',
|
||||
'age' => [
|
||||
'type' => 'INT',
|
||||
'constraint' => 10,
|
||||
'unsigned' => true,
|
||||
],
|
||||
'hits' => [
|
||||
'type' => 'INT',
|
||||
|
|
@ -47,13 +41,7 @@ class AddAnalyticsEpisodesByCountry extends Migration
|
|||
'default' => 1,
|
||||
],
|
||||
]);
|
||||
$this->forge->addKey('id', true);
|
||||
$this->forge->addUniqueKey([
|
||||
'podcast_id',
|
||||
'episode_id',
|
||||
'country_code',
|
||||
'date',
|
||||
]);
|
||||
$this->forge->addPrimaryKey(['podcast_id', 'episode_id', 'date']);
|
||||
$this->forge->addField(
|
||||
'`created_at` timestamp NOT NULL DEFAULT current_timestamp()'
|
||||
);
|
||||
|
|
@ -62,11 +50,11 @@ class AddAnalyticsEpisodesByCountry extends Migration
|
|||
);
|
||||
$this->forge->addForeignKey('podcast_id', 'podcasts', 'id');
|
||||
$this->forge->addForeignKey('episode_id', 'episodes', 'id');
|
||||
$this->forge->createTable('analytics_episodes_by_country');
|
||||
$this->forge->createTable('analytics_podcasts_by_episode');
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
$this->forge->dropTable('analytics_episodes_by_country');
|
||||
$this->forge->dropTable('analytics_podcasts_by_episode');
|
||||
}
|
||||
}
|
||||
|
|
@ -17,32 +17,45 @@ class AddAnalyticsPodcastsByPlayer extends Migration
|
|||
public function up()
|
||||
{
|
||||
$this->forge->addField([
|
||||
'id' => [
|
||||
'type' => 'BIGINT',
|
||||
'constraint' => 20,
|
||||
'unsigned' => true,
|
||||
'auto_increment' => true,
|
||||
],
|
||||
'podcast_id' => [
|
||||
'type' => 'BIGINT',
|
||||
'constraint' => 20,
|
||||
'unsigned' => true,
|
||||
],
|
||||
'player' => [
|
||||
'type' => 'VARCHAR',
|
||||
'constraint' => 191,
|
||||
],
|
||||
'date' => [
|
||||
'type' => 'date',
|
||||
],
|
||||
'app' => [
|
||||
'type' => 'VARCHAR',
|
||||
'constraint' => 128,
|
||||
],
|
||||
'device' => [
|
||||
'type' => 'VARCHAR',
|
||||
'constraint' => 32,
|
||||
],
|
||||
'os' => [
|
||||
'type' => 'VARCHAR',
|
||||
'constraint' => 32,
|
||||
],
|
||||
'bot' => [
|
||||
'type' => 'TINYINT',
|
||||
'constraint' => 1,
|
||||
'default' => 0,
|
||||
],
|
||||
'hits' => [
|
||||
'type' => 'INT',
|
||||
'constraint' => 10,
|
||||
'default' => 1,
|
||||
],
|
||||
]);
|
||||
$this->forge->addKey('id', true);
|
||||
$this->forge->addUniqueKey(['podcast_id', 'player', 'date']);
|
||||
$this->forge->addPrimaryKey([
|
||||
'podcast_id',
|
||||
'app',
|
||||
'device',
|
||||
'os',
|
||||
'bot',
|
||||
'date',
|
||||
]);
|
||||
$this->forge->addField(
|
||||
'`created_at` timestamp NOT NULL DEFAULT current_timestamp()'
|
||||
);
|
||||
|
|
@ -17,33 +17,26 @@ class AddAnalyticsPodcastsByCountry extends Migration
|
|||
public function up()
|
||||
{
|
||||
$this->forge->addField([
|
||||
'id' => [
|
||||
'type' => 'BIGINT',
|
||||
'constraint' => 20,
|
||||
'unsigned' => true,
|
||||
'auto_increment' => true,
|
||||
],
|
||||
'podcast_id' => [
|
||||
'type' => 'BIGINT',
|
||||
'constraint' => 20,
|
||||
'unsigned' => true,
|
||||
],
|
||||
'date' => [
|
||||
'type' => 'date',
|
||||
],
|
||||
'country_code' => [
|
||||
'type' => 'VARCHAR',
|
||||
'constraint' => 3,
|
||||
'comment' => 'ISO 3166-1 code.',
|
||||
],
|
||||
'date' => [
|
||||
'type' => 'date',
|
||||
],
|
||||
'hits' => [
|
||||
'type' => 'INT',
|
||||
'constraint' => 10,
|
||||
'default' => 1,
|
||||
],
|
||||
]);
|
||||
$this->forge->addKey('id', true);
|
||||
$this->forge->addUniqueKey(['podcast_id', 'country_code', 'date']);
|
||||
$this->forge->addPrimaryKey(['podcast_id', 'country_code', 'date']);
|
||||
$this->forge->addField(
|
||||
'`created_at` timestamp NOT NULL DEFAULT current_timestamp()'
|
||||
);
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Class AddAnalyticsWebsiteByCountry
|
||||
* Creates analytics_website_by_country table in database
|
||||
* Class AddAnalyticsPodcastsByRegion
|
||||
* Creates analytics_podcasts_by_region table in database
|
||||
* @copyright 2020 Podlibre
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
||||
* @link https://castopod.org/
|
||||
|
|
@ -12,29 +12,36 @@ namespace App\Database\Migrations;
|
|||
|
||||
use CodeIgniter\Database\Migration;
|
||||
|
||||
class AddAnalyticsWebsiteByCountry extends Migration
|
||||
class AddAnalyticsPodcastsByRegion extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
$this->forge->addField([
|
||||
'id' => [
|
||||
'type' => 'BIGINT',
|
||||
'constraint' => 20,
|
||||
'unsigned' => true,
|
||||
'auto_increment' => true,
|
||||
],
|
||||
'podcast_id' => [
|
||||
'type' => 'BIGINT',
|
||||
'constraint' => 20,
|
||||
'unsigned' => true,
|
||||
],
|
||||
'date' => [
|
||||
'type' => 'date',
|
||||
],
|
||||
'country_code' => [
|
||||
'type' => 'VARCHAR',
|
||||
'constraint' => 3,
|
||||
'comment' => 'ISO 3166-1 code.',
|
||||
],
|
||||
'date' => [
|
||||
'type' => 'date',
|
||||
'region_code' => [
|
||||
'type' => 'VARCHAR',
|
||||
'constraint' => 3,
|
||||
'comment' => 'ISO 3166-2 code.',
|
||||
],
|
||||
'latitude' => [
|
||||
'type' => 'FLOAT',
|
||||
'null' => true,
|
||||
],
|
||||
'longitude' => [
|
||||
'type' => 'FLOAT',
|
||||
'null' => true,
|
||||
],
|
||||
'hits' => [
|
||||
'type' => 'INT',
|
||||
|
|
@ -42,8 +49,12 @@ class AddAnalyticsWebsiteByCountry extends Migration
|
|||
'default' => 1,
|
||||
],
|
||||
]);
|
||||
$this->forge->addKey('id', true);
|
||||
$this->forge->addUniqueKey(['podcast_id', 'country_code', 'date']);
|
||||
$this->forge->addPrimaryKey([
|
||||
'podcast_id',
|
||||
'country_code',
|
||||
'region_code',
|
||||
'date',
|
||||
]);
|
||||
$this->forge->addField(
|
||||
'`created_at` timestamp NOT NULL DEFAULT current_timestamp()'
|
||||
);
|
||||
|
|
@ -51,11 +62,11 @@ class AddAnalyticsWebsiteByCountry extends Migration
|
|||
'`updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp()'
|
||||
);
|
||||
$this->forge->addForeignKey('podcast_id', 'podcasts', 'id');
|
||||
$this->forge->createTable('analytics_website_by_country');
|
||||
$this->forge->createTable('analytics_podcasts_by_region');
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
$this->forge->dropTable('analytics_website_by_country');
|
||||
$this->forge->dropTable('analytics_podcasts_by_region');
|
||||
}
|
||||
}
|
||||
|
|
@ -17,32 +17,26 @@ class AddAnalyticsWebsiteByBrowser extends Migration
|
|||
public function up()
|
||||
{
|
||||
$this->forge->addField([
|
||||
'id' => [
|
||||
'type' => 'BIGINT',
|
||||
'constraint' => 20,
|
||||
'unsigned' => true,
|
||||
'auto_increment' => true,
|
||||
],
|
||||
'podcast_id' => [
|
||||
'type' => 'BIGINT',
|
||||
'constraint' => 20,
|
||||
'unsigned' => true,
|
||||
],
|
||||
'date' => [
|
||||
'type' => 'date',
|
||||
],
|
||||
'browser' => [
|
||||
'type' => 'VARCHAR',
|
||||
'constraint' => 191,
|
||||
],
|
||||
'date' => [
|
||||
'type' => 'date',
|
||||
],
|
||||
|
||||
'hits' => [
|
||||
'type' => 'INT',
|
||||
'constraint' => 10,
|
||||
'default' => 1,
|
||||
],
|
||||
]);
|
||||
$this->forge->addKey('id', true);
|
||||
$this->forge->addUniqueKey(['podcast_id', 'browser', 'date']);
|
||||
$this->forge->addPrimaryKey(['podcast_id', 'browser', 'date']);
|
||||
$this->forge->addField(
|
||||
'`created_at` timestamp NOT NULL DEFAULT current_timestamp()'
|
||||
);
|
||||
|
|
@ -17,33 +17,36 @@ class AddAnalyticsWebsiteByReferer extends Migration
|
|||
public function up()
|
||||
{
|
||||
$this->forge->addField([
|
||||
'id' => [
|
||||
'type' => 'BIGINT',
|
||||
'constraint' => 20,
|
||||
'unsigned' => true,
|
||||
'auto_increment' => true,
|
||||
],
|
||||
'podcast_id' => [
|
||||
'type' => 'BIGINT',
|
||||
'constraint' => 20,
|
||||
'unsigned' => true,
|
||||
],
|
||||
'referer' => [
|
||||
'type' => 'VARCHAR',
|
||||
'constraint' => 191,
|
||||
'comment' => 'Referer URL.',
|
||||
],
|
||||
'date' => [
|
||||
'type' => 'date',
|
||||
],
|
||||
'referer' => [
|
||||
'type' => 'VARCHAR',
|
||||
'constraint' => 512,
|
||||
'comment' => 'Referer URL.',
|
||||
],
|
||||
'domain' => [
|
||||
'type' => 'VARCHAR',
|
||||
'constraint' => 128,
|
||||
'null' => true,
|
||||
],
|
||||
'keywords' => [
|
||||
'type' => 'VARCHAR',
|
||||
'constraint' => 384,
|
||||
'null' => true,
|
||||
],
|
||||
'hits' => [
|
||||
'type' => 'INT',
|
||||
'constraint' => 10,
|
||||
'default' => 1,
|
||||
],
|
||||
]);
|
||||
$this->forge->addKey('id', true);
|
||||
$this->forge->addUniqueKey(['podcast_id', 'referer', 'date']);
|
||||
$this->forge->addPrimaryKey(['podcast_id', 'referer', 'date']);
|
||||
$this->forge->addField(
|
||||
'`created_at` timestamp NOT NULL DEFAULT current_timestamp()'
|
||||
);
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Class AddAnalyticsWebsiteByReferer
|
||||
* Creates analytics_website_by_referer table in database
|
||||
* @copyright 2020 Podlibre
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
||||
* @link https://castopod.org/
|
||||
*/
|
||||
|
||||
namespace App\Database\Migrations;
|
||||
|
||||
use CodeIgniter\Database\Migration;
|
||||
|
||||
class AddAnalyticsWebsiteByEntryPage extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
$this->forge->addField([
|
||||
'podcast_id' => [
|
||||
'type' => 'BIGINT',
|
||||
'constraint' => 20,
|
||||
'unsigned' => true,
|
||||
],
|
||||
'date' => [
|
||||
'type' => 'date',
|
||||
],
|
||||
'entry_page' => [
|
||||
'type' => 'VARCHAR',
|
||||
'constraint' => 512,
|
||||
'comment' => 'Entry page URL.',
|
||||
],
|
||||
'hits' => [
|
||||
'type' => 'INT',
|
||||
'constraint' => 10,
|
||||
'default' => 1,
|
||||
],
|
||||
]);
|
||||
$this->forge->addPrimaryKey(['podcast_id', 'entry_page', 'date']);
|
||||
$this->forge->addField(
|
||||
'`created_at` timestamp NOT NULL DEFAULT current_timestamp()'
|
||||
);
|
||||
$this->forge->addField(
|
||||
'`updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp()'
|
||||
);
|
||||
$this->forge->addForeignKey('podcast_id', 'podcasts', 'id');
|
||||
$this->forge->createTable('analytics_website_by_entry_page');
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
$this->forge->dropTable('analytics_website_by_entry_page');
|
||||
}
|
||||
}
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Class AddAnalyticsEpisodesByPlayer
|
||||
* Creates analytics_episodes_by_player table in database
|
||||
* @copyright 2020 Podlibre
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
||||
* @link https://castopod.org/
|
||||
*/
|
||||
|
||||
namespace App\Database\Migrations;
|
||||
|
||||
use CodeIgniter\Database\Migration;
|
||||
|
||||
class AddAnalyticsEpisodesByPlayer extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
$this->forge->addField([
|
||||
'id' => [
|
||||
'type' => 'BIGINT',
|
||||
'constraint' => 20,
|
||||
'unsigned' => true,
|
||||
'auto_increment' => true,
|
||||
],
|
||||
'podcast_id' => [
|
||||
'type' => 'BIGINT',
|
||||
'constraint' => 20,
|
||||
'unsigned' => true,
|
||||
],
|
||||
'episode_id' => [
|
||||
'type' => 'BIGINT',
|
||||
'constraint' => 20,
|
||||
'unsigned' => true,
|
||||
],
|
||||
'player' => [
|
||||
'type' => 'VARCHAR',
|
||||
'constraint' => 191,
|
||||
],
|
||||
'date' => [
|
||||
'type' => 'date',
|
||||
],
|
||||
'hits' => [
|
||||
'type' => 'INT',
|
||||
'constraint' => 10,
|
||||
'default' => 1,
|
||||
],
|
||||
]);
|
||||
$this->forge->addKey('id', true);
|
||||
$this->forge->addUniqueKey([
|
||||
'podcast_id',
|
||||
'episode_id',
|
||||
'player',
|
||||
'date',
|
||||
]);
|
||||
$this->forge->addField(
|
||||
'`created_at` timestamp NOT NULL DEFAULT current_timestamp()'
|
||||
);
|
||||
$this->forge->addField(
|
||||
'`updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp()'
|
||||
);
|
||||
$this->forge->addForeignKey('podcast_id', 'podcasts', 'id');
|
||||
$this->forge->addForeignKey('episode_id', 'episodes', 'id');
|
||||
$this->forge->createTable('analytics_episodes_by_player');
|
||||
}
|
||||
|
||||
public function down()
|
||||
{
|
||||
$this->forge->dropTable('analytics_episodes_by_player');
|
||||
}
|
||||
}
|
||||
|
|
@ -18,26 +18,42 @@ class AddAnalyticsPodcastsStoredProcedure extends Migration
|
|||
{
|
||||
// Creates Stored Procedure for data insertion
|
||||
// Example: CALL analytics_podcasts(1,2,'FR','phone/android/Deezer');
|
||||
$procedureName = $this->db->prefixTable('analytics_podcasts');
|
||||
$episodesTableName = $this->db->prefixTable('analytics_episodes');
|
||||
$prefix = $this->db->getPrefix();
|
||||
|
||||
$createQuery = <<<EOD
|
||||
CREATE PROCEDURE `$procedureName` (IN `p_podcast_id` BIGINT(20) UNSIGNED, IN `p_episode_id` BIGINT(20) UNSIGNED, IN `p_country_code` VARCHAR(3) CHARSET utf8mb4, IN `p_player` VARCHAR(191) CHARSET utf8mb4) MODIFIES SQL DATA
|
||||
CREATE PROCEDURE `{$prefix}analytics_podcasts` (
|
||||
IN `p_podcast_id` BIGINT(20) UNSIGNED,
|
||||
IN `p_episode_id` BIGINT(20) UNSIGNED,
|
||||
IN `p_country_code` VARCHAR(3) CHARSET utf8mb4,
|
||||
IN `p_region_code` VARCHAR(3) CHARSET utf8mb4,
|
||||
IN `p_latitude` FLOAT,
|
||||
IN `p_longitude` FLOAT,
|
||||
IN `p_app` VARCHAR(128) CHARSET utf8mb4,
|
||||
IN `p_device` VARCHAR(32) CHARSET utf8mb4,
|
||||
IN `p_os` VARCHAR(32) CHARSET utf8mb4,
|
||||
IN `p_bot` TINYINT(1) UNSIGNED
|
||||
) MODIFIES SQL DATA
|
||||
DETERMINISTIC
|
||||
SQL SECURITY INVOKER
|
||||
COMMENT 'Add one hit in podcast logs tables.'
|
||||
BEGIN
|
||||
INSERT INTO `{$procedureName}_by_country`(`podcast_id`, `country_code`, `date`)
|
||||
VALUES (p_podcast_id, p_country_code, DATE(NOW()))
|
||||
ON DUPLICATE KEY UPDATE `hits`=`hits`+1;
|
||||
INSERT INTO `{$procedureName}_by_player`(`podcast_id`, `player`, `date`)
|
||||
VALUES (p_podcast_id, p_player, DATE(NOW()))
|
||||
ON DUPLICATE KEY UPDATE `hits`=`hits`+1;
|
||||
INSERT INTO `{$episodesTableName}_by_country`(`podcast_id`, `episode_id`, `country_code`, `date`)
|
||||
VALUES (p_podcast_id, p_episode_id, p_country_code, DATE(NOW()))
|
||||
ON DUPLICATE KEY UPDATE `hits`=`hits`+1;
|
||||
INSERT INTO `{$episodesTableName}_by_player`(`podcast_id`, `episode_id`, `player`, `date`)
|
||||
VALUES (p_podcast_id, p_episode_id, p_player, DATE(NOW()))
|
||||
ON DUPLICATE KEY UPDATE `hits`=`hits`+1;
|
||||
IF NOT `p_bot` THEN
|
||||
INSERT INTO `{$prefix}analytics_podcasts`(`podcast_id`, `date`)
|
||||
VALUES (p_podcast_id, DATE(NOW()))
|
||||
ON DUPLICATE KEY UPDATE `hits`=`hits`+1;
|
||||
INSERT INTO `{$prefix}analytics_podcasts_by_episode`(`podcast_id`, `episode_id`, `date`, `age`)
|
||||
SELECT p_podcast_id, p_episode_id, DATE(NOW()), datediff(now(),`published_at`) FROM `{$prefix}episodes` WHERE `id`= p_episode_id
|
||||
ON DUPLICATE KEY UPDATE `hits`=`hits`+1;
|
||||
INSERT INTO `{$prefix}analytics_podcasts_by_country`(`podcast_id`, `country_code`, `date`)
|
||||
VALUES (p_podcast_id, p_country_code, DATE(NOW()))
|
||||
ON DUPLICATE KEY UPDATE `hits`=`hits`+1;
|
||||
INSERT INTO `{$prefix}analytics_podcasts_by_region`(`podcast_id`, `country_code`, `region_code`, `latitude`, `longitude`, `date`)
|
||||
VALUES (p_podcast_id, p_country_code, p_region_code, p_latitude, p_longitude, DATE(NOW()))
|
||||
ON DUPLICATE KEY UPDATE `hits`=`hits`+1;
|
||||
END IF;
|
||||
INSERT INTO `{$prefix}analytics_podcasts_by_player`(`podcast_id`, `app`, `device`, `os`, `bot`, `date`)
|
||||
VALUES (p_podcast_id, p_app, p_device, p_os, p_bot, DATE(NOW()))
|
||||
ON DUPLICATE KEY UPDATE `hits`=`hits`+1;
|
||||
END
|
||||
EOD;
|
||||
$this->db->query($createQuery);
|
||||
|
|
@ -45,7 +61,9 @@ EOD;
|
|||
|
||||
public function down()
|
||||
{
|
||||
$procedureName = $this->db->prefixTable('analytics_podcasts');
|
||||
$this->db->query("DROP PROCEDURE IF EXISTS `$procedureName`");
|
||||
$prefix = $this->db->getPrefix();
|
||||
$this->db->query(
|
||||
"DROP PROCEDURE IF EXISTS `{$prefix}analytics_podcasts`"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,20 +20,20 @@ class AddAnalyticsWebsiteStoredProcedure extends Migration
|
|||
// Example: CALL analytics_website(1,'FR','Firefox');
|
||||
$procedureName = $this->db->prefixTable('analytics_website');
|
||||
$createQuery = <<<EOD
|
||||
CREATE PROCEDURE `$procedureName` (IN `p_podcast_id` BIGINT(20) UNSIGNED, IN `p_country_code` VARCHAR(3) CHARSET utf8mb4, IN `p_browser` VARCHAR(191) CHARSET utf8mb4, IN `p_referer` VARCHAR(191) CHARSET utf8mb4) MODIFIES SQL DATA
|
||||
CREATE PROCEDURE `$procedureName` (IN `p_podcast_id` BIGINT(20) UNSIGNED, IN `p_browser` VARCHAR(191) CHARSET utf8mb4, IN `p_entry_page` VARCHAR(512) CHARSET utf8mb4, IN `p_referer` VARCHAR(512) CHARSET utf8mb4, IN `p_domain` VARCHAR(128) CHARSET utf8mb4, IN `p_keywords` VARCHAR(384) CHARSET utf8mb4) MODIFIES SQL DATA
|
||||
DETERMINISTIC
|
||||
SQL SECURITY INVOKER
|
||||
COMMENT 'Add one hit in website logs tables.'
|
||||
BEGIN
|
||||
INSERT INTO {$procedureName}_by_country(`podcast_id`, `country_code`, `date`)
|
||||
VALUES (p_podcast_id, p_country_code, DATE(NOW()))
|
||||
ON DUPLICATE KEY UPDATE `hits`=`hits`+1;
|
||||
INSERT INTO {$procedureName}_by_browser(`podcast_id`, `browser`, `date`)
|
||||
VALUES (p_podcast_id, p_browser, DATE(NOW()))
|
||||
ON DUPLICATE KEY UPDATE `hits`=`hits`+1;
|
||||
INSERT INTO {$procedureName}_by_referer(`podcast_id`, `referer`, `date`)
|
||||
VALUES (p_podcast_id, p_referer, DATE(NOW()))
|
||||
ON DUPLICATE KEY UPDATE `hits`=`hits`+1;
|
||||
VALUES (p_podcast_id, p_browser, DATE(NOW()))
|
||||
ON DUPLICATE KEY UPDATE `hits`=`hits`+1;
|
||||
INSERT INTO {$procedureName}_by_referer(`podcast_id`, `referer`, `domain`, `keywords`, `date`)
|
||||
VALUES (p_podcast_id, p_referer, p_domain, p_keywords, DATE(NOW()))
|
||||
ON DUPLICATE KEY UPDATE `hits`=`hits`+1;
|
||||
INSERT INTO {$procedureName}_by_entry_page(`podcast_id`, `entry_page`, `date`)
|
||||
VALUES (p_podcast_id, p_entry_page, DATE(NOW()))
|
||||
ON DUPLICATE KEY UPDATE `hits`=`hits`+1;
|
||||
END
|
||||
EOD;
|
||||
$this->db->query($createQuery);
|
||||
|
|
|
|||
176
app/Database/Seeds/FakePodcastsAnalyticsSeeder.php
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Class FakePodcastsAnalyticsSeeder
|
||||
* Inserts Fake Analytics in the database
|
||||
*
|
||||
* @copyright 2020 Podlibre
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
||||
* @link https://castopod.org/
|
||||
*/
|
||||
|
||||
namespace App\Database\Seeds;
|
||||
use App\Models\PodcastModel;
|
||||
use App\Models\EpisodeModel;
|
||||
|
||||
use CodeIgniter\Database\Seeder;
|
||||
|
||||
class FakePodcastsAnalyticsSeeder extends Seeder
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$podcast = (new PodcastModel())->first();
|
||||
|
||||
$jsonUserAgents = json_decode(
|
||||
file_get_contents(
|
||||
'https://raw.githubusercontent.com/opawg/user-agents/master/src/user-agents.json'
|
||||
),
|
||||
true
|
||||
);
|
||||
|
||||
if ($podcast) {
|
||||
$firstEpisode = (new EpisodeModel())
|
||||
->selectMin('published_at')
|
||||
->first();
|
||||
|
||||
for (
|
||||
$date = strtotime($firstEpisode->published_at);
|
||||
$date < strtotime('now');
|
||||
$date = strtotime(date('Y-m-d', $date) . ' +1 day')
|
||||
) {
|
||||
$analytics_podcasts = [];
|
||||
$analytics_podcasts_by_country = [];
|
||||
$analytics_podcasts_by_episode = [];
|
||||
$analytics_podcasts_by_player = [];
|
||||
$analytics_podcasts_by_region = [];
|
||||
|
||||
$episodes = (new EpisodeModel())
|
||||
->where([
|
||||
'podcast_id' => $podcast->id,
|
||||
'DATE(published_at) <=' => date('Y-m-d', $date),
|
||||
])
|
||||
->findAll();
|
||||
foreach ($episodes as $episode) {
|
||||
$age = floor(
|
||||
($date - strtotime($episode->published_at)) / 86400
|
||||
);
|
||||
$proba1 = floor(exp(3 - $age / 40)) + 1;
|
||||
|
||||
for (
|
||||
$num_line = 0;
|
||||
$num_line < rand(1, $proba1);
|
||||
$num_line++
|
||||
) {
|
||||
$proba2 = floor(exp(6 - $age / 20)) + 10;
|
||||
|
||||
$player =
|
||||
$jsonUserAgents[
|
||||
rand(1, count($jsonUserAgents) - 1)
|
||||
];
|
||||
$app = isset($player['app']) ? $player['app'] : '';
|
||||
$device = isset($player['device'])
|
||||
? $player['device']
|
||||
: '';
|
||||
$os = isset($player['os']) ? $player['os'] : '';
|
||||
$bot = isset($player['bot']) ? $player['bot'] : 0;
|
||||
|
||||
$fakeIp =
|
||||
rand(0, 255) .
|
||||
'.' .
|
||||
rand(0, 255) .
|
||||
'.' .
|
||||
rand(0, 255) .
|
||||
'.' .
|
||||
rand(0, 255);
|
||||
|
||||
$cityReader = new \GeoIp2\Database\Reader(
|
||||
WRITEPATH .
|
||||
'uploads/GeoLite2-City/GeoLite2-City.mmdb'
|
||||
);
|
||||
|
||||
$countryCode = 'N/A';
|
||||
$regionCode = 'N/A';
|
||||
$latitude = null;
|
||||
$longitude = null;
|
||||
try {
|
||||
$city = $cityReader->city($fakeIp);
|
||||
|
||||
$countryCode = empty($city->country->isoCode)
|
||||
? 'N/A'
|
||||
: $city->country->isoCode;
|
||||
|
||||
$regionCode = empty($city->subdivisions[0]->isoCode)
|
||||
? 'N/A'
|
||||
: $city->subdivisions[0]->isoCode;
|
||||
$latitude = round($city->location->latitude, 3);
|
||||
$longitude = round($city->location->longitude, 3);
|
||||
} catch (\GeoIp2\Exception\AddressNotFoundException $ex) {
|
||||
//Bad luck, bad IP, nothing to do.
|
||||
}
|
||||
|
||||
$hits = rand(0, $proba2);
|
||||
|
||||
$analytics_podcasts[] = [
|
||||
'podcast_id' => $podcast->id,
|
||||
'date' => date('Y-m-d', $date),
|
||||
'hits' => $hits,
|
||||
];
|
||||
$analytics_podcasts_by_country[] = [
|
||||
'podcast_id' => $podcast->id,
|
||||
'date' => date('Y-m-d', $date),
|
||||
'country_code' => $countryCode,
|
||||
'hits' => $hits,
|
||||
];
|
||||
$analytics_podcasts_by_episode[] = [
|
||||
'podcast_id' => $podcast->id,
|
||||
'date' => date('Y-m-d', $date),
|
||||
'episode_id' => $episode->id,
|
||||
'age' => $age,
|
||||
'hits' => $hits,
|
||||
];
|
||||
$analytics_podcasts_by_player[] = [
|
||||
'podcast_id' => $podcast->id,
|
||||
'date' => date('Y-m-d', $date),
|
||||
'app' => $app,
|
||||
'device' => $device,
|
||||
'os' => $os,
|
||||
'bot' => $bot,
|
||||
'hits' => $hits,
|
||||
];
|
||||
$analytics_podcasts_by_region[] = [
|
||||
'podcast_id' => $podcast->id,
|
||||
'date' => date('Y-m-d', $date),
|
||||
'country_code' => $countryCode,
|
||||
'region_code' => $regionCode,
|
||||
'latitude' => $latitude,
|
||||
'longitude' => $longitude,
|
||||
'hits' => $hits,
|
||||
];
|
||||
}
|
||||
}
|
||||
$this->db
|
||||
->table('analytics_podcasts')
|
||||
->ignore(true)
|
||||
->insertBatch($analytics_podcasts);
|
||||
$this->db
|
||||
->table('analytics_podcasts_by_country')
|
||||
->ignore(true)
|
||||
->insertBatch($analytics_podcasts_by_country);
|
||||
$this->db
|
||||
->table('analytics_podcasts_by_episode')
|
||||
->ignore(true)
|
||||
->insertBatch($analytics_podcasts_by_episode);
|
||||
$this->db
|
||||
->table('analytics_podcasts_by_player')
|
||||
->ignore(true)
|
||||
->insertBatch($analytics_podcasts_by_player);
|
||||
$this->db
|
||||
->table('analytics_podcasts_by_region')
|
||||
->ignore(true)
|
||||
->insertBatch($analytics_podcasts_by_region);
|
||||
}
|
||||
} else {
|
||||
echo "Create one podcast and some episodes first.\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
260
app/Database/Seeds/FakeWebsiteAnalyticsSeeder.php
Normal file
|
|
@ -0,0 +1,260 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Class FakeWebsiteAnalyticsSeeder
|
||||
* Inserts Fake Analytics in the database
|
||||
*
|
||||
* @copyright 2020 Podlibre
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
||||
* @link https://castopod.org/
|
||||
*/
|
||||
|
||||
namespace App\Database\Seeds;
|
||||
use App\Models\PodcastModel;
|
||||
use App\Models\EpisodeModel;
|
||||
|
||||
use CodeIgniter\Database\Seeder;
|
||||
|
||||
class FakeWebsiteAnalyticsSeeder extends Seeder
|
||||
{
|
||||
protected $keywords = [
|
||||
'all the smoke podcast',
|
||||
'apple podcast',
|
||||
'bad friends podcast',
|
||||
'best podcast',
|
||||
'best podcasts',
|
||||
'best podcasts 2020',
|
||||
'blood ties',
|
||||
'call her daddy',
|
||||
'call her daddy podcast',
|
||||
'call her daddy podcast controversy',
|
||||
'call her daddy podcast drama',
|
||||
'counter clock podcast',
|
||||
'counterclock podcast',
|
||||
'crime junkie podcast',
|
||||
'crime podcast',
|
||||
'down the hill podcast',
|
||||
'gerry callahan podcast',
|
||||
'google podcast',
|
||||
'history podcast',
|
||||
'joe rogan',
|
||||
'joe rogan podcast',
|
||||
'lana rhoades and logan paul podcast',
|
||||
'last podcast on the left',
|
||||
'michael moore podcast',
|
||||
'michelle obama podcast',
|
||||
'missing in alaska podcast',
|
||||
'murder podcast',
|
||||
'nice white parents podcast',
|
||||
'nick cannon podcast',
|
||||
'npr podcast',
|
||||
'office ladies podcast',
|
||||
'podcast app',
|
||||
'podcasts',
|
||||
'rogan podcast',
|
||||
'rudy giuliani podcast',
|
||||
'savage podcast',
|
||||
'serial podcast',
|
||||
'smartless podcast',
|
||||
'ted cruz podcast',
|
||||
'the daily',
|
||||
'the daily podcast',
|
||||
'the last podcast on the left',
|
||||
'the new abnormal podcast',
|
||||
'tiger king podcast',
|
||||
'trey gowdy podcast',
|
||||
'true crime podcast',
|
||||
'what is a podcast',
|
||||
'what is podcast',
|
||||
'wind of change podcast',
|
||||
'your own backyard podcast',
|
||||
];
|
||||
protected $domains = [
|
||||
'360.cn ',
|
||||
'adobe.com ',
|
||||
'aliexpress.com ',
|
||||
'alipay.com ',
|
||||
'amazon.co.jp ',
|
||||
'amazon.com ',
|
||||
'amazon.in ',
|
||||
'apple.com ',
|
||||
'baidu.com ',
|
||||
'bing.com ',
|
||||
'bongacams.com ',
|
||||
'chaturbate.com ',
|
||||
'china.com.cn ',
|
||||
'csdn.net ',
|
||||
'ebay.com ',
|
||||
'facebook.com ',
|
||||
'google.co.in ',
|
||||
'google.com ',
|
||||
'google.com.hk ',
|
||||
'instagram.com ',
|
||||
'jd.com ',
|
||||
'live.com ',
|
||||
'livejasmin.com ',
|
||||
'microsoft.com ',
|
||||
'microsoftonline.com ',
|
||||
'myshopify.com ',
|
||||
'naver.com ',
|
||||
'netflix.com ',
|
||||
'office.com ',
|
||||
'okezone.com ',
|
||||
'panda.tv ',
|
||||
'qq.com ',
|
||||
'reddit.com ',
|
||||
'sina.com.cn ',
|
||||
'sohu.com ',
|
||||
'taobao.com ',
|
||||
'tianya.cn ',
|
||||
'tmall.com ',
|
||||
'tribunnews.com ',
|
||||
'twitch.tv ',
|
||||
'twitter.com ',
|
||||
'vk.com ',
|
||||
'weibo.com ',
|
||||
'wikipedia.org ',
|
||||
'xinhuanet.com ',
|
||||
'yahoo.co.jp ',
|
||||
'yahoo.com ',
|
||||
'youtube.com ',
|
||||
'zhanqi.tv ',
|
||||
'zoom.us ',
|
||||
];
|
||||
|
||||
protected $browsers = [
|
||||
'Android Browser',
|
||||
'Avast Secure Browser',
|
||||
'BlackBerry Browser',
|
||||
'Chrome',
|
||||
'Chrome Mobile',
|
||||
'Chrome Mobile iOS',
|
||||
'Chrome Webview',
|
||||
'Chromium',
|
||||
'Ecosia',
|
||||
'Fennec',
|
||||
'Firebird',
|
||||
'Firefox',
|
||||
'Firefox Mobile',
|
||||
'Firefox Mobile iOS',
|
||||
'Galeon',
|
||||
'GNOME Web',
|
||||
'Headless Chrome',
|
||||
'Huawei Browser',
|
||||
'IE Mobile',
|
||||
'Inconnu',
|
||||
'Internet Explorer',
|
||||
'Kindle Browser',
|
||||
'Konqueror',
|
||||
'Maxthon',
|
||||
'Meizu Browser',
|
||||
'Microsoft Edge',
|
||||
'MIUI Browser',
|
||||
'Mobile Safari',
|
||||
'Mobile Silk',
|
||||
'OmniWeb',
|
||||
'Openwave Mobile Browser',
|
||||
'Opera',
|
||||
'Opera Mini',
|
||||
'Opera Mobile',
|
||||
'Opera Next',
|
||||
'Palm Blazer',
|
||||
'Puffin',
|
||||
'QupZilla',
|
||||
'Safari',
|
||||
'Samsung Browser',
|
||||
'UC Browser',
|
||||
'WOSBrowser',
|
||||
];
|
||||
|
||||
public function run()
|
||||
{
|
||||
$podcast = (new PodcastModel())->first();
|
||||
|
||||
if ($podcast) {
|
||||
$firstEpisode = (new EpisodeModel())
|
||||
->selectMin('published_at')
|
||||
->first();
|
||||
|
||||
for (
|
||||
$date = strtotime($firstEpisode->published_at);
|
||||
$date < strtotime('now');
|
||||
$date = strtotime(date('Y-m-d', $date) . ' +1 day')
|
||||
) {
|
||||
$website_by_browser = [];
|
||||
$website_by_entry_page = [];
|
||||
$website_by_referer = [];
|
||||
|
||||
$episodes = (new EpisodeModel())
|
||||
->where([
|
||||
'podcast_id' => $podcast->id,
|
||||
'DATE(published_at) <=' => date('Y-m-d', $date),
|
||||
])
|
||||
->findAll();
|
||||
foreach ($episodes as $episode) {
|
||||
$age = floor(
|
||||
($date - strtotime($episode->published_at)) / 86400
|
||||
);
|
||||
$proba1 = floor(exp(3 - $age / 40)) + 1;
|
||||
|
||||
for (
|
||||
$num_line = 0;
|
||||
$num_line < rand(1, $proba1);
|
||||
$num_line++
|
||||
) {
|
||||
$proba2 = floor(exp(6 - $age / 20)) + 10;
|
||||
|
||||
$domain =
|
||||
$this->domains[rand(0, count($this->domains) - 1)];
|
||||
$keyword =
|
||||
$this->keywords[
|
||||
rand(0, count($this->keywords) - 1)
|
||||
];
|
||||
$browser =
|
||||
$this->browsers[
|
||||
rand(0, count($this->browsers) - 1)
|
||||
];
|
||||
|
||||
$hits = rand(0, $proba2);
|
||||
|
||||
$website_by_browser[] = [
|
||||
'podcast_id' => $podcast->id,
|
||||
'date' => date('Y-m-d', $date),
|
||||
'browser' => $browser,
|
||||
'hits' => $hits,
|
||||
];
|
||||
$website_by_entry_page[] = [
|
||||
'podcast_id' => $podcast->id,
|
||||
'date' => date('Y-m-d', $date),
|
||||
'entry_page' => $episode->link,
|
||||
'hits' => $hits,
|
||||
];
|
||||
$website_by_referer[] = [
|
||||
'podcast_id' => $podcast->id,
|
||||
'date' => date('Y-m-d', $date),
|
||||
'referer' =>
|
||||
'http://' . $domain . '/?q=' . $keyword,
|
||||
'domain' => $domain,
|
||||
'keywords' => $keyword,
|
||||
'hits' => $hits,
|
||||
];
|
||||
}
|
||||
}
|
||||
$this->db
|
||||
->table('analytics_website_by_browser')
|
||||
->ignore(true)
|
||||
->insertBatch($website_by_browser);
|
||||
$this->db
|
||||
->table('analytics_website_by_entry_page')
|
||||
->ignore(true)
|
||||
->insertBatch($website_by_entry_page);
|
||||
$this->db
|
||||
->table('analytics_website_by_referer')
|
||||
->ignore(true)
|
||||
->insertBatch($website_by_referer);
|
||||
}
|
||||
} else {
|
||||
echo "Create one podcast and some episodes first.\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Class AnalyticsWebsiteByCountry
|
||||
* Entity for AnalyticsWebsiteByCountry
|
||||
* Class AnalyticsPodcasts
|
||||
* Entity for AnalyticsPodcasts
|
||||
* @copyright 2020 Podlibre
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
||||
* @link https://castopod.org/
|
||||
|
|
@ -12,11 +12,10 @@ namespace App\Entities;
|
|||
|
||||
use CodeIgniter\Entity;
|
||||
|
||||
class AnalyticsWebsiteByCountry extends Entity
|
||||
class AnalyticsPodcasts extends Entity
|
||||
{
|
||||
protected $casts = [
|
||||
'podcast_id' => 'integer',
|
||||
'country_code' => 'string',
|
||||
'date' => 'datetime',
|
||||
'hits' => 'integer',
|
||||
];
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Class AnalyticsEpisodesByPlayer
|
||||
* Entity for AnalyticsEpisodesByPlayer
|
||||
* Class AnalyticsPodcastsByEpisode
|
||||
* Entity for AnalyticsPodcastsByEpisode
|
||||
* @copyright 2020 Podlibre
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
||||
* @link https://castopod.org/
|
||||
|
|
@ -12,12 +12,11 @@ namespace App\Entities;
|
|||
|
||||
use CodeIgniter\Entity;
|
||||
|
||||
class AnalyticsEpisodesByPlayer extends Entity
|
||||
class AnalyticsPodcastsByEpisode extends Entity
|
||||
{
|
||||
protected $casts = [
|
||||
'podcast_id' => 'integer',
|
||||
'episode_id' => 'integer',
|
||||
'player' => 'string',
|
||||
'date' => 'datetime',
|
||||
'hits' => 'integer',
|
||||
];
|
||||
|
|
@ -16,7 +16,10 @@ class AnalyticsPodcastsByPlayer extends Entity
|
|||
{
|
||||
protected $casts = [
|
||||
'podcast_id' => 'integer',
|
||||
'player' => 'string',
|
||||
'app' => '?string',
|
||||
'device' => '?string',
|
||||
'os' => '?string',
|
||||
'bot' => 'boolean',
|
||||
'date' => 'datetime',
|
||||
'hits' => 'integer',
|
||||
];
|
||||
|
|
|
|||
26
app/Entities/AnalyticsPodcastsByRegion.php
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Class AnalyticsPodcastsByRegion
|
||||
* Entity for AnalyticsPodcastsByRegion
|
||||
* @copyright 2020 Podlibre
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
||||
* @link https://castopod.org/
|
||||
*/
|
||||
|
||||
namespace App\Entities;
|
||||
|
||||
use CodeIgniter\Entity;
|
||||
|
||||
class AnalyticsPodcastsByRegion extends Entity
|
||||
{
|
||||
protected $casts = [
|
||||
'podcast_id' => 'integer',
|
||||
'country_code' => 'string',
|
||||
'region_code' => '?string',
|
||||
'latitude' => '?float',
|
||||
'longitude' => '?float',
|
||||
'date' => 'datetime',
|
||||
'hits' => 'integer',
|
||||
];
|
||||
}
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Class AnalyticsEpisodesByCountry
|
||||
* Entity for AnalyticsEpisodesByCountry
|
||||
* Class AnalyticsWebsiteByEntryPage
|
||||
* Entity for AnalyticsWebsiteByEntryPage
|
||||
* @copyright 2020 Podlibre
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
||||
* @link https://castopod.org/
|
||||
|
|
@ -12,12 +12,11 @@ namespace App\Entities;
|
|||
|
||||
use CodeIgniter\Entity;
|
||||
|
||||
class AnalyticsEpisodesByCountry extends Entity
|
||||
class AnalyticsWebsiteByEntryPage extends Entity
|
||||
{
|
||||
protected $casts = [
|
||||
'podcast_id' => 'integer',
|
||||
'episode_id' => 'integer',
|
||||
'country_code' => 'string',
|
||||
'entry_page' => '?string',
|
||||
'date' => 'datetime',
|
||||
'hits' => 'integer',
|
||||
];
|
||||
|
|
@ -64,6 +64,7 @@ class Episode extends Entity
|
|||
'enclosure_duration' => 'integer',
|
||||
'enclosure_mimetype' => 'string',
|
||||
'enclosure_filesize' => 'integer',
|
||||
'enclosure_headersize' => 'integer',
|
||||
'description' => 'string',
|
||||
'image_uri' => '?string',
|
||||
'parental_advisory' => '?string',
|
||||
|
|
@ -143,6 +144,8 @@ class Episode extends Entity
|
|||
$enclosure_metadata['mime_type'];
|
||||
$this->attributes['enclosure_filesize'] =
|
||||
$enclosure_metadata['filesize'];
|
||||
$this->attributes['enclosure_headersize'] =
|
||||
$enclosure_metadata['avdataoffset'];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
|
@ -167,6 +170,19 @@ class Episode extends Entity
|
|||
'analytics_hit',
|
||||
$this->attributes['podcast_id'],
|
||||
$this->attributes['id'],
|
||||
// bytes_threshold: number of bytes that must be downloaded for an episode to be counted in download analytics
|
||||
// - if file is shorter than 60sec, then it's enclosure_filesize
|
||||
// - if file is longer than 60 seconds then it's enclosure_headersize + 60 seconds
|
||||
$this->attributes['enclosure_duration'] <= 60
|
||||
? $this->attributes['enclosure_filesize']
|
||||
: $this->attributes['enclosure_headersize'] +
|
||||
floor(
|
||||
(($this->attributes['enclosure_filesize'] -
|
||||
$this->attributes['enclosure_headersize']) /
|
||||
$this->attributes['enclosure_duration']) *
|
||||
60
|
||||
),
|
||||
$this->attributes['enclosure_filesize'],
|
||||
$this->attributes['enclosure_uri']
|
||||
)
|
||||
);
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ class Podcast extends Entity
|
|||
'created_by' => 'integer',
|
||||
'updated_by' => 'integer',
|
||||
'imported_feed_url' => '?string',
|
||||
'new_feed_url' => '?string',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -33,25 +33,56 @@ if (!function_exists('getallheaders')) {
|
|||
/**
|
||||
* Set user country in session variable, for analytics purpose
|
||||
*/
|
||||
function set_user_session_country()
|
||||
function set_user_session_deny_list_ip()
|
||||
{
|
||||
$session = \Config\Services::session();
|
||||
$session->start();
|
||||
|
||||
$country = 'N/A';
|
||||
if (!$session->has('denyListIp')) {
|
||||
$session->set(
|
||||
'denyListIp',
|
||||
\Podlibre\Ipcat\IpDb::find($_SERVER['REMOTE_ADDR']) != null
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Finds country:
|
||||
if (!$session->has('country')) {
|
||||
/**
|
||||
* Set user country in session variable, for analytics purpose
|
||||
*/
|
||||
function set_user_session_location()
|
||||
{
|
||||
$session = \Config\Services::session();
|
||||
$session->start();
|
||||
|
||||
$location = [
|
||||
'countryCode' => 'N/A',
|
||||
'regionCode' => 'N/A',
|
||||
'latitude' => null,
|
||||
'longitude' => null,
|
||||
];
|
||||
|
||||
// Finds location:
|
||||
if (!$session->has('location')) {
|
||||
try {
|
||||
$reader = new \GeoIp2\Database\Reader(
|
||||
WRITEPATH . 'uploads/GeoLite2-Country/GeoLite2-Country.mmdb'
|
||||
$cityReader = new \GeoIp2\Database\Reader(
|
||||
WRITEPATH . 'uploads/GeoLite2-City/GeoLite2-City.mmdb'
|
||||
);
|
||||
$geoip = $reader->country($_SERVER['REMOTE_ADDR']);
|
||||
$country = $geoip->country->isoCode;
|
||||
$city = $cityReader->city($_SERVER['REMOTE_ADDR']);
|
||||
|
||||
$location = [
|
||||
'countryCode' => empty($city->country->isoCode)
|
||||
? 'N/A'
|
||||
: $city->country->isoCode,
|
||||
'regionCode' => empty($city->subdivisions[0]->isoCode)
|
||||
? 'N/A'
|
||||
: $city->subdivisions[0]->isoCode,
|
||||
'latitude' => round($city->location->latitude, 3),
|
||||
'longitude' => round($city->location->longitude, 3),
|
||||
];
|
||||
} catch (\Exception $e) {
|
||||
// If things go wrong the show must go on and the user must be able to download the file
|
||||
}
|
||||
$session->set('country', $country);
|
||||
$session->set('location', $location);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -67,58 +98,36 @@ function set_user_session_player()
|
|||
$session = \Config\Services::session();
|
||||
$session->start();
|
||||
|
||||
$playerName = '- Unknown Player -';
|
||||
|
||||
$useragent = $_SERVER['HTTP_USER_AGENT'];
|
||||
$playerFound = null;
|
||||
$userAgent = $_SERVER['HTTP_USER_AGENT'];
|
||||
|
||||
try {
|
||||
$jsonUserAgents = json_decode(
|
||||
file_get_contents(
|
||||
WRITEPATH . 'uploads/user-agents/src/user-agents.json'
|
||||
),
|
||||
true
|
||||
);
|
||||
|
||||
//Search for current HTTP_USER_AGENT in json file:
|
||||
foreach ($jsonUserAgents as $player) {
|
||||
foreach ($player['user_agents'] as $useragentsRegexp) {
|
||||
//Does the HTTP_USER_AGENT match this regexp:
|
||||
if (preg_match("#{$useragentsRegexp}#", $useragent)) {
|
||||
if (isset($player['bot'])) {
|
||||
//It’s a bot!
|
||||
$playerName = '- Bot -';
|
||||
} else {
|
||||
//It isn’t a bot, we store device/os/app:
|
||||
$playerName =
|
||||
(isset($player['device'])
|
||||
? $player['device'] . '/'
|
||||
: '') .
|
||||
(isset($player['os'])
|
||||
? $player['os'] . '/'
|
||||
: '') .
|
||||
(isset($player['app']) ? $player['app'] : '?');
|
||||
}
|
||||
//We found it!
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
$playerFound = \Podlibre\UserAgentsPhp\UserAgents::find($userAgent);
|
||||
} catch (\Exception $e) {
|
||||
// If things go wrong the show must go on and the user must be able to download the file
|
||||
}
|
||||
if ($playerName == '- Unknown Player -') {
|
||||
if ($playerFound) {
|
||||
$session->set('player', $playerFound);
|
||||
} else {
|
||||
$session->set('player', [
|
||||
'app' => '- unknown -',
|
||||
'device' => '',
|
||||
'os' => '',
|
||||
'bot' => 0,
|
||||
]);
|
||||
// Add to unknown list
|
||||
try {
|
||||
$db = \Config\Database::connect();
|
||||
$procedureNameAUU = $db->prefixTable(
|
||||
$procedureNameAnalyticsUnknownUseragents = $db->prefixTable(
|
||||
'analytics_unknown_useragents'
|
||||
);
|
||||
$db->query("CALL $procedureNameAUU(?)", [$useragent]);
|
||||
$db->query("CALL $procedureNameAnalyticsUnknownUseragents(?)", [
|
||||
$userAgent,
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
// If things go wrong the show must go on and the user must be able to download the file
|
||||
}
|
||||
}
|
||||
$session->set('player', $playerName);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -165,49 +174,149 @@ function set_user_session_referer()
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set user entry page in session variable, for analytics purpose
|
||||
*/
|
||||
function set_user_session_entry_page()
|
||||
{
|
||||
$session = \Config\Services::session();
|
||||
$session->start();
|
||||
|
||||
$entryPage = $_SERVER['REQUEST_URI'];
|
||||
if (!$session->has('entryPage')) {
|
||||
$session->set('entryPage', $entryPage);
|
||||
}
|
||||
}
|
||||
|
||||
function webpage_hit($podcast_id)
|
||||
{
|
||||
$session = \Config\Services::session();
|
||||
$session->start();
|
||||
$db = \Config\Database::connect();
|
||||
|
||||
$procedureName = $db->prefixTable('analytics_website');
|
||||
$db->query("call $procedureName(?,?,?,?)", [
|
||||
$podcast_id,
|
||||
$session->get('country'),
|
||||
$session->get('browser'),
|
||||
$session->get('referer'),
|
||||
]);
|
||||
if (!$session->get('denyListIp')) {
|
||||
$db = \Config\Database::connect();
|
||||
|
||||
$referer = $session->get('referer');
|
||||
$domain = empty(parse_url($referer, PHP_URL_HOST))
|
||||
? null
|
||||
: parse_url($referer, PHP_URL_HOST);
|
||||
parse_str(parse_url($referer, PHP_URL_QUERY), $queries);
|
||||
$keywords = empty($queries['q']) ? null : $queries['q'];
|
||||
|
||||
$procedureName = $db->prefixTable('analytics_website');
|
||||
$db->query("call $procedureName(?,?,?,?,?,?)", [
|
||||
$podcast_id,
|
||||
$session->get('browser'),
|
||||
$session->get('entryPage'),
|
||||
$referer,
|
||||
$domain,
|
||||
$keywords,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
function podcast_hit($p_podcast_id, $p_episode_id)
|
||||
/**
|
||||
* Counting podcast episode downloads for analytics purposes
|
||||
* ✅ No IP address is ever stored on the server.
|
||||
* ✅ Only aggregate data is stored in the database.
|
||||
* We follow IAB Podcast Measurement Technical Guidelines Version 2.0:
|
||||
* https://iabtechlab.com/standards/podcast-measurement-guidelines/
|
||||
* https://iabtechlab.com/wp-content/uploads/2017/12/Podcast_Measurement_v2-Dec-20-2017.pdf
|
||||
* ✅ Rolling 24-hour window
|
||||
* ✅ Castopod does not do pre-load
|
||||
* ✅ IP deny list https://github.com/client9/ipcat
|
||||
* ✅ User-agent Filtering https://github.com/opawg/user-agents
|
||||
* ✅ Ignores 2 bytes range "Range: 0-1" (performed by official Apple iOS Podcast app)
|
||||
* ✅ In case of partial content, adds up all requests to check >1mn was downloaded
|
||||
* ✅ Identifying Uniques is done with a combination of IP Address and User Agent
|
||||
* @param int $podcastId The podcast ID
|
||||
* @param int $episodeId The Episode ID
|
||||
* @param int $bytesThreshold The minimum total number of bytes that must be downloaded so that an episode is counted (>1mn)
|
||||
* @param int $fileSize The podcast complete file size
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function podcast_hit($podcastId, $episodeId, $bytesThreshold, $fileSize)
|
||||
{
|
||||
$session = \Config\Services::session();
|
||||
$session->start();
|
||||
$first_time_for_this_episode = true;
|
||||
|
||||
if ($session->has('episodes')) {
|
||||
if (in_array($p_episode_id, $session->get('episodes'))) {
|
||||
$first_time_for_this_episode = false;
|
||||
// We try to count (but if things went wrong the show should go on and the user should be able to download the file):
|
||||
try {
|
||||
// If the user IP is denied it's probably a bot:
|
||||
if ($session->get('denyListIp')) {
|
||||
$session->get('player')['bot'] = true;
|
||||
}
|
||||
$httpRange = $_SERVER['HTTP_RANGE'];
|
||||
// We create a sha1 hash for this IP_Address+User_Agent+Episode_ID:
|
||||
$hashID =
|
||||
'_IpUaEp_' .
|
||||
sha1(
|
||||
$_SERVER['REMOTE_ADDR'] .
|
||||
'_' .
|
||||
$_SERVER['HTTP_USER_AGENT'] .
|
||||
'_' .
|
||||
$episodeId
|
||||
);
|
||||
// Was this episode downloaded in the past 24h:
|
||||
$downloadedBytes = cache($hashID);
|
||||
// Rolling window is 24 hours (86400 seconds):
|
||||
$ttl = 86400;
|
||||
if ($downloadedBytes) {
|
||||
// In case it was already downloaded, TTL should be adjusted (rolling window is 24h since 1st download):
|
||||
$ttl = cache()->getMetadata($hashID)['expire'] - time();
|
||||
} else {
|
||||
$session->push('episodes', [$p_episode_id]);
|
||||
// If it was never downloaded that means that zero byte were downloaded:
|
||||
$downloadedBytes = 0;
|
||||
}
|
||||
} else {
|
||||
$session->set('episodes', [$p_episode_id]);
|
||||
}
|
||||
// If the number of downloaded bytes was previously below the 1mn threshold we go on:
|
||||
// (Otherwise it means that this was already counted, therefore we don't do anything)
|
||||
if ($downloadedBytes < $bytesThreshold) {
|
||||
// If HTTP_RANGE is null we are downloading the complete file:
|
||||
if (!isset($httpRange)) {
|
||||
$downloadedBytes = $fileSize;
|
||||
} else {
|
||||
// [0-1] bytes range requests are used (by Apple) to check that file exists and that 206 partial content is working.
|
||||
// We don't count these requests:
|
||||
if ($httpRange != 'bytes=0-1') {
|
||||
// We calculate how many bytes are being downloaded based on HTTP_RANGE values:
|
||||
$ranges = explode(',', substr($httpRange, 6));
|
||||
foreach ($ranges as $range) {
|
||||
$parts = explode('-', $range);
|
||||
$downloadedBytes += empty($parts[1])
|
||||
? $fileSize
|
||||
: $parts[1] - (empty($parts[0]) ? 0 : $parts[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
// We save the number of downloaded bytes for this user and this episode:
|
||||
cache()->save($hashID, $downloadedBytes, $ttl);
|
||||
|
||||
if ($first_time_for_this_episode) {
|
||||
$db = \Config\Database::connect();
|
||||
$procedureName = $db->prefixTable('analytics_podcasts');
|
||||
try {
|
||||
$db->query("CALL $procedureName(?,?,?,?);", [
|
||||
$p_podcast_id,
|
||||
$p_episode_id,
|
||||
$session->get('country'),
|
||||
$session->get('player'),
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
// If things go wrong the show must go on and the user must be able to download the file
|
||||
// If more that 1mn was downloaded, we send that to the database:
|
||||
if ($downloadedBytes >= $bytesThreshold) {
|
||||
$db = \Config\Database::connect();
|
||||
$procedureName = $db->prefixTable('analytics_podcasts');
|
||||
|
||||
$app = $session->get('player')['app'];
|
||||
$device = $session->get('player')['device'];
|
||||
$os = $session->get('player')['os'];
|
||||
$bot = $session->get('player')['bot'];
|
||||
|
||||
$db->query("CALL $procedureName(?,?,?,?,?,?,?,?,?,?);", [
|
||||
$podcastId,
|
||||
$episodeId,
|
||||
$session->get('location')['countryCode'],
|
||||
$session->get('location')['regionCode'],
|
||||
$session->get('location')['latitude'],
|
||||
$session->get('location')['longitude'],
|
||||
$app == null ? '' : $app,
|
||||
$device == null ? '' : $device,
|
||||
$os == null ? '' : $os,
|
||||
$bot == null ? 0 : $bot,
|
||||
]);
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// If things go wrong the show must go on and the user must be able to download the file
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ function get_file_tags($file)
|
|||
return [
|
||||
'filesize' => $FileInfo['filesize'],
|
||||
'mime_type' => $FileInfo['mime_type'],
|
||||
'avdataoffset' => $FileInfo['avdataoffset'],
|
||||
'playtime_seconds' => $FileInfo['playtime_seconds'],
|
||||
];
|
||||
}
|
||||
|
|
@ -68,7 +69,11 @@ function write_enclosure_tags($episode)
|
|||
'comment' => [$episode->description],
|
||||
'track_number' => [strval($episode->number)],
|
||||
'copyright_message' => [$episode->podcast->copyright],
|
||||
'publisher' => ['Podlibre'],
|
||||
'publisher' => [
|
||||
empty($episode->podcast->publisher)
|
||||
? $episode->podcast->owner_name
|
||||
: $episode->podcast->publisher,
|
||||
],
|
||||
'encoded_by' => ['Castopod'],
|
||||
|
||||
// TODO: find a way to add the remaining tags for podcasts as the library doesn't seem to allow it
|
||||
|
|
|
|||
|
|
@ -36,6 +36,14 @@ function get_rss_feed($podcast)
|
|||
$atom_link->addAttribute('rel', 'self');
|
||||
$atom_link->addAttribute('type', 'application/rss+xml');
|
||||
|
||||
if (!empty($podcast->new_feed_url)) {
|
||||
$channel->addChild(
|
||||
'new-feed-url',
|
||||
$podcast->new_feed_url,
|
||||
$itunes_namespace
|
||||
);
|
||||
}
|
||||
|
||||
// the last build date corresponds to the creation of the feed.xml cache
|
||||
$channel->addChild(
|
||||
'lastBuildDate',
|
||||
|
|
@ -50,7 +58,7 @@ function get_rss_feed($podcast)
|
|||
$channel->addChild('title', $podcast->title);
|
||||
$channel->addChildWithCDATA('description', $podcast->description_html);
|
||||
$itunes_image = $channel->addChild('image', null, $itunes_namespace);
|
||||
$itunes_image->addAttribute('href', $podcast->image->url);
|
||||
$itunes_image->addAttribute('href', $podcast->image->original_url);
|
||||
$channel->addChild('language', $podcast->language);
|
||||
|
||||
// set main category first, then other categories as apple
|
||||
|
|
|
|||
|
|
@ -22,4 +22,5 @@ return [
|
|||
'import' => 'feed import',
|
||||
'settings' => 'settings',
|
||||
'platforms' => 'platforms',
|
||||
'analytics' => 'Analytics',
|
||||
];
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ return [
|
|||
'create' => 'Create a podcast',
|
||||
'import' => 'Import a podcast',
|
||||
'new_episode' => 'New Episode',
|
||||
'feed' => 'RSS feed',
|
||||
'feed' => 'RSS',
|
||||
'view' => 'View podcast',
|
||||
'edit' => 'Edit podcast',
|
||||
'delete' => 'Delete podcast',
|
||||
|
|
|
|||
|
|
@ -7,6 +7,12 @@
|
|||
*/
|
||||
|
||||
return [
|
||||
'legal_dislaimer_title' => 'Legal Disclaimer',
|
||||
'legal_dislaimer_content' =>
|
||||
'Make sure you own the rights for this podcast before importing it.<br/>Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.',
|
||||
'warning_title' => 'Warning',
|
||||
'warning_content' =>
|
||||
'This procedure may take a long time.<br/>The current version does not show any progress while it runs. You will not see anything updated until it is done.<br/>In case of timeout error, increase max_execution_time value.',
|
||||
'old_podcast_section_title' => 'The podcast to import',
|
||||
'old_podcast_section_subtitle' => '',
|
||||
'imported_feed_url' => 'Feed URL',
|
||||
|
|
|
|||
|
|
@ -20,4 +20,5 @@ return [
|
|||
'contributor-add' => 'Add contributor',
|
||||
'settings' => 'Settings',
|
||||
'platforms' => 'Podcast platforms',
|
||||
'podcast-analytics' => 'Audiences Overview',
|
||||
];
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
/**
|
||||
* Class AnalyticsPodcastsByCountryModel
|
||||
* Model for analytics_episodes_by_country table in database
|
||||
* Model for analytics_podcasts_by_country table in database
|
||||
* @copyright 2020 Podlibre
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
||||
* @link https://castopod.org/
|
||||
|
|
@ -14,8 +14,7 @@ use CodeIgniter\Model;
|
|||
|
||||
class AnalyticsPodcastsByCountryModel extends Model
|
||||
{
|
||||
protected $table = 'analytics_episodes_by_country';
|
||||
protected $primaryKey = 'id';
|
||||
protected $table = 'analytics_podcasts_by_country';
|
||||
|
||||
protected $allowedFields = [];
|
||||
|
||||
|
|
|
|||
113
app/Models/AnalyticsPodcastsByEpisodeModel.php
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Class AnalyticsPodcastsByEpisodeModel
|
||||
* Model for analytics_podcasts_by_episodes table in database
|
||||
* @copyright 2020 Podlibre
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
||||
* @link https://castopod.org/
|
||||
*/
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use CodeIgniter\Model;
|
||||
|
||||
class AnalyticsPodcastsByEpisodeModel extends Model
|
||||
{
|
||||
protected $table = 'analytics_podcasts_by_episode';
|
||||
|
||||
protected $allowedFields = [];
|
||||
|
||||
protected $returnType = \App\Entities\AnalyticsPodcastsByEpisode::class;
|
||||
protected $useSoftDeletes = false;
|
||||
|
||||
protected $useTimestamps = false;
|
||||
|
||||
/**
|
||||
* @param int $podcastId, $episodeId
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getDataByDay(int $podcastId, int $episodeId = null): array
|
||||
{
|
||||
if (!$episodeId) {
|
||||
if (
|
||||
!($found = cache(
|
||||
"{$podcastId}_analytics_podcast_by_episode_by_day"
|
||||
))
|
||||
) {
|
||||
$lastEpisodes = (new EpisodeModel())
|
||||
->select('id, season_number, number, title')
|
||||
->orderBy('id', 'DESC')
|
||||
->where(['podcast_id' => $podcastId])
|
||||
->findAll(5);
|
||||
|
||||
$found = $this->select('age AS X');
|
||||
|
||||
$letter = 97;
|
||||
foreach ($lastEpisodes as $episode) {
|
||||
$found = $found
|
||||
->selectSum(
|
||||
'(CASE WHEN `episode_id`=' .
|
||||
$episode->id .
|
||||
' THEN `hits` END)',
|
||||
chr($letter) . 'Y'
|
||||
)
|
||||
->select(
|
||||
'"' .
|
||||
(empty($episode->season_number)
|
||||
? ''
|
||||
: $episode->season_number) .
|
||||
(empty($episode->number)
|
||||
? ''
|
||||
: '-' . $episode->number . '/ ') .
|
||||
$episode->title .
|
||||
'" AS ' .
|
||||
chr($letter) .
|
||||
'Value'
|
||||
);
|
||||
$letter++;
|
||||
}
|
||||
|
||||
$found = $found
|
||||
->where([
|
||||
'podcast_id' => $podcastId,
|
||||
'age <' => 60,
|
||||
])
|
||||
->groupBy('X')
|
||||
->orderBy('X', 'ASC')
|
||||
->findAll();
|
||||
|
||||
cache()->save(
|
||||
"{$podcastId}_analytics_podcast_by_episode_by_day",
|
||||
$found,
|
||||
14400
|
||||
);
|
||||
}
|
||||
return $found;
|
||||
} else {
|
||||
if (
|
||||
!($found = cache(
|
||||
"{$podcastId}_{$episodeId}_analytics_podcast_by_episode_by_day"
|
||||
))
|
||||
) {
|
||||
$found = $this->select('date as labels')
|
||||
->selectSum('hits', 'values')
|
||||
->where([
|
||||
'episode_id' => $episodeId,
|
||||
'podcast_id' => $podcastId,
|
||||
])
|
||||
->groupBy('labels')
|
||||
->orderBy('labels', 'ASC')
|
||||
->findAll();
|
||||
|
||||
cache()->save(
|
||||
"{$podcastId}_{$episodeId}_analytics_podcast_by_episode_by_day",
|
||||
$found,
|
||||
14400
|
||||
);
|
||||
}
|
||||
return $found;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -15,7 +15,6 @@ use CodeIgniter\Model;
|
|||
class AnalyticsPodcastsByPlayerModel extends Model
|
||||
{
|
||||
protected $table = 'analytics_podcasts_by_player';
|
||||
protected $primaryKey = 'id';
|
||||
|
||||
protected $allowedFields = [];
|
||||
|
||||
|
|
@ -23,4 +22,120 @@ class AnalyticsPodcastsByPlayerModel extends Model
|
|||
protected $useSoftDeletes = false;
|
||||
|
||||
protected $useTimestamps = false;
|
||||
|
||||
/**
|
||||
* Gets all data for a podcast
|
||||
*
|
||||
* @param int $podcastId
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getDataByApp(int $podcastId): array
|
||||
{
|
||||
if (
|
||||
!($found = cache(
|
||||
"{$podcastId}_analytics_podcasts_by_player_by_app"
|
||||
))
|
||||
) {
|
||||
$found = $this->select('`app` as `labels`')
|
||||
->selectSum('`hits`', '`values`')
|
||||
->where([
|
||||
'`podcast_id`' => $podcastId,
|
||||
'`app` !=' => null,
|
||||
'`bot`' => 0,
|
||||
'`date` >' => date('Y-m-d', strtotime('-1 week')),
|
||||
])
|
||||
->groupBy('`labels`')
|
||||
->orderBy('`values``', 'DESC')
|
||||
->findAll(10);
|
||||
|
||||
cache()->save(
|
||||
"{$podcastId}_analytics_podcasts_by_player_by_app",
|
||||
$found,
|
||||
14400
|
||||
);
|
||||
}
|
||||
|
||||
return $found;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all data for a podcast
|
||||
*
|
||||
* @param int $podcastId
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getDataByDevice(int $podcastId): array
|
||||
{
|
||||
if (
|
||||
!($found = cache(
|
||||
"{$podcastId}_analytics_podcasts_by_player_by_device"
|
||||
))
|
||||
) {
|
||||
$foundApp = $this->select(
|
||||
'CONCAT_WS("/", `device`, `os`, `app`) as `ids`, `app` as `labels`, CONCAT_WS("/", `device`, `os`) as `parents`'
|
||||
)
|
||||
->selectSum('`hits`', '`values`')
|
||||
->where([
|
||||
'`podcast_id`' => $podcastId,
|
||||
'`app` !=' => null,
|
||||
'`bot`' => 0,
|
||||
'`date` >' => date('Y-m-d', strtotime('-1 week')),
|
||||
])
|
||||
->groupBy('`ids`')
|
||||
->orderBy('`values``', 'DESC')
|
||||
->findAll();
|
||||
|
||||
$foundOs = $this->select(
|
||||
'CONCAT_WS("/", `device`, `os`) as `ids`, `os` as `labels`, `device` as `parents`'
|
||||
)
|
||||
->selectSum('`hits`', '`values`')
|
||||
->where([
|
||||
'`podcast_id`' => $podcastId,
|
||||
'`os` !=' => null,
|
||||
'`bot`' => 0,
|
||||
'`date` >' => date('Y-m-d', strtotime('-1 week')),
|
||||
])
|
||||
->groupBy('`ids`')
|
||||
->orderBy('`values``', 'DESC')
|
||||
->findAll();
|
||||
|
||||
$foundDevice = $this->select(
|
||||
'`device` as `ids`, `device` as `labels`, "" as `parents`'
|
||||
)
|
||||
->selectSum('`hits`', '`values`')
|
||||
->where([
|
||||
'`podcast_id`' => $podcastId,
|
||||
'`device` !=' => null,
|
||||
'`bot`' => 0,
|
||||
'`date` >' => date('Y-m-d', strtotime('-1 week')),
|
||||
])
|
||||
->groupBy('`ids`')
|
||||
->orderBy('`values``', 'DESC')
|
||||
->findAll();
|
||||
|
||||
$foundBot = $this->select(
|
||||
'"bots" as `ids`, "Bots" as `labels`, "" as `parents`'
|
||||
)
|
||||
->selectSum('`hits`', '`values`')
|
||||
->where([
|
||||
'`podcast_id`' => $podcastId,
|
||||
'`bot`' => 1,
|
||||
'`date` >' => date('Y-m-d', strtotime('-1 week')),
|
||||
])
|
||||
->groupBy('`ids`')
|
||||
->orderBy('`values``', 'DESC')
|
||||
->findAll();
|
||||
|
||||
$found = array_merge($foundApp, $foundOs, $foundDevice, $foundBot);
|
||||
cache()->save(
|
||||
"{$podcastId}_analytics_podcasts_by_player_by_device",
|
||||
$found,
|
||||
14400
|
||||
);
|
||||
}
|
||||
|
||||
return $found;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
25
app/Models/AnalyticsPodcastsByRegionModel.php
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Class AnalyticsPodcastsByRegionModel
|
||||
* Model for analytics_podcasts_by_region table in database
|
||||
* @copyright 2020 Podlibre
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
||||
* @link https://castopod.org/
|
||||
*/
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use CodeIgniter\Model;
|
||||
|
||||
class AnalyticsPodcastsByRegionModel extends Model
|
||||
{
|
||||
protected $table = 'analytics_podcasts_by_region';
|
||||
|
||||
protected $allowedFields = [];
|
||||
|
||||
protected $returnType = \App\Entities\AnalyticsPodcastsByRegion::class;
|
||||
protected $useSoftDeletes = false;
|
||||
|
||||
protected $useTimestamps = false;
|
||||
}
|
||||
55
app/Models/AnalyticsPodcastsModel.php
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Class AnalyticsPodcastsModel
|
||||
* Model for analytics_podcasts table in database
|
||||
* @copyright 2020 Podlibre
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
||||
* @link https://castopod.org/
|
||||
*/
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use CodeIgniter\Model;
|
||||
|
||||
class AnalyticsPodcastsModel extends Model
|
||||
{
|
||||
protected $table = 'analytics_podcasts';
|
||||
|
||||
protected $allowedFields = [];
|
||||
|
||||
protected $returnType = \App\Entities\AnalyticsPodcasts::class;
|
||||
protected $useSoftDeletes = false;
|
||||
|
||||
protected $useTimestamps = false;
|
||||
|
||||
/**
|
||||
* Gets all data for a podcast
|
||||
*
|
||||
* @param int $podcastId
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getDataByDay(int $podcastId): array
|
||||
{
|
||||
if (!($found = cache("{$podcastId}_analytics_podcast_by_day"))) {
|
||||
$found = $this->select('`date` as `labels`')
|
||||
->selectSum('`hits`', '`values`')
|
||||
->where([
|
||||
'`podcast_id`' => $podcastId,
|
||||
'`date` >' => date('Y-m-d', strtotime('-1 year')),
|
||||
])
|
||||
->groupBy('`labels`')
|
||||
->orderBy('`labels``', 'ASC')
|
||||
->findAll();
|
||||
|
||||
cache()->save(
|
||||
"{$podcastId}_analytics_podcast_by_day",
|
||||
$found,
|
||||
14400
|
||||
);
|
||||
}
|
||||
|
||||
return $found;
|
||||
}
|
||||
}
|
||||
|
|
@ -15,7 +15,6 @@ use CodeIgniter\Model;
|
|||
class AnalyticsWebsiteByBrowserModel extends Model
|
||||
{
|
||||
protected $table = 'analytics_website_by_browser';
|
||||
protected $primaryKey = 'id';
|
||||
|
||||
protected $allowedFields = [];
|
||||
|
||||
|
|
|
|||
25
app/Models/AnalyticsWebsiteByEntryPageModel.php
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Class AnalyticsWebsiteByEntryPageModel
|
||||
* Model for analytics_website_by_entry_page table in database
|
||||
* @copyright 2020 Podlibre
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
||||
* @link https://castopod.org/
|
||||
*/
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use CodeIgniter\Model;
|
||||
|
||||
class AnalyticsWebsiteByEntryPageModel extends Model
|
||||
{
|
||||
protected $table = 'analytics_website_by_entry_page';
|
||||
|
||||
protected $allowedFields = [];
|
||||
|
||||
protected $returnType = \App\Entities\AnalyticsWebsiteByEntryPage::class;
|
||||
protected $useSoftDeletes = false;
|
||||
|
||||
protected $useTimestamps = false;
|
||||
}
|
||||
|
|
@ -15,7 +15,6 @@ use CodeIgniter\Model;
|
|||
class AnalyticsWebsiteByRefererModel extends Model
|
||||
{
|
||||
protected $table = 'analytics_website_by_referer';
|
||||
protected $primaryKey = 'id';
|
||||
|
||||
protected $allowedFields = [];
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ class EpisodeModel extends Model
|
|||
'enclosure_duration',
|
||||
'enclosure_mimetype',
|
||||
'enclosure_filesize',
|
||||
'enclosure_headersize',
|
||||
'description',
|
||||
'image_uri',
|
||||
'parental_advisory',
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ class PodcastModel extends Model
|
|||
'created_by',
|
||||
'updated_by',
|
||||
'imported_feed_url',
|
||||
'new_feed_url',
|
||||
];
|
||||
|
||||
protected $returnType = \App\Entities\Podcast::class;
|
||||
|
|
|
|||
4
app/Views/_assets/charts.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
import "core-js";
|
||||
import DrawCharts from "./modules/Charts";
|
||||
|
||||
DrawCharts();
|
||||
26
app/Views/_assets/images/logo-castopod-circle.svg
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="64" height="64" version="1.1" viewBox="0 0 64 64" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><metadata><rdf:RDF><cc:Work rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/><dc:title/></cc:Work></rdf:RDF></metadata>
|
||||
<style type="text/css">
|
||||
.st0{fill:#009486;}
|
||||
.st1{fill:#E7F9E4;}
|
||||
.st2{fill:none;}
|
||||
.st3{fill:#E7FFE3;}
|
||||
</style>
|
||||
<circle cx="32" cy="32" r="32" fill="#e7f9e4" stroke-width="2.0334"/><g transform="matrix(.24971 0 0 .24971 6.7291 14.595)">
|
||||
<path id="dark_greeen_19_" class="st0" d="m181.9 131.7h-32.5s-1.2-2.5-2.5-4.9-4.4-2.3-4.4-2.3h-82.8s-3-0.4-4.5 2.3c-1.6 2.7-2.6 4.9-2.6 4.9h-32c-6.9 0-12.6-5.6-12.6-12.5v-98.9c0-6.9 5.6-12.6 12.5-12.6h161.3c6.9 0 12.6 5.6 12.6 12.5v98.9c0.1 6.9-5.6 12.6-12.5 12.6z"/>
|
||||
<path class="st1" d="m143.7 34.5h-85.1c-14.6 0-26.5 12-26.5 26.6s11.9 26.5 26.5 26.5h85.1c14.6 0 26.5-11.9 26.5-26.5 0.1-14.8-11.8-26.7-26.5-26.6zm-75.4 34.2s-3.9-2.9-9.4-2.9c-4.1 0-8.9 2.5-8.9 2.5-1.3-1.9-2.1-4.1-2.1-6.6 0-6.3 5.1-11.4 11.4-11.4s11.4 5.1 11.4 11.4c0 2.7-0.9 5.1-2.4 7zm32.9 6.6c-12.5 0-12-9.6-12-9.6-0.2-1.8 2.1-2.4 2.9-1.3 0.4 0.6 0.4 0.6 0.7 1.7 1.7 5.9 8.4 5.6 8.4 5.6s6.7 0.4 8.4-5.6c0.3-1 0.3-1.1 0.7-1.7 0.8-1 3.1-0.5 2.9 1.3 0 0 0.5 9.6-12 9.6zm51.1-6.9s-4.8-2.5-8.9-2.5c-5.5 0-9.4 2.9-9.4 2.9-1.5-1.9-2.4-4.3-2.4-7 0-6.3 5.1-11.4 11.4-11.4s11.4 5.1 11.4 11.4c0.1 2.4-0.7 4.7-2.1 6.6z"/>
|
||||
<path class="st2" d="m110.3 64.3c-0.4 0.6-0.4 0.6-0.7 1.7-1.7 5.9-8.4 5.6-8.4 5.6s-6.7 0.4-8.4-5.6c-0.3-1-0.3-1.1-0.7-1.7-0.8-1-3.1-0.5-2.9 1.3 0 0-0.5 9.6 12 9.6s12-9.6 12-9.6c0.2-1.7-2.1-2.3-2.9-1.3z"/>
|
||||
<path class="st2" d="m143.1 50.4c-6.3 0-11.4 5.1-11.4 11.4 0 2.6 0.9 5 2.4 7 0 0 3.9-2.9 9.4-2.9 4.1 0 8.9 2.5 8.9 2.5 1.3-1.9 2.1-4.1 2.1-6.6 0-6.3-5.1-11.4-11.4-11.4z"/>
|
||||
<path class="st2" d="m59.3 50.4c-6.3 0-11.4 5.1-11.4 11.4 0 2.5 0.8 4.7 2.1 6.6 0 0 4.8-2.5 8.9-2.5 5.5 0 9.4 2.9 9.4 2.9 1.5-1.9 2.4-4.3 2.4-7 0-6.3-5.1-11.4-11.4-11.4z"/>
|
||||
|
||||
|
||||
<path class="st3" d="m47.1 23.3c-6.3-1.7-11.7 2.1-14.7 7.3-0.7 1.2-0.2 2.2 0.5 2.6 1 0.3 1.7 0.1 2.8-1.5 2.2-3.9 5.9-6.1 10.1-5.3 0 0 2.9 0.9 3.3-1 0.3-1.2-0.8-1.8-2-2.1z"/>
|
||||
|
||||
|
||||
|
||||
|
||||
<path class="st3" d="m159.9 27.3c-0.1 1.9 2.9 1.9 2.9 1.9 4.2 0.4 6.8 2.3 7.8 6.7 0.6 1.9 1.2 2.2 2.3 2.2 0.8-0.1 1.6-1 1.2-2.4-1.4-5.8-5.1-9.8-11.7-9.9-1.2-0.1-2.4 0.2-2.5 1.5z"/>
|
||||
|
||||
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
|
|
@ -1,86 +1,40 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
inkscape:version="1.0beta1 (ee59332, 2019-11-28)"
|
||||
sodipodi:docname="castopod.svg"
|
||||
id="svg839"
|
||||
version="1.1"
|
||||
viewBox="0 0 64 63.999998"
|
||||
height="64"
|
||||
width="64">
|
||||
<metadata
|
||||
id="metadata845">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs843" />
|
||||
<sodipodi:namedview
|
||||
inkscape:current-layer="svg839"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:window-y="23"
|
||||
inkscape:window-x="0"
|
||||
inkscape:cy="33.560512"
|
||||
inkscape:cx="32"
|
||||
inkscape:zoom="8.9714173"
|
||||
showgrid="false"
|
||||
id="namedview841"
|
||||
inkscape:window-height="1035"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0"
|
||||
guidetolerance="10"
|
||||
gridtolerance="10"
|
||||
objecttolerance="10"
|
||||
borderopacity="1"
|
||||
inkscape:document-rotation="0"
|
||||
bordercolor="#666666"
|
||||
pagecolor="#ffffff" />
|
||||
<circle
|
||||
id="greencircle"
|
||||
fill="#37c837"
|
||||
cx="32"
|
||||
cy="32"
|
||||
r="31.684" />
|
||||
<g
|
||||
id="speak">
|
||||
<path
|
||||
d="M45.21 20.22H18.79c-6.473 0-11.74 5.266-11.74 11.74S12.317 43.7 18.79 43.7h10.756c1.08 0 1.957-.875 1.957-1.956 0-1.08-.877-1.957-1.957-1.957H18.79c-4.315 0-7.826-3.51-7.826-7.827 0-4.316 3.51-7.828 7.827-7.828h26.42c4.315 0 7.826 3.512 7.826 7.828 0 4.316-3.51 7.827-7.827 7.827H43.34v.002c-5.41.096-9.783 4.527-9.783 9.96 0 1.08.875 1.957 1.956 1.957 1.08 0 1.956-.876 1.956-1.957 0-3.336 2.714-6.05 6.05-6.05h1.687c6.473 0 11.74-5.266 11.74-11.74s-5.267-11.74-11.74-11.74"
|
||||
fill="#fff"
|
||||
id="phylactery" />
|
||||
<g
|
||||
id="threedots">
|
||||
<circle
|
||||
r="2"
|
||||
cy="32"
|
||||
cx="24.256159"
|
||||
id="leftdot"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;" />
|
||||
<circle
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;"
|
||||
id="middledot"
|
||||
cx="32"
|
||||
cy="32"
|
||||
r="2" />
|
||||
<circle
|
||||
r="2"
|
||||
cy="32"
|
||||
cx="39.743839"
|
||||
id="rightdot"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;" />
|
||||
</g>
|
||||
</g>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Calque_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 202.4 137.8" style="enable-background:new 0 0 202.4 137.8;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#009486;}
|
||||
.st1{fill:#E7F9E4;}
|
||||
.st2{fill:none;}
|
||||
.st3{fill:#E7FFE3;}
|
||||
</style>
|
||||
<g>
|
||||
<path id="dark_greeen_19_" class="st0" d="M181.9,131.7h-32.5c0,0-1.2-2.5-2.5-4.9c-1.3-2.4-4.4-2.3-4.4-2.3H59.7
|
||||
c0,0-3-0.4-4.5,2.3c-1.6,2.7-2.6,4.9-2.6,4.9H20.6c-6.9,0-12.6-5.6-12.6-12.5V20.3c0-6.9,5.6-12.6,12.5-12.6h161.3
|
||||
c6.9,0,12.6,5.6,12.6,12.5v98.9C194.5,126,188.8,131.7,181.9,131.7z"/>
|
||||
<path class="st1" d="M143.7,34.5H58.6c-14.6,0-26.5,12-26.5,26.6c0,14.6,11.9,26.5,26.5,26.5h85.1c14.6,0,26.5-11.9,26.5-26.5
|
||||
C170.3,46.3,158.4,34.4,143.7,34.5z M68.3,68.7c0,0-3.9-2.9-9.4-2.9c-4.1,0-8.9,2.5-8.9,2.5c-1.3-1.9-2.1-4.1-2.1-6.6
|
||||
c0-6.3,5.1-11.4,11.4-11.4s11.4,5.1,11.4,11.4C70.7,64.4,69.8,66.8,68.3,68.7z M101.2,75.3c-12.5,0-12-9.6-12-9.6
|
||||
c-0.2-1.8,2.1-2.4,2.9-1.3c0.4,0.6,0.4,0.6,0.7,1.7c1.7,5.9,8.4,5.6,8.4,5.6s6.7,0.4,8.4-5.6c0.3-1,0.3-1.1,0.7-1.7
|
||||
c0.8-1,3.1-0.5,2.9,1.3C113.2,65.7,113.7,75.3,101.2,75.3z M152.3,68.4c0,0-4.8-2.5-8.9-2.5c-5.5,0-9.4,2.9-9.4,2.9
|
||||
c-1.5-1.9-2.4-4.3-2.4-7c0-6.3,5.1-11.4,11.4-11.4s11.4,5.1,11.4,11.4C154.5,64.2,153.7,66.5,152.3,68.4z"/>
|
||||
<path class="st2" d="M110.3,64.3c-0.4,0.6-0.4,0.6-0.7,1.7c-1.7,5.9-8.4,5.6-8.4,5.6s-6.7,0.4-8.4-5.6c-0.3-1-0.3-1.1-0.7-1.7
|
||||
c-0.8-1-3.1-0.5-2.9,1.3c0,0-0.5,9.6,12,9.6c12.5,0,12-9.6,12-9.6C113.4,63.9,111.1,63.3,110.3,64.3z"/>
|
||||
<path class="st2" d="M143.1,50.4c-6.3,0-11.4,5.1-11.4,11.4c0,2.6,0.9,5,2.4,7c0,0,3.9-2.9,9.4-2.9c4.1,0,8.9,2.5,8.9,2.5
|
||||
c1.3-1.9,2.1-4.1,2.1-6.6C154.5,55.5,149.4,50.4,143.1,50.4z"/>
|
||||
<path class="st2" d="M59.3,50.4c-6.3,0-11.4,5.1-11.4,11.4c0,2.5,0.8,4.7,2.1,6.6c0,0,4.8-2.5,8.9-2.5c5.5,0,9.4,2.9,9.4,2.9
|
||||
c1.5-1.9,2.4-4.3,2.4-7C70.7,55.5,65.6,50.4,59.3,50.4z"/>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st3" d="M47.1,23.3c-6.3-1.7-11.7,2.1-14.7,7.3c-0.7,1.2-0.2,2.2,0.5,2.6c1,0.3,1.7,0.1,2.8-1.5
|
||||
c2.2-3.9,5.9-6.1,10.1-5.3c0,0,2.9,0.9,3.3-1C49.4,24.2,48.3,23.6,47.1,23.3z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st3" d="M159.9,27.3c-0.1,1.9,2.9,1.9,2.9,1.9c4.2,0.4,6.8,2.3,7.8,6.7c0.6,1.9,1.2,2.2,2.3,2.2
|
||||
c0.8-0.1,1.6-1,1.2-2.4c-1.4-5.8-5.1-9.8-11.7-9.9C161.2,25.7,160,26,159.9,27.3z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.4 KiB |
|
|
@ -1,7 +1,26 @@
|
|||
<svg id="default" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300">
|
||||
<rect width="300" height="300" rx="67" fill="#ebfaeb"/>
|
||||
<path id="phylactery" d="M195,112.36H105a40,40,0,0,0,0,80h36.65a6.67,6.67,0,0,0,0-13.33H105a26.67,26.67,0,0,1,0-53.34h90A26.67,26.67,0,0,1,195,179h-6.37A34,34,0,0,0,155.31,213a6.67,6.67,0,1,0,13.33,0,20.64,20.64,0,0,1,20.61-20.61H195a40,40,0,0,0,0-80" fill="#37c837"/>
|
||||
<circle id="leftdot" cx="123.62" cy="152.5" r="6.81" fill="#37c837"/>
|
||||
<circle id="middledot" cx="150.01" cy="152.5" r="6.81" fill="#37c837"/>
|
||||
<circle id="rightdot" cx="176.39" cy="152.5" r="6.81" fill="#37c837"/>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="64" height="64" version="1.1" viewBox="0 0 64 64" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><metadata><rdf:RDF><cc:Work rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/><dc:title/></cc:Work></rdf:RDF></metadata>
|
||||
<style type="text/css">
|
||||
.st0{fill:#AAAAAA;}
|
||||
.st1{fill:#CCCCCC;}
|
||||
.st2{fill:none;}
|
||||
.st3{fill:#EEEEEE;}
|
||||
</style>
|
||||
<rect width="64" height="64" fill="#fff" stroke-width=".94495"/><g transform="matrix(.32439 0 0 .32439 -.82859 9.3899)">
|
||||
<path id="dark_greeen_19_" class="st0" d="m181.9 131.7h-32.5s-1.2-2.5-2.5-4.9-4.4-2.3-4.4-2.3h-82.8s-3-0.4-4.5 2.3c-1.6 2.7-2.6 4.9-2.6 4.9h-32c-6.9 0-12.6-5.6-12.6-12.5v-98.9c0-6.9 5.6-12.6 12.5-12.6h161.3c6.9 0 12.6 5.6 12.6 12.5v98.9c0.1 6.9-5.6 12.6-12.5 12.6z"/>
|
||||
<path class="st1" d="m143.7 34.5h-85.1c-14.6 0-26.5 12-26.5 26.6s11.9 26.5 26.5 26.5h85.1c14.6 0 26.5-11.9 26.5-26.5 0.1-14.8-11.8-26.7-26.5-26.6zm-75.4 34.2s-3.9-2.9-9.4-2.9c-4.1 0-8.9 2.5-8.9 2.5-1.3-1.9-2.1-4.1-2.1-6.6 0-6.3 5.1-11.4 11.4-11.4s11.4 5.1 11.4 11.4c0 2.7-0.9 5.1-2.4 7zm32.9 6.6c-12.5 0-12-9.6-12-9.6-0.2-1.8 2.1-2.4 2.9-1.3 0.4 0.6 0.4 0.6 0.7 1.7 1.7 5.9 8.4 5.6 8.4 5.6s6.7 0.4 8.4-5.6c0.3-1 0.3-1.1 0.7-1.7 0.8-1 3.1-0.5 2.9 1.3 0 0 0.5 9.6-12 9.6zm51.1-6.9s-4.8-2.5-8.9-2.5c-5.5 0-9.4 2.9-9.4 2.9-1.5-1.9-2.4-4.3-2.4-7 0-6.3 5.1-11.4 11.4-11.4s11.4 5.1 11.4 11.4c0.1 2.4-0.7 4.7-2.1 6.6z"/>
|
||||
<path class="st2" d="m110.3 64.3c-0.4 0.6-0.4 0.6-0.7 1.7-1.7 5.9-8.4 5.6-8.4 5.6s-6.7 0.4-8.4-5.6c-0.3-1-0.3-1.1-0.7-1.7-0.8-1-3.1-0.5-2.9 1.3 0 0-0.5 9.6 12 9.6s12-9.6 12-9.6c0.2-1.7-2.1-2.3-2.9-1.3z"/>
|
||||
<path class="st2" d="m143.1 50.4c-6.3 0-11.4 5.1-11.4 11.4 0 2.6 0.9 5 2.4 7 0 0 3.9-2.9 9.4-2.9 4.1 0 8.9 2.5 8.9 2.5 1.3-1.9 2.1-4.1 2.1-6.6 0-6.3-5.1-11.4-11.4-11.4z"/>
|
||||
<path class="st2" d="m59.3 50.4c-6.3 0-11.4 5.1-11.4 11.4 0 2.5 0.8 4.7 2.1 6.6 0 0 4.8-2.5 8.9-2.5 5.5 0 9.4 2.9 9.4 2.9 1.5-1.9 2.4-4.3 2.4-7 0-6.3-5.1-11.4-11.4-11.4z"/>
|
||||
|
||||
|
||||
<path class="st3" d="m47.1 23.3c-6.3-1.7-11.7 2.1-14.7 7.3-0.7 1.2-0.2 2.2 0.5 2.6 1 0.3 1.7 0.1 2.8-1.5 2.2-3.9 5.9-6.1 10.1-5.3 0 0 2.9 0.9 3.3-1 0.3-1.2-0.8-1.8-2-2.1z"/>
|
||||
|
||||
|
||||
|
||||
|
||||
<path class="st3" d="m159.9 27.3c-0.1 1.9 2.9 1.9 2.9 1.9 4.2 0.4 6.8 2.3 7.8 6.7 0.6 1.9 1.2 2.2 2.3 2.2 0.8-0.1 1.6-1 1.2-2.4-1.4-5.8-5.1-9.8-11.7-9.9-1.2-0.1-2.4 0.2-2.5 1.5z"/>
|
||||
|
||||
|
||||
</g>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 631 B After Width: | Height: | Size: 2.5 KiB |
134
app/Views/_assets/modules/Charts.ts
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
// Import modules
|
||||
import * as am4charts from "@amcharts/amcharts4/charts";
|
||||
import * as am4core from "@amcharts/amcharts4/core";
|
||||
import am4themes_material from "@amcharts/amcharts4/themes/material";
|
||||
|
||||
const drawPieChart = (chartDivId: string, dataUrl: string | null): void => {
|
||||
// Create chart instance
|
||||
const chart = am4core.create(chartDivId, am4charts.PieChart);
|
||||
am4core.percent(100);
|
||||
|
||||
// Set theme
|
||||
am4core.useTheme(am4themes_material);
|
||||
|
||||
chart.innerRadius = am4core.percent(10);
|
||||
|
||||
// Add data
|
||||
chart.dataSource.url = dataUrl || "";
|
||||
chart.dataSource.parser.options.emptyAs = 0;
|
||||
|
||||
// Add and configure Series
|
||||
const pieSeries = chart.series.push(new am4charts.PieSeries());
|
||||
pieSeries.dataFields.value = "values";
|
||||
pieSeries.dataFields.category = "labels";
|
||||
|
||||
pieSeries.slices.template.stroke = am4core.color("#ffffff");
|
||||
pieSeries.slices.template.strokeWidth = 1;
|
||||
pieSeries.slices.template.strokeOpacity = 1;
|
||||
pieSeries.labels.template.disabled = true;
|
||||
pieSeries.ticks.template.disabled = true;
|
||||
|
||||
chart.legend = new am4charts.Legend();
|
||||
chart.legend.position = "right";
|
||||
chart.legend.scrollable = true;
|
||||
};
|
||||
|
||||
const drawXYChart = (chartDivId: string, dataUrl: string | null): void => {
|
||||
// Create chart instance
|
||||
const chart = am4core.create(chartDivId, am4charts.XYChart);
|
||||
am4core.percent(100);
|
||||
|
||||
// Set theme
|
||||
am4core.useTheme(am4themes_material);
|
||||
|
||||
// Create axes
|
||||
const dateAxis = chart.xAxes.push(new am4charts.DateAxis());
|
||||
dateAxis.renderer.minGridDistance = 60;
|
||||
|
||||
chart.yAxes.push(new am4charts.ValueAxis());
|
||||
|
||||
// Add data
|
||||
chart.dataSource.url = dataUrl || "";
|
||||
chart.dataSource.parser.options.emptyAs = 0;
|
||||
|
||||
// Create series
|
||||
const series = chart.series.push(new am4charts.LineSeries());
|
||||
series.dataFields.valueY = "values";
|
||||
series.dataFields.dateX = "labels";
|
||||
series.tooltipText = "{valueY} downloads";
|
||||
|
||||
series.tooltip.pointerOrientation = "vertical";
|
||||
|
||||
chart.cursor = new am4charts.XYCursor();
|
||||
chart.cursor.snapToSeries = series;
|
||||
chart.cursor.xAxis = dateAxis;
|
||||
|
||||
chart.scrollbarX = new am4core.Scrollbar();
|
||||
};
|
||||
|
||||
const drawXYSeriesChart = (
|
||||
chartDivId: string,
|
||||
dataUrl: string | null
|
||||
): void => {
|
||||
// Create chart instance
|
||||
const chart = am4core.create(chartDivId, am4charts.XYChart);
|
||||
am4core.percent(100);
|
||||
|
||||
// Set theme
|
||||
am4core.useTheme(am4themes_material);
|
||||
|
||||
// Create axes
|
||||
chart.xAxes.push(new am4charts.ValueAxis());
|
||||
chart.yAxes.push(new am4charts.ValueAxis());
|
||||
|
||||
// Add data
|
||||
chart.dataSource.url = dataUrl || "";
|
||||
chart.dataSource.parser.options.emptyAs = 0;
|
||||
|
||||
// Create series
|
||||
const series1 = chart.series.push(new am4charts.LineSeries());
|
||||
series1.dataFields.valueX = "X";
|
||||
series1.dataFields.valueY = "aY";
|
||||
|
||||
const series2 = chart.series.push(new am4charts.LineSeries());
|
||||
series2.dataFields.valueX = "X";
|
||||
series2.dataFields.valueY = "bY";
|
||||
|
||||
const series3 = chart.series.push(new am4charts.LineSeries());
|
||||
series3.dataFields.valueX = "X";
|
||||
series3.dataFields.valueY = "cY";
|
||||
|
||||
const series4 = chart.series.push(new am4charts.LineSeries());
|
||||
series4.dataFields.valueX = "X";
|
||||
series4.dataFields.valueY = "dY";
|
||||
|
||||
const series5 = chart.series.push(new am4charts.LineSeries());
|
||||
series5.dataFields.valueX = "X";
|
||||
series5.dataFields.valueY = "eY";
|
||||
};
|
||||
|
||||
const DrawCharts = (): void => {
|
||||
const chartDivs: NodeListOf<HTMLDivElement> = document.querySelectorAll(
|
||||
"div[data-chart-type]"
|
||||
);
|
||||
|
||||
for (let i = 0; i < chartDivs.length; i++) {
|
||||
const chartDiv: HTMLDivElement = chartDivs[i];
|
||||
const chartType = chartDiv.dataset.chartType;
|
||||
switch (chartType) {
|
||||
case "pie-chart":
|
||||
drawPieChart(chartDiv.id, chartDiv.getAttribute("data-chart-url"));
|
||||
break;
|
||||
case "xy-chart":
|
||||
drawXYChart(chartDiv.id, chartDiv.getAttribute("data-chart-url"));
|
||||
break;
|
||||
case "xy-series-chart":
|
||||
drawXYSeriesChart(chartDiv.id, chartDiv.getAttribute("data-chart-url"));
|
||||
break;
|
||||
default:
|
||||
console.error("Unknown chart type:" + chartType);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default DrawCharts;
|
||||
|
|
@ -24,7 +24,7 @@
|
|||
<?= render_page_links() ?>
|
||||
<small><?= lang('Common.powered_by', [
|
||||
'castopod' =>
|
||||
'<a class="underline hover:no-underline" href="https://castopod.org" target="_blank" rel="noreferrer noopener">Castopod</a>',
|
||||
'<a class="underline hover:no-underline" href="https://castopod.org/" target="_blank" rel="noreferrer noopener">Castopod</a>',
|
||||
]) ?></small>
|
||||
</footer>
|
||||
</body>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
<link rel="shortcut icon" type="image/png" href="/favicon.ico" />
|
||||
<link rel="stylesheet" href="/assets/admin.css"/>
|
||||
<link rel="stylesheet" href="/assets/index.css"/>
|
||||
<script src="/assets/admin.js" defer></script>
|
||||
<script src="/assets/admin.js" type="module" defer></script>
|
||||
</head>
|
||||
|
||||
<body class="relative bg-gray-100 holy-grail-grid">
|
||||
|
|
@ -43,12 +43,12 @@
|
|||
<footer class="px-2 py-2 mx-auto text-xs text-right holy-grail-footer">
|
||||
<small><?= lang('Common.powered_by', [
|
||||
'castopod' =>
|
||||
'<a class="underline hover:no-underline" href="https://castopod.org" target="_blank" rel="noreferrer noopener">Castopod</a>',
|
||||
'<a class="underline hover:no-underline" href="https://castopod.org/" target="_blank" rel="noreferrer noopener">Castopod</a>',
|
||||
]) ?></small>
|
||||
</footer>
|
||||
<button
|
||||
type="button"
|
||||
id="sidebar-toggler"
|
||||
class="fixed bottom-0 left-0 z-50 p-3 mb-3 ml-3 text-xl transition duration-300 ease-in-out bg-white border-2 rounded-full shadow-lg focus:outline-none md:hidden hover:bg-gray-100 focus:shadow-outline"
|
||||
class="fixed bottom-0 left-0 z-50 p-3 mb-3 ml-3 text-xl transition duration-300 ease-in-out bg-white border-2 rounded-full shadow-lg focus:outline-none md:hidden hover:bg-gray-100 focus:shadow-outline"
|
||||
style="transform: translateX(0px);"><?= icon('menu') ?></button>
|
||||
</body>
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ $podcastNavigation = [
|
|||
],
|
||||
'analytics' => [
|
||||
'icon' => 'line-chart',
|
||||
'items' => [],
|
||||
'items' => ['podcast-analytics'],
|
||||
],
|
||||
'contributors' => [
|
||||
'icon' => 'group',
|
||||
|
|
|
|||
32
app/Views/admin/podcast/analytics.php
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<?= $this->extend('admin/_layout') ?>
|
||||
|
||||
<?= $this->section('title') ?>
|
||||
<?= $podcast->title ?>
|
||||
<?= $this->endSection() ?>
|
||||
|
||||
<?= $this->section('pageTitle') ?>
|
||||
<?= $podcast->title ?>
|
||||
<?= $this->endSection() ?>
|
||||
|
||||
<?= $this->section('content') ?>
|
||||
<div class="h-64" id="by-app-pie" data-chart-type="pie-chart" data-chart-url="<?= route_to(
|
||||
'analytics-data',
|
||||
$podcast->id,
|
||||
'PodcastsByPlayer',
|
||||
'ByApp'
|
||||
) ?>"></div>
|
||||
<div class="h-64" id="by-day-graph" data-chart-type="xy-chart" data-chart-url="<?= route_to(
|
||||
'analytics-data',
|
||||
$podcast->id,
|
||||
'Podcasts',
|
||||
'ByDay'
|
||||
) ?>"></div>
|
||||
<div class="h-64" id="by-age-graph" data-chart-type="xy-series-chart" data-chart-url="<?= route_to(
|
||||
'analytics-data',
|
||||
$podcast->id,
|
||||
'PodcastsByEpisode',
|
||||
'ByDay'
|
||||
) ?>"></div>
|
||||
|
||||
<script src="/assets/charts.js" type="module"></script>
|
||||
<?= $this->endSection() ?>
|
||||
|
|
@ -13,7 +13,9 @@
|
|||
"codeigniter4/codeigniter4": "dev-develop",
|
||||
"league/commonmark": "^1.5",
|
||||
"vlucas/phpdotenv": "^5.2",
|
||||
"league/html-to-markdown": "^4.10"
|
||||
"league/html-to-markdown": "^4.10",
|
||||
"podlibre/user-agents-php": "*",
|
||||
"podlibre/ipcat": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"mikey179/vfsstream": "1.6.*",
|
||||
|
|
@ -27,8 +29,14 @@
|
|||
},
|
||||
"scripts": {
|
||||
"test": "phpunit",
|
||||
"post-install-cmd": [
|
||||
"@php vendor/podlibre/user-agents-php/src/UserAgentsGenerate.php > vendor/podlibre/user-agents-php/src/UserAgents.php",
|
||||
"@php vendor/podlibre/ipcat/IpDbGenerate.php > vendor/podlibre/ipcat/IpDb.php"
|
||||
],
|
||||
"post-update-cmd": [
|
||||
"@composer dump-autoload"
|
||||
"@composer dump-autoload",
|
||||
"@php vendor/podlibre/user-agents-php/src/UserAgentsGenerate.php > vendor/podlibre/user-agents-php/src/UserAgents.php",
|
||||
"@php vendor/podlibre/ipcat/IpDbGenerate.php > vendor/podlibre/ipcat/IpDb.php"
|
||||
]
|
||||
},
|
||||
"support": {
|
||||
|
|
|
|||
146
composer.lock
generated
|
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "38eeae7f5d0143863430cda9df10d487",
|
||||
"content-hash": "47b9f628f03f8c494a9339b054359ec8",
|
||||
"packages": [
|
||||
{
|
||||
"name": "codeigniter4/codeigniter4",
|
||||
|
|
@ -12,12 +12,12 @@
|
|||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/codeigniter4/CodeIgniter4.git",
|
||||
"reference": "9204aef421921f2c07021dda418ebfc200fe4a31"
|
||||
"reference": "ccf68e1d7fc44bfe5abacc39bf16edae45794a83"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/codeigniter4/CodeIgniter4/zipball/9204aef421921f2c07021dda418ebfc200fe4a31",
|
||||
"reference": "9204aef421921f2c07021dda418ebfc200fe4a31",
|
||||
"url": "https://api.github.com/repos/codeigniter4/CodeIgniter4/zipball/ccf68e1d7fc44bfe5abacc39bf16edae45794a83",
|
||||
"reference": "ccf68e1d7fc44bfe5abacc39bf16edae45794a83",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -37,6 +37,7 @@
|
|||
"phpstan/phpstan": "^0.12",
|
||||
"phpunit/phpunit": "^8.5",
|
||||
"predis/predis": "^1.1",
|
||||
"rector/rector": "^0.8",
|
||||
"squizlabs/php_codesniffer": "^3.3"
|
||||
},
|
||||
"type": "project",
|
||||
|
|
@ -45,6 +46,11 @@
|
|||
"CodeIgniter\\": "system/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Utils\\": "utils"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"post-update-cmd": [
|
||||
"@composer dump-autoload",
|
||||
|
|
@ -69,7 +75,7 @@
|
|||
"slack": "https://codeigniterchat.slack.com",
|
||||
"issues": "https://github.com/codeigniter4/CodeIgniter4/issues"
|
||||
},
|
||||
"time": "2020-09-24T17:15:24+00:00"
|
||||
"time": "2020-10-04T20:15:33+00:00"
|
||||
},
|
||||
{
|
||||
"name": "composer/ca-bundle",
|
||||
|
|
@ -143,27 +149,27 @@
|
|||
},
|
||||
{
|
||||
"name": "geoip2/geoip2",
|
||||
"version": "v2.10.0",
|
||||
"version": "v2.11.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/maxmind/GeoIP2-php.git",
|
||||
"reference": "419557cd21d9fe039721a83490701a58c8ce784a"
|
||||
"reference": "d01be5894a5c1a3381c58c9b1795cd07f96c30f7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/maxmind/GeoIP2-php/zipball/419557cd21d9fe039721a83490701a58c8ce784a",
|
||||
"reference": "419557cd21d9fe039721a83490701a58c8ce784a",
|
||||
"url": "https://api.github.com/repos/maxmind/GeoIP2-php/zipball/d01be5894a5c1a3381c58c9b1795cd07f96c30f7",
|
||||
"reference": "d01be5894a5c1a3381c58c9b1795cd07f96c30f7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"maxmind-db/reader": "~1.5",
|
||||
"maxmind/web-service-common": "~0.6",
|
||||
"php": ">=5.6"
|
||||
"maxmind-db/reader": "~1.8",
|
||||
"maxmind/web-service-common": "~0.8",
|
||||
"php": ">=7.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "2.*",
|
||||
"phpunit/phpunit": "5.*",
|
||||
"phpunit/phpunit": "^8.0 || ^9.0",
|
||||
"squizlabs/php_codesniffer": "3.*"
|
||||
},
|
||||
"type": "library",
|
||||
|
|
@ -192,7 +198,7 @@
|
|||
"geolocation",
|
||||
"maxmind"
|
||||
],
|
||||
"time": "2019-12-12T18:48:39+00:00"
|
||||
"time": "2020-10-01T18:48:34+00:00"
|
||||
},
|
||||
{
|
||||
"name": "graham-campbell/result-type",
|
||||
|
|
@ -689,23 +695,23 @@
|
|||
},
|
||||
{
|
||||
"name": "maxmind-db/reader",
|
||||
"version": "v1.7.0",
|
||||
"version": "v1.8.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/maxmind/MaxMind-DB-Reader-php.git",
|
||||
"reference": "942553da239f12051275f9c666538b5dd09e2908"
|
||||
"reference": "b566d429ac9aec10594b0935be8ff38302f8d5c8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/maxmind/MaxMind-DB-Reader-php/zipball/942553da239f12051275f9c666538b5dd09e2908",
|
||||
"reference": "942553da239f12051275f9c666538b5dd09e2908",
|
||||
"url": "https://api.github.com/repos/maxmind/MaxMind-DB-Reader-php/zipball/b566d429ac9aec10594b0935be8ff38302f8d5c8",
|
||||
"reference": "b566d429ac9aec10594b0935be8ff38302f8d5c8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2"
|
||||
},
|
||||
"conflict": {
|
||||
"ext-maxminddb": "<1.7.0,>=2.0.0"
|
||||
"ext-maxminddb": "<1.8.0,>=2.0.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "2.*",
|
||||
|
|
@ -745,31 +751,31 @@
|
|||
"geolocation",
|
||||
"maxmind"
|
||||
],
|
||||
"time": "2020-08-07T22:10:05+00:00"
|
||||
"time": "2020-10-01T17:30:21+00:00"
|
||||
},
|
||||
{
|
||||
"name": "maxmind/web-service-common",
|
||||
"version": "v0.7.0",
|
||||
"version": "v0.8.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/maxmind/web-service-common-php.git",
|
||||
"reference": "74c996c218ada5c639c8c2f076756e059f5552fc"
|
||||
"reference": "ba67d9532cfaf499bd71774b8170d05df4f75fb7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/maxmind/web-service-common-php/zipball/74c996c218ada5c639c8c2f076756e059f5552fc",
|
||||
"reference": "74c996c218ada5c639c8c2f076756e059f5552fc",
|
||||
"url": "https://api.github.com/repos/maxmind/web-service-common-php/zipball/ba67d9532cfaf499bd71774b8170d05df4f75fb7",
|
||||
"reference": "ba67d9532cfaf499bd71774b8170d05df4f75fb7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"composer/ca-bundle": "^1.0.3",
|
||||
"ext-curl": "*",
|
||||
"ext-json": "*",
|
||||
"php": ">=5.6"
|
||||
"php": ">=7.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "2.*",
|
||||
"phpunit/phpunit": "^4.8.36 || ^5.7 || ^6.5 || ^7.0",
|
||||
"phpunit/phpunit": "^8.0 || ^9.0",
|
||||
"squizlabs/php_codesniffer": "3.*"
|
||||
},
|
||||
"type": "library",
|
||||
|
|
@ -791,7 +797,7 @@
|
|||
],
|
||||
"description": "Internal MaxMind Web Service API",
|
||||
"homepage": "https://github.com/maxmind/web-service-common-php",
|
||||
"time": "2020-05-06T14:07:26+00:00"
|
||||
"time": "2020-10-01T15:28:36+00:00"
|
||||
},
|
||||
{
|
||||
"name": "myth/auth",
|
||||
|
|
@ -918,6 +924,76 @@
|
|||
],
|
||||
"time": "2020-07-20T17:29:33+00:00"
|
||||
},
|
||||
{
|
||||
"name": "podlibre/ipcat",
|
||||
"version": "dev-master",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/podlibre/ipcat.git",
|
||||
"reference": "1adfc821be508ddc8a742f6a5d5e6e42fdf28e86"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/podlibre/ipcat/zipball/1adfc821be508ddc8a742f6a5d5e6e42fdf28e86",
|
||||
"reference": "1adfc821be508ddc8a742f6a5d5e6e42fdf28e86",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Podlibre\\Ipcat\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"GPL-3.0-only"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Benjamin Bellamy",
|
||||
"email": "ben@podlibre.org",
|
||||
"homepage": "https://podlibre.org/"
|
||||
}
|
||||
],
|
||||
"description": "Categorization of IP Addresses forked from https://github.com/client9/ipcat",
|
||||
"homepage": "https://github.com/podlibre/ipcat",
|
||||
"time": "2020-10-05T17:15:07+00:00"
|
||||
},
|
||||
{
|
||||
"name": "podlibre/user-agents-php",
|
||||
"version": "dev-main",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/podlibre/user-agents-php.git",
|
||||
"reference": "891066bae6b4881a8b7a57eb72a67fca1fcf67c0"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/podlibre/user-agents-php/zipball/891066bae6b4881a8b7a57eb72a67fca1fcf67c0",
|
||||
"reference": "891066bae6b4881a8b7a57eb72a67fca1fcf67c0",
|
||||
"shasum": ""
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Podlibre\\UserAgentsPhp\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Benjamin Bellamy",
|
||||
"email": "ben@podlibre.org",
|
||||
"homepage": "https://podlibre.org/"
|
||||
}
|
||||
],
|
||||
"description": "PHP implementation for opawg/user-agents.",
|
||||
"homepage": "https://github.com/podlibre/user-agents-php",
|
||||
"time": "2020-10-05T16:58:13+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/cache",
|
||||
"version": "1.0.1",
|
||||
|
|
@ -1801,28 +1877,28 @@
|
|||
},
|
||||
{
|
||||
"name": "phpspec/prophecy",
|
||||
"version": "1.11.1",
|
||||
"version": "1.12.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpspec/prophecy.git",
|
||||
"reference": "b20034be5efcdab4fb60ca3a29cba2949aead160"
|
||||
"reference": "8ce87516be71aae9b956f81906aaf0338e0d8a2d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/b20034be5efcdab4fb60ca3a29cba2949aead160",
|
||||
"reference": "b20034be5efcdab4fb60ca3a29cba2949aead160",
|
||||
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/8ce87516be71aae9b956f81906aaf0338e0d8a2d",
|
||||
"reference": "8ce87516be71aae9b956f81906aaf0338e0d8a2d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"doctrine/instantiator": "^1.2",
|
||||
"php": "^7.2",
|
||||
"phpdocumentor/reflection-docblock": "^5.0",
|
||||
"php": "^7.2 || ~8.0, <8.1",
|
||||
"phpdocumentor/reflection-docblock": "^5.2",
|
||||
"sebastian/comparator": "^3.0 || ^4.0",
|
||||
"sebastian/recursion-context": "^3.0 || ^4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpspec/phpspec": "^6.0",
|
||||
"phpunit/phpunit": "^8.0"
|
||||
"phpunit/phpunit": "^8.0 || ^9.0 <9.3"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
|
|
@ -1860,7 +1936,7 @@
|
|||
"spy",
|
||||
"stub"
|
||||
],
|
||||
"time": "2020-07-08T12:44:21+00:00"
|
||||
"time": "2020-09-29T09:10:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
|
|
|
|||
|
|
@ -104,6 +104,13 @@ docker ps -a
|
|||
docker-compose run --rm app php spark migrate -all
|
||||
```
|
||||
|
||||
In case you need to roll back, use this command:
|
||||
|
||||
```
|
||||
# rolls back database schema loading (deletes all tables and their content)
|
||||
docker-compose run --rm app php spark migrate:rollback
|
||||
```
|
||||
|
||||
2. Populate the database with the required data:
|
||||
|
||||
```bash
|
||||
|
|
|
|||
1448
package-lock.json
generated
|
|
@ -4,6 +4,39 @@
|
|||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@amcharts/amcharts4": {
|
||||
"version": "4.10.5",
|
||||
"resolved": "https://registry.npmjs.org/@amcharts/amcharts4/-/amcharts4-4.10.5.tgz",
|
||||
"integrity": "sha512-H4PlVd4jSsD0V0loCg1Jd1gXMCqMaWwQabjd8qejP2lew2ZiXEaJ8eoIuXXoAakehCq/fewtgNO9lq95hdklvA==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.6.3",
|
||||
"core-js": "^3.0.0",
|
||||
"d3-force": "^2.0.1",
|
||||
"d3-geo": "^2.0.1",
|
||||
"d3-geo-projection": "^3.0.0",
|
||||
"pdfmake": "^0.1.36",
|
||||
"polylabel": "^1.0.2",
|
||||
"raf": "^3.4.1",
|
||||
"regression": "^2.0.1",
|
||||
"rgbcolor": "^1.0.1",
|
||||
"stackblur-canvas": "^2.0.0",
|
||||
"tslib": "^2.0.1",
|
||||
"venn.js": "^0.2.20",
|
||||
"xlsx": "^0.16.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"tslib": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz",
|
||||
"integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@amcharts/amcharts4-geodata": {
|
||||
"version": "4.1.17",
|
||||
"resolved": "https://registry.npmjs.org/@amcharts/amcharts4-geodata/-/amcharts4-geodata-4.1.17.tgz",
|
||||
"integrity": "sha512-ylzshiOq/aMRlVrRq8dOznZP7fp4xg/XkmhTjGm2dN6O1WqvoVBBOOnGyzrmb2gBlqN5zj59PQyOqSDyQUNe/Q=="
|
||||
},
|
||||
"@babel/code-frame": {
|
||||
"version": "7.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.1.tgz",
|
||||
|
|
@ -1220,7 +1253,6 @@
|
|||
"version": "7.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.10.4.tgz",
|
||||
"integrity": "sha512-UpTN5yUJr9b4EX2CnGNWIvER7Ab83ibv0pcvvHc4UOdrBI5jb8bj+32cCwPX6xu0mt2daFNjYhoi+X7beH0RSw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
},
|
||||
|
|
@ -1228,8 +1260,7 @@
|
|||
"regenerator-runtime": {
|
||||
"version": "0.13.5",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz",
|
||||
"integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -2465,8 +2496,7 @@
|
|||
"acorn": {
|
||||
"version": "7.4.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz",
|
||||
"integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==",
|
||||
"dev": true
|
||||
"integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w=="
|
||||
},
|
||||
"acorn-jsx": {
|
||||
"version": "5.3.1",
|
||||
|
|
@ -2478,7 +2508,6 @@
|
|||
"version": "1.8.2",
|
||||
"resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz",
|
||||
"integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"acorn": "^7.0.0",
|
||||
"acorn-walk": "^7.0.0",
|
||||
|
|
@ -2488,8 +2517,16 @@
|
|||
"acorn-walk": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz",
|
||||
"integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA=="
|
||||
},
|
||||
"adler-32": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.2.0.tgz",
|
||||
"integrity": "sha1-aj5r8KY5ALoVZSgIyxXGgT0aXyU=",
|
||||
"requires": {
|
||||
"exit-on-epipe": "~1.0.1",
|
||||
"printj": "~1.1.0"
|
||||
}
|
||||
},
|
||||
"aggregate-error": {
|
||||
"version": "3.1.0",
|
||||
|
|
@ -2513,12 +2550,42 @@
|
|||
"uri-js": "^4.2.2"
|
||||
}
|
||||
},
|
||||
"align-text": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz",
|
||||
"integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=",
|
||||
"requires": {
|
||||
"kind-of": "^3.0.2",
|
||||
"longest": "^1.0.1",
|
||||
"repeat-string": "^1.5.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"kind-of": {
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
|
||||
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
|
||||
"requires": {
|
||||
"is-buffer": "^1.1.5"
|
||||
}
|
||||
},
|
||||
"longest": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
|
||||
"integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc="
|
||||
}
|
||||
}
|
||||
},
|
||||
"alphanum-sort": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz",
|
||||
"integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=",
|
||||
"dev": true
|
||||
},
|
||||
"amdefine": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
|
||||
"integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU="
|
||||
},
|
||||
"ansi-colors": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
|
||||
|
|
@ -2582,6 +2649,11 @@
|
|||
"integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
|
||||
"dev": true
|
||||
},
|
||||
"array-from": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz",
|
||||
"integrity": "sha1-z+nYwmYoudxa7MYqn12PHzUsEZU="
|
||||
},
|
||||
"array-ify": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz",
|
||||
|
|
@ -2612,6 +2684,58 @@
|
|||
"integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
|
||||
"dev": true
|
||||
},
|
||||
"ast-transform": {
|
||||
"version": "0.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ast-transform/-/ast-transform-0.0.0.tgz",
|
||||
"integrity": "sha1-dJRAWIh9goPhidlUYAlHvJj+AGI=",
|
||||
"requires": {
|
||||
"escodegen": "~1.2.0",
|
||||
"esprima": "~1.0.4",
|
||||
"through": "~2.3.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"escodegen": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.2.0.tgz",
|
||||
"integrity": "sha1-Cd55Z3kcyVi3+Jot220jRRrzJ+E=",
|
||||
"requires": {
|
||||
"esprima": "~1.0.4",
|
||||
"estraverse": "~1.5.0",
|
||||
"esutils": "~1.0.0",
|
||||
"source-map": "~0.1.30"
|
||||
}
|
||||
},
|
||||
"esprima": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz",
|
||||
"integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0="
|
||||
},
|
||||
"estraverse": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.5.1.tgz",
|
||||
"integrity": "sha1-hno+jlip+EYYr7bC3bzZFrfLr3E="
|
||||
},
|
||||
"esutils": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/esutils/-/esutils-1.0.0.tgz",
|
||||
"integrity": "sha1-gVHTWOIMisx/t0XnRywAJf5JZXA="
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.1.43",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz",
|
||||
"integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=",
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"amdefine": ">=0.0.4"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ast-types": {
|
||||
"version": "0.7.8",
|
||||
"resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.7.8.tgz",
|
||||
"integrity": "sha1-kC0uDWDQcb3NRtwRXhgJ7RHBOKk="
|
||||
},
|
||||
"astral-regex": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
|
||||
|
|
@ -2667,6 +2791,27 @@
|
|||
"object.assign": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"babel-runtime": {
|
||||
"version": "6.26.0",
|
||||
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
|
||||
"integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
|
||||
"requires": {
|
||||
"core-js": "^2.4.0",
|
||||
"regenerator-runtime": "^0.11.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": {
|
||||
"version": "2.6.11",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz",
|
||||
"integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg=="
|
||||
},
|
||||
"regenerator-runtime": {
|
||||
"version": "0.11.1",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
|
||||
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"bail": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz",
|
||||
|
|
@ -2676,8 +2821,7 @@
|
|||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
|
||||
"dev": true
|
||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
|
||||
},
|
||||
"base": {
|
||||
"version": "0.11.2",
|
||||
|
|
@ -2734,6 +2878,11 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"base64-js": {
|
||||
"version": "0.0.8",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz",
|
||||
"integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg="
|
||||
},
|
||||
"big.js": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
|
||||
|
|
@ -2756,7 +2905,6 @@
|
|||
"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"
|
||||
|
|
@ -2791,6 +2939,68 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"brfs": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/brfs/-/brfs-2.0.2.tgz",
|
||||
"integrity": "sha512-IrFjVtwu4eTJZyu8w/V2gxU7iLTtcHih67sgEdzrhjLBMHp2uYefUBfdM4k2UvcuWMgV7PQDZHSLeNWnLFKWVQ==",
|
||||
"requires": {
|
||||
"quote-stream": "^1.0.1",
|
||||
"resolve": "^1.1.5",
|
||||
"static-module": "^3.0.2",
|
||||
"through2": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"through2": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
|
||||
"integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
|
||||
"requires": {
|
||||
"readable-stream": "~2.3.6",
|
||||
"xtend": "~4.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"brotli": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.2.tgz",
|
||||
"integrity": "sha1-UlqcrU/LqWR119OI9q7LE+7VL0Y=",
|
||||
"requires": {
|
||||
"base64-js": "^1.1.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"base64-js": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
|
||||
"integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"browser-resolve": {
|
||||
"version": "1.11.3",
|
||||
"resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.3.tgz",
|
||||
"integrity": "sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ==",
|
||||
"requires": {
|
||||
"resolve": "1.1.7"
|
||||
},
|
||||
"dependencies": {
|
||||
"resolve": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
|
||||
"integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs="
|
||||
}
|
||||
}
|
||||
},
|
||||
"browserify-optional": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/browserify-optional/-/browserify-optional-1.0.1.tgz",
|
||||
"integrity": "sha1-HhNyLP3g2F8SFnbCpyztUzoBiGk=",
|
||||
"requires": {
|
||||
"ast-transform": "0.0.0",
|
||||
"ast-types": "^0.7.0",
|
||||
"browser-resolve": "^1.8.1"
|
||||
}
|
||||
},
|
||||
"browserslist": {
|
||||
"version": "4.12.0",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.12.0.tgz",
|
||||
|
|
@ -2803,11 +3013,15 @@
|
|||
"pkg-up": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"buffer-equal": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz",
|
||||
"integrity": "sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs="
|
||||
},
|
||||
"buffer-from": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
|
||||
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
|
||||
"dev": true
|
||||
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
|
||||
},
|
||||
"builtin-modules": {
|
||||
"version": "3.1.0",
|
||||
|
|
@ -2915,6 +3129,25 @@
|
|||
"integrity": "sha512-MOli1W+nfbPLlKEhInaxhRdp7KVLFxLN5ykwzHgLsLI3H3gs5jjFAK4Eoj3OzzcxCtumDaI8onoVDeQyWaNTkw==",
|
||||
"dev": true
|
||||
},
|
||||
"center-align": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
|
||||
"integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=",
|
||||
"requires": {
|
||||
"align-text": "^0.1.3",
|
||||
"lazy-cache": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"cfb": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.0.tgz",
|
||||
"integrity": "sha512-sXMvHsKCICVR3Naq+J556K+ExBo9n50iKl6LGarlnvuA2035uMlGA/qVrc0wQtow5P1vJEw9UyrKLCbtIKz+TQ==",
|
||||
"requires": {
|
||||
"adler-32": "~1.2.0",
|
||||
"crc-32": "~1.2.0",
|
||||
"printj": "~1.1.2"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz",
|
||||
|
|
@ -3239,6 +3472,11 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"clone": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
|
||||
"integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4="
|
||||
},
|
||||
"clone-regexp": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/clone-regexp/-/clone-regexp-2.2.0.tgz",
|
||||
|
|
@ -3280,6 +3518,22 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"codepage": {
|
||||
"version": "1.14.0",
|
||||
"resolved": "https://registry.npmjs.org/codepage/-/codepage-1.14.0.tgz",
|
||||
"integrity": "sha1-jL4lSBMjVZ19MHVxsP/5HnodL5k=",
|
||||
"requires": {
|
||||
"commander": "~2.14.1",
|
||||
"exit-on-epipe": "~1.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"commander": {
|
||||
"version": "2.14.1",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.14.1.tgz",
|
||||
"integrity": "sha512-+YR16o3rK53SmWHU3rEM3tPAh2rwb1yPcQX5irVn7mb0gXbwuCCrnkbV5+PBfETdfg1vui07nM6PCG1zndcjQw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"collapse-white-space": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-1.0.6.tgz",
|
||||
|
|
@ -3444,8 +3698,18 @@
|
|||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
||||
"dev": true
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
|
||||
},
|
||||
"concat-stream": {
|
||||
"version": "1.6.2",
|
||||
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
|
||||
"integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
|
||||
"requires": {
|
||||
"buffer-from": "^1.0.0",
|
||||
"inherits": "^2.0.3",
|
||||
"readable-stream": "^2.2.2",
|
||||
"typedarray": "^0.0.6"
|
||||
}
|
||||
},
|
||||
"concat-with-sourcemaps": {
|
||||
"version": "1.1.0",
|
||||
|
|
@ -3464,6 +3728,11 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"contour_plot": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/contour_plot/-/contour_plot-0.0.1.tgz",
|
||||
"integrity": "sha1-R1hw8DK44zhBKqX8UHiA8L9JXHc="
|
||||
},
|
||||
"conventional-changelog-angular": {
|
||||
"version": "5.0.11",
|
||||
"resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.11.tgz",
|
||||
|
|
@ -3510,7 +3779,6 @@
|
|||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz",
|
||||
"integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safe-buffer": "~5.1.1"
|
||||
}
|
||||
|
|
@ -3524,8 +3792,7 @@
|
|||
"core-js": {
|
||||
"version": "3.6.5",
|
||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz",
|
||||
"integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA=="
|
||||
},
|
||||
"core-js-compat": {
|
||||
"version": "3.6.5",
|
||||
|
|
@ -3548,8 +3815,7 @@
|
|||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
|
||||
"dev": true
|
||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
|
||||
},
|
||||
"cosmiconfig": {
|
||||
"version": "5.2.1",
|
||||
|
|
@ -3563,6 +3829,15 @@
|
|||
"parse-json": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"crc-32": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz",
|
||||
"integrity": "sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==",
|
||||
"requires": {
|
||||
"exit-on-epipe": "~1.0.1",
|
||||
"printj": "~1.1.0"
|
||||
}
|
||||
},
|
||||
"crelt": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.4.tgz",
|
||||
|
|
@ -3599,6 +3874,11 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"crypto-js": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.3.0.tgz",
|
||||
"integrity": "sha512-DIT51nX0dCfKltpRiXV+/TVZq+Qq2NgF4644+K7Ttnla7zEzqc+kjJyiB96BHNyUTBxyjzRcZYpUdZa+QAqi6Q=="
|
||||
},
|
||||
"css-blank-pseudo": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz",
|
||||
|
|
@ -3954,12 +4234,130 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"d": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
|
||||
"integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
|
||||
"requires": {
|
||||
"es5-ext": "^0.10.50",
|
||||
"type": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"d3-array": {
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.8.0.tgz",
|
||||
"integrity": "sha512-6V272gsOeg7+9pTW1jSYOR1QE37g95I3my1hBmY+vOUNHRrk9yt4OTz/gK7PMkVAVDrYYq4mq3grTiZ8iJdNIw=="
|
||||
},
|
||||
"d3-color": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz",
|
||||
"integrity": "sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q=="
|
||||
},
|
||||
"d3-dispatch": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-2.0.0.tgz",
|
||||
"integrity": "sha512-S/m2VsXI7gAti2pBoLClFFTMOO1HTtT0j99AuXLoGFKO6deHDdnv6ZGTxSTTUTgO1zVcv82fCOtDjYK4EECmWA=="
|
||||
},
|
||||
"d3-ease": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.7.tgz",
|
||||
"integrity": "sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ=="
|
||||
},
|
||||
"d3-force": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/d3-force/-/d3-force-2.1.1.tgz",
|
||||
"integrity": "sha512-nAuHEzBqMvpFVMf9OX75d00OxvOXdxY+xECIXjW6Gv8BRrXu6gAWbv/9XKrvfJ5i5DCokDW7RYE50LRoK092ew==",
|
||||
"requires": {
|
||||
"d3-dispatch": "1 - 2",
|
||||
"d3-quadtree": "1 - 2",
|
||||
"d3-timer": "1 - 2"
|
||||
}
|
||||
},
|
||||
"d3-geo": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-2.0.1.tgz",
|
||||
"integrity": "sha512-M6yzGbFRfxzNrVhxDJXzJqSLQ90q1cCyb3EWFZ1LF4eWOBYxFypw7I/NFVBNXKNqxv1bqLathhYvdJ6DC+th3A==",
|
||||
"requires": {
|
||||
"d3-array": ">=2.5"
|
||||
}
|
||||
},
|
||||
"d3-geo-projection": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/d3-geo-projection/-/d3-geo-projection-3.0.0.tgz",
|
||||
"integrity": "sha512-1JE+filVbkEX2bT25dJdQ05iA4QHvUwev6o0nIQHOSrNlHCAKfVss/U10vEM3pA4j5v7uQoFdQ4KLbx9BlEbWA==",
|
||||
"requires": {
|
||||
"commander": "2",
|
||||
"d3-array": "1 - 2",
|
||||
"d3-geo": "1.12.0 - 2",
|
||||
"resolve": "^1.1.10"
|
||||
},
|
||||
"dependencies": {
|
||||
"commander": {
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"d3-interpolate": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.4.0.tgz",
|
||||
"integrity": "sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==",
|
||||
"requires": {
|
||||
"d3-color": "1"
|
||||
}
|
||||
},
|
||||
"d3-quadtree": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-2.0.0.tgz",
|
||||
"integrity": "sha512-b0Ed2t1UUalJpc3qXzKi+cPGxeXRr4KU9YSlocN74aTzp6R/Ud43t79yLLqxHRWZfsvWXmbDWPpoENK1K539xw=="
|
||||
},
|
||||
"d3-selection": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.4.2.tgz",
|
||||
"integrity": "sha512-SJ0BqYihzOjDnnlfyeHT0e30k0K1+5sR3d5fNueCNeuhZTnGw4M4o8mqJchSwgKMXCNFo+e2VTChiSJ0vYtXkg=="
|
||||
},
|
||||
"d3-timer": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-2.0.0.tgz",
|
||||
"integrity": "sha512-TO4VLh0/420Y/9dO3+f9abDEFYeCUr2WZRlxJvbp4HPTQcSylXNiL6yZa9FIUvV1yRiFufl1bszTCLDqv9PWNA=="
|
||||
},
|
||||
"d3-transition": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.3.2.tgz",
|
||||
"integrity": "sha512-sc0gRU4PFqZ47lPVHloMn9tlPcv8jxgOQg+0zjhfZXMQuvppjG6YuwdMBE0TuqCZjeJkLecku/l9R0JPcRhaDA==",
|
||||
"requires": {
|
||||
"d3-color": "1",
|
||||
"d3-dispatch": "1",
|
||||
"d3-ease": "1",
|
||||
"d3-interpolate": "1",
|
||||
"d3-selection": "^1.1.0",
|
||||
"d3-timer": "1"
|
||||
},
|
||||
"dependencies": {
|
||||
"d3-dispatch": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.6.tgz",
|
||||
"integrity": "sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA=="
|
||||
},
|
||||
"d3-timer": {
|
||||
"version": "1.0.10",
|
||||
"resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz",
|
||||
"integrity": "sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"dargs": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz",
|
||||
"integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==",
|
||||
"dev": true
|
||||
},
|
||||
"dash-ast": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz",
|
||||
"integrity": "sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA=="
|
||||
},
|
||||
"debug": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
|
||||
|
|
@ -3972,8 +4370,7 @@
|
|||
"decamelize": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
|
||||
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
|
||||
"dev": true
|
||||
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
|
||||
},
|
||||
"decamelize-keys": {
|
||||
"version": "1.1.0",
|
||||
|
|
@ -4005,11 +4402,23 @@
|
|||
"integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=",
|
||||
"dev": true
|
||||
},
|
||||
"deep-equal": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz",
|
||||
"integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==",
|
||||
"requires": {
|
||||
"is-arguments": "^1.0.4",
|
||||
"is-date-object": "^1.0.1",
|
||||
"is-regex": "^1.0.4",
|
||||
"object-is": "^1.0.1",
|
||||
"object-keys": "^1.1.1",
|
||||
"regexp.prototype.flags": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"deep-is": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
|
||||
"integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
|
||||
"dev": true
|
||||
"integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ="
|
||||
},
|
||||
"deepmerge": {
|
||||
"version": "4.2.2",
|
||||
|
|
@ -4020,7 +4429,6 @@
|
|||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
|
||||
"integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"object-keys": "^1.0.12"
|
||||
}
|
||||
|
|
@ -4069,8 +4477,7 @@
|
|||
"defined": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz",
|
||||
"integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=",
|
||||
"dev": true
|
||||
"integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM="
|
||||
},
|
||||
"dependency-graph": {
|
||||
"version": "0.9.0",
|
||||
|
|
@ -4101,6 +4508,11 @@
|
|||
"minimist": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"dfa": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz",
|
||||
"integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q=="
|
||||
},
|
||||
"dir-glob": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
|
||||
|
|
@ -4177,6 +4589,22 @@
|
|||
"is-obj": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"dotignore": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/dotignore/-/dotignore-0.1.2.tgz",
|
||||
"integrity": "sha512-UGGGWfSauusaVJC+8fgV+NVvBXkCTmVv7sk6nojDZZvuOUNGUy0Zk4UpHQD6EDjS0jpBwcACvH4eofvyzBcRDw==",
|
||||
"requires": {
|
||||
"minimatch": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"duplexer2": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
|
||||
"integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=",
|
||||
"requires": {
|
||||
"readable-stream": "^2.0.2"
|
||||
}
|
||||
},
|
||||
"electron-to-chromium": {
|
||||
"version": "1.3.459",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.459.tgz",
|
||||
|
|
@ -4240,7 +4668,6 @@
|
|||
"version": "1.17.6",
|
||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz",
|
||||
"integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"es-to-primitive": "^1.2.1",
|
||||
"function-bind": "^1.1.1",
|
||||
|
|
@ -4258,8 +4685,7 @@
|
|||
"object-inspect": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz",
|
||||
"integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -4267,13 +4693,77 @@
|
|||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
|
||||
"integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-callable": "^1.1.4",
|
||||
"is-date-object": "^1.0.1",
|
||||
"is-symbol": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"es5-ext": {
|
||||
"version": "0.10.53",
|
||||
"resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz",
|
||||
"integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==",
|
||||
"requires": {
|
||||
"es6-iterator": "~2.0.3",
|
||||
"es6-symbol": "~3.1.3",
|
||||
"next-tick": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"es6-iterator": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
|
||||
"integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
|
||||
"requires": {
|
||||
"d": "1",
|
||||
"es5-ext": "^0.10.35",
|
||||
"es6-symbol": "^3.1.1"
|
||||
}
|
||||
},
|
||||
"es6-map": {
|
||||
"version": "0.1.5",
|
||||
"resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz",
|
||||
"integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=",
|
||||
"requires": {
|
||||
"d": "1",
|
||||
"es5-ext": "~0.10.14",
|
||||
"es6-iterator": "~2.0.1",
|
||||
"es6-set": "~0.1.5",
|
||||
"es6-symbol": "~3.1.1",
|
||||
"event-emitter": "~0.3.5"
|
||||
}
|
||||
},
|
||||
"es6-set": {
|
||||
"version": "0.1.5",
|
||||
"resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz",
|
||||
"integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=",
|
||||
"requires": {
|
||||
"d": "1",
|
||||
"es5-ext": "~0.10.14",
|
||||
"es6-iterator": "~2.0.1",
|
||||
"es6-symbol": "3.1.1",
|
||||
"event-emitter": "~0.3.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"es6-symbol": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz",
|
||||
"integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=",
|
||||
"requires": {
|
||||
"d": "1",
|
||||
"es5-ext": "~0.10.14"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"es6-symbol": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz",
|
||||
"integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
|
||||
"requires": {
|
||||
"d": "^1.0.1",
|
||||
"ext": "^1.1.2"
|
||||
}
|
||||
},
|
||||
"escalade": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.0.tgz",
|
||||
|
|
@ -4283,8 +4773,62 @@
|
|||
"escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
|
||||
"dev": true
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
|
||||
},
|
||||
"escodegen": {
|
||||
"version": "1.14.3",
|
||||
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz",
|
||||
"integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==",
|
||||
"requires": {
|
||||
"esprima": "^4.0.1",
|
||||
"estraverse": "^4.2.0",
|
||||
"esutils": "^2.0.2",
|
||||
"optionator": "^0.8.1",
|
||||
"source-map": "~0.6.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"levn": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
|
||||
"integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
|
||||
"requires": {
|
||||
"prelude-ls": "~1.1.2",
|
||||
"type-check": "~0.3.2"
|
||||
}
|
||||
},
|
||||
"optionator": {
|
||||
"version": "0.8.3",
|
||||
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
|
||||
"integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==",
|
||||
"requires": {
|
||||
"deep-is": "~0.1.3",
|
||||
"fast-levenshtein": "~2.0.6",
|
||||
"levn": "~0.3.0",
|
||||
"prelude-ls": "~1.1.2",
|
||||
"type-check": "~0.3.2",
|
||||
"word-wrap": "~1.2.3"
|
||||
}
|
||||
},
|
||||
"prelude-ls": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
|
||||
"integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ="
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"optional": true
|
||||
},
|
||||
"type-check": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
|
||||
"integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
|
||||
"requires": {
|
||||
"prelude-ls": "~1.1.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"eslint": {
|
||||
"version": "7.10.0",
|
||||
|
|
@ -4484,8 +5028,7 @@
|
|||
"esprima": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
||||
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
|
||||
"dev": true
|
||||
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
|
||||
},
|
||||
"esquery": {
|
||||
"version": "1.3.1",
|
||||
|
|
@ -4524,8 +5067,12 @@
|
|||
"estraverse": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
|
||||
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw=="
|
||||
},
|
||||
"estree-is-function": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/estree-is-function/-/estree-is-function-1.0.0.tgz",
|
||||
"integrity": "sha512-nSCWn1jkSq2QAtkaVLJZY2ezwcFO161HVc174zL1KPW3RJ+O6C3eJb8Nx7OXzvhoEv+nLgSR1g71oWUHUDTrJA=="
|
||||
},
|
||||
"estree-walker": {
|
||||
"version": "1.0.1",
|
||||
|
|
@ -4536,8 +5083,16 @@
|
|||
"esutils": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
|
||||
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
|
||||
"dev": true
|
||||
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="
|
||||
},
|
||||
"event-emitter": {
|
||||
"version": "0.3.5",
|
||||
"resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz",
|
||||
"integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=",
|
||||
"requires": {
|
||||
"d": "1",
|
||||
"es5-ext": "~0.10.14"
|
||||
}
|
||||
},
|
||||
"eventemitter3": {
|
||||
"version": "4.0.7",
|
||||
|
|
@ -4588,6 +5143,11 @@
|
|||
"clone-regexp": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"exit-on-epipe": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz",
|
||||
"integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw=="
|
||||
},
|
||||
"expand-brackets": {
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
|
||||
|
|
@ -4647,6 +5207,21 @@
|
|||
"homedir-polyfill": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"ext": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz",
|
||||
"integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==",
|
||||
"requires": {
|
||||
"type": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"type": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/type/-/type-2.1.0.tgz",
|
||||
"integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"extend": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||
|
|
@ -4830,8 +5405,7 @@
|
|||
"fast-levenshtein": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
|
||||
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
|
||||
"dev": true
|
||||
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc="
|
||||
},
|
||||
"fastest-levenshtein": {
|
||||
"version": "1.0.12",
|
||||
|
|
@ -4965,12 +5539,129 @@
|
|||
"integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==",
|
||||
"dev": true
|
||||
},
|
||||
"fmin": {
|
||||
"version": "0.0.2",
|
||||
"resolved": "https://registry.npmjs.org/fmin/-/fmin-0.0.2.tgz",
|
||||
"integrity": "sha1-Wbu0DUP/3ByUzQClaMQflfGXMBc=",
|
||||
"requires": {
|
||||
"contour_plot": "^0.0.1",
|
||||
"json2module": "^0.0.3",
|
||||
"rollup": "^0.25.8",
|
||||
"tape": "^4.5.1",
|
||||
"uglify-js": "^2.6.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
||||
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
|
||||
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
|
||||
},
|
||||
"chalk": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
||||
"requires": {
|
||||
"ansi-styles": "^2.2.1",
|
||||
"escape-string-regexp": "^1.0.2",
|
||||
"has-ansi": "^2.0.0",
|
||||
"strip-ansi": "^3.0.0",
|
||||
"supports-color": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"rollup": {
|
||||
"version": "0.25.8",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-0.25.8.tgz",
|
||||
"integrity": "sha1-v2zoO4dRDRY0Ru6qV37WpvxYNeA=",
|
||||
"requires": {
|
||||
"chalk": "^1.1.1",
|
||||
"minimist": "^1.2.0",
|
||||
"source-map-support": "^0.3.2"
|
||||
}
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.1.32",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.32.tgz",
|
||||
"integrity": "sha1-yLbBZ3l7pHQKjqMyUhYv8IWRsmY=",
|
||||
"requires": {
|
||||
"amdefine": ">=0.0.4"
|
||||
}
|
||||
},
|
||||
"source-map-support": {
|
||||
"version": "0.3.3",
|
||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.3.3.tgz",
|
||||
"integrity": "sha1-NJAJd9W6PwfHdX7nLnO7GptTdU8=",
|
||||
"requires": {
|
||||
"source-map": "0.1.32"
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
|
||||
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
|
||||
}
|
||||
}
|
||||
},
|
||||
"fontkit": {
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/fontkit/-/fontkit-1.8.1.tgz",
|
||||
"integrity": "sha512-BsNCjDoYRxmNWFdAuK1y9bQt+igIxGtTC9u/jSFjR9MKhmI00rP1fwSvERt+5ddE82544l0XH5mzXozQVUy2Tw==",
|
||||
"requires": {
|
||||
"babel-runtime": "^6.26.0",
|
||||
"brfs": "^2.0.0",
|
||||
"brotli": "^1.2.0",
|
||||
"browserify-optional": "^1.0.1",
|
||||
"clone": "^1.0.4",
|
||||
"deep-equal": "^1.0.0",
|
||||
"dfa": "^1.2.0",
|
||||
"restructure": "^0.5.3",
|
||||
"tiny-inflate": "^1.0.2",
|
||||
"unicode-properties": "^1.2.2",
|
||||
"unicode-trie": "^0.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"unicode-trie": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-0.3.1.tgz",
|
||||
"integrity": "sha1-1nHd3YkQGgi6w3tqUWEBBgIFIIU=",
|
||||
"requires": {
|
||||
"pako": "^0.2.5",
|
||||
"tiny-inflate": "^1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"for-each": {
|
||||
"version": "0.3.3",
|
||||
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
|
||||
"integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
|
||||
"requires": {
|
||||
"is-callable": "^1.1.3"
|
||||
}
|
||||
},
|
||||
"for-in": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
|
||||
"integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
|
||||
"dev": true
|
||||
},
|
||||
"frac": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz",
|
||||
"integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA=="
|
||||
},
|
||||
"fragment-cache": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
|
||||
|
|
@ -4994,8 +5685,7 @@
|
|||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
|
||||
"dev": true
|
||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
|
||||
},
|
||||
"fsevents": {
|
||||
"version": "2.1.3",
|
||||
|
|
@ -5007,8 +5697,7 @@
|
|||
"function-bind": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
|
||||
"dev": true
|
||||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
|
||||
},
|
||||
"functional-red-black-tree": {
|
||||
"version": "1.0.1",
|
||||
|
|
@ -5036,6 +5725,11 @@
|
|||
"integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==",
|
||||
"dev": true
|
||||
},
|
||||
"get-assigned-identifiers": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz",
|
||||
"integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ=="
|
||||
},
|
||||
"get-caller-file": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
||||
|
|
@ -5086,7 +5780,6 @@
|
|||
"version": "7.1.6",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
|
||||
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
|
|
@ -5189,7 +5882,6 @@
|
|||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
|
||||
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"function-bind": "^1.1.1"
|
||||
}
|
||||
|
|
@ -5198,7 +5890,6 @@
|
|||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
|
||||
"integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
},
|
||||
|
|
@ -5206,8 +5897,7 @@
|
|||
"ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
||||
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
|
||||
"dev": true
|
||||
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -5220,8 +5910,7 @@
|
|||
"has-symbols": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
|
||||
"integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg=="
|
||||
},
|
||||
"has-value": {
|
||||
"version": "1.0.0",
|
||||
|
|
@ -5471,7 +6160,6 @@
|
|||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
|
|
@ -5480,8 +6168,7 @@
|
|||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
|
|
@ -5580,6 +6267,11 @@
|
|||
"is-decimal": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"is-arguments": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz",
|
||||
"integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA=="
|
||||
},
|
||||
"is-arrayish": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
|
||||
|
|
@ -5598,14 +6290,12 @@
|
|||
"is-buffer": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
|
||||
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
|
||||
"dev": true
|
||||
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
|
||||
},
|
||||
"is-callable": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz",
|
||||
"integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw=="
|
||||
},
|
||||
"is-color-stop": {
|
||||
"version": "1.1.0",
|
||||
|
|
@ -5644,8 +6334,7 @@
|
|||
"is-date-object": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz",
|
||||
"integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==",
|
||||
"dev": true
|
||||
"integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g=="
|
||||
},
|
||||
"is-decimal": {
|
||||
"version": "1.0.4",
|
||||
|
|
@ -5717,6 +6406,11 @@
|
|||
"integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=",
|
||||
"dev": true
|
||||
},
|
||||
"is-negative-zero": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz",
|
||||
"integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE="
|
||||
},
|
||||
"is-number": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
|
||||
|
|
@ -5771,7 +6465,6 @@
|
|||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz",
|
||||
"integrity": "sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-symbols": "^1.0.1"
|
||||
}
|
||||
|
|
@ -5807,7 +6500,6 @@
|
|||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz",
|
||||
"integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-symbols": "^1.0.1"
|
||||
}
|
||||
|
|
@ -5854,8 +6546,7 @@
|
|||
"isarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
|
||||
"dev": true
|
||||
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
|
||||
},
|
||||
"isexe": {
|
||||
"version": "2.0.0",
|
||||
|
|
@ -5942,6 +6633,14 @@
|
|||
"integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
|
||||
"dev": true
|
||||
},
|
||||
"json2module": {
|
||||
"version": "0.0.3",
|
||||
"resolved": "https://registry.npmjs.org/json2module/-/json2module-0.0.3.tgz",
|
||||
"integrity": "sha1-APtfSpt638PwZHwpyxe80Zeb6bI=",
|
||||
"requires": {
|
||||
"rw": "^1.3.2"
|
||||
}
|
||||
},
|
||||
"json5": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz",
|
||||
|
|
@ -5978,6 +6677,11 @@
|
|||
"integrity": "sha512-eYboRV94Vco725nKMlpkn3nV2+96p9c3gKXRsYqAJSswSENvBhN7n5L+uDhY58xQa0UukWsDMTGELzmD8Q+wTA==",
|
||||
"dev": true
|
||||
},
|
||||
"lazy-cache": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
|
||||
"integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4="
|
||||
},
|
||||
"leven": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
|
||||
|
|
@ -6003,6 +6707,16 @@
|
|||
"type-check": "~0.4.0"
|
||||
}
|
||||
},
|
||||
"linebreak": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/linebreak/-/linebreak-1.0.2.tgz",
|
||||
"integrity": "sha512-bJwSRsJeAmaZYnkcwl5sCQNfSDAhBuXxb6L27tb+qkBRtUQSSTUa5bcgCPD6hFEkRNlpWHfK7nFMmcANU7ZP1w==",
|
||||
"requires": {
|
||||
"base64-js": "0.0.8",
|
||||
"brfs": "^2.0.2",
|
||||
"unicode-trie": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"lines-and-columns": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz",
|
||||
|
|
@ -6665,6 +7379,14 @@
|
|||
"integrity": "sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ==",
|
||||
"dev": true
|
||||
},
|
||||
"merge-source-map": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.0.4.tgz",
|
||||
"integrity": "sha1-pd5GU42uhNQRTMXqArR3KmNGcB8=",
|
||||
"requires": {
|
||||
"source-map": "^0.5.6"
|
||||
}
|
||||
},
|
||||
"merge-stream": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
||||
|
|
@ -6720,7 +7442,6 @@
|
|||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
|
|
@ -6728,8 +7449,7 @@
|
|||
"minimist": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
|
||||
},
|
||||
"minimist-options": {
|
||||
"version": "4.1.0",
|
||||
|
|
@ -6809,6 +7529,11 @@
|
|||
"integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
|
||||
"dev": true
|
||||
},
|
||||
"next-tick": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
|
||||
"integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw="
|
||||
},
|
||||
"node-emoji": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.10.0.tgz",
|
||||
|
|
@ -6933,11 +7658,69 @@
|
|||
"integrity": "sha512-JPKn0GMu+Fa3zt3Bmr66JhokJU5BaNBIh4ZeTlaCBzrBsOeXzwcKKAK1tbLiPKgvwmPXsDvvLHoWh5Bm7ofIYg==",
|
||||
"dev": true
|
||||
},
|
||||
"object-inspect": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz",
|
||||
"integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA=="
|
||||
},
|
||||
"object-is": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.3.tgz",
|
||||
"integrity": "sha512-teyqLvFWzLkq5B9ki8FVWA902UER2qkxmdA4nLf+wjOLAWgxzCWZNCxpDq9MvE8MmhWNr+I8w3BN49Vx36Y6Xg==",
|
||||
"requires": {
|
||||
"define-properties": "^1.1.3",
|
||||
"es-abstract": "^1.18.0-next.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"es-abstract": {
|
||||
"version": "1.18.0-next.1",
|
||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz",
|
||||
"integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==",
|
||||
"requires": {
|
||||
"es-to-primitive": "^1.2.1",
|
||||
"function-bind": "^1.1.1",
|
||||
"has": "^1.0.3",
|
||||
"has-symbols": "^1.0.1",
|
||||
"is-callable": "^1.2.2",
|
||||
"is-negative-zero": "^2.0.0",
|
||||
"is-regex": "^1.1.1",
|
||||
"object-inspect": "^1.8.0",
|
||||
"object-keys": "^1.1.1",
|
||||
"object.assign": "^4.1.1",
|
||||
"string.prototype.trimend": "^1.0.1",
|
||||
"string.prototype.trimstart": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"is-callable": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz",
|
||||
"integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA=="
|
||||
},
|
||||
"is-regex": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz",
|
||||
"integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==",
|
||||
"requires": {
|
||||
"has-symbols": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"object.assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz",
|
||||
"integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==",
|
||||
"requires": {
|
||||
"define-properties": "^1.1.3",
|
||||
"es-abstract": "^1.18.0-next.0",
|
||||
"has-symbols": "^1.0.1",
|
||||
"object-keys": "^1.1.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"object-keys": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
|
||||
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
|
||||
},
|
||||
"object-visit": {
|
||||
"version": "1.0.1",
|
||||
|
|
@ -6952,7 +7735,6 @@
|
|||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
|
||||
"integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"define-properties": "^1.1.2",
|
||||
"function-bind": "^1.1.1",
|
||||
|
|
@ -6995,7 +7777,6 @@
|
|||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
|
|
@ -7112,6 +7893,11 @@
|
|||
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
|
||||
"dev": true
|
||||
},
|
||||
"pako": {
|
||||
"version": "0.2.9",
|
||||
"resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
|
||||
"integrity": "sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU="
|
||||
},
|
||||
"parent-module": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
||||
|
|
@ -7174,8 +7960,7 @@
|
|||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
|
||||
"dev": true
|
||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
|
||||
},
|
||||
"path-key": {
|
||||
"version": "3.1.1",
|
||||
|
|
@ -7186,8 +7971,7 @@
|
|||
"path-parse": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
|
||||
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw=="
|
||||
},
|
||||
"path-type": {
|
||||
"version": "4.0.0",
|
||||
|
|
@ -7195,6 +7979,44 @@
|
|||
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
|
||||
"dev": true
|
||||
},
|
||||
"pdfkit": {
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/pdfkit/-/pdfkit-0.11.0.tgz",
|
||||
"integrity": "sha512-1s9gaumXkYxcVF1iRtSmLiISF2r4nHtsTgpwXiK8Swe+xwk/1pm8FJjYqN7L3x13NsWnGyUFntWcO8vfqq+wwA==",
|
||||
"requires": {
|
||||
"crypto-js": "^3.1.9-1",
|
||||
"fontkit": "^1.8.0",
|
||||
"linebreak": "^1.0.2",
|
||||
"png-js": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"pdfmake": {
|
||||
"version": "0.1.68",
|
||||
"resolved": "https://registry.npmjs.org/pdfmake/-/pdfmake-0.1.68.tgz",
|
||||
"integrity": "sha512-oE1VEjkluro3+QqvLbFgFU/rRgyKdbPy/Fh8SS/nsUxnsiUcm85ChpmD6YD0hQW1E0d3hppAo4Yh+xdXucenIA==",
|
||||
"requires": {
|
||||
"iconv-lite": "^0.6.2",
|
||||
"linebreak": "^1.0.2",
|
||||
"pdfkit": "^0.11.0",
|
||||
"svg-to-pdfkit": "^0.1.8",
|
||||
"xmldoc": "^1.1.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"iconv-lite": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz",
|
||||
"integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==",
|
||||
"requires": {
|
||||
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"performance-now": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
|
||||
},
|
||||
"php-parser": {
|
||||
"version": "github:glayzzle/php-parser#5a0e2e1bf12517bd1c544c0f4e68482d0362a7b5",
|
||||
"from": "github:glayzzle/php-parser#5a0e2e1bf12517bd1c544c0f4e68482d0362a7b5",
|
||||
|
|
@ -7290,6 +8112,19 @@
|
|||
"semver-compare": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"png-js": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/png-js/-/png-js-1.0.0.tgz",
|
||||
"integrity": "sha512-k+YsbhpA9e+EFfKjTCH3VW6aoKlyNYI6NYdTfDL4CIvFnvsuO84ttonmZE7rc+v23SLTH8XX+5w/Ak9v0xGY4g=="
|
||||
},
|
||||
"polylabel": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/polylabel/-/polylabel-1.1.0.tgz",
|
||||
"integrity": "sha512-bxaGcA40sL3d6M4hH72Z4NdLqxpXRsCFk8AITYg6x1rn1Ei3izf00UMLklerBZTO49aPA3CYrIwVulx2Bce2pA==",
|
||||
"requires": {
|
||||
"tinyqueue": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"posix-character-classes": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
|
||||
|
|
@ -8798,11 +9633,15 @@
|
|||
"integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=",
|
||||
"dev": true
|
||||
},
|
||||
"printj": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz",
|
||||
"integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ=="
|
||||
},
|
||||
"process-nextick-args": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
|
||||
"dev": true
|
||||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
|
||||
},
|
||||
"progress": {
|
||||
"version": "2.0.3",
|
||||
|
|
@ -9003,6 +9842,35 @@
|
|||
"integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==",
|
||||
"dev": true
|
||||
},
|
||||
"quote-stream": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/quote-stream/-/quote-stream-1.0.2.tgz",
|
||||
"integrity": "sha1-hJY/jJwmuULhU/7rU6rnRlK34LI=",
|
||||
"requires": {
|
||||
"buffer-equal": "0.0.1",
|
||||
"minimist": "^1.1.3",
|
||||
"through2": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"through2": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
|
||||
"integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
|
||||
"requires": {
|
||||
"readable-stream": "~2.3.6",
|
||||
"xtend": "~4.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"raf": {
|
||||
"version": "3.4.1",
|
||||
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
|
||||
"integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
|
||||
"requires": {
|
||||
"performance-now": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"randombytes": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||
|
|
@ -9076,7 +9944,6 @@
|
|||
"version": "2.3.7",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
|
||||
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"core-util-is": "~1.0.0",
|
||||
"inherits": "~2.0.3",
|
||||
|
|
@ -9173,6 +10040,15 @@
|
|||
"safe-regex": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"regexp.prototype.flags": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz",
|
||||
"integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==",
|
||||
"requires": {
|
||||
"define-properties": "^1.1.3",
|
||||
"es-abstract": "^1.17.0-next.1"
|
||||
}
|
||||
},
|
||||
"regexpp": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz",
|
||||
|
|
@ -9216,6 +10092,11 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"regression": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/regression/-/regression-2.0.1.tgz",
|
||||
"integrity": "sha1-jSnD6CJKEIUMNeM36FqLL6w7DIc="
|
||||
},
|
||||
"remark": {
|
||||
"version": "12.0.1",
|
||||
"resolved": "https://registry.npmjs.org/remark/-/remark-12.0.1.tgz",
|
||||
|
|
@ -9282,8 +10163,7 @@
|
|||
"repeat-string": {
|
||||
"version": "1.6.1",
|
||||
"resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
|
||||
"integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
|
||||
"dev": true
|
||||
"integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc="
|
||||
},
|
||||
"replace-ext": {
|
||||
"version": "1.0.0",
|
||||
|
|
@ -9307,7 +10187,6 @@
|
|||
"version": "1.17.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
|
||||
"integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"path-parse": "^1.0.6"
|
||||
}
|
||||
|
|
@ -9353,6 +10232,22 @@
|
|||
"signal-exit": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"restructure": {
|
||||
"version": "0.5.4",
|
||||
"resolved": "https://registry.npmjs.org/restructure/-/restructure-0.5.4.tgz",
|
||||
"integrity": "sha1-9U591WNZD7NP1r9Vh2EJrsyyjeg=",
|
||||
"requires": {
|
||||
"browserify-optional": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"resumer": {
|
||||
"version": "0.0.0",
|
||||
"resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz",
|
||||
"integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=",
|
||||
"requires": {
|
||||
"through": "~2.3.4"
|
||||
}
|
||||
},
|
||||
"ret": {
|
||||
"version": "0.1.15",
|
||||
"resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
|
||||
|
|
@ -9377,6 +10272,19 @@
|
|||
"integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=",
|
||||
"dev": true
|
||||
},
|
||||
"rgbcolor": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz",
|
||||
"integrity": "sha1-1lBezbMEplldom+ktDMHMGd1lF0="
|
||||
},
|
||||
"right-align": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
|
||||
"integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=",
|
||||
"requires": {
|
||||
"align-text": "^0.1.1"
|
||||
}
|
||||
},
|
||||
"rimraf": {
|
||||
"version": "2.6.3",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
|
||||
|
|
@ -9582,6 +10490,11 @@
|
|||
"integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==",
|
||||
"dev": true
|
||||
},
|
||||
"rw": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz",
|
||||
"integrity": "sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q="
|
||||
},
|
||||
"rxjs": {
|
||||
"version": "6.6.2",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.2.tgz",
|
||||
|
|
@ -9594,8 +10507,7 @@
|
|||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||
"dev": true
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||
},
|
||||
"safe-identifier": {
|
||||
"version": "0.4.2",
|
||||
|
|
@ -9615,14 +10527,26 @@
|
|||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"sax": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
|
||||
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
|
||||
},
|
||||
"scope-analyzer": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/scope-analyzer/-/scope-analyzer-2.1.1.tgz",
|
||||
"integrity": "sha512-azEAihtQ9mEyZGhfgTJy3IbOWEzeOrYbg7NcYEshPKnKd+LZmC3TNd5dmDxbLBsTG/JVWmCp+vDJ03vJjeXMHg==",
|
||||
"requires": {
|
||||
"array-from": "^2.1.1",
|
||||
"dash-ast": "^1.0.0",
|
||||
"es6-map": "^0.1.5",
|
||||
"es6-set": "^0.1.5",
|
||||
"es6-symbol": "^3.1.1",
|
||||
"estree-is-function": "^1.0.0",
|
||||
"get-assigned-identifiers": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "5.7.1",
|
||||
|
|
@ -9680,6 +10604,11 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"shallow-copy": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz",
|
||||
"integrity": "sha1-QV9CcC1z2BAzApLMXuhurhoRoXA="
|
||||
},
|
||||
"shebang-command": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||
|
|
@ -9852,8 +10781,7 @@
|
|||
"source-map": {
|
||||
"version": "0.5.7",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
|
||||
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
|
||||
"dev": true
|
||||
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w="
|
||||
},
|
||||
"source-map-resolve": {
|
||||
"version": "0.5.3",
|
||||
|
|
@ -9895,8 +10823,7 @@
|
|||
"sourcemap-codec": {
|
||||
"version": "1.4.8",
|
||||
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
|
||||
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA=="
|
||||
},
|
||||
"spdx-correct": {
|
||||
"version": "3.1.1",
|
||||
|
|
@ -9971,18 +10898,39 @@
|
|||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
|
||||
},
|
||||
"ssf": {
|
||||
"version": "0.11.2",
|
||||
"resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz",
|
||||
"integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==",
|
||||
"requires": {
|
||||
"frac": "~1.1.2"
|
||||
}
|
||||
},
|
||||
"stable": {
|
||||
"version": "0.1.8",
|
||||
"resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz",
|
||||
"integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==",
|
||||
"dev": true
|
||||
},
|
||||
"stackblur-canvas": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.4.0.tgz",
|
||||
"integrity": "sha512-Z+HixfgYV0ss3C342DxPwc+UvN1SYWqoz7Wsi3xEDWEnaBkSCL3Ey21gF4io+WlLm8/RIrSnCrDBIEcH4O+q5Q=="
|
||||
},
|
||||
"state-toggle": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/state-toggle/-/state-toggle-1.0.3.tgz",
|
||||
"integrity": "sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ==",
|
||||
"dev": true
|
||||
},
|
||||
"static-eval": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.1.0.tgz",
|
||||
"integrity": "sha512-agtxZ/kWSsCkI5E4QifRwsaPs0P0JmZV6dkLz6ILYfFYQGn+5plctanRN+IC8dJRiFkyXHrwEE3W9Wmx67uDbw==",
|
||||
"requires": {
|
||||
"escodegen": "^1.11.1"
|
||||
}
|
||||
},
|
||||
"static-extend": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
|
||||
|
|
@ -10004,6 +10952,46 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"static-module": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/static-module/-/static-module-3.0.4.tgz",
|
||||
"integrity": "sha512-gb0v0rrgpBkifXCa3yZXxqVmXDVE+ETXj6YlC/jt5VzOnGXR2C15+++eXuMDUYsePnbhf+lwW0pE1UXyOLtGCw==",
|
||||
"requires": {
|
||||
"acorn-node": "^1.3.0",
|
||||
"concat-stream": "~1.6.0",
|
||||
"convert-source-map": "^1.5.1",
|
||||
"duplexer2": "~0.1.4",
|
||||
"escodegen": "^1.11.1",
|
||||
"has": "^1.0.1",
|
||||
"magic-string": "0.25.1",
|
||||
"merge-source-map": "1.0.4",
|
||||
"object-inspect": "^1.6.0",
|
||||
"readable-stream": "~2.3.3",
|
||||
"scope-analyzer": "^2.0.1",
|
||||
"shallow-copy": "~0.0.1",
|
||||
"static-eval": "^2.0.5",
|
||||
"through2": "~2.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"magic-string": {
|
||||
"version": "0.25.1",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.1.tgz",
|
||||
"integrity": "sha512-sCuTz6pYom8Rlt4ISPFn6wuFodbKMIHUMv4Qko9P17dpxb7s52KJTmRuZZqHdGmLCK9AOcDare039nRIcfdkEg==",
|
||||
"requires": {
|
||||
"sourcemap-codec": "^1.4.1"
|
||||
}
|
||||
},
|
||||
"through2": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
|
||||
"integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
|
||||
"requires": {
|
||||
"readable-stream": "~2.3.6",
|
||||
"xtend": "~4.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"string-argv": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz",
|
||||
|
|
@ -10037,11 +11025,64 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"string.prototype.trim": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.2.tgz",
|
||||
"integrity": "sha512-b5yrbl3BXIjHau9Prk7U0RRYcUYdN4wGSVaqoBQS50CCE3KBuYU0TYRNPFCP7aVoNMX87HKThdMRVIP3giclKg==",
|
||||
"requires": {
|
||||
"define-properties": "^1.1.3",
|
||||
"es-abstract": "^1.18.0-next.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"es-abstract": {
|
||||
"version": "1.18.0-next.1",
|
||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz",
|
||||
"integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==",
|
||||
"requires": {
|
||||
"es-to-primitive": "^1.2.1",
|
||||
"function-bind": "^1.1.1",
|
||||
"has": "^1.0.3",
|
||||
"has-symbols": "^1.0.1",
|
||||
"is-callable": "^1.2.2",
|
||||
"is-negative-zero": "^2.0.0",
|
||||
"is-regex": "^1.1.1",
|
||||
"object-inspect": "^1.8.0",
|
||||
"object-keys": "^1.1.1",
|
||||
"object.assign": "^4.1.1",
|
||||
"string.prototype.trimend": "^1.0.1",
|
||||
"string.prototype.trimstart": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"is-callable": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz",
|
||||
"integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA=="
|
||||
},
|
||||
"is-regex": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz",
|
||||
"integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==",
|
||||
"requires": {
|
||||
"has-symbols": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"object.assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz",
|
||||
"integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==",
|
||||
"requires": {
|
||||
"define-properties": "^1.1.3",
|
||||
"es-abstract": "^1.18.0-next.0",
|
||||
"has-symbols": "^1.0.1",
|
||||
"object-keys": "^1.1.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"string.prototype.trimend": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz",
|
||||
"integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"define-properties": "^1.1.3",
|
||||
"es-abstract": "^1.17.5"
|
||||
|
|
@ -10051,7 +11092,6 @@
|
|||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz",
|
||||
"integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"define-properties": "^1.1.3",
|
||||
"es-abstract": "^1.17.5"
|
||||
|
|
@ -10061,7 +11101,6 @@
|
|||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"safe-buffer": "~5.1.0"
|
||||
}
|
||||
|
|
@ -10548,6 +11587,14 @@
|
|||
"integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=",
|
||||
"dev": true
|
||||
},
|
||||
"svg-to-pdfkit": {
|
||||
"version": "0.1.8",
|
||||
"resolved": "https://registry.npmjs.org/svg-to-pdfkit/-/svg-to-pdfkit-0.1.8.tgz",
|
||||
"integrity": "sha512-QItiGZBy5TstGy+q8mjQTMGRlDDOARXLxH+sgVm1n/LYeo0zFcQlcCh8m4zi8QxctrxB9Kue/lStc/RD5iLadQ==",
|
||||
"requires": {
|
||||
"pdfkit": ">=0.8.1"
|
||||
}
|
||||
},
|
||||
"svgo": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz",
|
||||
|
|
@ -10648,6 +11695,43 @@
|
|||
"resolve": "^1.14.2"
|
||||
}
|
||||
},
|
||||
"tape": {
|
||||
"version": "4.13.3",
|
||||
"resolved": "https://registry.npmjs.org/tape/-/tape-4.13.3.tgz",
|
||||
"integrity": "sha512-0/Y20PwRIUkQcTCSi4AASs+OANZZwqPKaipGCEwp10dQMipVvSZwUUCi01Y/OklIGyHKFhIcjock+DKnBfLAFw==",
|
||||
"requires": {
|
||||
"deep-equal": "~1.1.1",
|
||||
"defined": "~1.0.0",
|
||||
"dotignore": "~0.1.2",
|
||||
"for-each": "~0.3.3",
|
||||
"function-bind": "~1.1.1",
|
||||
"glob": "~7.1.6",
|
||||
"has": "~1.0.3",
|
||||
"inherits": "~2.0.4",
|
||||
"is-regex": "~1.0.5",
|
||||
"minimist": "~1.2.5",
|
||||
"object-inspect": "~1.7.0",
|
||||
"resolve": "~1.17.0",
|
||||
"resumer": "~0.0.0",
|
||||
"string.prototype.trim": "~1.2.1",
|
||||
"through": "~2.3.8"
|
||||
},
|
||||
"dependencies": {
|
||||
"is-regex": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz",
|
||||
"integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==",
|
||||
"requires": {
|
||||
"has": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"object-inspect": {
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz",
|
||||
"integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"terser": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-5.3.2.tgz",
|
||||
|
|
@ -10688,8 +11772,7 @@
|
|||
"through": {
|
||||
"version": "2.3.8",
|
||||
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
|
||||
"dev": true
|
||||
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
|
||||
},
|
||||
"through2": {
|
||||
"version": "3.0.2",
|
||||
|
|
@ -10707,6 +11790,16 @@
|
|||
"integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=",
|
||||
"dev": true
|
||||
},
|
||||
"tiny-inflate": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz",
|
||||
"integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw=="
|
||||
},
|
||||
"tinyqueue": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-2.0.3.tgz",
|
||||
"integrity": "sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA=="
|
||||
},
|
||||
"tmp": {
|
||||
"version": "0.0.33",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
|
||||
|
|
@ -10815,6 +11908,11 @@
|
|||
"tslib": "^1.8.1"
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
|
||||
"integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg=="
|
||||
},
|
||||
"type-check": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||
|
|
@ -10830,6 +11928,11 @@
|
|||
"integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==",
|
||||
"dev": true
|
||||
},
|
||||
"typedarray": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
|
||||
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
|
||||
},
|
||||
"typedarray-to-buffer": {
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
|
||||
|
|
@ -10850,6 +11953,50 @@
|
|||
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
|
||||
"integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA=="
|
||||
},
|
||||
"uglify-js": {
|
||||
"version": "2.8.29",
|
||||
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz",
|
||||
"integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=",
|
||||
"requires": {
|
||||
"source-map": "~0.5.1",
|
||||
"uglify-to-browserify": "~1.0.0",
|
||||
"yargs": "~3.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"camelcase": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
|
||||
"integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk="
|
||||
},
|
||||
"cliui": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
|
||||
"integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=",
|
||||
"requires": {
|
||||
"center-align": "^0.1.1",
|
||||
"right-align": "^0.1.1",
|
||||
"wordwrap": "0.0.2"
|
||||
}
|
||||
},
|
||||
"yargs": {
|
||||
"version": "3.10.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
|
||||
"integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=",
|
||||
"requires": {
|
||||
"camelcase": "^1.0.2",
|
||||
"cliui": "^2.1.0",
|
||||
"decamelize": "^1.0.0",
|
||||
"window-size": "0.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"uglify-to-browserify": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz",
|
||||
"integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=",
|
||||
"optional": true
|
||||
},
|
||||
"unherit": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz",
|
||||
|
|
@ -10882,12 +12029,46 @@
|
|||
"integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==",
|
||||
"dev": true
|
||||
},
|
||||
"unicode-properties": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.3.1.tgz",
|
||||
"integrity": "sha512-nIV3Tf3LcUEZttY/2g4ZJtGXhWwSkuLL+rCu0DIAMbjyVPj+8j5gNVz4T/sVbnQybIsd5SFGkPKg/756OY6jlA==",
|
||||
"requires": {
|
||||
"base64-js": "^1.3.0",
|
||||
"unicode-trie": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"base64-js": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
|
||||
"integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g=="
|
||||
},
|
||||
"unicode-trie": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz",
|
||||
"integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==",
|
||||
"requires": {
|
||||
"pako": "^0.2.5",
|
||||
"tiny-inflate": "^1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"unicode-property-aliases-ecmascript": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz",
|
||||
"integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==",
|
||||
"dev": true
|
||||
},
|
||||
"unicode-trie": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-1.0.0.tgz",
|
||||
"integrity": "sha512-v5raLKsobbFbWLMoX9+bChts/VhPPj3XpkNr/HbqkirXR1DPk8eo9IYKyvk0MQZFkaoRsFj2Rmaqgi2rfAZYtA==",
|
||||
"requires": {
|
||||
"pako": "^0.2.5",
|
||||
"tiny-inflate": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"unified": {
|
||||
"version": "9.2.0",
|
||||
"resolved": "https://registry.npmjs.org/unified/-/unified-9.2.0.tgz",
|
||||
|
|
@ -11070,8 +12251,7 @@
|
|||
"util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
|
||||
"dev": true
|
||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
|
||||
},
|
||||
"util.promisify": {
|
||||
"version": "1.0.1",
|
||||
|
|
@ -11107,6 +12287,16 @@
|
|||
"integrity": "sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==",
|
||||
"dev": true
|
||||
},
|
||||
"venn.js": {
|
||||
"version": "0.2.20",
|
||||
"resolved": "https://registry.npmjs.org/venn.js/-/venn.js-0.2.20.tgz",
|
||||
"integrity": "sha512-bb5SYq/wamY9fvcuErb9a0FJkgIFHJjkLZWonQ+DoKKuDX3WPH2B4ouI1ce4K2iejBklQy6r1ly8nOGIyOCO6w==",
|
||||
"requires": {
|
||||
"d3-selection": "^1.0.2",
|
||||
"d3-transition": "^1.0.1",
|
||||
"fmin": "0.0.2"
|
||||
}
|
||||
},
|
||||
"vfile": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/vfile/-/vfile-4.2.0.tgz",
|
||||
|
|
@ -11170,11 +12360,30 @@
|
|||
"integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=",
|
||||
"dev": true
|
||||
},
|
||||
"window-size": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
|
||||
"integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0="
|
||||
},
|
||||
"wmf": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz",
|
||||
"integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw=="
|
||||
},
|
||||
"word": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz",
|
||||
"integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA=="
|
||||
},
|
||||
"word-wrap": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
|
||||
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ=="
|
||||
},
|
||||
"wordwrap": {
|
||||
"version": "0.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
|
||||
"integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8="
|
||||
},
|
||||
"wrap-ansi": {
|
||||
"version": "6.2.0",
|
||||
|
|
@ -11249,8 +12458,7 @@
|
|||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
||||
"dev": true
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||
},
|
||||
"write": {
|
||||
"version": "1.0.3",
|
||||
|
|
@ -11273,11 +12481,41 @@
|
|||
"typedarray-to-buffer": "^3.1.5"
|
||||
}
|
||||
},
|
||||
"xlsx": {
|
||||
"version": "0.16.7",
|
||||
"resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.16.7.tgz",
|
||||
"integrity": "sha512-Xc4NRjci2Grbh9NDk/XoaWycJurxEug1wwn0aJCmB0NvIMyQuHYq2muWLWGidYNZPf94aUbqm6K8Fbjd7gKTZg==",
|
||||
"requires": {
|
||||
"adler-32": "~1.2.0",
|
||||
"cfb": "^1.1.4",
|
||||
"codepage": "~1.14.0",
|
||||
"commander": "~2.17.1",
|
||||
"crc-32": "~1.2.0",
|
||||
"exit-on-epipe": "~1.0.1",
|
||||
"ssf": "~0.11.2",
|
||||
"wmf": "~1.0.1",
|
||||
"word": "~0.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"commander": {
|
||||
"version": "2.17.1",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz",
|
||||
"integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"xmldoc": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/xmldoc/-/xmldoc-1.1.2.tgz",
|
||||
"integrity": "sha512-ruPC/fyPNck2BD1dpz0AZZyrEwMOrWTO5lDdIXS91rs3wtm4j+T8Rp2o+zoOYkkAxJTZRPOSnOGei1egoRmKMQ==",
|
||||
"requires": {
|
||||
"sax": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"xtend": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
|
||||
},
|
||||
"y18n": {
|
||||
"version": "4.0.0",
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
"commit": "git-cz"
|
||||
},
|
||||
"dependencies": {
|
||||
"@amcharts/amcharts4": "^4.9.37",
|
||||
"@amcharts/amcharts4-geodata": "^4.1.17",
|
||||
"@popperjs/core": "^2.5.3",
|
||||
"choices.js": "^9.0.1",
|
||||
"prosemirror-example-setup": "^1.1.2",
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 2.6 KiB |