├── .env-example.js
├── .github
└── workflows
│ └── node.js.yml
├── .gitignore
├── .travis.yml
├── README.md
├── bin
├── _ver.js
├── envjslint.js
└── server.js
├── data
├── chef-world-resume.geo.json
├── historic-geo.json
└── world-audio-geo.json
├── dist
└── geojson-popup.js
├── example
├── css
│ └── style.css
├── ev-charger.html
├── historic.html
├── resume.html
└── world.html
├── index.js
├── npm-deprecate
├── README.md
├── index.js
└── package.json
├── package-lock.json
├── package.json
└── src
├── popup-geojson-map.js
└── utils.js
/.env-example.js:
--------------------------------------------------------------------------------
1 | // Template for the Javascript (JSON) '.env.js' file.
2 |
3 | window.ENV =
4 | {
5 | "//": "Your Mapbox access token ('world' example only)",
6 | "ACCESS_TOKEN": "your.mapbox.public.access.token"
7 | }
8 |
--------------------------------------------------------------------------------
/.github/workflows/node.js.yml:
--------------------------------------------------------------------------------
1 | # This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
3 |
4 | # https://github.com/actions/starter-workflows/blob/main/ci/node.js.yml
5 |
6 | name: Node.js CI
7 |
8 | on:
9 | push:
10 | branches: [ master ]
11 | pull_request:
12 | branches: [ master ]
13 |
14 | jobs:
15 | build:
16 |
17 | runs-on: ubuntu-latest
18 |
19 | strategy:
20 | matrix:
21 | node-version: [ 14.x, 15.x ]
22 | # node-version: [10.x, 12.x, 14.x, 15.x]
23 | # See supported Node.js release schedule at https://nodejs.org/en/about/releases/
24 |
25 | steps:
26 | - uses: actions/checkout@v2
27 | - name: Use Node.js ${{ matrix.node-version }}
28 | uses: actions/setup-node@v1
29 | with:
30 | node-version: ${{ matrix.node-version }}
31 | - run: npm ci
32 | - run: npm run build --if-present
33 | - run: npm test
34 | - run: npm run copy-env
35 | - run: npm run envjslint-ci
36 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | #
2 |
3 | .env
4 | .env.js
5 | node_modules/
6 | npm-debug.log
7 | # package-lock.json
8 |
9 | # *.html
10 | !example/ev-charger.html
11 | !example/historic.html
12 | !example/resume.html
13 | !example/world.html
14 |
15 | dist/*
16 | !dist/geojson-popup.js
17 |
18 | *.png
19 |
20 | bin/_unc.js
21 | npm-deprecate*
22 | uncomment-*
23 |
24 | *BAK*
25 |
26 | # End.
27 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 |
3 | node_js: 14
4 |
5 | cache: npm
6 |
7 | git:
8 | depth: 8
9 |
10 | # install: npm ci
11 |
12 | before_script: npm run copy-env
13 |
14 | script:
15 | - npm run build
16 | - npm test
17 | - npm run envjslint-ci
18 |
19 | after_script:
20 | #- npm run envjs
21 | - ls -alh dist/
22 | - npm audit
23 | - npm outdated
24 |
25 | # End.
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | [![Node.js CI][gci-icon]][gci]
3 | [![Build status — Travis-CI][travis-icon]][travis]
4 | [![geojson-popup on Npmjs][npm-icon]][npm]
5 | [![js-semistandard-style][semi-icon]][semi]
6 | [![License][license-icon]][mit]
7 | [![Total downloads - NPMJS.com][downl-icon]][npm]
8 |
9 | # nfreear / geojson-popup
10 |
11 | Add GeoJSON-based templated popups to a [Leaflet][] map. See the audio-player example(s).
12 |
13 | Easily create interactive maps, with popups containing structured data, for example, audio players.
14 |
15 | Read the [introductory blog post][blog].
16 |
17 | ## Changelog
18 |
19 | * [Release notes on GitHub][rel]
20 |
21 | ## Build & test
22 |
23 | ```sh
24 | git clone https://github.com/nfreear/popup-geojson-map geojson-popup
25 | cd geojson-popup
26 | npm install && npm run build && npm test
27 | npm start
28 | ```
29 |
30 | ## Usage
31 |
32 | HTML containing a template, with placeholders, `title` and `audio_url`
33 |
34 | ```html
35 |
36 |
37 |
43 |
44 |
45 |
46 |
47 | ```
48 |
49 | GeoJSON, with properties corresponding to the template placeholders, `title` and `audio_url`:
50 |
51 | ```json
52 | "features": [
53 | {
54 | "type": "Feature",
55 | "properties": {
56 | "title": "raining on the roof of Jennie Lee Building.wav",
57 | "audio_url": "https://freesound.org/data/previews/92/92744_1315834-lq.mp3"
58 | },
59 | "geometry": {
60 | "type": "Point",
61 | "coordinates": [ -0.7110, 52.0241 ]
62 | }
63 | }
64 | ]
65 | ```
66 |
67 | ### `marker-symbol`
68 |
69 | [GeoJSON with `marker-symbol`][ev], and built in support for [Maki icons][maki]:
70 |
71 | ```html
72 |
78 | ```
79 |
80 | ```json
81 | {
82 | "type": "FeatureCollection",
83 | "features": [
84 | {
85 | "type": "Feature",
86 | "properties": {
87 | "marker-symbol": "fuel",
88 | "marker-class": "custom",
89 | "marker-html": "HTML",
90 | "title": "Estates charging point (7 kW)"
91 | },
92 | "geometry": {
93 | "type": "Point",
94 | "coordinates": [ -0.71138, 52.02565 ]
95 | }
96 | }
97 | ]
98 | }
99 | ```
100 |
101 | ---
102 |
103 | Software & specs:
104 | * [GeoJSON][]
105 | * [Leaflet][]
106 | * [Lodash.template][_tpl] - _bundled_
107 | * [SuperAgent][] - _bundled_
108 |
109 | Map tiles:
110 | * [Leaflet providers][prov] — _default / free._
111 | * [Mapbox][]
112 | * [National Library of Scotland - Historic Maps][NLS]
113 |
114 | Sources for example data & audio files:
115 | * [Freesound][]
116 | * [Commons][]
117 |
118 | ## Rename
119 |
120 | I'm renaming the NPM package from [`popup-geojson-map`][npm-old] to the clearer [`geojson-popup`][npm].
121 | (I'll probably re-name the GitHub repo. too.) _Sorry for any hassle!_
122 |
123 |
124 | ---
125 |
126 | * NPM: [geojson-popup][npm]
127 | * GitHub: [nfreear/popup-geojson-map][]
128 | * Gist: [nfreear/fd10..][gist]
129 |
130 | ---
131 | © 2016-2021 Nick Freear, | License: [MIT][].
132 |
133 |
134 | [blog]: https://nick.freear.org.uk/2017/06/27/geojson-popup-leaflet.html?utm_source=npm
135 | [MIT]: https://nfreear.mit-license.org/2016-2021 "MIT License | © 2016-2021 Nick Freear (date: 2016-09-26)"
136 | [travis-icon]: https://travis-ci.org/nfreear/popup-geojson-map.svg
137 | [travis]: https://travis-ci.org/nfreear/popup-geojson-map "Build status – Travis-CI"
138 | [npm-old]: https://npmjs.com/package/popup-geojson-map
139 | [npm]: https://npmjs.com/package/geojson-popup
140 | [nfreear/popup-geojson-map]: https://github.com/nfreear/popup-geojson-map
141 | [rel]: https://github.com/nfreear/popup-geojson-map/releases
142 | [gist]: https://gist.github.com/nfreear/fd1005a2af7a8166862011b8fcb8a821 "Gist: original JS (27-Sep-2016)"
143 | [resume]: https://gist.github.com/nfreear/cceecc6e1cabdf8f8f4302aaed10923d "Resume GeoJSON"
144 | [ev]: https://gist.github.com/nfreear/d1cb9d672dd33511056fa472c9bde36f "OU ev-charging GeoJSON"
145 |
146 | [RFC]: https://tools.ietf.org/html/rfc7946 "The GeoJSON Format, August 2016."
147 | [GeoJSON]: https://geojson.org/
148 | [Leaflet]: https://leafletjs.com/examples/geojson/ "Using GeoJSON with Leaflet"
149 | [SuperAgent]: https://visionmedia.github.io/superagent/
150 | [Superagent-X]: http://smalljs.org/ajax/superagent/
151 | [Lodash]: https://lodash.com/
152 | [_tpl]: https://npmjs.com/package/lodash.template
153 | [Underscore.js]: https://underscorejs.org/
154 | [Freesound]: https://freesound.org/search/?q=metro "Freesound search: 'metro'"
155 | [Commons]: https://commons.wikimedia.org/wiki/Category:Audio_files_of_music
156 | [prov]: https://leaflet-extras.github.io/leaflet-providers/preview/
157 | "'This page shows mini maps for all the layers available in Leaflet-providers.'"
158 | [Mapbox]: https://www.mapbox.com/
159 | [NLS]: http://maps.nls.uk/projects/api/ "National Library of Scotland - Historic Maps API."
160 | [maki]: https://www.mapbox.com/maki-icons/ "Maki is an icon set made for map designers."
161 |
162 | [semi]: https://github.com/Flet/semistandard
163 | [semi-icon]: https://img.shields.io/badge/code_style-semistandard-brightgreen.svg
164 | "Javascript coding style — 'semistandard'"
165 | [npm-icon]: https://img.shields.io/npm/v/geojson-popup.svg "Latest version ~ on NPM"
166 | [license-icon]: https://img.shields.io/npm/l/geojson-popup.svg
167 | [downl-icon]: https://img.shields.io/npm/dt/geojson-popup.svg "Count of total downloads ~NPM"
168 | [gci]: https://github.com/nfreear/popup-geojson-map/actions/workflows/node.js.yml
169 | [gci-icon]: https://github.com/nfreear/popup-geojson-map/actions/workflows/node.js.yml/badge.svg
170 |
171 |
172 | [End]: //.
173 |
--------------------------------------------------------------------------------
/bin/_ver.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | /**
4 | * CLI. Implant `package.version` in index.js, README.md etc.
5 | *
6 | * @copyright © Nick Freear, 04-June-, 25-June-2017.
7 | * @license MIT
8 | * @see https://github.com/nfreear/gaad-widget
9 | */
10 |
11 | const replace = require('replace');
12 | const INDEX_JS = path('/../index.js');
13 | const README = path('/../README.md');
14 | // const TEST_HTML = path('/../example/world.html');
15 | const PKG = require('../package.json');
16 | const VERSION_TAG = PKG.version; // Was: .replace(/\.0(-.+)?/, '$1');
17 | const LEAFLET_VER = PKG.peerDependencies.leaflet;
18 |
19 | console.warn('VERSION_TAG :', VERSION_TAG);
20 | console.warn('Leaflet JS :', LEAFLET_VER);
21 |
22 | replace({
23 | paths: [INDEX_JS],
24 | regex: /VERSION = '.+';(.+Auto.)?/,
25 | replacement: version('VERSION = \'%s\'; // '),
26 | count: true,
27 | recursive: false
28 | });
29 |
30 | replace({
31 | paths: [INDEX_JS],
32 | regex: /@version \d\.\d\.\d(-[.\w]+)?/,
33 | replacement: version('@version %s'),
34 | count: true,
35 | recursive: false
36 | });
37 |
38 | replace({
39 | paths: [README], // TEST_HTML ?
40 | regex: /\/(geojson-popup|popup-geojson-map)(\/|@)(\d\.\d\.\d(-[.\w]+)?)/g,
41 | replacement: version('/geojson-popup$2%s'),
42 | count: true,
43 | recursive: false
44 | });
45 |
46 | replace({
47 | paths: [ex('ev-charger'), ex('historic'), ex('resume'), ex('world')],
48 | regex: /leaflet@\d\.\d\.\d/g,
49 | replacement: 'leaflet@' + LEAFLET_VER,
50 | count: true,
51 | recursive: false
52 | });
53 |
54 | function ex (base) {
55 | return require('path').join(__dirname, '../example', base + '.html');
56 | }
57 |
58 | function path (file) {
59 | return require('path').join(__dirname, file);
60 | }
61 |
62 | function version (str) {
63 | return str.replace('%s', VERSION_TAG);
64 | }
65 |
--------------------------------------------------------------------------------
/bin/envjslint.js:
--------------------------------------------------------------------------------
1 | /*!
2 | Simple JSON linter for '.env.js' files.
3 | */
4 |
5 | /* global require, console */
6 |
7 | const envfile = '.env.js';
8 | const fs = require('fs');
9 | let script = fs.readFileSync(envfile, 'utf8');
10 |
11 | // script = script.replace(/(.*=|^\/\/.*|^;.*)/g, '');
12 | script = script.replace(/[\n;]/g, '').replace(/.*=/, '');
13 |
14 | const obj = JSON.parse(script);
15 |
16 | console.info('File contains valid JSON: ' + envfile);
17 | console.log(obj);
18 |
--------------------------------------------------------------------------------
/bin/server.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | /*!
4 | Web server for examples.
5 |
6 | In a terminal, type:
7 | npm start
8 | # node bin/index.js
9 |
10 | In a browser, visit:
11 | http://localhost:9000/example/world.html
12 |
13 | http://stackoverflow.com/questions/16333790/node-js-quick-file-server-static-files-over-http
14 |
15 | © Nick Freear, 27 October 2016.
16 | */
17 |
18 | /* global require, console, __dirname */
19 |
20 | const PORT = 9000;
21 | const nodeStatic = require('node-static');
22 | const path = require('path').join;
23 | const fileServer = new nodeStatic.Server(path(__dirname, '..'));
24 |
25 | require('http').createServer(function (request, response) {
26 | request.addListener('end', function () {
27 | fileServer.serve(request, response);
28 | }).resume();
29 | }).listen(PORT); // (8080);
30 |
31 | console.info('Web server running...');
32 | console.info('Visit: http://localhost:%d/example/world.html', PORT);
33 | console.info('Type control + C to exit.');
34 |
--------------------------------------------------------------------------------
/data/chef-world-resume.geo.json:
--------------------------------------------------------------------------------
1 | {
2 | "#": [
3 | "Example of a CV or résumé for a globe-trotting chef, based on a world map!",
4 | "https://gist.github.com/nfreear/cceecc6e1cabdf8f8f4302aaed10923d"
5 | ],
6 | "type": "FeatureCollection",
7 | "features": [
8 | {
9 | "type": "Feature",
10 | "properties": {
11 | "Employer": "Sofitel Hyland Shanghai, China.",
12 | "Job title": "Sou Chef",
13 | "Period": "2001 - 2003",
14 | "Summary": "This was my first job after food college. I learned lots about Chinese culture and food.",
15 | "url": "https://www.google.com/maps/place/Nanjing+Road/@31.2357851,121.4802126,19.93z/",
16 | "marker-symbol": "lodging",
17 | "marker-size": "medium",
18 | "marker-color": "6a94c4"
19 | },
20 | "geometry": {
21 | "type": "Point",
22 | "coordinates": [
23 | 121.4802126,
24 | 31.2357851
25 | ]
26 | }
27 | },
28 |
29 | {
30 | "type": "Feature",
31 | "properties": {
32 | "Employer": "Novotel Paris Gare de Lyon, France.",
33 | "Job title": "Head Chef",
34 | "Period": "2003-2008",
35 | "Summary": "I supervised the re-development of the restaurants in this long-established hotel. Under my stewardship, the restaurants went from 32% to 57% mean occupancy, over the course of 24 months",
36 | "url": "https://google.com/maps/place/Novotel+Paris+Gare+de+Lyon/@48.8453195,2.3732829,17z/",
37 | "marker-symbol": "restaurant",
38 | "marker-size": "large",
39 | "marker-color": "c48d6a"
40 | },
41 | "geometry": {
42 | "type": "Point",
43 | "coordinates": [
44 | 2.3732829,
45 | 48.8453195
46 | ]
47 | }
48 | },
49 |
50 | {
51 | "type": "Feature",
52 | "properties": {
53 | "Employer": "British Embassy, Washington DC, USA.",
54 | "Job title": "Head Chef",
55 | "Period": "2009-2012",
56 | "Summary": "We cater for everything from intimate meals for the ambassador and her family, through to formal banquets for visiting dignitaries with complex dietary requirements.",
57 | "url": "https://google.com/maps/place/British+Embassy/@38.9202794,-77.0651596,17z/",
58 | "marker-symbol": "commercial",
59 | "marker-size": "large",
60 | "marker-color": "c4ba6a",
61 | "marker-color-x": "af6ac4"
62 | },
63 | "geometry": {
64 | "type": "Point",
65 | "coordinates": [
66 | -77.0651596,
67 | 38.9202794
68 | ]
69 | }
70 | }
71 | ],
72 |
73 | "x-useful-resources": [
74 | "https://en.support.wordpress.com/shortcodes/#miscellaneous",
75 | "https://github.com/blog/1528-there-s-a-map-for-that",
76 | "https://help.github.com/articles/mapping-geojson-files-on-github/",
77 | "https://mapbox.com/maki-icons/",
78 | "https://sessions.edu/color-calculator/"
79 | ]
80 | }
81 |
--------------------------------------------------------------------------------
/data/historic-geo.json:
--------------------------------------------------------------------------------
1 | {
2 | "#": [
3 | "Interesting sounds relating to Milton Keynes and London, UK."
4 | ],
5 | "type": "FeatureCollection",
6 | "features": [
7 | {
8 | "type": "Feature",
9 | "properties": {
10 | "title": "raining on the roof of Jennie Lee Building.wav",
11 | "description": "'Rain on the roof of the Jennie Lee Building of Open University in Milton Keynes...'",
12 | "audio_url": "http://freesound.org/data/previews/92/92744_1315834-lq.mp3",
13 | "credit_url": "http://freesound.org/people/laspaziale/sounds/92744/"
14 | },
15 | "geometry": {
16 | "type": "Point",
17 | "coordinates": [ -0.711009, 52.024157 ]
18 | }
19 | },
20 | {
21 | "type": "Feature",
22 | "properties": {
23 | "title": "London Underground - Mind The Gap",
24 | "description": "'Short sample of the famous 'mind the gap' announcement...'",
25 | "audio_url": "https://freesound.org/data/previews/327/327942_4486188-lq.mp3",
26 | "credit_url": "http://freesound.org/people/kwahmah_02/sounds/327942/"
27 | },
28 | "geometry": {
29 | "type": "Point",
30 | "coordinates": [ -0.09, 51.505 ]
31 | }
32 | }
33 | ]
34 | }
35 |
--------------------------------------------------------------------------------
/data/world-audio-geo.json:
--------------------------------------------------------------------------------
1 | {
2 | "#": [
3 | "Short audio files from Wikipedia & Freesound, relating to radio and undergrounds/ subways, from round the world."
4 | ],
5 | "type": "FeatureCollection",
6 | "features": [
7 | {
8 | "type": "Feature",
9 | "properties": {
10 | "title": "Budapest metro Jingle",
11 | "description": "Budapest, Hungary",
12 | "audio_url": "https://upload.wikimedia.org/wikipedia/commons/4/41/Budapest_metro_jingle.ogg",
13 | "credit_url": "https://commons.wikimedia.org/wiki/File:Budapest_metro_jingle.ogg",
14 | "marker-symbol": "commercial",
15 | "marker-size": "large",
16 | "marker-color": "c4ba6a"
17 | },
18 | "geometry": {
19 | "type": "Point",
20 | "coordinates": [ 18.8494264, 47.4808706 ]
21 | }
22 | },
23 | {
24 | "type": "Feature",
25 | "properties": {
26 | "title": "News CS jingle",
27 | "description": "Prague, Czech Republic",
28 | "audio_url": "https://upload.wikimedia.org/wikipedia/commons/d/da/News-cs-jingle.ogg",
29 | "credit_url": "https://commons.wikimedia.org/wiki/File:News-cs-jingle.ogg"
30 | },
31 | "geometry": {
32 | "type": "Point",
33 | "coordinates": [ 14.3819975, 50.0842324 ]
34 | }
35 | },
36 |
37 | {
38 | "type": "Feature",
39 | "properties": {
40 | "title": "Sleepys jingle",
41 | "description": "Bed maker — Hicksville, New York.",
42 | "audio_url": "https://upload.wikimedia.org/wikipedia/commons/c/c9/Sleepys_jingle_60_seconds.ogg",
43 | "credit_url": "https://commons.wikimedia.org/wiki/File:Sleepys_jingle_60_seconds.ogg"
44 | },
45 | "geometry": {
46 | "type": "Point",
47 | "coordinates": [ -73.523333, 40.763333 ]
48 | }
49 | },
50 | {
51 | "type": "Feature",
52 | "properties": {
53 | "title": "ding-dong3",
54 | "description": "'Recorded at a metro station in Barcelona'",
55 | "audio_url": "https://freesound.org/data/previews/155/155776_2767757-lq.mp3",
56 | "credit_url": "http://freesound.org/people/MetroSoundBCN/sounds/155776/"
57 | },
58 | "geometry": {
59 | "type": "Point",
60 | "coordinates": [ 2.0083379, 41.3947046 ]
61 | }
62 | },
63 | {
64 | "type": "Feature",
65 | "properties": {
66 | "title": "London Underground - Mind The Gap",
67 | "description": "'Short sample of the famous 'mind the gap' announcement...'",
68 | "audio_url": "https://freesound.org/data/previews/327/327942_4486188-lq.mp3",
69 | "credit_url": "http://freesound.org/people/kwahmah_02/sounds/327942/"
70 | },
71 | "geometry": {
72 | "type": "Point",
73 | "coordinates": [ -0.09, 51.505 ]
74 | }
75 | }
76 | ]
77 | }
78 |
--------------------------------------------------------------------------------
/dist/geojson-popup.js:
--------------------------------------------------------------------------------
1 | (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i
12 |
13 | const utils = require('./src/utils');
14 | const lodashish = {
15 | template: require('lodash.template'),
16 | extend: utils.extend,
17 | cdn: utils.cdn
18 | };
19 | const window = global; // || window;
20 |
21 | require('./src/popup-geojson-map')(window, lodashish, VERSION);
22 |
23 | }).call(this)}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
24 |
25 | },{"./src/popup-geojson-map":5,"./src/utils":6,"lodash.template":3}],2:[function(require,module,exports){
26 | /**
27 | * lodash 3.0.0 (Custom Build)
28 | * Build: `lodash modern modularize exports="npm" -o ./`
29 | * Copyright 2012-2015 The Dojo Foundation
30 | * Based on Underscore.js 1.7.0
31 | * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
32 | * Available under MIT license
33 | */
34 |
35 | /** Used to match template delimiters. */
36 | var reInterpolate = /<%=([\s\S]+?)%>/g;
37 |
38 | module.exports = reInterpolate;
39 |
40 | },{}],3:[function(require,module,exports){
41 | (function (global){(function (){
42 | /**
43 | * Lodash (Custom Build)
44 | * Build: `lodash modularize exports="npm" -o ./`
45 | * Copyright OpenJS Foundation and other contributors
46 | * Released under MIT license
47 | * Based on Underscore.js 1.8.3
48 | * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
49 | */
50 | var reInterpolate = require('lodash._reinterpolate'),
51 | templateSettings = require('lodash.templatesettings');
52 |
53 | /** Used to detect hot functions by number of calls within a span of milliseconds. */
54 | var HOT_COUNT = 800,
55 | HOT_SPAN = 16;
56 |
57 | /** Used as references for various `Number` constants. */
58 | var INFINITY = 1 / 0,
59 | MAX_SAFE_INTEGER = 9007199254740991;
60 |
61 | /** `Object#toString` result references. */
62 | var argsTag = '[object Arguments]',
63 | arrayTag = '[object Array]',
64 | asyncTag = '[object AsyncFunction]',
65 | boolTag = '[object Boolean]',
66 | dateTag = '[object Date]',
67 | domExcTag = '[object DOMException]',
68 | errorTag = '[object Error]',
69 | funcTag = '[object Function]',
70 | genTag = '[object GeneratorFunction]',
71 | mapTag = '[object Map]',
72 | numberTag = '[object Number]',
73 | nullTag = '[object Null]',
74 | objectTag = '[object Object]',
75 | proxyTag = '[object Proxy]',
76 | regexpTag = '[object RegExp]',
77 | setTag = '[object Set]',
78 | stringTag = '[object String]',
79 | symbolTag = '[object Symbol]',
80 | undefinedTag = '[object Undefined]',
81 | weakMapTag = '[object WeakMap]';
82 |
83 | var arrayBufferTag = '[object ArrayBuffer]',
84 | dataViewTag = '[object DataView]',
85 | float32Tag = '[object Float32Array]',
86 | float64Tag = '[object Float64Array]',
87 | int8Tag = '[object Int8Array]',
88 | int16Tag = '[object Int16Array]',
89 | int32Tag = '[object Int32Array]',
90 | uint8Tag = '[object Uint8Array]',
91 | uint8ClampedTag = '[object Uint8ClampedArray]',
92 | uint16Tag = '[object Uint16Array]',
93 | uint32Tag = '[object Uint32Array]';
94 |
95 | /** Used to match empty string literals in compiled template source. */
96 | var reEmptyStringLeading = /\b__p \+= '';/g,
97 | reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
98 | reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
99 |
100 | /**
101 | * Used to match `RegExp`
102 | * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
103 | */
104 | var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;
105 |
106 | /**
107 | * Used to match
108 | * [ES template delimiters](http://ecma-international.org/ecma-262/7.0/#sec-template-literal-lexical-components).
109 | */
110 | var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
111 |
112 | /** Used to detect host constructors (Safari). */
113 | var reIsHostCtor = /^\[object .+?Constructor\]$/;
114 |
115 | /** Used to detect unsigned integer values. */
116 | var reIsUint = /^(?:0|[1-9]\d*)$/;
117 |
118 | /** Used to ensure capturing order of template delimiters. */
119 | var reNoMatch = /($^)/;
120 |
121 | /** Used to match unescaped characters in compiled string literals. */
122 | var reUnescapedString = /['\n\r\u2028\u2029\\]/g;
123 |
124 | /** Used to identify `toStringTag` values of typed arrays. */
125 | var typedArrayTags = {};
126 | typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
127 | typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
128 | typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
129 | typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
130 | typedArrayTags[uint32Tag] = true;
131 | typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
132 | typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
133 | typedArrayTags[dataViewTag] = typedArrayTags[dateTag] =
134 | typedArrayTags[errorTag] = typedArrayTags[funcTag] =
135 | typedArrayTags[mapTag] = typedArrayTags[numberTag] =
136 | typedArrayTags[objectTag] = typedArrayTags[regexpTag] =
137 | typedArrayTags[setTag] = typedArrayTags[stringTag] =
138 | typedArrayTags[weakMapTag] = false;
139 |
140 | /** Used to escape characters for inclusion in compiled string literals. */
141 | var stringEscapes = {
142 | '\\': '\\',
143 | "'": "'",
144 | '\n': 'n',
145 | '\r': 'r',
146 | '\u2028': 'u2028',
147 | '\u2029': 'u2029'
148 | };
149 |
150 | /** Detect free variable `global` from Node.js. */
151 | var freeGlobal = typeof global == 'object' && global && global.Object === Object && global;
152 |
153 | /** Detect free variable `self`. */
154 | var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
155 |
156 | /** Used as a reference to the global object. */
157 | var root = freeGlobal || freeSelf || Function('return this')();
158 |
159 | /** Detect free variable `exports`. */
160 | var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;
161 |
162 | /** Detect free variable `module`. */
163 | var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;
164 |
165 | /** Detect the popular CommonJS extension `module.exports`. */
166 | var moduleExports = freeModule && freeModule.exports === freeExports;
167 |
168 | /** Detect free variable `process` from Node.js. */
169 | var freeProcess = moduleExports && freeGlobal.process;
170 |
171 | /** Used to access faster Node.js helpers. */
172 | var nodeUtil = (function() {
173 | try {
174 | // Use `util.types` for Node.js 10+.
175 | var types = freeModule && freeModule.require && freeModule.require('util').types;
176 |
177 | if (types) {
178 | return types;
179 | }
180 |
181 | // Legacy `process.binding('util')` for Node.js < 10.
182 | return freeProcess && freeProcess.binding && freeProcess.binding('util');
183 | } catch (e) {}
184 | }());
185 |
186 | /* Node.js helper references. */
187 | var nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;
188 |
189 | /**
190 | * A faster alternative to `Function#apply`, this function invokes `func`
191 | * with the `this` binding of `thisArg` and the arguments of `args`.
192 | *
193 | * @private
194 | * @param {Function} func The function to invoke.
195 | * @param {*} thisArg The `this` binding of `func`.
196 | * @param {Array} args The arguments to invoke `func` with.
197 | * @returns {*} Returns the result of `func`.
198 | */
199 | function apply(func, thisArg, args) {
200 | switch (args.length) {
201 | case 0: return func.call(thisArg);
202 | case 1: return func.call(thisArg, args[0]);
203 | case 2: return func.call(thisArg, args[0], args[1]);
204 | case 3: return func.call(thisArg, args[0], args[1], args[2]);
205 | }
206 | return func.apply(thisArg, args);
207 | }
208 |
209 | /**
210 | * A specialized version of `_.map` for arrays without support for iteratee
211 | * shorthands.
212 | *
213 | * @private
214 | * @param {Array} [array] The array to iterate over.
215 | * @param {Function} iteratee The function invoked per iteration.
216 | * @returns {Array} Returns the new mapped array.
217 | */
218 | function arrayMap(array, iteratee) {
219 | var index = -1,
220 | length = array == null ? 0 : array.length,
221 | result = Array(length);
222 |
223 | while (++index < length) {
224 | result[index] = iteratee(array[index], index, array);
225 | }
226 | return result;
227 | }
228 |
229 | /**
230 | * The base implementation of `_.times` without support for iteratee shorthands
231 | * or max array length checks.
232 | *
233 | * @private
234 | * @param {number} n The number of times to invoke `iteratee`.
235 | * @param {Function} iteratee The function invoked per iteration.
236 | * @returns {Array} Returns the array of results.
237 | */
238 | function baseTimes(n, iteratee) {
239 | var index = -1,
240 | result = Array(n);
241 |
242 | while (++index < n) {
243 | result[index] = iteratee(index);
244 | }
245 | return result;
246 | }
247 |
248 | /**
249 | * The base implementation of `_.unary` without support for storing metadata.
250 | *
251 | * @private
252 | * @param {Function} func The function to cap arguments for.
253 | * @returns {Function} Returns the new capped function.
254 | */
255 | function baseUnary(func) {
256 | return function(value) {
257 | return func(value);
258 | };
259 | }
260 |
261 | /**
262 | * The base implementation of `_.values` and `_.valuesIn` which creates an
263 | * array of `object` property values corresponding to the property names
264 | * of `props`.
265 | *
266 | * @private
267 | * @param {Object} object The object to query.
268 | * @param {Array} props The property names to get values for.
269 | * @returns {Object} Returns the array of property values.
270 | */
271 | function baseValues(object, props) {
272 | return arrayMap(props, function(key) {
273 | return object[key];
274 | });
275 | }
276 |
277 | /**
278 | * Used by `_.template` to escape characters for inclusion in compiled string literals.
279 | *
280 | * @private
281 | * @param {string} chr The matched character to escape.
282 | * @returns {string} Returns the escaped character.
283 | */
284 | function escapeStringChar(chr) {
285 | return '\\' + stringEscapes[chr];
286 | }
287 |
288 | /**
289 | * Gets the value at `key` of `object`.
290 | *
291 | * @private
292 | * @param {Object} [object] The object to query.
293 | * @param {string} key The key of the property to get.
294 | * @returns {*} Returns the property value.
295 | */
296 | function getValue(object, key) {
297 | return object == null ? undefined : object[key];
298 | }
299 |
300 | /**
301 | * Creates a unary function that invokes `func` with its argument transformed.
302 | *
303 | * @private
304 | * @param {Function} func The function to wrap.
305 | * @param {Function} transform The argument transform.
306 | * @returns {Function} Returns the new function.
307 | */
308 | function overArg(func, transform) {
309 | return function(arg) {
310 | return func(transform(arg));
311 | };
312 | }
313 |
314 | /** Used for built-in method references. */
315 | var funcProto = Function.prototype,
316 | objectProto = Object.prototype;
317 |
318 | /** Used to detect overreaching core-js shims. */
319 | var coreJsData = root['__core-js_shared__'];
320 |
321 | /** Used to resolve the decompiled source of functions. */
322 | var funcToString = funcProto.toString;
323 |
324 | /** Used to check objects for own properties. */
325 | var hasOwnProperty = objectProto.hasOwnProperty;
326 |
327 | /** Used to detect methods masquerading as native. */
328 | var maskSrcKey = (function() {
329 | var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
330 | return uid ? ('Symbol(src)_1.' + uid) : '';
331 | }());
332 |
333 | /**
334 | * Used to resolve the
335 | * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
336 | * of values.
337 | */
338 | var nativeObjectToString = objectProto.toString;
339 |
340 | /** Used to infer the `Object` constructor. */
341 | var objectCtorString = funcToString.call(Object);
342 |
343 | /** Used to detect if a method is native. */
344 | var reIsNative = RegExp('^' +
345 | funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
346 | .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
347 | );
348 |
349 | /** Built-in value references. */
350 | var Buffer = moduleExports ? root.Buffer : undefined,
351 | Symbol = root.Symbol,
352 | getPrototype = overArg(Object.getPrototypeOf, Object),
353 | propertyIsEnumerable = objectProto.propertyIsEnumerable,
354 | symToStringTag = Symbol ? Symbol.toStringTag : undefined;
355 |
356 | var defineProperty = (function() {
357 | try {
358 | var func = getNative(Object, 'defineProperty');
359 | func({}, '', {});
360 | return func;
361 | } catch (e) {}
362 | }());
363 |
364 | /* Built-in method references for those with the same name as other `lodash` methods. */
365 | var nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined,
366 | nativeKeys = overArg(Object.keys, Object),
367 | nativeMax = Math.max,
368 | nativeNow = Date.now;
369 |
370 | /** Used to convert symbols to primitives and strings. */
371 | var symbolProto = Symbol ? Symbol.prototype : undefined,
372 | symbolToString = symbolProto ? symbolProto.toString : undefined;
373 |
374 | /**
375 | * Creates an array of the enumerable property names of the array-like `value`.
376 | *
377 | * @private
378 | * @param {*} value The value to query.
379 | * @param {boolean} inherited Specify returning inherited property names.
380 | * @returns {Array} Returns the array of property names.
381 | */
382 | function arrayLikeKeys(value, inherited) {
383 | var isArr = isArray(value),
384 | isArg = !isArr && isArguments(value),
385 | isBuff = !isArr && !isArg && isBuffer(value),
386 | isType = !isArr && !isArg && !isBuff && isTypedArray(value),
387 | skipIndexes = isArr || isArg || isBuff || isType,
388 | result = skipIndexes ? baseTimes(value.length, String) : [],
389 | length = result.length;
390 |
391 | for (var key in value) {
392 | if ((inherited || hasOwnProperty.call(value, key)) &&
393 | !(skipIndexes && (
394 | // Safari 9 has enumerable `arguments.length` in strict mode.
395 | key == 'length' ||
396 | // Node.js 0.10 has enumerable non-index properties on buffers.
397 | (isBuff && (key == 'offset' || key == 'parent')) ||
398 | // PhantomJS 2 has enumerable non-index properties on typed arrays.
399 | (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||
400 | // Skip index properties.
401 | isIndex(key, length)
402 | ))) {
403 | result.push(key);
404 | }
405 | }
406 | return result;
407 | }
408 |
409 | /**
410 | * Assigns `value` to `key` of `object` if the existing value is not equivalent
411 | * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
412 | * for equality comparisons.
413 | *
414 | * @private
415 | * @param {Object} object The object to modify.
416 | * @param {string} key The key of the property to assign.
417 | * @param {*} value The value to assign.
418 | */
419 | function assignValue(object, key, value) {
420 | var objValue = object[key];
421 | if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||
422 | (value === undefined && !(key in object))) {
423 | baseAssignValue(object, key, value);
424 | }
425 | }
426 |
427 | /**
428 | * The base implementation of `assignValue` and `assignMergeValue` without
429 | * value checks.
430 | *
431 | * @private
432 | * @param {Object} object The object to modify.
433 | * @param {string} key The key of the property to assign.
434 | * @param {*} value The value to assign.
435 | */
436 | function baseAssignValue(object, key, value) {
437 | if (key == '__proto__' && defineProperty) {
438 | defineProperty(object, key, {
439 | 'configurable': true,
440 | 'enumerable': true,
441 | 'value': value,
442 | 'writable': true
443 | });
444 | } else {
445 | object[key] = value;
446 | }
447 | }
448 |
449 | /**
450 | * The base implementation of `getTag` without fallbacks for buggy environments.
451 | *
452 | * @private
453 | * @param {*} value The value to query.
454 | * @returns {string} Returns the `toStringTag`.
455 | */
456 | function baseGetTag(value) {
457 | if (value == null) {
458 | return value === undefined ? undefinedTag : nullTag;
459 | }
460 | return (symToStringTag && symToStringTag in Object(value))
461 | ? getRawTag(value)
462 | : objectToString(value);
463 | }
464 |
465 | /**
466 | * The base implementation of `_.isArguments`.
467 | *
468 | * @private
469 | * @param {*} value The value to check.
470 | * @returns {boolean} Returns `true` if `value` is an `arguments` object,
471 | */
472 | function baseIsArguments(value) {
473 | return isObjectLike(value) && baseGetTag(value) == argsTag;
474 | }
475 |
476 | /**
477 | * The base implementation of `_.isNative` without bad shim checks.
478 | *
479 | * @private
480 | * @param {*} value The value to check.
481 | * @returns {boolean} Returns `true` if `value` is a native function,
482 | * else `false`.
483 | */
484 | function baseIsNative(value) {
485 | if (!isObject(value) || isMasked(value)) {
486 | return false;
487 | }
488 | var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
489 | return pattern.test(toSource(value));
490 | }
491 |
492 | /**
493 | * The base implementation of `_.isTypedArray` without Node.js optimizations.
494 | *
495 | * @private
496 | * @param {*} value The value to check.
497 | * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
498 | */
499 | function baseIsTypedArray(value) {
500 | return isObjectLike(value) &&
501 | isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
502 | }
503 |
504 | /**
505 | * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
506 | *
507 | * @private
508 | * @param {Object} object The object to query.
509 | * @returns {Array} Returns the array of property names.
510 | */
511 | function baseKeys(object) {
512 | if (!isPrototype(object)) {
513 | return nativeKeys(object);
514 | }
515 | var result = [];
516 | for (var key in Object(object)) {
517 | if (hasOwnProperty.call(object, key) && key != 'constructor') {
518 | result.push(key);
519 | }
520 | }
521 | return result;
522 | }
523 |
524 | /**
525 | * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.
526 | *
527 | * @private
528 | * @param {Object} object The object to query.
529 | * @returns {Array} Returns the array of property names.
530 | */
531 | function baseKeysIn(object) {
532 | if (!isObject(object)) {
533 | return nativeKeysIn(object);
534 | }
535 | var isProto = isPrototype(object),
536 | result = [];
537 |
538 | for (var key in object) {
539 | if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
540 | result.push(key);
541 | }
542 | }
543 | return result;
544 | }
545 |
546 | /**
547 | * The base implementation of `_.rest` which doesn't validate or coerce arguments.
548 | *
549 | * @private
550 | * @param {Function} func The function to apply a rest parameter to.
551 | * @param {number} [start=func.length-1] The start position of the rest parameter.
552 | * @returns {Function} Returns the new function.
553 | */
554 | function baseRest(func, start) {
555 | return setToString(overRest(func, start, identity), func + '');
556 | }
557 |
558 | /**
559 | * The base implementation of `setToString` without support for hot loop shorting.
560 | *
561 | * @private
562 | * @param {Function} func The function to modify.
563 | * @param {Function} string The `toString` result.
564 | * @returns {Function} Returns `func`.
565 | */
566 | var baseSetToString = !defineProperty ? identity : function(func, string) {
567 | return defineProperty(func, 'toString', {
568 | 'configurable': true,
569 | 'enumerable': false,
570 | 'value': constant(string),
571 | 'writable': true
572 | });
573 | };
574 |
575 | /**
576 | * The base implementation of `_.toString` which doesn't convert nullish
577 | * values to empty strings.
578 | *
579 | * @private
580 | * @param {*} value The value to process.
581 | * @returns {string} Returns the string.
582 | */
583 | function baseToString(value) {
584 | // Exit early for strings to avoid a performance hit in some environments.
585 | if (typeof value == 'string') {
586 | return value;
587 | }
588 | if (isArray(value)) {
589 | // Recursively convert values (susceptible to call stack limits).
590 | return arrayMap(value, baseToString) + '';
591 | }
592 | if (isSymbol(value)) {
593 | return symbolToString ? symbolToString.call(value) : '';
594 | }
595 | var result = (value + '');
596 | return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
597 | }
598 |
599 | /**
600 | * Copies properties of `source` to `object`.
601 | *
602 | * @private
603 | * @param {Object} source The object to copy properties from.
604 | * @param {Array} props The property identifiers to copy.
605 | * @param {Object} [object={}] The object to copy properties to.
606 | * @param {Function} [customizer] The function to customize copied values.
607 | * @returns {Object} Returns `object`.
608 | */
609 | function copyObject(source, props, object, customizer) {
610 | var isNew = !object;
611 | object || (object = {});
612 |
613 | var index = -1,
614 | length = props.length;
615 |
616 | while (++index < length) {
617 | var key = props[index];
618 |
619 | var newValue = customizer
620 | ? customizer(object[key], source[key], key, object, source)
621 | : undefined;
622 |
623 | if (newValue === undefined) {
624 | newValue = source[key];
625 | }
626 | if (isNew) {
627 | baseAssignValue(object, key, newValue);
628 | } else {
629 | assignValue(object, key, newValue);
630 | }
631 | }
632 | return object;
633 | }
634 |
635 | /**
636 | * Creates a function like `_.assign`.
637 | *
638 | * @private
639 | * @param {Function} assigner The function to assign values.
640 | * @returns {Function} Returns the new assigner function.
641 | */
642 | function createAssigner(assigner) {
643 | return baseRest(function(object, sources) {
644 | var index = -1,
645 | length = sources.length,
646 | customizer = length > 1 ? sources[length - 1] : undefined,
647 | guard = length > 2 ? sources[2] : undefined;
648 |
649 | customizer = (assigner.length > 3 && typeof customizer == 'function')
650 | ? (length--, customizer)
651 | : undefined;
652 |
653 | if (guard && isIterateeCall(sources[0], sources[1], guard)) {
654 | customizer = length < 3 ? undefined : customizer;
655 | length = 1;
656 | }
657 | object = Object(object);
658 | while (++index < length) {
659 | var source = sources[index];
660 | if (source) {
661 | assigner(object, source, index, customizer);
662 | }
663 | }
664 | return object;
665 | });
666 | }
667 |
668 | /**
669 | * Used by `_.defaults` to customize its `_.assignIn` use to assign properties
670 | * of source objects to the destination object for all destination properties
671 | * that resolve to `undefined`.
672 | *
673 | * @private
674 | * @param {*} objValue The destination value.
675 | * @param {*} srcValue The source value.
676 | * @param {string} key The key of the property to assign.
677 | * @param {Object} object The parent object of `objValue`.
678 | * @returns {*} Returns the value to assign.
679 | */
680 | function customDefaultsAssignIn(objValue, srcValue, key, object) {
681 | if (objValue === undefined ||
682 | (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) {
683 | return srcValue;
684 | }
685 | return objValue;
686 | }
687 |
688 | /**
689 | * Gets the native function at `key` of `object`.
690 | *
691 | * @private
692 | * @param {Object} object The object to query.
693 | * @param {string} key The key of the method to get.
694 | * @returns {*} Returns the function if it's native, else `undefined`.
695 | */
696 | function getNative(object, key) {
697 | var value = getValue(object, key);
698 | return baseIsNative(value) ? value : undefined;
699 | }
700 |
701 | /**
702 | * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
703 | *
704 | * @private
705 | * @param {*} value The value to query.
706 | * @returns {string} Returns the raw `toStringTag`.
707 | */
708 | function getRawTag(value) {
709 | var isOwn = hasOwnProperty.call(value, symToStringTag),
710 | tag = value[symToStringTag];
711 |
712 | try {
713 | value[symToStringTag] = undefined;
714 | var unmasked = true;
715 | } catch (e) {}
716 |
717 | var result = nativeObjectToString.call(value);
718 | if (unmasked) {
719 | if (isOwn) {
720 | value[symToStringTag] = tag;
721 | } else {
722 | delete value[symToStringTag];
723 | }
724 | }
725 | return result;
726 | }
727 |
728 | /**
729 | * Checks if `value` is a valid array-like index.
730 | *
731 | * @private
732 | * @param {*} value The value to check.
733 | * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
734 | * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
735 | */
736 | function isIndex(value, length) {
737 | var type = typeof value;
738 | length = length == null ? MAX_SAFE_INTEGER : length;
739 |
740 | return !!length &&
741 | (type == 'number' ||
742 | (type != 'symbol' && reIsUint.test(value))) &&
743 | (value > -1 && value % 1 == 0 && value < length);
744 | }
745 |
746 | /**
747 | * Checks if the given arguments are from an iteratee call.
748 | *
749 | * @private
750 | * @param {*} value The potential iteratee value argument.
751 | * @param {*} index The potential iteratee index or key argument.
752 | * @param {*} object The potential iteratee object argument.
753 | * @returns {boolean} Returns `true` if the arguments are from an iteratee call,
754 | * else `false`.
755 | */
756 | function isIterateeCall(value, index, object) {
757 | if (!isObject(object)) {
758 | return false;
759 | }
760 | var type = typeof index;
761 | if (type == 'number'
762 | ? (isArrayLike(object) && isIndex(index, object.length))
763 | : (type == 'string' && index in object)
764 | ) {
765 | return eq(object[index], value);
766 | }
767 | return false;
768 | }
769 |
770 | /**
771 | * Checks if `func` has its source masked.
772 | *
773 | * @private
774 | * @param {Function} func The function to check.
775 | * @returns {boolean} Returns `true` if `func` is masked, else `false`.
776 | */
777 | function isMasked(func) {
778 | return !!maskSrcKey && (maskSrcKey in func);
779 | }
780 |
781 | /**
782 | * Checks if `value` is likely a prototype object.
783 | *
784 | * @private
785 | * @param {*} value The value to check.
786 | * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
787 | */
788 | function isPrototype(value) {
789 | var Ctor = value && value.constructor,
790 | proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;
791 |
792 | return value === proto;
793 | }
794 |
795 | /**
796 | * This function is like
797 | * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
798 | * except that it includes inherited enumerable properties.
799 | *
800 | * @private
801 | * @param {Object} object The object to query.
802 | * @returns {Array} Returns the array of property names.
803 | */
804 | function nativeKeysIn(object) {
805 | var result = [];
806 | if (object != null) {
807 | for (var key in Object(object)) {
808 | result.push(key);
809 | }
810 | }
811 | return result;
812 | }
813 |
814 | /**
815 | * Converts `value` to a string using `Object.prototype.toString`.
816 | *
817 | * @private
818 | * @param {*} value The value to convert.
819 | * @returns {string} Returns the converted string.
820 | */
821 | function objectToString(value) {
822 | return nativeObjectToString.call(value);
823 | }
824 |
825 | /**
826 | * A specialized version of `baseRest` which transforms the rest array.
827 | *
828 | * @private
829 | * @param {Function} func The function to apply a rest parameter to.
830 | * @param {number} [start=func.length-1] The start position of the rest parameter.
831 | * @param {Function} transform The rest array transform.
832 | * @returns {Function} Returns the new function.
833 | */
834 | function overRest(func, start, transform) {
835 | start = nativeMax(start === undefined ? (func.length - 1) : start, 0);
836 | return function() {
837 | var args = arguments,
838 | index = -1,
839 | length = nativeMax(args.length - start, 0),
840 | array = Array(length);
841 |
842 | while (++index < length) {
843 | array[index] = args[start + index];
844 | }
845 | index = -1;
846 | var otherArgs = Array(start + 1);
847 | while (++index < start) {
848 | otherArgs[index] = args[index];
849 | }
850 | otherArgs[start] = transform(array);
851 | return apply(func, this, otherArgs);
852 | };
853 | }
854 |
855 | /**
856 | * Sets the `toString` method of `func` to return `string`.
857 | *
858 | * @private
859 | * @param {Function} func The function to modify.
860 | * @param {Function} string The `toString` result.
861 | * @returns {Function} Returns `func`.
862 | */
863 | var setToString = shortOut(baseSetToString);
864 |
865 | /**
866 | * Creates a function that'll short out and invoke `identity` instead
867 | * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`
868 | * milliseconds.
869 | *
870 | * @private
871 | * @param {Function} func The function to restrict.
872 | * @returns {Function} Returns the new shortable function.
873 | */
874 | function shortOut(func) {
875 | var count = 0,
876 | lastCalled = 0;
877 |
878 | return function() {
879 | var stamp = nativeNow(),
880 | remaining = HOT_SPAN - (stamp - lastCalled);
881 |
882 | lastCalled = stamp;
883 | if (remaining > 0) {
884 | if (++count >= HOT_COUNT) {
885 | return arguments[0];
886 | }
887 | } else {
888 | count = 0;
889 | }
890 | return func.apply(undefined, arguments);
891 | };
892 | }
893 |
894 | /**
895 | * Converts `func` to its source code.
896 | *
897 | * @private
898 | * @param {Function} func The function to convert.
899 | * @returns {string} Returns the source code.
900 | */
901 | function toSource(func) {
902 | if (func != null) {
903 | try {
904 | return funcToString.call(func);
905 | } catch (e) {}
906 | try {
907 | return (func + '');
908 | } catch (e) {}
909 | }
910 | return '';
911 | }
912 |
913 | /**
914 | * Performs a
915 | * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
916 | * comparison between two values to determine if they are equivalent.
917 | *
918 | * @static
919 | * @memberOf _
920 | * @since 4.0.0
921 | * @category Lang
922 | * @param {*} value The value to compare.
923 | * @param {*} other The other value to compare.
924 | * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
925 | * @example
926 | *
927 | * var object = { 'a': 1 };
928 | * var other = { 'a': 1 };
929 | *
930 | * _.eq(object, object);
931 | * // => true
932 | *
933 | * _.eq(object, other);
934 | * // => false
935 | *
936 | * _.eq('a', 'a');
937 | * // => true
938 | *
939 | * _.eq('a', Object('a'));
940 | * // => false
941 | *
942 | * _.eq(NaN, NaN);
943 | * // => true
944 | */
945 | function eq(value, other) {
946 | return value === other || (value !== value && other !== other);
947 | }
948 |
949 | /**
950 | * Checks if `value` is likely an `arguments` object.
951 | *
952 | * @static
953 | * @memberOf _
954 | * @since 0.1.0
955 | * @category Lang
956 | * @param {*} value The value to check.
957 | * @returns {boolean} Returns `true` if `value` is an `arguments` object,
958 | * else `false`.
959 | * @example
960 | *
961 | * _.isArguments(function() { return arguments; }());
962 | * // => true
963 | *
964 | * _.isArguments([1, 2, 3]);
965 | * // => false
966 | */
967 | var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {
968 | return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&
969 | !propertyIsEnumerable.call(value, 'callee');
970 | };
971 |
972 | /**
973 | * Checks if `value` is classified as an `Array` object.
974 | *
975 | * @static
976 | * @memberOf _
977 | * @since 0.1.0
978 | * @category Lang
979 | * @param {*} value The value to check.
980 | * @returns {boolean} Returns `true` if `value` is an array, else `false`.
981 | * @example
982 | *
983 | * _.isArray([1, 2, 3]);
984 | * // => true
985 | *
986 | * _.isArray(document.body.children);
987 | * // => false
988 | *
989 | * _.isArray('abc');
990 | * // => false
991 | *
992 | * _.isArray(_.noop);
993 | * // => false
994 | */
995 | var isArray = Array.isArray;
996 |
997 | /**
998 | * Checks if `value` is array-like. A value is considered array-like if it's
999 | * not a function and has a `value.length` that's an integer greater than or
1000 | * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
1001 | *
1002 | * @static
1003 | * @memberOf _
1004 | * @since 4.0.0
1005 | * @category Lang
1006 | * @param {*} value The value to check.
1007 | * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
1008 | * @example
1009 | *
1010 | * _.isArrayLike([1, 2, 3]);
1011 | * // => true
1012 | *
1013 | * _.isArrayLike(document.body.children);
1014 | * // => true
1015 | *
1016 | * _.isArrayLike('abc');
1017 | * // => true
1018 | *
1019 | * _.isArrayLike(_.noop);
1020 | * // => false
1021 | */
1022 | function isArrayLike(value) {
1023 | return value != null && isLength(value.length) && !isFunction(value);
1024 | }
1025 |
1026 | /**
1027 | * Checks if `value` is a buffer.
1028 | *
1029 | * @static
1030 | * @memberOf _
1031 | * @since 4.3.0
1032 | * @category Lang
1033 | * @param {*} value The value to check.
1034 | * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
1035 | * @example
1036 | *
1037 | * _.isBuffer(new Buffer(2));
1038 | * // => true
1039 | *
1040 | * _.isBuffer(new Uint8Array(2));
1041 | * // => false
1042 | */
1043 | var isBuffer = nativeIsBuffer || stubFalse;
1044 |
1045 | /**
1046 | * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`,
1047 | * `SyntaxError`, `TypeError`, or `URIError` object.
1048 | *
1049 | * @static
1050 | * @memberOf _
1051 | * @since 3.0.0
1052 | * @category Lang
1053 | * @param {*} value The value to check.
1054 | * @returns {boolean} Returns `true` if `value` is an error object, else `false`.
1055 | * @example
1056 | *
1057 | * _.isError(new Error);
1058 | * // => true
1059 | *
1060 | * _.isError(Error);
1061 | * // => false
1062 | */
1063 | function isError(value) {
1064 | if (!isObjectLike(value)) {
1065 | return false;
1066 | }
1067 | var tag = baseGetTag(value);
1068 | return tag == errorTag || tag == domExcTag ||
1069 | (typeof value.message == 'string' && typeof value.name == 'string' && !isPlainObject(value));
1070 | }
1071 |
1072 | /**
1073 | * Checks if `value` is classified as a `Function` object.
1074 | *
1075 | * @static
1076 | * @memberOf _
1077 | * @since 0.1.0
1078 | * @category Lang
1079 | * @param {*} value The value to check.
1080 | * @returns {boolean} Returns `true` if `value` is a function, else `false`.
1081 | * @example
1082 | *
1083 | * _.isFunction(_);
1084 | * // => true
1085 | *
1086 | * _.isFunction(/abc/);
1087 | * // => false
1088 | */
1089 | function isFunction(value) {
1090 | if (!isObject(value)) {
1091 | return false;
1092 | }
1093 | // The use of `Object#toString` avoids issues with the `typeof` operator
1094 | // in Safari 9 which returns 'object' for typed arrays and other constructors.
1095 | var tag = baseGetTag(value);
1096 | return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
1097 | }
1098 |
1099 | /**
1100 | * Checks if `value` is a valid array-like length.
1101 | *
1102 | * **Note:** This method is loosely based on
1103 | * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
1104 | *
1105 | * @static
1106 | * @memberOf _
1107 | * @since 4.0.0
1108 | * @category Lang
1109 | * @param {*} value The value to check.
1110 | * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
1111 | * @example
1112 | *
1113 | * _.isLength(3);
1114 | * // => true
1115 | *
1116 | * _.isLength(Number.MIN_VALUE);
1117 | * // => false
1118 | *
1119 | * _.isLength(Infinity);
1120 | * // => false
1121 | *
1122 | * _.isLength('3');
1123 | * // => false
1124 | */
1125 | function isLength(value) {
1126 | return typeof value == 'number' &&
1127 | value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
1128 | }
1129 |
1130 | /**
1131 | * Checks if `value` is the
1132 | * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
1133 | * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
1134 | *
1135 | * @static
1136 | * @memberOf _
1137 | * @since 0.1.0
1138 | * @category Lang
1139 | * @param {*} value The value to check.
1140 | * @returns {boolean} Returns `true` if `value` is an object, else `false`.
1141 | * @example
1142 | *
1143 | * _.isObject({});
1144 | * // => true
1145 | *
1146 | * _.isObject([1, 2, 3]);
1147 | * // => true
1148 | *
1149 | * _.isObject(_.noop);
1150 | * // => true
1151 | *
1152 | * _.isObject(null);
1153 | * // => false
1154 | */
1155 | function isObject(value) {
1156 | var type = typeof value;
1157 | return value != null && (type == 'object' || type == 'function');
1158 | }
1159 |
1160 | /**
1161 | * Checks if `value` is object-like. A value is object-like if it's not `null`
1162 | * and has a `typeof` result of "object".
1163 | *
1164 | * @static
1165 | * @memberOf _
1166 | * @since 4.0.0
1167 | * @category Lang
1168 | * @param {*} value The value to check.
1169 | * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
1170 | * @example
1171 | *
1172 | * _.isObjectLike({});
1173 | * // => true
1174 | *
1175 | * _.isObjectLike([1, 2, 3]);
1176 | * // => true
1177 | *
1178 | * _.isObjectLike(_.noop);
1179 | * // => false
1180 | *
1181 | * _.isObjectLike(null);
1182 | * // => false
1183 | */
1184 | function isObjectLike(value) {
1185 | return value != null && typeof value == 'object';
1186 | }
1187 |
1188 | /**
1189 | * Checks if `value` is a plain object, that is, an object created by the
1190 | * `Object` constructor or one with a `[[Prototype]]` of `null`.
1191 | *
1192 | * @static
1193 | * @memberOf _
1194 | * @since 0.8.0
1195 | * @category Lang
1196 | * @param {*} value The value to check.
1197 | * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
1198 | * @example
1199 | *
1200 | * function Foo() {
1201 | * this.a = 1;
1202 | * }
1203 | *
1204 | * _.isPlainObject(new Foo);
1205 | * // => false
1206 | *
1207 | * _.isPlainObject([1, 2, 3]);
1208 | * // => false
1209 | *
1210 | * _.isPlainObject({ 'x': 0, 'y': 0 });
1211 | * // => true
1212 | *
1213 | * _.isPlainObject(Object.create(null));
1214 | * // => true
1215 | */
1216 | function isPlainObject(value) {
1217 | if (!isObjectLike(value) || baseGetTag(value) != objectTag) {
1218 | return false;
1219 | }
1220 | var proto = getPrototype(value);
1221 | if (proto === null) {
1222 | return true;
1223 | }
1224 | var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;
1225 | return typeof Ctor == 'function' && Ctor instanceof Ctor &&
1226 | funcToString.call(Ctor) == objectCtorString;
1227 | }
1228 |
1229 | /**
1230 | * Checks if `value` is classified as a `Symbol` primitive or object.
1231 | *
1232 | * @static
1233 | * @memberOf _
1234 | * @since 4.0.0
1235 | * @category Lang
1236 | * @param {*} value The value to check.
1237 | * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
1238 | * @example
1239 | *
1240 | * _.isSymbol(Symbol.iterator);
1241 | * // => true
1242 | *
1243 | * _.isSymbol('abc');
1244 | * // => false
1245 | */
1246 | function isSymbol(value) {
1247 | return typeof value == 'symbol' ||
1248 | (isObjectLike(value) && baseGetTag(value) == symbolTag);
1249 | }
1250 |
1251 | /**
1252 | * Checks if `value` is classified as a typed array.
1253 | *
1254 | * @static
1255 | * @memberOf _
1256 | * @since 3.0.0
1257 | * @category Lang
1258 | * @param {*} value The value to check.
1259 | * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
1260 | * @example
1261 | *
1262 | * _.isTypedArray(new Uint8Array);
1263 | * // => true
1264 | *
1265 | * _.isTypedArray([]);
1266 | * // => false
1267 | */
1268 | var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
1269 |
1270 | /**
1271 | * Converts `value` to a string. An empty string is returned for `null`
1272 | * and `undefined` values. The sign of `-0` is preserved.
1273 | *
1274 | * @static
1275 | * @memberOf _
1276 | * @since 4.0.0
1277 | * @category Lang
1278 | * @param {*} value The value to convert.
1279 | * @returns {string} Returns the converted string.
1280 | * @example
1281 | *
1282 | * _.toString(null);
1283 | * // => ''
1284 | *
1285 | * _.toString(-0);
1286 | * // => '-0'
1287 | *
1288 | * _.toString([1, 2, 3]);
1289 | * // => '1,2,3'
1290 | */
1291 | function toString(value) {
1292 | return value == null ? '' : baseToString(value);
1293 | }
1294 |
1295 | /**
1296 | * This method is like `_.assignIn` except that it accepts `customizer`
1297 | * which is invoked to produce the assigned values. If `customizer` returns
1298 | * `undefined`, assignment is handled by the method instead. The `customizer`
1299 | * is invoked with five arguments: (objValue, srcValue, key, object, source).
1300 | *
1301 | * **Note:** This method mutates `object`.
1302 | *
1303 | * @static
1304 | * @memberOf _
1305 | * @since 4.0.0
1306 | * @alias extendWith
1307 | * @category Object
1308 | * @param {Object} object The destination object.
1309 | * @param {...Object} sources The source objects.
1310 | * @param {Function} [customizer] The function to customize assigned values.
1311 | * @returns {Object} Returns `object`.
1312 | * @see _.assignWith
1313 | * @example
1314 | *
1315 | * function customizer(objValue, srcValue) {
1316 | * return _.isUndefined(objValue) ? srcValue : objValue;
1317 | * }
1318 | *
1319 | * var defaults = _.partialRight(_.assignInWith, customizer);
1320 | *
1321 | * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
1322 | * // => { 'a': 1, 'b': 2 }
1323 | */
1324 | var assignInWith = createAssigner(function(object, source, srcIndex, customizer) {
1325 | copyObject(source, keysIn(source), object, customizer);
1326 | });
1327 |
1328 | /**
1329 | * Creates an array of the own enumerable property names of `object`.
1330 | *
1331 | * **Note:** Non-object values are coerced to objects. See the
1332 | * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
1333 | * for more details.
1334 | *
1335 | * @static
1336 | * @since 0.1.0
1337 | * @memberOf _
1338 | * @category Object
1339 | * @param {Object} object The object to query.
1340 | * @returns {Array} Returns the array of property names.
1341 | * @example
1342 | *
1343 | * function Foo() {
1344 | * this.a = 1;
1345 | * this.b = 2;
1346 | * }
1347 | *
1348 | * Foo.prototype.c = 3;
1349 | *
1350 | * _.keys(new Foo);
1351 | * // => ['a', 'b'] (iteration order is not guaranteed)
1352 | *
1353 | * _.keys('hi');
1354 | * // => ['0', '1']
1355 | */
1356 | function keys(object) {
1357 | return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
1358 | }
1359 |
1360 | /**
1361 | * Creates an array of the own and inherited enumerable property names of `object`.
1362 | *
1363 | * **Note:** Non-object values are coerced to objects.
1364 | *
1365 | * @static
1366 | * @memberOf _
1367 | * @since 3.0.0
1368 | * @category Object
1369 | * @param {Object} object The object to query.
1370 | * @returns {Array} Returns the array of property names.
1371 | * @example
1372 | *
1373 | * function Foo() {
1374 | * this.a = 1;
1375 | * this.b = 2;
1376 | * }
1377 | *
1378 | * Foo.prototype.c = 3;
1379 | *
1380 | * _.keysIn(new Foo);
1381 | * // => ['a', 'b', 'c'] (iteration order is not guaranteed)
1382 | */
1383 | function keysIn(object) {
1384 | return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);
1385 | }
1386 |
1387 | /**
1388 | * Creates a compiled template function that can interpolate data properties
1389 | * in "interpolate" delimiters, HTML-escape interpolated data properties in
1390 | * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data
1391 | * properties may be accessed as free variables in the template. If a setting
1392 | * object is given, it takes precedence over `_.templateSettings` values.
1393 | *
1394 | * **Note:** In the development build `_.template` utilizes
1395 | * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)
1396 | * for easier debugging.
1397 | *
1398 | * For more information on precompiling templates see
1399 | * [lodash's custom builds documentation](https://lodash.com/custom-builds).
1400 | *
1401 | * For more information on Chrome extension sandboxes see
1402 | * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval).
1403 | *
1404 | * @static
1405 | * @since 0.1.0
1406 | * @memberOf _
1407 | * @category String
1408 | * @param {string} [string=''] The template string.
1409 | * @param {Object} [options={}] The options object.
1410 | * @param {RegExp} [options.escape=_.templateSettings.escape]
1411 | * The HTML "escape" delimiter.
1412 | * @param {RegExp} [options.evaluate=_.templateSettings.evaluate]
1413 | * The "evaluate" delimiter.
1414 | * @param {Object} [options.imports=_.templateSettings.imports]
1415 | * An object to import into the template as free variables.
1416 | * @param {RegExp} [options.interpolate=_.templateSettings.interpolate]
1417 | * The "interpolate" delimiter.
1418 | * @param {string} [options.sourceURL='templateSources[n]']
1419 | * The sourceURL of the compiled template.
1420 | * @param {string} [options.variable='obj']
1421 | * The data object variable name.
1422 | * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
1423 | * @returns {Function} Returns the compiled template function.
1424 | * @example
1425 | *
1426 | * // Use the "interpolate" delimiter to create a compiled template.
1427 | * var compiled = _.template('hello <%= user %>!');
1428 | * compiled({ 'user': 'fred' });
1429 | * // => 'hello fred!'
1430 | *
1431 | * // Use the HTML "escape" delimiter to escape data property values.
1432 | * var compiled = _.template('<%- value %>');
1433 | * compiled({ 'value': '
17 |
18 |
19 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 | © 2018 Nick Freear | License: MIT.
40 |
41 |
42 |