added all files to project

This commit is contained in:
2022-03-10 10:36:59 +01:00
parent 09dd957b33
commit 46a936d7de
25351 changed files with 3883356 additions and 0 deletions
@@ -0,0 +1,17 @@
engines:
markdownlint:
enabled: true
# ... CONFIG CONTENT ...
checks:
# trailing spaces
MD009:
enabled: false
# multiple blank lines
MD012:
enabled: false
# line length
MD013:
enabled: false
# raw html
MD033:
enabled: false
@@ -0,0 +1,16 @@
language: node_js
node_js:
- '10'
script:
- npm run
cache:
directories:
- node_modules
before_install:
- "[[ $(node -v) =~ ^v9.*$ ]] || npm install -g npm@latest"
- npm install -g greenkeeper-lockfile@1
before_script: greenkeeper-lockfile-update
after_script: greenkeeper-lockfile-upload
env:
global:
secure: pG2uUo6UCEAAr8xftPcthjc6RJQuvgl9N+nR6Ew5bwXPMvAf8ELQidPG3EUTyrWp4cyfA4N86/s94rR3qsW6kHuvlq+8DWKpin8EXl2Lp3PUxvYR3E5sMK3S1dAA0Ol0cxFoy2Smfpksu2TfibsL2WmfS7AhevEaMZ4FnHhA6liAtnELGf33SjFDJjUG0yXzRcdmrfSPP9St5saZtxVL9Tfk9WflD9oP6V2xMpY1prVqdc/xft4ODv3dhStwS+GvML/ActOkdWLkSIukiYs+TyzHEB8PgmXqdMti2vgCohR1onoyf6hvxdze6RS9Np4Yh7jmkhxu8zpC8Dcv5MYc97IEa5TER3gQwZRVPb8BrIZfi2I32O92VaE3v18rxW4SiMJGVDc1KchdUa0KjqGnZnfwfh8SmX1NTNxef9cDBjdVkVGdgqzlrtv2UkYpMOcnVipCvk1R45AX+RpInMTH8wbPhBy+h+FPaszcwtDYMRKgFX5MRKeulgVhMUscwZxvLnB0q4mWfo/6xX0meo0m0+Q4m+g9EmfKMHdds6L9Ca/T9eUEpgGgp/5AagtNIF3OlaoTD+rTuitBwecTs2NwPyGv/go+0qHHKPX4uzp81PCGyCA5CKS+8PCuQcZPuvbNEHO4l8KnP7b2bRUYU9wrSMw0lUhDaerlB8NYl3Fm7r8=
@@ -0,0 +1,46 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at ray@skillbird.de. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/
Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 Ray Wojciechowski
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
@@ -0,0 +1,295 @@
/*
* Update by AgP42 the 18/07/2018
*
* Modification added :
* - Management of a PIR sensor with the module MMM-PIR-Sensor (by PaViRo). In case PIR module detect no user,
* the update of the ToDoIst is stopped and will be requested again at the return of the user
* - Management of the "module.hidden" by the core system : same behaviour as "User_Presence" by the PIR sensor
* - Possibility to add the last update time from server at the end of the module.
* This can be configured using "displayLastUpdate" and "displayLastUpdateFormat"
* */
"use strict";
//UserPresence Management (PIR sensor)
var UserPresence = true; //true by default, so no impact for user without a PIR sensor
Module.register("MMM-PublicTransportHafas", {
// default values
defaults: {
// Module misc
name: "MMM-PublicTransportHafas",
hafasProfile: "db", // Which HAFAS profile should be used?
hidden: false,
updatesEvery: 120, // How often should the table be updated in s?
// Header
headerPrefix: "",
headerAppendix: "",
// Display last update time
displayLastUpdate: false, // Add or not a line after the tasks with the last server update time
displayLastUpdateFormat: 'dd - HH:mm:ss', // Format to display the last update. See Moment.js documentation for all display possibilities
// Departures options
direction: "", // Show only departures heading to this station. (A station ID.)
ignoredLines: [], // Which lines should be ignored? (comma-separated list of line names)
excludedTransportationTypes: [], // Which transportation types should not be shown on the mirror? (comma-separated list of types) possible values: "tram", "bus", "suburban", "subway", "regional" and "national"
timeToStation: 10, // How long do you need to walk to the Station? (in minutes)
timeInFuture: 40, // Show departures for the next *timeInFuture* minutes.
// Look and Feel
marqueeLongDirections: true, // Use Marquee effect for long station names?
replaceInDirections: {}, // key-value pairs which are used to replace `key` by `value` in the displayed directions
showColoredLineSymbols: true, // Want colored line symbols?
useColorForRealtimeInfo: true, // Want colored real time information (timeToStation, early)?
showAbsoluteTime: true, // How should the departure time be displayed? "15:10" (absolute) or "in 5 minutes" (relative)
showTableHeaders: true, // Show table headers?
showTableHeadersAsSymbols: true, // Table Headers as symbols or written?
tableHeaderOrder: [ "time", "line", "direction" ], // In which order should the table headers appear? (add "platform" if you like)
maxUnreachableDepartures: 0, // How many unreachable departures should be shown?
maxReachableDepartures: 7, // How many reachable departures should be shown?
fadeUnreachableDepartures: true,
fadeReachableDepartures: true,
fadePointForReachableDepartures: 0.25,
customLineStyles: "", // Prefix for the name of the custom css file. ex: Leipzig-lines.css (case sensitive)
showOnlyLineNumbers: false, // Display only the line number instead of the complete name, i. e. "11" instead of "STR 11"
animationSpeed: 1500 // Refresh animation speed in milliseconds
},
start: function () {
Log.info("Starting module: " + this.name + " with identifier: " + this.identifier);
this.ModulePublicTransportHafasHidden = false; // By default we display the module (if no carousel or other module)
this.updatesIntervalID = 0; // To stop and start auto update for each module instance
this.lastUpdate = 0; // Timestamp of the last module update. set at 0 at start-up
this.departures = [];
this.initialized = false;
this.error = {};
this.sanitzeConfig();
if (!this.config.stationID) {
Log.error("stationID not set! " + this.config.stationID);
this.error.message = this.translate("NO_STATION_ID_SET");
return;
}
let fetcherOptions = {
identifier: this.identifier,
hafasProfile: this.config.hafasProfile,
stationID: this.config.stationID,
timeToStation: this.config.timeToStation,
timeInFuture: this.config.timeInFuture,
direction: this.config.direction,
ignoredLines: this.config.ignoredLines,
excludedTransportationTypes: this.config.excludedTransportationTypes,
maxReachableDepartures: this.config.maxReachableDepartures,
maxUnreachableDepartures: this.config.maxUnreachableDepartures
};
this.sendSocketNotification("CREATE_FETCHER", fetcherOptions);
},
//Modif AgP42 - 12/07/2018
suspend: function() { // Core function called when the module is hidden
this.ModulePublicTransportHafasHidden = true; // Module hidden
// Log.log("Function suspend - Module PublicTransportHafas is hidden " + this.config.stationName);
this.GestionUpdateIntervalHafas(); // Call the function which manages all the cases
},
resume: function() { // Core function called when the module is displayed
this.ModulePublicTransportHafasHidden = false;
// Log.log("Function working - Module PublicTransportHafas is displayed " + this.config.stationName);
this.GestionUpdateIntervalHafas();
},
notificationReceived: function(notification, payload) {
if (notification === "USER_PRESENCE") { // Notification sent by the MMM-PIR-Sensor module. See its doc.
// Log.log("NotificationReceived USER_PRESENCE = " + payload);
UserPresence = payload;
this.GestionUpdateIntervalHafas();
}
},
GestionUpdateIntervalHafas: function() {
if (UserPresence === true && this.ModulePublicTransportHafasHidden === false){ // Make sure to have a user present in front of the screen (PIR sensor) and that the module is displayed
let self = this;
// Log.log(this.config.stationName + " is displayed and user present! Update it");
// Update now and start again the update timer
this.startFetchingLoop(this.config.updatesEvery);
}else{ // (UserPresence = false OU ModulePublicTransportHafasHidden = true)
// Log.log("No one is watching: Stop the update!" + this.config.stationName);
clearInterval(this.updatesIntervalID); // Stop the current update interval
this.updatesIntervalID = 0; // Reset the variable
}
},
getDom: function () {
let domBuilder = new PTHAFASDomBuilder(this.config);
if (this.hasErrors()) {
return domBuilder.getSimpleDom(this.error.message);
}
if (!this.initialized) {
return domBuilder.getSimpleDom(this.translate("LOADING"));
}
let headings = {
time: this.translate("PTH_DEPARTURE_TIME"),
line: this.translate("PTH_LINE"),
direction: this.translate("PTH_TO"),
platform: this.translate("PTH_PLATFORM")
};
let noDeparturesMessage = this.translate("PTH_NO_DEPARTURES");
let wrapper = domBuilder.getDom(this.departures, headings, noDeparturesMessage);
// display the update time at the end, if defined so by the user config
if(this.config.displayLastUpdate){
let updateinfo = document.createElement("div");
updateinfo.className = "xsmall light align-left";
updateinfo.innerHTML = "Update: " + moment.unix(this.lastUpdate).format(this.config.displayLastUpdateFormat);
wrapper.appendChild(updateinfo);
}
return wrapper;
},
getStyles: function () {
let styles = [
this.file("css/styles.css"),
"font-awesome.css"
];
if (this.config.customLineStyles !== "") {
let customStyle = "css/" + this.config.customLineStyles + "-lines.css";
styles.push(this.file(customStyle));
}
return styles;
},
getScripts: function () {
return [
"moment.js",
this.file("core/PTHAFASDomBuilder.js"),
this.file("core/PTHAFASTableBodyBuilder.js")
];
},
getTranslations: function() {
return {
en: "translations/en.json",
de: "translations/de.json"
};
},
socketNotificationReceived: function (notification, payload) {
if (!this.isForThisStation(payload)) {
return;
}
switch (notification) {
case "FETCHER_INITIALIZED":
this.initialized = true;
this.startFetchingLoop(this.config.updatesEvery);
break;
case "DEPARTURES_FETCHED":
//AgP
if(this.config.displayLastUpdate){
this.lastUpdate = Date.now() / 1000 ; //save the timestamp of the last update to be able to display it
}
Log.log("TransportHafas update OK, station : " + this.config.stationName + " at : "
+ moment.unix(this.lastUpdate).format(this.config.displayLastUpdateFormat));
//this.sendNotification("SHOW_ALERT",{type:"notification",message:"Update Transport Berlin recue"});
// reset error object
this.error = {};
this.departures = payload.departures;
this.updateDom(this.config.animationSpeed);
this.sendNotification('TRANSPORT_HAFAS', payload.departures)
break;
case "FETCH_ERROR":
this.error = payload.error;
this.departures = [];
this.updateDom(this.config.animationSpeed);
break;
}
},
isForThisStation: function (payload) {
return payload.identifier === this.identifier;
},
sanitzeConfig: function () {
if (this.config.updatesEvery < 30) {
this.config.updatesEvery = 30;
}
if (this.config.timeToStation < 0) {
this.config.timeToStation = 0;
}
if (this.config.timeInFuture < this.config.timeToStation + 30) {
this.config.timeInFuture = this.config.timeToStation + 30;
}
if (this.config.maxUnreachableDepartures < 0) {
this.config.maxUnreachableDepartures = 0;
}
if (this.config.maxReachableDepartures < 0) {
this.config.maxReachableDepartures = this.defaults.maxReachableDepartures;
}
},
startFetchingLoop: function(interval) {
// start immediately ...
this.sendSocketNotification("FETCH_DEPARTURES", this.identifier);
// ... and then repeat in the given interval
// Log.log("Hello, update module Transport requested! (non-recurring)");
// this.sendNotification("SHOW_ALERT",{type:"notification",message:"Update Transport Berlin requested"});
if (this.updatesIntervalID === 0){//if this instance as no auto update defined, then we create one. Otherwise : nothing.
this.updatesIntervalID = setInterval(() => {
this.sendSocketNotification("FETCH_DEPARTURES", this.identifier);
}, interval * 1000);
}
},
hasErrors: function () {
return (Object.keys(this.error).length > 0);
},
});
+258
View File
@@ -0,0 +1,258 @@
[![npm version](https://img.shields.io/npm/v/hafas-client.svg)](https://www.npmjs.com/package/hafas-client)
[![GitHub issues](https://img.shields.io/github/issues/KristjanESPERANTO/mmm-publictransporthafas)](https://github.com/KristjanESPERANTO/mmm-publictransporthafas/issues)
[![GitHub forks](https://img.shields.io/github/forks/KristjanESPERANTO/mmm-publictransporthafas)](https://github.com/KristjanESPERANTO/mmm-publictransporthafas/network)
[![GitHub stars](https://img.shields.io/github/stars/KristjanESPERANTO/mmm-publictransporthafas)](https://github.com/KristjanESPERANTO/mmm-publictransporthafas/stargazers)
[![GitHub license](https://img.shields.io/github/license/KristjanESPERANTO/mmm-publictransporthafas?style=plastic)](https://github.com/KristjanESPERANTO/mmm-publictransporthafas/blob/master/LICENSE)
# MMM-PublicTransportHafas
**MMM-PublicTransportHafas is a module for the [MagicMirror²](https://github.com/MichMich/MagicMirror) project.**
- [Description](#description)
- [How it works](#how-it-works)
- [Screenshots](#screenshots)
- [Preconditions](#preconditions)
- [Installing](#installing)
- [Updating](#updating)
- [How to get the `stationID`](#how-to-get-the-stationid)
- [Configuration](#configuration)
- [Multiple instances](#multiple-instances)
- [Providing a custom css file](#providing-a-custom-css-file)
- [Technical background details](#technical-background-details)
- [Special Thanks](#special-thanks)
- [Contributing](#contributing)
## Description
This module shows live public transport information in Germany for all stations known to the Deutsche Bahn system. Most public transportation providers in Germany providing information for that system so the coverage should be quite good. The data is provided by the fantastic [hafas-client](https://github.com/public-transport/hafas-client). Even in other european contries this module should work as HAFAS is widely used throughout Europe.
You can very easy adapt the shapes and line colors of your local transport companies. See [Providing a custom css file](#providing-a-custom-css-file).
## How it works
After you installed MMM-PublicTransportHafas you just configure it to your needs and that’s it. The only config you really need to set is the stationID property. This determines the station you want to display. Everything else is covered by defaults but can be configured by you anyway. For instance you can enter a time you need to get to the station (`timeToStation` in config). The module then only shows departures you can reach respecting the set time.
For more information see the [Configuration](#configuration) section.
## Screenshots
|![Example: Goerdelerring Leipzig, all directions](img/Goerdelerring_all.png)<br>*Leipzig, Goerdelerring (all directions)*|![Example: Goerdelerring Leipzig, heading to main station](img/Goerdelerring_to_hbf.png)<br>*Leipzig, Goerdelerring (heading to main station)*|
|---|---|
|![Example: Hauptbahnhof, Leipzig, only tram](img/Hauptbahnhof_tram_only.png)<br>*Hauptbahnhof, Leipzig (displaying only trams and two unreachable departures)*|![Example: Hauptbahnhof, Leipzig, only regional and national trains](img/Hauptbahnhof_train_only.png)<br>*Hauptbahnhof, Leipzig (displaying only regional and national trains)*|
|![Example: Leuschner Platz with relative departure time and reorderd columns](img/Leuschner_Platz_relative.png)<br>*Leuschner Platz, Leipzig (displaying departure times in relative format and reordered columns)*|
![Example: Multiple instances in Berlin, showing the last update time](img/UpdateTimeDisplayed.png)<br>*Several instances in Berlin, showing the last update time*
## Preconditions
* MagicMirror² instance
* Node.js version >= 10
* npm
## Installing
Just clone the module into your MagicMirror modules folder and execute `npm install` in the module’s directory:
```bash
git clone https://github.com/KristjanESPERANTO/MMM-PublicTransportHafas.git
cd MMM-PublicTransportHafas
npm install
```
## Updating
Go to the module’s folder inside MagicMirror modules folder and pull the latest version from GitHub and install:
```bash
git pull
npm install
```
## How to get the `stationID`
For your convenience a script to query the hafas system for a `stationID` is included. The script is located in the `convenience` folder inside the module’s folder. Run the script and enter the station name. It is useful to enter a city name too since the system knows a lot of stations even outside Germany.
Running the script:
change to `MagicMirror/modules/MMM-PublicTransportHafas` then start the script by typing
```bash
node ./convenience/query_stations.js
```
The following example shows a query for "Leipzig, Wilhelm-Leuschner-Platz". This station is included two times in the result. You have to experiment which ID gives the best results.
```
Geben Sie eine Adresse oder einen Stationsnamen ein: Leipzig, Wilhelm-Leuschner-Platz
Gefundene Haltestellen für "Leipzig, Wilhelm-Leuschner-Platz":
> Haltestelle: "Leipzig Wilhelm-Leuschner-Platz"
ID: 008012202
Verkehrsmittel: S-Bahn, Bus, Tram
> Haltestelle: "Wilhelm-Leuschner-Platz, Leipzig"
ID: 000955252
Verkehrsmittel: Bus, Tram
> Haltestelle: "Wilhelm-Leuschner-Platz, Weiterstadt"
ID: 000115849
Verkehrsmittel: Bus
> Haltestelle: "Wilhelm-Liebknecht-Platz, Leipzig"
ID: 000956558
Verkehrsmittel: Bus, Tram
```
By default, the module uses the `db` profile of the `hafas-client`. In some cases it can be advantageous to use a different profile - e.g. the default profile often does not provide platform information from local transport companies. [Here](https://github.com/public-transport/hafas-client/blob/master/p/readme.md) you can find the name of all supported interfaces. Just add the name as a parameter to the command. Like 'sbb' for the profile of Swiss Railways.
```bash
node ./convenience/query_stations.js sbb
```
## Configuration
The module is quite configurable. These are the possible options:
| Option | Description |
|--------|-------------|
| `hafasProfile` | <p>The name of the hafas profile.</p><p>**Type:** `string` **OPTIONAL**<br>**Example:** `"insa"`<br>**Default Value:** `"db"`</p><p>**Note:** In most cases you don't need to change the value. You can find supported profiles and there names [here](https://github.com/public-transport/hafas-client/blob/master/p/readme.md).</p><p>Each profile uses its own StaionIDs. So if you change the profile, you have to find out the StationID again.</p>|
| `stationID` | <p>The ID you want to display departures for.</p><p>**Type:** `string` **REQUIRED**<br>**Example:** `"008012202"`<br>**Default Value:** none</p><p>**Note:** How to get the ID is described [here](#how-to-get-the-stationid).</p>|
| `stationName` | <p>The name of the station as it should appear on the display.</p><p>**Type:** `string` **OPTIONAL**<br>**Example:** `"Wilhelm-Leuschner-Platz"`<br>**Default Value:** none</p><p>**Note:** If you leave this setting, `headerPrefix` and `headerAppendix` blank the module will show an empty header.</p>|
| `headerPrefix` | <p>The text to be prepended to the `stationName`.</p><p>**Type:** `string` **OPTIONAL** <br>**Example:** `"von"` (Will result in “von Wilhelm-Leuschner-Platz” being displayed.) <br>**Default Value:** `""`</p><p>**Note:** A blank between `headerPrefix` and `stationName` is automatically inserted.</p>|
| `headerAppendix` | <p>The text to be prepended to the `stationName`.</p><p>**Type:** `string` **OPTIONAL** <br>**Example:** `"(Richtung HBF)"`<br>**Default Value:** `""`</p><p>**Note:** A blank between `headerAppendix` and `stationName` is automatically inserted.</p>|
| `updatesEvery` | <p>The time in seconds when the displayed departures should be updated.</p><p>**Type:** `integer` **OPTIONAL** <br>**Example:** `60` (The departures will be refreshed every minute.)<br>**Default Value:** `120`</p><p>**Note:** The minimal refresh time is 30 seconds.</p>|
| `direction` | <p>An ID of a station. It is used to display only those departures heading to this station. </p><p>**Type:** `string` **OPTIONAL**<br>**Example:** `"000954609"`<br>**Default Value:** `""`</p><p>**Note:** It is not neccessary to find the ID of the end station. Just use the next station which is on the route you are after.<br>It is not possible to list multiple IDs. If you want to display different directions for one station use multiple instances of this module.</p>|
| `ignoredLines` | <p>An array of strings describing the lines you want to exclude from the displayed departures.</p><p>**Type:** `array` **OPTIONAL** <br>**Example:** `[ "STR 11", "STR 10" ]` (Displays all lines except tram 10 and 11.)<br>**Default Value:** `[]`</p><p>**Note:** You need to provide the line names exactly as they are otherwise displayed. This setting is case sensitive. Blanks need to be exactly as they are display. If a line is usually displayes as `BUS 89` (two blanks) you need to type exactly that into the array. </p>|
| `excludedTransportationTypes` | <p>An array of strings describing the transportation types you want to exclude from the displayed departures.</p><p>**Type:** `array` **OPTIONAL** <br>**Example:** `[ "suburban", "bus" ]`<br>**Default Value:** `[]`<br>**Possible Values:** <table><tr><th>Type</th><th>Use in Germany</th></tr><tr><td>`"bus"`</td><td>bus</td></tr><tr><td>`"ferry"`</td><td>F&auml;hre</td></tr><tr><td>`"express"`</td><td>?</td></tr><tr><td>`"national"`</td><td>IC trains</td></tr><tr><td>`"nationalExpress"`</td><td>ICE trains</td></tr><tr><td>`"regional"`</td><td>RB or RE</td></tr><tr><td>`"suburban"`</td><td>S-Bahn</td></tr><tr><td>`"subway"`</td><td>U-Bahn</td></tr><tr><td>`"tram"`</td><td>Tram</td></tr><tr><td>`"taxi"`</td><td>Taxi</td></tr></table></p>|
| `timeToStation` | <p>An integer indicating how long it takes you to get to the station.</p><p>**Type:** `integer` **OPTIONAL**<br>**Example:** `5`<br>**Default Value:** `10` </p><p>**Note:** The time is given in minutes.</p>|
| `timeInFuture` | <p>An integer indicating how far in the future a departure can be to be still included in the shown departures.</p><p>**Type:** `integer` **OPTIONAL** <br>**Example:** `60` (Show departures for the next hour.)<br>**Default Value:** `40`</p><p>**Note:** The time is given in minutes.<br>Use this setting on stations where there is a big time gap between departures. This way you will see more than one or two departures. **Don’t use** this setting to limit the amount of displayed departures! The module will set this value to be at least `timeToStation + 30` anyway. Use the option `maxReachableDepartures` to limit the displayed departures. </p>|
| `marqueeLongDirections` | <p>A boolean value indicating whether you want scrolling long destination name or not.</p><p>**Type:** `boolean` **OPTIONAL** <br>**Example:** `false` <br>**Default Value:** `true`</p><p>**Note:** If set to `true` destination names longer than 24 characters will scroll through the display. If set to `false` names will be truncated at 24 characters.</p>|
| `replaceInDirections` | <p>An object defining strings which are to be replaced in the displayed directions.</p><p>**Type:** `object` **OPTIONAL** <br>**Example:** `{ "Leipzig": "LE", "\\(Saale\\)": "", "Hbf": "" }` <br>**Default Value:** `{}`</p><p>**Note:** The strings which appear as the keys of the object will be replaced by their values. Given a direction `"Leipzig, Hbf"` and the above mentioned example setting the displayed direction will be `"LE,"`. `"Leipzig"` was replaced by `"LE"` and `"Hbf"` was replaced by the empty string. If you want to replace special symbols like `"("`, `")"` or `"-"` you must escape these characters by placing **two** `"\"` in front of the character (see example above). </p>|
| `showColoredLineSymbols` | <p>A boolean value indicating whether the line symbols should be colored or black and white.</p><p>**Type:** `boolean` **OPTIONAL** <br>**Example:** `false` <br>**Default Value:** `true`</p><p>**Note:** If set to `true` it is possible to decorate the line labels with the colors which are used in your town. This module comes with decorations for Leipzig. To provide your own colors see [Providing a custom css file](#providing-a-custom-css-file).</p>|
| `useColorForRealtimeInfo` | <p>A boolean value indicating whether delays should be displayed in color.</p><p>**Type:** `boolean` **OPTIONAL** <br>**Example:** `false` <br>**Default Value:** `true` </p><p>**Note:** If set to `true` a delay will be displayed in red. Values `<= 0` (transport arrives in time or early) will be displayed in green. If you want to customize that see [Providing a custom css file](#customizing-the-color-for-delays). </p>|
| `showAbsoluteTime` | <p>A boolean indicating whether the departure time should be displayed as an absolute value or not.</p><p>**Type:** `boolean` **OPTIONAL** <br>**Example:** `false`<br>**Default Value:** `true`</p><p>**Note:** If set to `true` the departure time would be displayed as “10:15+0”. If set to `false` the departure time would be displayed in a relative manner like so: `in 5 minutes`. The displayed string is determined by your locale. If your locale is set to `de` the string would be `in 5 Minuten`. </p> |
| `showTableHeaders` | <p>A boolean indicating whether a table header should be shown or not.</p><p>**Type:** `boolean` **OPTIONAL** <br>**Example:** `false`<br>**Default Value:** `true`</p><p>**Note:** If set to `false` no table headings like “time” or “direction” will be shown. Also no symbols are shown.</p>|
| `showTableHeadersAsSymbols` | <p>A boolean value indicating whether table headers should be shown as symbols or text.</p><p>**Type:** `boolean` **OPTIONAL** <br>**Example:** `false` <br>**Default Value:** `true` </p><p>**Note:** If set to `true` table headers will use symbols, else text will be shown. This setting is only effective if `showTableHeaders` is set to `true`. The shown text is available in English and German. Feel free to add translations to this project.</p> |
| `tableHeaderOrder` | <p>An array determining the order of the table headers.</p><p>**Type:** `array` **OPTIONAL** <br>**Example:** `[ "line", "direction", "time" ]` <br>**Default Value:** `[ "time", "line", "direction" ]` </p><p>**Note 1:** If the HAFAS API delivers information about the platforms, you can add here the header `"platform"`.</p><p>**Note 2:** Sort the table headings as you like it. Please keep in mind that you must use the values `"line"`, `"time"`, `"direction"` and `"platform"`. These will be the only ones the module recognizes.</p>|
| `maxUnreachableDepartures` | <p>An integer value denoting how many unreachable departures should be displayed.</p><p>**Type:** `integer` **OPTIONAL** <br>**Example:** `3`<br>**Default Value:** `0`</p><p>**Note:** A departure is unreachable if you can't reach the station in time for the departure with respect to your `timeToStation` setting.<br>Sometimes it is useful to set this option to a value greater than `0` if you are the type of person which walks really fast. Maybe other users of the mirror usually take 10 minutes to the station but you take only 5. So you’ll see also departures the other users couldn’t reach.</p>|
| `maxReachableDepartures` | <p>An integer value denoting how many reachable departures should be displayed.</p><p>**Type:** `integer` **OPTIONAL** <br>**Example:** `5` <br>**Default Value:** `7` </p><p>**Note:** A departure is reachable if you can make it to the station in time for the departure with respect to your `timeToStation` setting.</p>|
| `fadeUnreachableDepartures` | <p>A boolean value indicating whether unreachable departures should be dimmed.</p><p>**Type:** `boolean` **OPTIONAL** <br>**Example:** `false` <br>**Default Value:** `true` </p>|
| `fadeReachableDepartures` | <p>A boolean value indicating whether reachable departures should be faded out.</p><p>**Type:** `boolean` **OPTIONAL** <br>**Example:** `false` <br>**Default Value:** `true` </p><p>**Note:** If set to `true` departures after `fadePointForReachableDepartures` will be gradually faded out so that the last departure is barely visible. </p>|
| `fadePointForReachableDepartures` | <p>A floating point value indicating where to start the fading of departure rows.</p><p>**Type:** `float` **OPTIONAL** <br>**Example:** `0.5` (Start fading after half of the rows.)<br>**Default Value:** `0.25` </p><p>**Note:** This value is actually a percentage. The default value of `0.25` denotes that after a quarter of the visible rows set by `maxReachableDepartures` the fading should start. This setting is only effective if `fadeReachableDepartures` is set to `true`. </p>|
| `customLineStyles` | <p>A string value describing the name of a custom css file.</p><p>**Type:** `string` **OPTIONAL** <br>**Example:** `"dresden"`<br>**Default Value:** `"leipzig"`</p><p>**Note:** If the setting `showColoredLineSymbols` is `true` the module will try to use colored labels for the line name. Per default it uses the colors used in Leipzig. This style works best if `showOnlyLineNumbers` is set to `true`. If it doesn’t suit your taste you can provide your own settings. See [Providing a custom css file](#providing-a-custom-css-file). </p>|
| `showOnlyLineNumbers` | <p>A boolean value denoting whether the line name should be displayed as a number only or the full name should be used. </p><p>**Type:** `boolean` **OPTIONAL** <br>**Example:** `true` <br>**Default Value:** `false` </p><p>**Note:** If set to `true` the module will try to separate line numbers from the line name and display only these. If the line name is “STR 11” only “11” will be displayed. This only works if there are blanks present in the line name. This setting is only tested with departures in Leipzig. If you encounter problems [let me know](https://github.com/KristjanESPERANTO/MMM-PublicTransportHafas/issues).</p>|
| `displayLastUpdate` | <p>If true this will display the last update time at the end of the task list. See screenshot above</p><p>**Type:** `boolean` **OPTIONAL** <br>**Default Value:** `false`</p></p>|
| `displayLastUpdateFormat` | <p>Format to use for the time display if displayLastUpdate:true </p><p>**Type:** `string` **OPTIONAL** <br>**Example:** `'dd - HH:mm:ss'` <br>**Default Value:** `'dd - HH:mm:ss'` </p>See [Moment.js formats](http://momentjs.com/docs/#/parsing/string-format/) for the other format possibilities. </p>|
| `animationSpeed` | <p>Speed of the update animation. (Milliseconds)</p><p>**Type:** `integer` **OPTIONAL** <br>**Possible values:** `0` - `5000` <br>**Default Value:** `2000` </p>|
Here is an example for an entry in `config.js`
```javascript
{
module: "MMM-PublicTransportHafas",
position: "bottom_right",
config: {
// Departures options
stationID: "008012202", // Replace with your stationID!
stationName: "Wilhelm-Leuschner-Platz", // Replace with your station name!
direction: "", // Show only departures heading to this station. (A station ID.)
excludedTransportationTypes: [], // Which transportation types should not be shown on the mirror? (comma-separated list of types) possible values: "tram", "bus", "suburban", "subway", "regional" and "national"
ignoredLines: [], // Which lines should be ignored? (comma-separated list of line names)
timeToStation: 10, // How long do you need to walk to the next Station?
// Look and Feel
displayLastUpdate: true, // Display the last time of module update.
maxUnreachableDepartures: 0, // How many unreachable departures should be shown?
maxReachableDepartures: 7, // How many reachable departures should be shown?
showColoredLineSymbols: true, // Want colored line symbols?
customLineStyles: "", // Prefix for the name of the custom css file. ex: Leipzig-lines.css (case sensitive)
showOnlyLineNumbers: false, // Display only the line number instead of the complete name, i. e. "11" instead of "STR 11"
showTableHeadersAsSymbols: true, // Table Headers as symbols or text?
useColorForRealtimeInfo: true // Want colored real time information (timeToStation, early)?
}
},
```
## Multiple instances
It is possible to use multiple instances of this module just by adding another entry of the MMM-PublicTransportHafas module to the `config.js` of your mirror.
You can even use the same `stationID` in different instances. So you can display in one instance something like “main station heading eastbound” and in another instance “main station heading westbound”.
## Providing a custom css file
### Colored line labels
If you set `showColoredLineSymbols` to `true` the module will try to colorize the line symbols. This is done by appending a css class to the line symbol. This class is named after the line name but blanks are left out and all letters are lower case. So if the line name is “STR 11” the appended css class name is `.str11`.
To provide your own classes create a css file in the `css` directory of the module. It must be named like `<your custom name>-lines.css`, where `<your custom name>` can be any valid file name but should not contain blanks or dots. The part `<your custom name>` is then used in the config file as value for the `customLineStyles` property.
#### Example:
In the example above “leipzig” is used as value for the `customLineStyles` property. Therefore there must be a file named `leipzig-lines.css` inside the `css` folder. If this is not the case the module won’t be started and it will not be visible. The browser’s console will show an error.
Basically you can set whatever you want in the css file but it is recommended to only set the foreground and background color and the width. In some cases it is useful to change the border radius too. See the file `css/leipzig-lines.css` for reference and as a guideline.
#### Example:
In Leipzig the tram lines 2, 8 and 9 use a yellow color. Since the lines share the same settings the css class names are listed with commas so that the settings apply to each listed class.
```css
.str2, .str8, .str9 {
background-color: #F8C623; /* yellow background */
color: black; /* text color black */
width: 1em; /* the width is equal to the font size (the line symbol will be a square) */
}
```
Some night buses in Leipzig use an orange-ish color. All bus symbols are circles in Leipzig.
```css
.busn1, .busn1e, .busn5, .busn5e, .busn8, .busn8e {
background-color: #EE9F2E; /* orange-ish background */
border-radius: 1em; /* border radius is the same as the width so a circle will appear */
color: #164585; /* blue-ish text color */
width: 1em; /* the width is equal to the font size (the line symbol will be a square, or in this case a circle) */
}
```
### Customizing the color for delays
Alongside the departure time a small figure displays the delay as reported by the transport provider.
![Time with delay](img/time_with_delay.png) ![Time without delay](img/time_without_delay.png)
Delays are displayed as red. No delay or negative delays (the transport will arrive early) are displayed in green. If you want to customize that include the classes `pthHasDelay` and `pthIsTooEarly` in your custom css file and make the appropriate settings.
## Technical background details
To limit the server request only when the module is displayed and/or the user is present, the update will be stopped when no instance of the module are displayed (module hidden e.g. by a [MMM-Carousel](https://github.com/lawrence-jeff/MMM-Carousel), [MMM-Pages](https://github.com/edward-shen/MMM-pages) or [MMM-Remote-Control](https://github.com/Jopyth/MMM-Remote-Control)). The update will also be stopped by the use of a PIR sensor using the module [MMM-PIR-Sensor](https://github.com/paviro/MMM-PIR-Sensor) (that sends the notification 'USER_PRESENCE'). No special configuration is needed for this behaviour.
## Special Thanks
* [Michael Teeuw](https://github.com/MichMich) for creating the inspiring project [MagicMirror²](https://github.com/MichMich/MagicMirror). You can sponsor him and the MagicMirror² project through [GitHub](https://github.com/sponsors/MichMich).
* [Jannis Redmann](https://github.com/derhuerst) for creating the most useful [hafas-client](https://github.com/derhuerst/hafas-client) library which provides the data for this module. You can sponsor him and a lot of his public transport projects through [GitHub](https://github.com/sponsors/derhuerst) or [Patreon](https://www.patreon.com/derhuerst).
* [deg0nz](https://github.com/deg0nz) for creating the [MMM-PublicTransportBerlin](https://github.com/deg0nz/MMM-PublicTransportBerlin) module, on which this one is originally based.
* [Ray Wojciechowski](https://github.com/raywo) for initiating this module and maintaining it until 2018.
* The community of magicmirror.builders for help in the development process and all contributors for finding and fixing errors in this module.
## Contributing
If you find any problems, bugs or have questions, please [open a GitHub issue](https://github.com/KristjanESPERANTO/MMM-PublicTransportHafas/issues) in this repository.
Pull requests are of course also very welcome 🙂
@@ -0,0 +1,89 @@
"use strict";
const createClient = require("hafas-client");
const readline = require("readline");
const arrayUnique = require("array-unique");
let profileName = "";
let profile = "";
const productMap = {
bus: "Bus",
ferry: "Fähre",
national: "Fernverkehr",
nationalExpress: "Fernverkehr",
regional: "Regionalverkehr",
suburban: "S-Bahn",
subway: "U-Bahn",
taxi: "Taxi",
tram: "Tram"
};
if (process.argv.length == 3) {
profileName = process.argv[2];
console.log("Using hafas-client profile: " + profileName);
} else {
console.log("Using default hafas-client profile: 'db'");
profileName = "db";
}
try {
profile = require("hafas-client/p/" + profileName);
}
catch(err) {
console.error("\n" + err.message + "\n Did you choose the right profile name? \n");
}
if (profile !== "") {
const client = createClient(profile, 'MMM-PublicTransportHafas');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question("Geben Sie eine Adresse oder einen Stationsnamen ein: ", (answer) => {
rl.close();
const opt = {
results: 10,
stations: true,
adresses: false,
poi: false
};
client.locations(answer, opt).then((response) => {
console.log("\nGefundene Haltestellen für \"" + answer + "\":\n");
response.forEach((element) => {
printStationInfo(element);
});
process.exit(0);
}).catch(console.error);
});
}
function printStationInfo(element) {
let id = element.id;
let name = element.name;
let products = element.products;
if (id && name) {
console.log("> Haltestelle: \"" + name + "\"\n ID: " + id + "\n " + refineProducts(products) + "\n");
}
}
function refineProducts(products) {
let result = "Verkehrsmittel: ";
if (!products) {
return result + "keine";
}
let availableProducts = Object.keys(products).filter(key => products[key]);
let availableProductsReadable = arrayUnique(availableProducts.map(product => productMap[product]));
return result + availableProductsReadable.join(", ");
}
@@ -0,0 +1,164 @@
"use strict";
const moment = require("moment");
const createClient = require("hafas-client");
const arrayDiff = require("arr-diff");
module.exports = class HafasFetcher {
/**
*
* @param config The configuration used for this fetcher. It has the following format:
* config = {
* identifier: *a string identifying this fetcher, must be unique for all instances of the module*
* hafasProfile: *a valid hafas-client profile name*,
* stationID: *a valid station id*,
* timeToStation: *an integer describing how long it takes to get to the station (in minutes)*,
* timeInFuture: *an integer describing how far in the future the departure can lie*
* direction: *an array of station ids*,
* ignoredLines: *an array of line names which are to be ignored*,
* excludedTransportationTypes: *an array of product names which are not to be shown*,
* maxReachableDepartures: *an integer describing how many departures should be fetched*,
* maxUnreachableDepartures: *an integer describing how many unreachable departures should be fetched*
* }
*/
constructor(config) {
this.leadTime = 40; // minutes
this.config = config;
const profile = require("hafas-client/p/" + this.config.hafasProfile);
this.hafasClient = createClient(profile, 'MMM-PublicTransportHafas');
// types given by the api
this.possibleTypes = [
"bus",
"ferry",
"express",
"national",
"nationalExpress",
"regional",
"suburban",
"subway",
"tram",
"taxi",
// for SVV
"bahn-s-bahn",
"u-bahn",
"strassenbahn",
"fernbus",
"regionalbus",
"stadtbus",
"seilbahn-zahnradbahn",
"schiff",
// for SBB
"express-train",
"international-train",
"interregional-train",
"regional-express-train",
"watercraft",
"suburban-train",
"bus-taxi",
"gondola",
"car-train",
];
this.config.includedTransportationTypes = arrayDiff(this.possibleTypes, this.config.excludedTransportationTypes);
}
getIdentifier() {
return this.config.identifier;
}
getStationID() {
return this.config.stationID;
}
fetchDepartures() {
let options = {
when: this.getDepartureTime(),
direction: this.config.direction,
duration: this.config.timeInFuture
};
return this.hafasClient.departures(this.config.stationID, options)
.then((departures) => {
let maxElements = this.config.maxReachableDepartures + this.config.maxUnreachableDepartures;
let filteredDepartures = this.filterByTransportationTypes(departures);
filteredDepartures = this.filterByIgnoredLines(filteredDepartures);
filteredDepartures = this.departuresMarkedWithReachability(filteredDepartures);
filteredDepartures = this.departuresRemovedSurplusUnreachableDepartures(filteredDepartures);
filteredDepartures = filteredDepartures.slice(0, maxElements);
return filteredDepartures;
}).catch((e) => {
throw e;
});
}
getDepartureTime() {
let departureTime = this.getReachableTime();
if (this.config.maxUnreachableDepartures > 0) {
departureTime = moment(departureTime).subtract(this.leadTime, "minutes");
}
return departureTime;
}
getReachableTime() {
return moment().add(this.config.timeToStation, "minutes");
}
filterByTransportationTypes(departures) {
return departures.filter((departure) => {
let product = departure.line.product;
let index = this.config.includedTransportationTypes.indexOf(product);
return index !== -1;
});
}
filterByIgnoredLines(departures) {
return departures.filter((departure) => {
let line = departure.line.name;
let index = this.config.ignoredLines.indexOf(line);
return index === -1;
});
}
departuresMarkedWithReachability(departures) {
return departures.map((departure) => {
departure.isReachable = this.isReachable(departure);
return departure;
});
}
departuresRemovedSurplusUnreachableDepartures(departures) {
let unreachableDeparturesCount = departures.filter(departure => !departure.isReachable).length;
let result = departures;
if (unreachableDeparturesCount > this.config.maxUnreachableDepartures) {
let toBeRemoved = unreachableDeparturesCount - this.config.maxUnreachableDepartures;
for (let i = 0; i < toBeRemoved; i++) {
result.shift();
}
}
return result;
}
isReachable(departure) {
return moment(departure.when).isSameOrAfter(moment(this.getReachableTime()));
}
};
@@ -0,0 +1,138 @@
"use strict";
class PTHAFASDomBuilder {
constructor(config) {
this.config = config;
this.headingSymbols = {
time: "fa fa-clock-o",
line: "fa fa-bus",
direction: "fa fa-exchange",
platform: "fa fa-map-marker"
};
}
getSimpleDom(message) {
let wrapper = this.getWrapper();
wrapper.appendChild(this.getDiv(message));
return wrapper;
}
getDom(departures, headings, noDeparturesMessage) {
let wrapper = this.getWrapper();
let departuresTable = this.getDeparturesTable(departures, headings, noDeparturesMessage);
wrapper.appendChild(departuresTable);
return wrapper;
}
getWrapper() {
let wrapper = document.createElement("div");
wrapper.className = "pthWrapper";
wrapper.appendChild(this.createHeadingElement(this.config.headerPrefix, this.config.stationName, this.config.headerAppendix));
return wrapper;
}
getDiv(message, cssClasses = "small light dimmed") {
let messageDiv = document.createElement("div");
messageDiv.className = cssClasses;
messageDiv.innerHTML = message;
return messageDiv;
}
// Create the module header. Prepend headerPrefix if given.
createHeadingElement(headerPrefix, stationName, headerAppendix) {
let headingElement = document.createElement("header");
let heading = stationName;
if (headerPrefix !== "") {
heading = headerPrefix + " " + heading;
}
if (headerAppendix !== "") {
heading += " " + headerAppendix;
}
headingElement.innerHTML = heading;
return headingElement;
}
getDeparturesTable(departures, headings, noDepartureMessage) {
let table = document.createElement("table");
table.className = "pthTable small";
if (this.config.showTableHeaders) {
let tableHeader = this.getDeparturesTableHeader(headings);
table.appendChild(tableHeader);
}
let tableBodyBuilder = new PTHAFASTableBodyBuilder(this.config);
let tableBody = tableBodyBuilder.getDeparturesTableBody(departures, noDepartureMessage);
table.appendChild(tableBody);
return table;
}
getDeparturesTableHeader(headings) {
let tHead = document.createElement("thead");
let headerRow = document.createElement("tr");
headerRow.className = "bold dimmed";
this.config.tableHeaderOrder.forEach((key) => {
let values = this.getHeadingValues(key, headings);
headerRow.appendChild(this.getHeaderCell(values));
});
tHead.appendChild(headerRow);
return tHead;
}
getHeadingValues(key, headings) {
let result = {
text: headings[key],
symbol: this.headingSymbols[key],
cssClass: ""
};
if (key === "line" || key === "direction" || key === "platform") {
result.cssClass = "pthTextCenter";
}
return result;
}
getHeaderCell(values) {
let textContent = values.text;
let symbol = values.symbol;
let cssClass = values.cssClass;
let cell = document.createElement("td");
cell.className = cssClass;
if (this.config.showTableHeadersAsSymbols) {
let content = document.createElement("i");
content.className = symbol;
cell.appendChild(content);
} else {
cell.innerHTML = textContent;
}
return cell;
}
}
@@ -0,0 +1,382 @@
"use strict";
class PTHAFASTableBodyBuilder {
constructor(config) {
this.config = config;
}
getDeparturesTableBody(departures, noDepartureMessage) {
let tBody = document.createElement("tbody");
tBody.className = "light";
if (departures.length === 0) {
let row = this.getDeparturesTableNoDeparturesRow(noDepartureMessage);
tBody.appendChild(row);
return tBody;
}
let reachableCount = departures.length;
let unreachableCount = departures.filter(departure => !departure.isReachable).length;
departures.forEach((departure, index) => {
let row = this.getDeparturesTableRow(departure, index, reachableCount, unreachableCount);
tBody.appendChild(row);
let nextDeparture = departures[index + 1];
this.insertRulerIfNecessary(tBody, departure, nextDeparture, noDepartureMessage);
});
return tBody;
}
insertRulerIfNecessary(tBody, departure, nextDeparture, noDepartureMessage) {
if (nextDeparture && !departure.isReachable && nextDeparture.isReachable) {
tBody.appendChild(this.getRulerRow());
}
if (!departure.isReachable && !nextDeparture) {
tBody.appendChild(this.getRulerRow());
tBody.appendChild(this.getDeparturesTableNoDeparturesRow(noDepartureMessage));
}
}
getTableCell(content, cssClass = "") {
let cell = document.createElement("td");
cell.className = cssClass;
if (typeof content === "string") {
cell.innerHTML = content;
} else {
cell.appendChild(content);
}
return cell;
}
getDeparturesTableNoDeparturesRow(noDepartureMessage) {
let row = document.createElement("tr");
row.className = "dimmed";
let cell = document.createElement("td");
cell.colSpan = 3;
cell.innerHTML = noDepartureMessage;
row.appendChild(cell);
return row;
}
getDeparturesTableRow(departure, index, departuresCount, unreachableCount) {
let row = document.createElement("tr");
row.className = "bright";
if (departure.isReachable) {
row.style.opacity = this.getRowOpacity(index - unreachableCount, departuresCount);
} else {
row.style.opacity = this.getUnreachableRowOpacity(index, unreachableCount);
}
this.config.tableHeaderOrder.forEach((key) => {
let cell = this.getCell(key, departure);
row.appendChild(cell);
});
return row;
}
getCell(key, departure) {
let cell;
switch (key) {
case "time":
let time = departure.when;
let delay = departure.delay;
// Use planned time if canceled
if (departure.canceled == true) time = departure.plannedWhen;
// Get time cell
cell = this.getTimeCell(time, delay);
// Add class if canceled
if (departure.canceled == true) cell.className += " pthCanceled";
break;
case "line":
let line = departure.line.name;
cell = this.getLineCell(line);
break;
case "direction":
let direction = departure.direction;
cell = this.getDirectionCell(direction);
break;
case "platform":
let platform = departure.platform;
if (platform == null) platform = departure.plannedPlatform;
if (platform == null) platform = "";
cell = this.getPlatformCell(platform);
break;
}
return cell;
}
getTimeCell(departure, delay) {
let time = this.getDisplayDepartureTime(departure, delay);
let cell = document.createElement("td");
if (moment(departure).isValid()) {
cell.className = "pthTimeCell";
cell.appendChild(document.createTextNode(time));
if (this.config.showAbsoluteTime) {
cell.appendChild(this.getDelaySpan(delay));
}
} else {
cell.className = "pthTimeCanceled";
cell.appendChild(document.createTextNode("Fällt aus"));
}
return cell;
}
getDelaySpan(delay) {
let delaySpan = document.createElement("span");
delaySpan.innerHTML = this.getDelay(delay);
let cssClass = "dimmed";
// +n === +n --> Test, if n is numeric
if (this.config.useColorForRealtimeInfo && (+delay === +delay)) {
cssClass = delay > 0 ? "pthHasDelay" : "pthIsTooEarly";
}
delaySpan.className = "pthDelay " + cssClass;
return delaySpan;
}
// +n === +n --> Test, if n is numeric
getDelay(delay) {
if (+delay === +delay) {
let sign = delay < 0 ? "-" : "+";
return "&nbsp;" + sign + delay / 60 + "&nbsp;";
} else {
return "&nbsp; +? &nbsp;";
}
}
getDisplayDepartureTime(when, delay) {
if (this.config.showAbsoluteTime) {
let time = moment(when).subtract(delay, "seconds");
return time.format("LT");
} else {
let time = moment(when);
return time.fromNow();
}
}
getLineId(lineName) {
let lineId = lineName;
if (lineName.search(" ") == -1) {
let lineNameWithoutSpaces = lineName.replace(/\s/g, "");
let firstNumberPosition = lineNameWithoutSpaces.search(/\d/);
lineId = lineNameWithoutSpaces;
if (firstNumberPosition > 0) {
lineId = lineNameWithoutSpaces.slice(firstNumberPosition);
}
} else {
lineId = lineName.split(" ")[1];
}
return lineId;
}
getLineCell(lineName) {
let line;
if (this.config.showOnlyLineNumbers) {
line = this.getLineId(lineName);
} else {
line = lineName;
}
let lineDiv = document.createElement("div");
lineDiv.innerHTML = line;
lineDiv.className = this.getLineCssClass(lineName) + " pthTextCenter";
return this.getTableCell(lineDiv);
}
getLineCssClass(lineName) {
if (this.config.showColoredLineSymbols) {
return this.getColoredCssClass(lineName);
} else {
return "pthSign pthBWLineSign";
}
}
/**
* Get product of a line name
*
* Some HAFAS interfaces output line names with a space after the product name and
* some do not. As an example: `RB50` <->` RB 50`.
* This function returns the product name. In the two examples already mentioned
* (`RB50` and` RB 50`) the string `RB` would be returned. If there is no product name
* (if the line name starts with a digit), `undefined` is returned.
*
* @param {String} lineName The line name as it was delivered by the HAFAS API.
* @return {String} product The product ('RB', 'S', 'U', ...).
*/
getProduct(lineName) {
let product = lineName;
if (lineName.search(" ") == -1) {
let lineNameWithoutSpaces = lineName.replace(/\s/g, "");
let firstNumberPosition = lineNameWithoutSpaces.search(/\d/);
product = lineNameWithoutSpaces;
if (firstNumberPosition > 0) {
product = lineNameWithoutSpaces.slice(0, firstNumberPosition);
}
} else {
product = lineName.split(" ")[0];
}
return product;
}
/**
* Get css class names
*
* Class names are returned depending on the line name. This enables CSS styles
* to be defined on the basis of various properties.
*
* @param {String} lineName The linename as it was delivered by the HAFAS API.
* @return {String} classNames Series of class names
*/
getColoredCssClass(lineName) {
let classNames = "pthSign";
let product = this.getProduct(lineName);
let dbProducts = ["IC", "ICE", "RE", "RB", "S"];
let ignoreShowOnlyLineNumbers = ["IC", "ICE", "RE", "RB", "S", "U"];
if (dbProducts.includes(product)) {
classNames += " pthDbStandard";
}
if (ignoreShowOnlyLineNumbers.includes(product) && this.config.showOnlyLineNumbers) {
classNames += " " + product.toLowerCase() + "WithProductName";
}
classNames += " " + product.toLowerCase();
classNames += " " + lineName.replace(/\s/g, "").toLowerCase();
return classNames;
}
getDirectionCell(direction) {
let truncatePosition = 26;
let content = this.getProcessedDirection(direction);
let className = "pthDirectionCell";
if (this.config.marqueeLongDirections && content.length > truncatePosition) {
content = document.createElement("span");
content.innerHTML = this.getProcessedDirection(direction);
className += " pthMarquee";
}
if (!this.config.showAbsoluteTime) {
className += " pthTextLeft";
}
return this.getTableCell(content, className);
}
getProcessedDirection(direction) {
let replacements = this.config.replaceInDirections;
let processed = direction;
Object.keys(replacements).forEach((key) => {
processed = processed.replace(new RegExp(key, "g"), replacements[key]);
});
return processed;
}
getPlatformCell(platform) {
let className = "pthPlatformCell pthTextCenter";
return this.getTableCell(platform, className);
}
getRowOpacity(index, departuresCount) {
if (!this.config.fadeReachableDepartures) {
return 1.0;
}
let threshold = departuresCount * this.config.fadePointForReachableDepartures;
let opacity = 1;
let startOpacity = 0.8;
let endOpacity = 0.2;
let opacityDiff = (startOpacity - endOpacity) / (departuresCount - threshold);
if (index > threshold) {
let fadingIndex = index - threshold;
let currentOpacity = fadingIndex * opacityDiff;
opacity = startOpacity - currentOpacity;
}
return opacity;
}
getUnreachableRowOpacity(index, count) {
if (!this.config.fadeUnreachableDepartures) {
return 1.0;
}
let startOpacity = 0.3;
let endOpacity = 0.6;
let opacityDiff = (endOpacity - startOpacity) / count;
if (index + 1 === count) {
return endOpacity;
} else {
return startOpacity + opacityDiff * index;
}
}
getRulerRow() {
let row = document.createElement("tr");
let cell = document.createElement("td");
cell.colSpan = 3;
cell.className = "pthRulerCell";
row.appendChild(cell);
return row;
}
}
@@ -0,0 +1,4 @@
/* Override default background-color for all busses */
.bus {
background-color: #F8C623;
}
@@ -0,0 +1,59 @@
/*
This stylesheet contains the css classes needed to colorize the line
labels in the display.
To customize this use as class name the name of the line without any
blanks and all lower case. For instance "Bus N9" becomes ".busn9".
Try to use color attributes only. Like background-color and color.
*/
/* Colors for each tram line */
.str1 {background-color: rgb( 251, 186, 0)}
.str2 {background-color: rgb( 239, 124, 0)}
.str3 {background-color: rgb( 0, 139, 210)}
.str4 {background-color: rgb( 155, 16, 6)}
.str5 {background-color: rgb( 15, 63, 147)}
.str7 {background-color: rgb( 234, 80, 151)}
.str8 {background-color: rgb( 136, 75,0)}
.str9 {background-color: rgb( 173, 175, 23)}
.str10 {background-color: rgb( 51, 102, 51)}
.str11 {background-color: rgb( 153, 102, 0)}
.str12 {background-color: rgb( 153, 204, 0)}
.str15 {background-color: rgb( 255, 102, 102)}
.str16 {background-color: rgb( 175, 24, 103)}
.str17 {background-color: rgb( 25, 204, 102)}
.str94 {background-color: rgb( 111, 17, 5)}
.str95 {background-color: rgb( 5, 21, 65)}
.str99 {background-color: rgb( 51, 204, 255)}
/* Colors for each bus line */
.bus21 {background-color: rgb( 255, 0, 0)}
.bus22 {background-color: rgb( 9, 146, 184)}
.bus23 {background-color: rgb( 0, 102, 51)}
.bus24 {background-color: rgb( 119, 67, 50)}
.bus25 {background-color: rgb( 171, 76, 0)}
.bus26 {background-color: rgb( 89, 11, 34)}
.bus27 {background-color: rgb( 141, 0, 75)}
.bus28 {background-color: rgb( 226, 141, 0)}
.bus30 {background-color: rgb( 116, 58, 118)}
.bus31 {background-color: rgb( 201, 75, 24)}
.bus32 {background-color: rgb( 153, 153, 0)}
.bus34 {background-color: rgb( 0, 153, 153)}
.bus35 {background-color: rgb( 23, 62, 112)}
.bus36 {background-color: rgb( 139, 100, 37)}
.bus40 {background-color: rgb( 204, 102, 119)}
.bus41 {background-color: rgb( 0, 51, 255)}
.bus42 {background-color: rgb( 111, 36, 114)}
.bus43 {background-color: rgb( 0, 91, 55)}
.bus44 {background-color: rgb( 0, 104, 180)}
.bus52 {background-color: rgb( 214, 126, 43)}
.bus53 {background-color: rgb( 181, 109, 40)}
.bus60 {background-color: rgb( 255, 115, 0)}
.bus61 {background-color: rgb( 181, 168, 0)}
.bus62 {background-color: rgb( 245, 130, 32)}
.bus65 {background-color: rgb( 68, 64, 136)}
.bus91 {background-color: rgb( 184, 67, 11)}
.bus97 {background-color: rgb( 90, 108, 2)}
@@ -0,0 +1,110 @@
/*
This stylesheet contains the css classes needed to colorize the line
labels in the display.
To customize this use as class name the name of the line without any
blanks and all lower case. For instance "Bus N9" becomes ".busn9"
*/
/*
All suburban lines share the same settings so they are listed with commas
separating them.
The border radius is slightly bigger than the font size. This will result
in nice round corners.
*/
.s1, .s2, .s3, .s4, .s5, .s5x, .s6 {
background-color: #1E944B;
border-radius: 1.25rem;
color: white;
width: 2em;
}
/*
The tram lines 1, 3 and 3e use all a green background color and a white
text color. The width of the line symbol is equal to the font size. This
will result in a square symbol.
*/
.str1, .str3, .str3e {
background-color: #5EB246;
color: white;
width: 1em;
}
.str2, .str8, .str9 {
background-color: #F8C623;
color: black;
width: 1em;
}
.str14 {
background-color: #00A8DB;
color: black;
width: 1em;
}
.str4, .str7, .str12, .str15 {
background-color: #174489;
color: white;
width: 1em;
}
.str10, .str11, .str16, .str51, .str56 {
background-color: #D8232A;
color: white;
width: 1em;
}
/*
Bus symbols should be displayed as a circle. That’s why the width and the
border-radius are both 1em.
*/
.bus65,
.bus70, .bus72, .bus73, .bus73e, .bus74, .bus74e,
.bus80, .bus81, .bus82, .bus89,
.bus90 {
background-color: #912A7D;
border-radius: 1em;
color: white;
width: 1em;
}
.bus61, .bus63,
.bus75, .bus79,
.bus83, .bus86, .bus87, .bus88,
.bus91, .bus91e,
.bus100, .bus105, .bus106, .bus107, .bus108,
.bus120, .bus130, .bus131, .bus135, .bus141, .bus145,
.bus161, .bus163, .bus164, .bus165,
.bus172, .bus175, .bus176,
.bus190, .bus191, .bus192, .bus195, .bus196, .bus197,
.bus202, .bus207, .bus215,
.bus412,
.bus645, .bus690, .bus691,
.bus724, .bus743 {
background-color: #A3A3A2;
border-radius: 1em;
color: white;
width: 1em;
}
.busn1, .busn1e, .busn5, .busn5e, .busn8, .busn8e {
background-color: #EE9F2E;
border-radius: 1em;
color: #164585;
width: 1em;
}
.busn2, .busn2e, .busn7, .busn7e {
background-color: #FBDE89;
border-radius: 1em;
color: #164585;
width: 1em;
}
.busn3, .busn3e, .busn4, .busn4e, .busn6, .busn6e, .busn9, .busn9e {
background-color: #FCD120;
border-radius: 1em;
color: #164585;
width: 1em;
}
@@ -0,0 +1,87 @@
/*
This stylesheet contains the css classes needed to colorize the line
labels in the display.
To customize this use as class name the name of the line without any
blanks and all lower case. For instance "Bus N9" becomes ".busn9"
*/
/*
S-Bahn
*/
.s1 {background-color: #6bbee6;}
.s2 {background-color: #8cbd4f;}
.s3 {background-color: #7d2a8b;}
.s4 {background-color: #cb1e47;}
.s5 {background-color: #7d2a8a;}
.s6 {background-color: #5da570;}
.s7 {background-color: #833c37;}
.s8 {background-color: #262425;}
.s20 {background-color: #d45e71;}
/*
U-Bahn
*/
.u1 {background-color: #5c803e;}
.u2 {background-color: #a6123a;}
.u3 {background-color: #d66f38;}
.u4 {background-color: #64b28d;}
.u5 {background-color: #a67322;}
.u6 {background-color: #406fb7;}
.u7 {background-color: #5b803e;}
.u8 {background-color: #9f1a31;}
/*
Straßenbahn
*/
.str12 {background-color: #903f98;}
.str15 {
background-color: white;
border: 1px solid #f58f98;
color: #f58f98;
}
.str16 {background-color: #006cb2;}
.str17 {background-color: #875b46;}
.str18 {background-color: #0db14b;}
.str19 {background-color: #ed1d24;}
.str20 {background-color: #00c0e8;}
.str21 {background-color: #b999c7;}
.str23 {background-color: #b3d334;}
.str25 {background-color: #f58f98;}
.str27 {
background-color: #faa61a;
}
.str28 {
background-color: white;
border: 1px solid #faa61a;
color: #faa61a;
}
.str29 {
background-color: white;
border: 1px solid #ed1d24;
color: #ed1d24;
}
/*
Bus
*/
.bus {
background-color: #d0672f;
border-radius: 1em;
color: white;
width: 3.5em;
}
/*
X-Bus
*/
div[class^="x"], div[class*=" x"] {
background-color: #779986;
border-radius: 1em;
color: white;
width: 3.5em;
}
@@ -0,0 +1,9 @@
/* Default properties for subways
** Unlike in other cities, subways in Stuttgart are
** classified as light rail (Stadtbahn, stb).
*/
[class^="pthSign stb stbu"] {
background-color: rgb(0,101,173);
color: white;
}
@@ -0,0 +1,210 @@
/*
All classes used by this module use the prefix "pth" (PublicTransportHafas) to separate
them from the rest of the interface.
*/
.pthWrapper {
position: relative;
}
.pthTable {
border-collapse: collapse;
border-spacing: 1px;
display: table;
}
.pthTable>thead {
text-align: left;
}
.pthTable td {
vertical-align: middle;
}
.pthTimeCell {
text-align: left;
}
.pthCanceled {
text-decoration: line-through;
}
.pthDirectionCell {
max-width: 24ch;
min-width: 16ch;
overflow: hidden;
padding-left: 1ch;
padding-right: 1ch;
text-overflow: ellipsis;
white-space: nowrap;
}
.pthPlatformCell {
padding-left: 1ch;
padding-right: 1ch;
}
.pthRulerCell {
border-bottom: 1px dotted #666;
border-spacing: 10px;
line-height: 0;
}
.pthTextLeft {
text-align: left;
}
.pthTextRight {
text-align: right;
}
.pthTextCenter {
text-align: center;
}
.pthDelay {
font-size: 0.8em;
font-weight: bolder;
}
.pthHasDelay {
color: red;
}
.pthIsTooEarly {
color: green;
}
.pthMarquee {
box-sizing: border-box;
margin: 0 auto;
overflow: hidden;
text-align: left;
white-space: nowrap;
}
.pthMarquee span {
animation: pthMarquee 3s linear infinite alternate;
display: inline-block;
white-space: nowrap;
}
@keyframes pthMarquee {
/* Two keyframe positions each to generate a little delay between animations. */
0%, 30% {
transform: translate(0%, 0);
}
95%, 100% {
transform: translate(-35%, 0);
}
}
/* Styles for line symbols. */
.pthSign {
background-color: #333333;
color: #666666;
min-width: 2.5ch;
font-size: 0.9em;
font-weight: bold;
margin: 0.2rem auto;
padding: 0 0.3rem;
position: relative;
text-align: center;
}
.pthBWLineSign {
background-color: #333333;
color: #666666;
margin-right: 0.3em;
}
/* Default properties for Deutsche Bahn products. */
.pthDbStandard {
border-radius: 0.25rem;
font-size: 0.8em;
}
.ice, .ic {
background-color: white;
border-bottom: 4px #F01414 solid;
color: #F01414;
}
.rb, .re {
background-color: rgb(31, 131, 50);
border: 0.5px white solid;
color: white;
}
.s {
background-color: rgb(0, 111, 53);
border: 0.5px white solid;
color: white;
width: max-content;
}
/* Default properties for busses (general) and obusses (SVV) */
.bus, .obus {
border-radius: 1em;
background-color: rgb(122, 32, 106);
color: white;
width: max-content;
}
/* Default properties for "Rufbusse" */
.ruf:before {
content: "☎ ";
color: white;
font-size: 0.8em;
}
.ruf {
border-radius: 1rem;
background-color: rgb(122, 32, 106);
color: white;
width: max-content;
}
/* Default properties for trams */
.str, .stb {
background-color: rgb(255, 0, 0);
color: white;
width: max-content;
}
/* Default properties for subways */
.u {
background-color: rgb(0, 101, 173);
color: white;
width: max-content;
}
.iceWithProductName:before {
content: "ICE ";
}
.icWithProductName:before {
content: "IC ";
}
.reWithProductName:before {
content: "RE ";
}
.rbWithProductName:before {
content: "RB ";
}
.sWithProductName:before {
content: "S";
}
.uWithProductName:before {
content: "U";
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

@@ -0,0 +1,72 @@
"use strict";
const NodeHelper = require("node_helper");
const HafasFetcher = require("./core/HafasFetcher");
module.exports = NodeHelper.create({
start: function () {
this.departuresFetchers = [];
},
socketNotificationReceived: function(notification, payload) {
switch (notification) {
case "CREATE_FETCHER":
this.createFetcher(payload);
break;
case "FETCH_DEPARTURES":
this.fetchDepartures(payload);
break;
}
},
createFetcher: function (config) {
let fetcher;
if (typeof this.departuresFetchers[config.identifier] === "undefined") {
fetcher = new HafasFetcher(config);
this.departuresFetchers[config.identifier] = fetcher;
console.log("Transportation fetcher for station with id '" + fetcher.getStationID() + "' created.");
this.sendFetcherLoaded(fetcher);
} else {
fetcher = this.departuresFetchers[config.identifier];
console.log("Using existing transportation fetcher for station id '" + fetcher.getStationID() + "'.");
this.sendFetcherLoaded(fetcher);
}
},
sendFetcherLoaded: function (fetcher) {
this.sendSocketNotification("FETCHER_INITIALIZED", {
identifier: fetcher.getIdentifier()
});
},
fetchDepartures(identifier) {
let fetcher = this.departuresFetchers[identifier];
fetcher.fetchDepartures().then((fetchedDepartures) => {
let payload = {
identifier: fetcher.getIdentifier(),
departures: fetchedDepartures
};
this.sendSocketNotification("DEPARTURES_FETCHED", payload);
}).catch((error) => {
let payload = {
identifier: fetcher.getIdentifier(),
error: error
};
this.sendSocketNotification("FETCH_ERROR", payload);
});
}
});
@@ -0,0 +1,9 @@
'use strict'
const br2nl = require('.')
console.log(br2nl('foo<br>bar'))
console.log(br2nl('foo<br> bar'))
console.log(br2nl('foo<br/>bar'))
console.log(br2nl('foo<br />bar'))
console.log(br2nl('foo<br a="b" />bar'))
@@ -0,0 +1,7 @@
'use strict'
const regex = /<br\b[^>]*>/gi
const br2nl = html => html.replace(regex, '\n')
module.exports = br2nl
@@ -0,0 +1,5 @@
Copyright (c) 2018, Jannis R
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
@@ -0,0 +1,62 @@
{
"_from": "@derhuerst/br2nl@^1.0.0",
"_id": "@derhuerst/br2nl@1.0.0",
"_inBundle": false,
"_integrity": "sha512-aGzqSMKM9eqHd9orDSe7yOvekRM9EMt9Jbc9vAG+a3jbn50WOTThVQX20c75yk0WBmu+6A5hdHGRM49dlp0I9w==",
"_location": "/@derhuerst/br2nl",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "@derhuerst/br2nl@^1.0.0",
"name": "@derhuerst/br2nl",
"escapedName": "@derhuerst%2fbr2nl",
"scope": "@derhuerst",
"rawSpec": "^1.0.0",
"saveSpec": null,
"fetchSpec": "^1.0.0"
},
"_requiredBy": [
"/hafas-client"
],
"_resolved": "https://registry.npmjs.org/@derhuerst/br2nl/-/br2nl-1.0.0.tgz",
"_shasum": "e2d18fd5ebbae8fa27b31e2f24bac846873fa895",
"_spec": "@derhuerst/br2nl@^1.0.0",
"_where": "/home/pi/MagicMirror/modules/MMM-PublicTransportHafas/node_modules/hafas-client",
"author": {
"name": "Jannis R",
"email": "mail@jannisr.de"
},
"bugs": {
"url": "https://github.com/derhuerst/br2nl/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "Replace HTML <br> tags with newline characters.",
"engines": {
"node": ">=6"
},
"files": [
"index.js",
"example.js"
],
"homepage": "https://github.com/derhuerst/br2nl",
"keywords": [
"br2nl",
"br",
"break",
"newline"
],
"license": "ISC",
"main": "index.js",
"name": "@derhuerst/br2nl",
"repository": {
"type": "git",
"url": "git+https://github.com/derhuerst/br2nl.git"
},
"scripts": {
"prepublishOnly": "npm test",
"test": "env NODE_ENV=dev node test.js"
},
"version": "1.0.0"
}
@@ -0,0 +1,36 @@
# br2nl
Yet another function to **replace HTML `<br>` tags with [newline characters](https://en.wikipedia.org/wiki/Newline)**.
*Note:* This package does *not* do [HTML sanitization](https://en.wikipedia.org/wiki/HTML_sanitization)! It merely replaces `<br>`.
[![npm version](https://img.shields.io/npm/v/br2nl.svg)](https://www.npmjs.com/package/br2nl)
[![build status](https://api.travis-ci.org/derhuerst/br2nl.svg?branch=master)](https://travis-ci.org/derhuerst/br2nl)
![ISC-licensed](https://img.shields.io/github/license/derhuerst/br2nl.svg)
[![chat with me on Gitter](https://img.shields.io/badge/chat%20with%20me-on%20gitter-512e92.svg)](https://gitter.im/derhuerst)
[![support me on Patreon](https://img.shields.io/badge/support%20me-on%20patreon-fa7664.svg)](https://patreon.com/derhuerst)
## Installation
```shell
npm install @derhuerst/br2nl
```
## Usage
```js
const br2nl = require('@derhuerst/br2nl')
console.log(br2nl('foo<br>bar'))
console.log(br2nl('foo<br> bar'))
console.log(br2nl('foo<br/>bar'))
console.log(br2nl('foo<br />bar'))
console.log(br2nl('foo<br a="b" />bar'))
```
## Contributing
If you have a question or need support using `br2nl`, please double-check your code and setup first. If you think you have found a bug or want to propose a feature, refer to [the issues page](https://github.com/derhuerst/br2nl/issues).
@@ -0,0 +1,45 @@
'use strict'
const RoundRobin = {
init: function (values) {
if (!Array.isArray(values)) throw new Error('values must be an array')
this.values = Array.from(values)
this.length = this.values.length
this.i = 0
},
get: function () {
if (this.i >= this.length) {
this.i = 1
return this.values[0]
}
return this.values[this.i++]
},
has: function (val) {
return this.values.indexOf(val) >= 0
},
findIndex: function (fn) {
return this.values.findIndex(fn)
},
add: function (val) {
this.values.push(val)
return this.length++
},
remove: function (i) {
if (i < 0 || i > this.length) return false
this.values.splice(i, 1)
this.length--
return true
}
}
const createRoundRobinScheduler = (values) => {
const roundRobin = Object.create(RoundRobin)
roundRobin.init(values || [])
return roundRobin
}
createRoundRobinScheduler.RoundRobin = RoundRobin
module.exports = createRoundRobinScheduler
@@ -0,0 +1,5 @@
Copyright (c) 2018, Jannis R
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
@@ -0,0 +1,68 @@
{
"_from": "@derhuerst/round-robin-scheduler@^1.0.4",
"_id": "@derhuerst/round-robin-scheduler@1.0.4",
"_inBundle": false,
"_integrity": "sha512-2oOeCz+wrLspXUNHET1ToHYK0nRbxzWRr3cRi9tSUzUdG2OEvw5myLdk7JSjueOWKmD26OHSh1M3SS3XSQ1w5w==",
"_location": "/@derhuerst/round-robin-scheduler",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "@derhuerst/round-robin-scheduler@^1.0.4",
"name": "@derhuerst/round-robin-scheduler",
"escapedName": "@derhuerst%2fround-robin-scheduler",
"scope": "@derhuerst",
"rawSpec": "^1.0.4",
"saveSpec": null,
"fetchSpec": "^1.0.4"
},
"_requiredBy": [
"/hafas-client"
],
"_resolved": "https://registry.npmjs.org/@derhuerst/round-robin-scheduler/-/round-robin-scheduler-1.0.4.tgz",
"_shasum": "2d2cd770a07d9eb4f1881345d5c6de5f101c3f9d",
"_spec": "@derhuerst/round-robin-scheduler@^1.0.4",
"_where": "/home/pi/MagicMirror/modules/MMM-PublicTransportHafas/node_modules/hafas-client",
"author": {
"name": "Jannis R",
"email": "mail@jannisr.de"
},
"bugs": {
"url": "https://github.com/derhuerst/round-robin-scheduler/issues"
},
"bundleDependencies": false,
"dependencies": {},
"deprecated": false,
"description": "A round-robin scheduler, compatible with the abstract-scheduler interface.",
"devDependencies": {
"abstract-scheduler": "^3.0.0",
"tap-min": "^1.2.2"
},
"engines": {
"node": ">=6"
},
"files": [
"index.js"
],
"homepage": "https://github.com/derhuerst/round-robin-scheduler",
"keywords": [
"round",
"robin",
"scheduler",
"abstract-scheduler",
"load balancer",
"load balancing"
],
"license": "LAGPL",
"main": "index.js",
"name": "@derhuerst/round-robin-scheduler",
"repository": {
"type": "git",
"url": "git+https://github.com/derhuerst/round-robin-scheduler.git"
},
"scripts": {
"prepublishOnly": "npm test",
"test": "env NODE_ENV=dev node test.js | tap-min"
},
"version": "1.0.4"
}
@@ -0,0 +1,42 @@
# round-robin-scheduler
**A [round-robin](https://en.wikipedia.org/wiki/Round-robin_scheduling) [scheduler](https://en.wikipedia.org/wiki/Scheduling_(computing)), compatible with the [`abstract-scheduler` interface](https://www.npmjs.com/package/abstract-scheduler).**
[![compatible with abstract-scheduler](https://unpkg.com/abstract-scheduler@3/badge.svg)](https://github.com/derhuerst/abstract-scheduler)
[![npm version](https://img.shields.io/npm/v/@derhuerst/round-robin-scheduler.svg)](https://www.npmjs.com/package/@derhuerst/round-robin-scheduler)
[![build status](https://api.travis-ci.org/derhuerst/round-robin-scheduler.svg?branch=master)](https://travis-ci.org/derhuerst/round-robin-scheduler)
![ISC-licensed](https://img.shields.io/github/license/derhuerst/round-robin-scheduler.svg)
[![chat with me on Gitter](https://img.shields.io/badge/chat%20with%20me-on%20gitter-512e92.svg)](https://gitter.im/derhuerst)
[![support me on Patreon](https://img.shields.io/badge/support%20me-on%20patreon-fa7664.svg)](https://patreon.com/derhuerst)
## Installation
```shell
npm install @derhuerst/round-robin-scheduler
```
## Usage
```js
const createRoundRobin = require('@derhuerst/round-robin-scheduler')
const roundRobin = createRoundRobin(['foo', 'bar'])
roundRobin.get() // foo
roundRobin.get() // bar
roundRobin.add('baz') // 2
roundRobin.length // 3
roundRobin.get() // baz
roundRobin.remove(0) // remove first item
roundRobin.get() // bar
```
`roundRobin` is compatible with the [`abstract-scheduler` interface](https://www.npmjs.com/package/abstract-scheduler).
## Contributing
If you have a question or need support using `round-robin-scheduler`, please double-check your code and setup first. If you think you have found a bug or want to propose a feature, refer to [the issues page](https://github.com/derhuerst/round-robin-scheduler/issues).
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) Microsoft Corporation.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE
+16
View File
@@ -0,0 +1,16 @@
# Installation
> `npm install --save @types/retry`
# Summary
This package contains type definitions for retry (https://github.com/tim-kos/node-retry).
# Details
Files were exported from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/retry.
### Additional Details
* Last updated: Wed, 07 Jul 2021 18:02:26 GMT
* Dependencies: none
* Global values: none
# Credits
These definitions were written by [Stan Goldmann](https://github.com/krenor), and [BendingBender](https://github.com/BendingBender).
+151
View File
@@ -0,0 +1,151 @@
// Type definitions for retry 0.12
// Project: https://github.com/tim-kos/node-retry
// Definitions by: Stan Goldmann <https://github.com/krenor>
// BendingBender <https://github.com/BendingBender>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.3
export interface RetryOperation {
/**
* Returns an array of all errors that have been passed to `retryOperation.retry()` so far.
* The returning array has the errors ordered chronologically based on when they were passed to
* `retryOperation.retry()`, which means the first passed error is at index zero and the last is at the last index.
*/
errors(): Error[];
/**
* A reference to the error object that occured most frequently.
* Errors are compared using the `error.message` property.
* If multiple error messages occured the same amount of time, the last error object with that message is returned.
*
* @return If no errors occured so far the value will be `null`.
*/
mainError(): Error | null;
/**
* Defines the function that is to be retried and executes it for the first time right away.
*
* @param fn The function that is to be retried. `currentAttempt` represents the number of attempts
* callback has been executed so far.
* @param [timeoutOps.timeout] A timeout in milliseconds.
* @param [timeoutOps.callback] Callback to execute when the operation takes longer than the timeout.
*/
attempt(fn: (currentAttempt: number) => void, timeoutOps?: AttemptTimeoutOptions): void;
/**
* Returns `false` when no `error` value is given, or the maximum amount of retries has been reached.
* Otherwise it returns `true`, and retries the operation after the timeout for the current attempt number.
*/
retry(err?: Error): boolean;
/**
* Stops the operation being retried. Useful for aborting the operation on a fatal error etc.
*/
stop(): void;
/**
* Resets the internal state of the operation object, so that you can call `attempt()` again as if
* this was a new operation object.
*/
reset(): void;
/**
* Returns an int representing the number of attempts it took to call `fn` before it was successful.
*/
attempts(): number;
}
export interface AttemptTimeoutOptions {
/**
* A timeout in milliseconds.
*/
timeout?: number | undefined;
/**
* Callback to execute when the operation takes longer than the timeout.
*/
callback?(): void;
}
/**
* Create a new RetryOperation object.
*
* @param [options.retries=10] The maximum amount of times to retry the operation.
* @param [options.factor=2] The exponential factor to use.
* @param [options.minTimeout=1000] The number of milliseconds before starting the first retry.
* @param [options.maxTimeout=Infinity] The maximum number of milliseconds between two retries.
* @param [options.randomize=false] Randomizes the timeouts by multiplying a factor between 1-2.
* @param [options.forever=false] Wether to retry forever.
* @param [options.unref=false] Wether to unref the setTimeout's.
*
*/
export function operation(options?: OperationOptions): RetryOperation;
export interface OperationOptions extends TimeoutsOptions {
/**
* Whether to retry forever.
* @default false
*/
forever?: boolean | undefined;
/**
* Whether to [unref](https://nodejs.org/api/timers.html#timers_unref) the setTimeout's.
* @default false
*/
unref?: boolean | undefined;
/**
* The maximum time (in milliseconds) that the retried operation is allowed to run.
* @default Infinity
*/
maxRetryTime?: number | undefined;
}
/** Get an array with timeouts and their return values in milliseconds. */
export function timeouts(options?: TimeoutsOptions): number[];
export interface TimeoutsOptions extends CreateTimeoutOptions {
/**
* The maximum amount of times to retry the operation.
* @default 10
*/
retries?: number | undefined;
}
/**
* Create a new timeout (in milliseconds) based on the given parameters.
*
* @param attempt Representing for which retry the timeout should be calculated.
* @return timeout
*/
export function createTimeout(attempt: number, options?: CreateTimeoutOptions): number;
export interface CreateTimeoutOptions {
/**
* The exponential factor to use.
* @default 2
*/
factor?: number | undefined;
/**
* The number of milliseconds before starting the first retry.
* @default 1000
*/
minTimeout?: number | undefined;
/**
* The maximum number of milliseconds between two retries.
* @default Infinity
*/
maxTimeout?: number | undefined;
/**
* Randomizes the timeouts by multiplying a factor between 1-2.
* @default false
*/
randomize?: boolean | undefined;
}
/**
* Wrap all functions of the object with retry.
*
* @param object The object to be wrapped
* @param methods Methods which need to be wrapped
*
*/
export function wrap(object: object, methods?: string[]): void;
export function wrap(object: object, options?: OperationOptions, methods?: string[]): void;
@@ -0,0 +1,57 @@
{
"_from": "@types/retry@^0.12.0",
"_id": "@types/retry@0.12.1",
"_inBundle": false,
"_integrity": "sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==",
"_location": "/@types/retry",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "@types/retry@^0.12.0",
"name": "@types/retry",
"escapedName": "@types%2fretry",
"scope": "@types",
"rawSpec": "^0.12.0",
"saveSpec": null,
"fetchSpec": "^0.12.0"
},
"_requiredBy": [
"/p-retry"
],
"_resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.1.tgz",
"_shasum": "d8f1c0d0dc23afad6dc16a9e993a0865774b4065",
"_spec": "@types/retry@^0.12.0",
"_where": "/home/pi/MagicMirror/modules/MMM-PublicTransportHafas/node_modules/p-retry",
"bugs": {
"url": "https://github.com/DefinitelyTyped/DefinitelyTyped/issues"
},
"bundleDependencies": false,
"contributors": [
{
"name": "Stan Goldmann",
"url": "https://github.com/krenor"
},
{
"name": "BendingBender",
"url": "https://github.com/BendingBender"
}
],
"dependencies": {},
"deprecated": false,
"description": "TypeScript definitions for retry",
"homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/retry",
"license": "MIT",
"main": "",
"name": "@types/retry",
"repository": {
"type": "git",
"url": "git+https://github.com/DefinitelyTyped/DefinitelyTyped.git",
"directory": "types/retry"
},
"scripts": {},
"typeScriptVersion": "3.6",
"types": "index.d.ts",
"typesPublisherContentHash": "1f47bb1a205340c2ce3816cbd526a396c6abccdd0aa138a440aa244f7da840e1",
"version": "0.12.1"
}
+145
View File
@@ -0,0 +1,145 @@
agent-base
==========
### Turn a function into an [`http.Agent`][http.Agent] instance
[![Build Status](https://github.com/TooTallNate/node-agent-base/workflows/Node%20CI/badge.svg)](https://github.com/TooTallNate/node-agent-base/actions?workflow=Node+CI)
This module provides an `http.Agent` generator. That is, you pass it an async
callback function, and it returns a new `http.Agent` instance that will invoke the
given callback function when sending outbound HTTP requests.
#### Some subclasses:
Here's some more interesting uses of `agent-base`.
Send a pull request to list yours!
* [`http-proxy-agent`][http-proxy-agent]: An HTTP(s) proxy `http.Agent` implementation for HTTP endpoints
* [`https-proxy-agent`][https-proxy-agent]: An HTTP(s) proxy `http.Agent` implementation for HTTPS endpoints
* [`pac-proxy-agent`][pac-proxy-agent]: A PAC file proxy `http.Agent` implementation for HTTP and HTTPS
* [`socks-proxy-agent`][socks-proxy-agent]: A SOCKS proxy `http.Agent` implementation for HTTP and HTTPS
Installation
------------
Install with `npm`:
``` bash
$ npm install agent-base
```
Example
-------
Here's a minimal example that creates a new `net.Socket` connection to the server
for every HTTP request (i.e. the equivalent of `agent: false` option):
```js
var net = require('net');
var tls = require('tls');
var url = require('url');
var http = require('http');
var agent = require('agent-base');
var endpoint = 'http://nodejs.org/api/';
var parsed = url.parse(endpoint);
// This is the important part!
parsed.agent = agent(function (req, opts) {
var socket;
// `secureEndpoint` is true when using the https module
if (opts.secureEndpoint) {
socket = tls.connect(opts);
} else {
socket = net.connect(opts);
}
return socket;
});
// Everything else works just like normal...
http.get(parsed, function (res) {
console.log('"response" event!', res.headers);
res.pipe(process.stdout);
});
```
Returning a Promise or using an `async` function is also supported:
```js
agent(async function (req, opts) {
await sleep(1000);
// etc…
});
```
Return another `http.Agent` instance to "pass through" the responsibility
for that HTTP request to that agent:
```js
agent(function (req, opts) {
return opts.secureEndpoint ? https.globalAgent : http.globalAgent;
});
```
API
---
## Agent(Function callback[, Object options]) → [http.Agent][]
Creates a base `http.Agent` that will execute the callback function `callback`
for every HTTP request that it is used as the `agent` for. The callback function
is responsible for creating a `stream.Duplex` instance of some kind that will be
used as the underlying socket in the HTTP request.
The `options` object accepts the following properties:
* `timeout` - Number - Timeout for the `callback()` function in milliseconds. Defaults to Infinity (optional).
The callback function should have the following signature:
### callback(http.ClientRequest req, Object options, Function cb) → undefined
The ClientRequest `req` can be accessed to read request headers and
and the path, etc. The `options` object contains the options passed
to the `http.request()`/`https.request()` function call, and is formatted
to be directly passed to `net.connect()`/`tls.connect()`, or however
else you want a Socket to be created. Pass the created socket to
the callback function `cb` once created, and the HTTP request will
continue to proceed.
If the `https` module is used to invoke the HTTP request, then the
`secureEndpoint` property on `options` _will be set to `true`_.
License
-------
(The MIT License)
Copyright (c) 2013 Nathan Rajlich &lt;nathan@tootallnate.net&gt;
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
[http-proxy-agent]: https://github.com/TooTallNate/node-http-proxy-agent
[https-proxy-agent]: https://github.com/TooTallNate/node-https-proxy-agent
[pac-proxy-agent]: https://github.com/TooTallNate/node-pac-proxy-agent
[socks-proxy-agent]: https://github.com/TooTallNate/node-socks-proxy-agent
[http.Agent]: https://nodejs.org/api/http.html#http_class_http_agent
@@ -0,0 +1,78 @@
/// <reference types="node" />
import net from 'net';
import http from 'http';
import https from 'https';
import { Duplex } from 'stream';
import { EventEmitter } from 'events';
declare function createAgent(opts?: createAgent.AgentOptions): createAgent.Agent;
declare function createAgent(callback: createAgent.AgentCallback, opts?: createAgent.AgentOptions): createAgent.Agent;
declare namespace createAgent {
interface ClientRequest extends http.ClientRequest {
_last?: boolean;
_hadError?: boolean;
method: string;
}
interface AgentRequestOptions {
host?: string;
path?: string;
port: number;
}
interface HttpRequestOptions extends AgentRequestOptions, Omit<http.RequestOptions, keyof AgentRequestOptions> {
secureEndpoint: false;
}
interface HttpsRequestOptions extends AgentRequestOptions, Omit<https.RequestOptions, keyof AgentRequestOptions> {
secureEndpoint: true;
}
type RequestOptions = HttpRequestOptions | HttpsRequestOptions;
type AgentLike = Pick<createAgent.Agent, 'addRequest'> | http.Agent;
type AgentCallbackReturn = Duplex | AgentLike;
type AgentCallbackCallback = (err?: Error | null, socket?: createAgent.AgentCallbackReturn) => void;
type AgentCallbackPromise = (req: createAgent.ClientRequest, opts: createAgent.RequestOptions) => createAgent.AgentCallbackReturn | Promise<createAgent.AgentCallbackReturn>;
type AgentCallback = typeof Agent.prototype.callback;
type AgentOptions = {
timeout?: number;
};
/**
* Base `http.Agent` implementation.
* No pooling/keep-alive is implemented by default.
*
* @param {Function} callback
* @api public
*/
class Agent extends EventEmitter {
timeout: number | null;
maxFreeSockets: number;
maxTotalSockets: number;
maxSockets: number;
sockets: {
[key: string]: net.Socket[];
};
freeSockets: {
[key: string]: net.Socket[];
};
requests: {
[key: string]: http.IncomingMessage[];
};
options: https.AgentOptions;
private promisifiedCallback?;
private explicitDefaultPort?;
private explicitProtocol?;
constructor(callback?: createAgent.AgentCallback | createAgent.AgentOptions, _opts?: createAgent.AgentOptions);
get defaultPort(): number;
set defaultPort(v: number);
get protocol(): string;
set protocol(v: string);
callback(req: createAgent.ClientRequest, opts: createAgent.RequestOptions, fn: createAgent.AgentCallbackCallback): void;
callback(req: createAgent.ClientRequest, opts: createAgent.RequestOptions): createAgent.AgentCallbackReturn | Promise<createAgent.AgentCallbackReturn>;
/**
* Called by node-core's "_http_client.js" module when creating
* a new HTTP request with this Agent instance.
*
* @api public
*/
addRequest(req: ClientRequest, _opts: RequestOptions): void;
freeSocket(socket: net.Socket, opts: AgentOptions): void;
destroy(): void;
}
}
export = createAgent;
@@ -0,0 +1,203 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
const events_1 = require("events");
const debug_1 = __importDefault(require("debug"));
const promisify_1 = __importDefault(require("./promisify"));
const debug = debug_1.default('agent-base');
function isAgent(v) {
return Boolean(v) && typeof v.addRequest === 'function';
}
function isSecureEndpoint() {
const { stack } = new Error();
if (typeof stack !== 'string')
return false;
return stack.split('\n').some(l => l.indexOf('(https.js:') !== -1 || l.indexOf('node:https:') !== -1);
}
function createAgent(callback, opts) {
return new createAgent.Agent(callback, opts);
}
(function (createAgent) {
/**
* Base `http.Agent` implementation.
* No pooling/keep-alive is implemented by default.
*
* @param {Function} callback
* @api public
*/
class Agent extends events_1.EventEmitter {
constructor(callback, _opts) {
super();
let opts = _opts;
if (typeof callback === 'function') {
this.callback = callback;
}
else if (callback) {
opts = callback;
}
// Timeout for the socket to be returned from the callback
this.timeout = null;
if (opts && typeof opts.timeout === 'number') {
this.timeout = opts.timeout;
}
// These aren't actually used by `agent-base`, but are required
// for the TypeScript definition files in `@types/node` :/
this.maxFreeSockets = 1;
this.maxSockets = 1;
this.maxTotalSockets = Infinity;
this.sockets = {};
this.freeSockets = {};
this.requests = {};
this.options = {};
}
get defaultPort() {
if (typeof this.explicitDefaultPort === 'number') {
return this.explicitDefaultPort;
}
return isSecureEndpoint() ? 443 : 80;
}
set defaultPort(v) {
this.explicitDefaultPort = v;
}
get protocol() {
if (typeof this.explicitProtocol === 'string') {
return this.explicitProtocol;
}
return isSecureEndpoint() ? 'https:' : 'http:';
}
set protocol(v) {
this.explicitProtocol = v;
}
callback(req, opts, fn) {
throw new Error('"agent-base" has no default implementation, you must subclass and override `callback()`');
}
/**
* Called by node-core's "_http_client.js" module when creating
* a new HTTP request with this Agent instance.
*
* @api public
*/
addRequest(req, _opts) {
const opts = Object.assign({}, _opts);
if (typeof opts.secureEndpoint !== 'boolean') {
opts.secureEndpoint = isSecureEndpoint();
}
if (opts.host == null) {
opts.host = 'localhost';
}
if (opts.port == null) {
opts.port = opts.secureEndpoint ? 443 : 80;
}
if (opts.protocol == null) {
opts.protocol = opts.secureEndpoint ? 'https:' : 'http:';
}
if (opts.host && opts.path) {
// If both a `host` and `path` are specified then it's most
// likely the result of a `url.parse()` call... we need to
// remove the `path` portion so that `net.connect()` doesn't
// attempt to open that as a unix socket file.
delete opts.path;
}
delete opts.agent;
delete opts.hostname;
delete opts._defaultAgent;
delete opts.defaultPort;
delete opts.createConnection;
// Hint to use "Connection: close"
// XXX: non-documented `http` module API :(
req._last = true;
req.shouldKeepAlive = false;
let timedOut = false;
let timeoutId = null;
const timeoutMs = opts.timeout || this.timeout;
const onerror = (err) => {
if (req._hadError)
return;
req.emit('error', err);
// For Safety. Some additional errors might fire later on
// and we need to make sure we don't double-fire the error event.
req._hadError = true;
};
const ontimeout = () => {
timeoutId = null;
timedOut = true;
const err = new Error(`A "socket" was not created for HTTP request before ${timeoutMs}ms`);
err.code = 'ETIMEOUT';
onerror(err);
};
const callbackError = (err) => {
if (timedOut)
return;
if (timeoutId !== null) {
clearTimeout(timeoutId);
timeoutId = null;
}
onerror(err);
};
const onsocket = (socket) => {
if (timedOut)
return;
if (timeoutId != null) {
clearTimeout(timeoutId);
timeoutId = null;
}
if (isAgent(socket)) {
// `socket` is actually an `http.Agent` instance, so
// relinquish responsibility for this `req` to the Agent
// from here on
debug('Callback returned another Agent instance %o', socket.constructor.name);
socket.addRequest(req, opts);
return;
}
if (socket) {
socket.once('free', () => {
this.freeSocket(socket, opts);
});
req.onSocket(socket);
return;
}
const err = new Error(`no Duplex stream was returned to agent-base for \`${req.method} ${req.path}\``);
onerror(err);
};
if (typeof this.callback !== 'function') {
onerror(new Error('`callback` is not defined'));
return;
}
if (!this.promisifiedCallback) {
if (this.callback.length >= 3) {
debug('Converting legacy callback function to promise');
this.promisifiedCallback = promisify_1.default(this.callback);
}
else {
this.promisifiedCallback = this.callback;
}
}
if (typeof timeoutMs === 'number' && timeoutMs > 0) {
timeoutId = setTimeout(ontimeout, timeoutMs);
}
if ('port' in opts && typeof opts.port !== 'number') {
opts.port = Number(opts.port);
}
try {
debug('Resolving socket for %o request: %o', opts.protocol, `${req.method} ${req.path}`);
Promise.resolve(this.promisifiedCallback(req, opts)).then(onsocket, callbackError);
}
catch (err) {
Promise.reject(err).catch(callbackError);
}
}
freeSocket(socket, opts) {
debug('Freeing socket %o %o', socket.constructor.name, opts);
socket.destroy();
}
destroy() {
debug('Destroying agent %o', this.constructor.name);
}
}
createAgent.Agent = Agent;
// So that `instanceof` works correctly
createAgent.prototype = createAgent.Agent.prototype;
})(createAgent || (createAgent = {}));
module.exports = createAgent;
//# sourceMappingURL=index.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,4 @@
import { ClientRequest, RequestOptions, AgentCallbackCallback, AgentCallbackPromise } from './index';
declare type LegacyCallback = (req: ClientRequest, opts: RequestOptions, fn: AgentCallbackCallback) => void;
export default function promisify(fn: LegacyCallback): AgentCallbackPromise;
export {};
@@ -0,0 +1,18 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function promisify(fn) {
return function (req, opts) {
return new Promise((resolve, reject) => {
fn.call(this, req, opts, (err, rtn) => {
if (err) {
reject(err);
}
else {
resolve(rtn);
}
});
});
};
}
exports.default = promisify;
//# sourceMappingURL=promisify.js.map
@@ -0,0 +1 @@
{"version":3,"file":"promisify.js","sourceRoot":"","sources":["../../src/promisify.ts"],"names":[],"mappings":";;AAeA,SAAwB,SAAS,CAAC,EAAkB;IACnD,OAAO,UAAsB,GAAkB,EAAE,IAAoB;QACpE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACtC,EAAE,CAAC,IAAI,CACN,IAAI,EACJ,GAAG,EACH,IAAI,EACJ,CAAC,GAA6B,EAAE,GAAyB,EAAE,EAAE;gBAC5D,IAAI,GAAG,EAAE;oBACR,MAAM,CAAC,GAAG,CAAC,CAAC;iBACZ;qBAAM;oBACN,OAAO,CAAC,GAAG,CAAC,CAAC;iBACb;YACF,CAAC,CACD,CAAC;QACH,CAAC,CAAC,CAAC;IACJ,CAAC,CAAC;AACH,CAAC;AAjBD,4BAiBC"}
+94
View File
@@ -0,0 +1,94 @@
{
"_from": "agent-base@6",
"_id": "agent-base@6.0.2",
"_inBundle": false,
"_integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
"_location": "/agent-base",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "agent-base@6",
"name": "agent-base",
"escapedName": "agent-base",
"rawSpec": "6",
"saveSpec": null,
"fetchSpec": "6"
},
"_requiredBy": [
"/https-proxy-agent"
],
"_resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
"_shasum": "49fff58577cfee3f37176feab4c22e00f86d7f77",
"_spec": "agent-base@6",
"_where": "/home/pi/MagicMirror/modules/MMM-PublicTransportHafas/node_modules/https-proxy-agent",
"author": {
"name": "Nathan Rajlich",
"email": "nathan@tootallnate.net",
"url": "http://n8.io/"
},
"bugs": {
"url": "https://github.com/TooTallNate/node-agent-base/issues"
},
"bundleDependencies": false,
"dependencies": {
"debug": "4"
},
"deprecated": false,
"description": "Turn a function into an `http.Agent` instance",
"devDependencies": {
"@types/debug": "4",
"@types/mocha": "^5.2.7",
"@types/node": "^14.0.20",
"@types/semver": "^7.1.0",
"@types/ws": "^6.0.3",
"@typescript-eslint/eslint-plugin": "1.6.0",
"@typescript-eslint/parser": "1.1.0",
"async-listen": "^1.2.0",
"cpy-cli": "^2.0.0",
"eslint": "5.16.0",
"eslint-config-airbnb": "17.1.0",
"eslint-config-prettier": "4.1.0",
"eslint-import-resolver-typescript": "1.1.1",
"eslint-plugin-import": "2.16.0",
"eslint-plugin-jsx-a11y": "6.2.1",
"eslint-plugin-react": "7.12.4",
"mocha": "^6.2.0",
"rimraf": "^3.0.0",
"semver": "^7.1.2",
"typescript": "^3.5.3",
"ws": "^3.0.0"
},
"engines": {
"node": ">= 6.0.0"
},
"files": [
"dist/src",
"src"
],
"homepage": "https://github.com/TooTallNate/node-agent-base#readme",
"keywords": [
"http",
"agent",
"base",
"barebones",
"https"
],
"license": "MIT",
"main": "dist/src/index",
"name": "agent-base",
"repository": {
"type": "git",
"url": "git://github.com/TooTallNate/node-agent-base.git"
},
"scripts": {
"build": "tsc",
"postbuild": "cpy --parents src test '!**/*.ts' dist",
"prebuild": "rimraf dist",
"prepublishOnly": "npm run build",
"test": "mocha --reporter spec dist/test/*.js",
"test-lint": "eslint src --ext .js,.ts"
},
"typings": "dist/src/index",
"version": "6.0.2"
}
+345
View File
@@ -0,0 +1,345 @@
import net from 'net';
import http from 'http';
import https from 'https';
import { Duplex } from 'stream';
import { EventEmitter } from 'events';
import createDebug from 'debug';
import promisify from './promisify';
const debug = createDebug('agent-base');
function isAgent(v: any): v is createAgent.AgentLike {
return Boolean(v) && typeof v.addRequest === 'function';
}
function isSecureEndpoint(): boolean {
const { stack } = new Error();
if (typeof stack !== 'string') return false;
return stack.split('\n').some(l => l.indexOf('(https.js:') !== -1 || l.indexOf('node:https:') !== -1);
}
function createAgent(opts?: createAgent.AgentOptions): createAgent.Agent;
function createAgent(
callback: createAgent.AgentCallback,
opts?: createAgent.AgentOptions
): createAgent.Agent;
function createAgent(
callback?: createAgent.AgentCallback | createAgent.AgentOptions,
opts?: createAgent.AgentOptions
) {
return new createAgent.Agent(callback, opts);
}
namespace createAgent {
export interface ClientRequest extends http.ClientRequest {
_last?: boolean;
_hadError?: boolean;
method: string;
}
export interface AgentRequestOptions {
host?: string;
path?: string;
// `port` on `http.RequestOptions` can be a string or undefined,
// but `net.TcpNetConnectOpts` expects only a number
port: number;
}
export interface HttpRequestOptions
extends AgentRequestOptions,
Omit<http.RequestOptions, keyof AgentRequestOptions> {
secureEndpoint: false;
}
export interface HttpsRequestOptions
extends AgentRequestOptions,
Omit<https.RequestOptions, keyof AgentRequestOptions> {
secureEndpoint: true;
}
export type RequestOptions = HttpRequestOptions | HttpsRequestOptions;
export type AgentLike = Pick<createAgent.Agent, 'addRequest'> | http.Agent;
export type AgentCallbackReturn = Duplex | AgentLike;
export type AgentCallbackCallback = (
err?: Error | null,
socket?: createAgent.AgentCallbackReturn
) => void;
export type AgentCallbackPromise = (
req: createAgent.ClientRequest,
opts: createAgent.RequestOptions
) =>
| createAgent.AgentCallbackReturn
| Promise<createAgent.AgentCallbackReturn>;
export type AgentCallback = typeof Agent.prototype.callback;
export type AgentOptions = {
timeout?: number;
};
/**
* Base `http.Agent` implementation.
* No pooling/keep-alive is implemented by default.
*
* @param {Function} callback
* @api public
*/
export class Agent extends EventEmitter {
public timeout: number | null;
public maxFreeSockets: number;
public maxTotalSockets: number;
public maxSockets: number;
public sockets: {
[key: string]: net.Socket[];
};
public freeSockets: {
[key: string]: net.Socket[];
};
public requests: {
[key: string]: http.IncomingMessage[];
};
public options: https.AgentOptions;
private promisifiedCallback?: createAgent.AgentCallbackPromise;
private explicitDefaultPort?: number;
private explicitProtocol?: string;
constructor(
callback?: createAgent.AgentCallback | createAgent.AgentOptions,
_opts?: createAgent.AgentOptions
) {
super();
let opts = _opts;
if (typeof callback === 'function') {
this.callback = callback;
} else if (callback) {
opts = callback;
}
// Timeout for the socket to be returned from the callback
this.timeout = null;
if (opts && typeof opts.timeout === 'number') {
this.timeout = opts.timeout;
}
// These aren't actually used by `agent-base`, but are required
// for the TypeScript definition files in `@types/node` :/
this.maxFreeSockets = 1;
this.maxSockets = 1;
this.maxTotalSockets = Infinity;
this.sockets = {};
this.freeSockets = {};
this.requests = {};
this.options = {};
}
get defaultPort(): number {
if (typeof this.explicitDefaultPort === 'number') {
return this.explicitDefaultPort;
}
return isSecureEndpoint() ? 443 : 80;
}
set defaultPort(v: number) {
this.explicitDefaultPort = v;
}
get protocol(): string {
if (typeof this.explicitProtocol === 'string') {
return this.explicitProtocol;
}
return isSecureEndpoint() ? 'https:' : 'http:';
}
set protocol(v: string) {
this.explicitProtocol = v;
}
callback(
req: createAgent.ClientRequest,
opts: createAgent.RequestOptions,
fn: createAgent.AgentCallbackCallback
): void;
callback(
req: createAgent.ClientRequest,
opts: createAgent.RequestOptions
):
| createAgent.AgentCallbackReturn
| Promise<createAgent.AgentCallbackReturn>;
callback(
req: createAgent.ClientRequest,
opts: createAgent.AgentOptions,
fn?: createAgent.AgentCallbackCallback
):
| createAgent.AgentCallbackReturn
| Promise<createAgent.AgentCallbackReturn>
| void {
throw new Error(
'"agent-base" has no default implementation, you must subclass and override `callback()`'
);
}
/**
* Called by node-core's "_http_client.js" module when creating
* a new HTTP request with this Agent instance.
*
* @api public
*/
addRequest(req: ClientRequest, _opts: RequestOptions): void {
const opts: RequestOptions = { ..._opts };
if (typeof opts.secureEndpoint !== 'boolean') {
opts.secureEndpoint = isSecureEndpoint();
}
if (opts.host == null) {
opts.host = 'localhost';
}
if (opts.port == null) {
opts.port = opts.secureEndpoint ? 443 : 80;
}
if (opts.protocol == null) {
opts.protocol = opts.secureEndpoint ? 'https:' : 'http:';
}
if (opts.host && opts.path) {
// If both a `host` and `path` are specified then it's most
// likely the result of a `url.parse()` call... we need to
// remove the `path` portion so that `net.connect()` doesn't
// attempt to open that as a unix socket file.
delete opts.path;
}
delete opts.agent;
delete opts.hostname;
delete opts._defaultAgent;
delete opts.defaultPort;
delete opts.createConnection;
// Hint to use "Connection: close"
// XXX: non-documented `http` module API :(
req._last = true;
req.shouldKeepAlive = false;
let timedOut = false;
let timeoutId: ReturnType<typeof setTimeout> | null = null;
const timeoutMs = opts.timeout || this.timeout;
const onerror = (err: NodeJS.ErrnoException) => {
if (req._hadError) return;
req.emit('error', err);
// For Safety. Some additional errors might fire later on
// and we need to make sure we don't double-fire the error event.
req._hadError = true;
};
const ontimeout = () => {
timeoutId = null;
timedOut = true;
const err: NodeJS.ErrnoException = new Error(
`A "socket" was not created for HTTP request before ${timeoutMs}ms`
);
err.code = 'ETIMEOUT';
onerror(err);
};
const callbackError = (err: NodeJS.ErrnoException) => {
if (timedOut) return;
if (timeoutId !== null) {
clearTimeout(timeoutId);
timeoutId = null;
}
onerror(err);
};
const onsocket = (socket: AgentCallbackReturn) => {
if (timedOut) return;
if (timeoutId != null) {
clearTimeout(timeoutId);
timeoutId = null;
}
if (isAgent(socket)) {
// `socket` is actually an `http.Agent` instance, so
// relinquish responsibility for this `req` to the Agent
// from here on
debug(
'Callback returned another Agent instance %o',
socket.constructor.name
);
(socket as createAgent.Agent).addRequest(req, opts);
return;
}
if (socket) {
socket.once('free', () => {
this.freeSocket(socket as net.Socket, opts);
});
req.onSocket(socket as net.Socket);
return;
}
const err = new Error(
`no Duplex stream was returned to agent-base for \`${req.method} ${req.path}\``
);
onerror(err);
};
if (typeof this.callback !== 'function') {
onerror(new Error('`callback` is not defined'));
return;
}
if (!this.promisifiedCallback) {
if (this.callback.length >= 3) {
debug('Converting legacy callback function to promise');
this.promisifiedCallback = promisify(this.callback);
} else {
this.promisifiedCallback = this.callback;
}
}
if (typeof timeoutMs === 'number' && timeoutMs > 0) {
timeoutId = setTimeout(ontimeout, timeoutMs);
}
if ('port' in opts && typeof opts.port !== 'number') {
opts.port = Number(opts.port);
}
try {
debug(
'Resolving socket for %o request: %o',
opts.protocol,
`${req.method} ${req.path}`
);
Promise.resolve(this.promisifiedCallback(req, opts)).then(
onsocket,
callbackError
);
} catch (err) {
Promise.reject(err).catch(callbackError);
}
}
freeSocket(socket: net.Socket, opts: AgentOptions) {
debug('Freeing socket %o %o', socket.constructor.name, opts);
socket.destroy();
}
destroy() {
debug('Destroying agent %o', this.constructor.name);
}
}
// So that `instanceof` works correctly
createAgent.prototype = createAgent.Agent.prototype;
}
export = createAgent;
@@ -0,0 +1,33 @@
import {
Agent,
ClientRequest,
RequestOptions,
AgentCallbackCallback,
AgentCallbackPromise,
AgentCallbackReturn
} from './index';
type LegacyCallback = (
req: ClientRequest,
opts: RequestOptions,
fn: AgentCallbackCallback
) => void;
export default function promisify(fn: LegacyCallback): AgentCallbackPromise {
return function(this: Agent, req: ClientRequest, opts: RequestOptions) {
return new Promise((resolve, reject) => {
fn.call(
this,
req,
opts,
(err: Error | null | undefined, rtn?: AgentCallbackReturn) => {
if (err) {
reject(err);
} else {
resolve(rtn);
}
}
);
});
};
}
+21
View File
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014-2017, Jon Schlinkert
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+130
View File
@@ -0,0 +1,130 @@
# arr-diff [![NPM version](https://img.shields.io/npm/v/arr-diff.svg?style=flat)](https://www.npmjs.com/package/arr-diff) [![NPM monthly downloads](https://img.shields.io/npm/dm/arr-diff.svg?style=flat)](https://npmjs.org/package/arr-diff) [![Linux Build Status](https://img.shields.io/travis/jonschlinkert/arr-diff.svg?style=flat&label=Travis)](https://travis-ci.org/jonschlinkert/arr-diff)
> Returns an array with only the unique values from the first array, by excluding all values from additional arrays using strict equality for comparisons.
## Install
Install with [npm](https://www.npmjs.com/):
```sh
$ npm install --save arr-diff
```
Install with [yarn](https://yarnpkg.com):
```sh
$ yarn add arr-diff
```
Install with [bower](https://bower.io/)
```sh
$ bower install arr-diff --save
```
## Usage
Returns the difference between the first array and additional arrays.
```js
var diff = require('arr-diff');
var a = ['a', 'b', 'c', 'd'];
var b = ['b', 'c'];
console.log(diff(a, b))
//=> ['a', 'd']
```
## Benchmarks
This library versus [array-differ](https://github.com/sindresorhus/array-differ), on April 14, 2017:
```
Benchmarking: (4 of 4)
· long-dupes
· long
· med
· short
# benchmark/fixtures/long-dupes.js (100804 bytes)
arr-diff-3.0.0 x 822 ops/sec ±0.67% (86 runs sampled)
arr-diff-4.0.0 x 2,141 ops/sec ±0.42% (89 runs sampled)
array-differ x 708 ops/sec ±0.70% (89 runs sampled)
fastest is arr-diff-4.0.0
# benchmark/fixtures/long.js (94529 bytes)
arr-diff-3.0.0 x 882 ops/sec ±0.60% (87 runs sampled)
arr-diff-4.0.0 x 2,329 ops/sec ±0.97% (83 runs sampled)
array-differ x 769 ops/sec ±0.61% (90 runs sampled)
fastest is arr-diff-4.0.0
# benchmark/fixtures/med.js (708 bytes)
arr-diff-3.0.0 x 856,150 ops/sec ±0.42% (89 runs sampled)
arr-diff-4.0.0 x 4,665,249 ops/sec ±1.06% (89 runs sampled)
array-differ x 653,888 ops/sec ±1.02% (86 runs sampled)
fastest is arr-diff-4.0.0
# benchmark/fixtures/short.js (60 bytes)
arr-diff-3.0.0 x 3,078,467 ops/sec ±0.77% (93 runs sampled)
arr-diff-4.0.0 x 9,213,296 ops/sec ±0.65% (89 runs sampled)
array-differ x 1,337,051 ops/sec ±0.91% (92 runs sampled)
fastest is arr-diff-4.0.0
```
## About
### Related projects
* [arr-flatten](https://www.npmjs.com/package/arr-flatten): Recursively flatten an array or arrays. This is the fastest implementation of array flatten. | [homepage](https://github.com/jonschlinkert/arr-flatten "Recursively flatten an array or arrays. This is the fastest implementation of array flatten.")
* [array-filter](https://www.npmjs.com/package/array-filter): Array#filter for older browsers. | [homepage](https://github.com/juliangruber/array-filter "Array#filter for older browsers.")
* [array-intersection](https://www.npmjs.com/package/array-intersection): Return an array with the unique values present in _all_ given arrays using strict equality… [more](https://github.com/jonschlinkert/array-intersection) | [homepage](https://github.com/jonschlinkert/array-intersection "Return an array with the unique values present in _all_ given arrays using strict equality for comparisons.")
### Contributing
Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
### Contributors
| **Commits** | **Contributor** |
| --- | --- |
| 33 | [jonschlinkert](https://github.com/jonschlinkert) |
| 2 | [paulmillr](https://github.com/paulmillr) |
### Building docs
_(This project's readme.md is generated by [verb](https://github.com/verbose/verb-generate-readme), please don't edit the readme directly. Any changes to the readme must be made in the [.verb.md](.verb.md) readme template.)_
To generate the readme, run the following command:
```sh
$ npm install -g verbose/verb#dev verb-generate-readme && verb
```
### Running tests
Running and reviewing unit tests is a great way to get familiarized with a library and its API. You can install dependencies and run tests with the following command:
```sh
$ npm install && npm test
```
### Author
**Jon Schlinkert**
* [github/jonschlinkert](https://github.com/jonschlinkert)
* [twitter/jonschlinkert](https://twitter.com/jonschlinkert)
### License
Copyright © 2017, [Jon Schlinkert](https://github.com/jonschlinkert).
Released under the [MIT License](LICENSE).
***
_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.5.0, on April 14, 2017._
+47
View File
@@ -0,0 +1,47 @@
/*!
* arr-diff <https://github.com/jonschlinkert/arr-diff>
*
* Copyright (c) 2014-2017, Jon Schlinkert.
* Released under the MIT License.
*/
'use strict';
module.exports = function diff(arr/*, arrays*/) {
var len = arguments.length;
var idx = 0;
while (++idx < len) {
arr = diffArray(arr, arguments[idx]);
}
return arr;
};
function diffArray(one, two) {
if (!Array.isArray(two)) {
return one.slice();
}
var tlen = two.length
var olen = one.length;
var idx = -1;
var arr = [];
while (++idx < olen) {
var ele = one[idx];
var hasEle = false;
for (var i = 0; i < tlen; i++) {
var val = two[i];
if (ele === val) {
hasEle = true;
break;
}
}
if (hasEle === false) {
arr.push(ele);
}
}
return arr;
}
+108
View File
@@ -0,0 +1,108 @@
{
"_from": "arr-diff@^4.0.0",
"_id": "arr-diff@4.0.0",
"_inBundle": false,
"_integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
"_location": "/arr-diff",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "arr-diff@^4.0.0",
"name": "arr-diff",
"escapedName": "arr-diff",
"rawSpec": "^4.0.0",
"saveSpec": null,
"fetchSpec": "^4.0.0"
},
"_requiredBy": [
"/"
],
"_resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
"_shasum": "d6461074febfec71e7e15235761a329a5dc7c520",
"_spec": "arr-diff@^4.0.0",
"_where": "/home/pi/MagicMirror/modules/MMM-PublicTransportHafas",
"author": {
"name": "Jon Schlinkert",
"url": "https://github.com/jonschlinkert"
},
"bugs": {
"url": "https://github.com/jonschlinkert/arr-diff/issues"
},
"bundleDependencies": false,
"contributors": [
{
"name": "Jon Schlinkert",
"email": "jon.schlinkert@sellside.com",
"url": "http://twitter.com/jonschlinkert"
},
{
"name": "Paul Miller",
"email": "paul+gh@paulmillr.com",
"url": "paulmillr.com"
}
],
"dependencies": {},
"deprecated": false,
"description": "Returns an array with only the unique values from the first array, by excluding all values from additional arrays using strict equality for comparisons.",
"devDependencies": {
"ansi-bold": "^0.1.1",
"arr-flatten": "^1.0.1",
"array-differ": "^1.0.0",
"benchmarked": "^0.2.4",
"gulp-format-md": "^0.1.9",
"minimist": "^1.2.0",
"mocha": "^2.4.5"
},
"engines": {
"node": ">=0.10.0"
},
"files": [
"index.js"
],
"homepage": "https://github.com/jonschlinkert/arr-diff",
"keywords": [
"arr",
"array",
"array differ",
"array-differ",
"diff",
"differ",
"difference"
],
"license": "MIT",
"main": "index.js",
"name": "arr-diff",
"repository": {
"type": "git",
"url": "git+https://github.com/jonschlinkert/arr-diff.git"
},
"scripts": {
"test": "mocha"
},
"verb": {
"toc": false,
"layout": "default",
"tasks": [
"readme"
],
"plugins": [
"gulp-format-md"
],
"related": {
"list": [
"arr-flatten",
"array-filter",
"array-intersection"
]
},
"reflinks": [
"array-differ",
"verb"
],
"lint": {
"reflinks": true
}
},
"version": "4.0.0"
}
+21
View File
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014-2016, Jon Schlinkert
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+77
View File
@@ -0,0 +1,77 @@
# array-unique [![NPM version](https://img.shields.io/npm/v/array-unique.svg?style=flat)](https://www.npmjs.com/package/array-unique) [![NPM downloads](https://img.shields.io/npm/dm/array-unique.svg?style=flat)](https://npmjs.org/package/array-unique) [![Build Status](https://img.shields.io/travis/jonschlinkert/array-unique.svg?style=flat)](https://travis-ci.org/jonschlinkert/array-unique)
Remove duplicate values from an array. Fastest ES5 implementation.
## Install
Install with [npm](https://www.npmjs.com/):
```sh
$ npm install --save array-unique
```
## Usage
```js
var unique = require('array-unique');
var arr = ['a', 'b', 'c', 'c'];
console.log(unique(arr)) //=> ['a', 'b', 'c']
console.log(arr) //=> ['a', 'b', 'c']
/* The above modifies the input array. To prevent that at a slight performance cost: */
var unique = require("array-unique").immutable;
var arr = ['a', 'b', 'c', 'c'];
console.log(unique(arr)) //=> ['a', 'b', 'c']
console.log(arr) //=> ['a', 'b', 'c', 'c']
```
## About
### Related projects
* [arr-diff](https://www.npmjs.com/package/arr-diff): Returns an array with only the unique values from the first array, by excluding all… [more](https://github.com/jonschlinkert/arr-diff) | [homepage](https://github.com/jonschlinkert/arr-diff "Returns an array with only the unique values from the first array, by excluding all values from additional arrays using strict equality for comparisons.")
* [arr-flatten](https://www.npmjs.com/package/arr-flatten): Recursively flatten an array or arrays. This is the fastest implementation of array flatten. | [homepage](https://github.com/jonschlinkert/arr-flatten "Recursively flatten an array or arrays. This is the fastest implementation of array flatten.")
* [arr-map](https://www.npmjs.com/package/arr-map): Faster, node.js focused alternative to JavaScript's native array map. | [homepage](https://github.com/jonschlinkert/arr-map "Faster, node.js focused alternative to JavaScript's native array map.")
* [arr-pluck](https://www.npmjs.com/package/arr-pluck): Retrieves the value of a specified property from all elements in the collection. | [homepage](https://github.com/jonschlinkert/arr-pluck "Retrieves the value of a specified property from all elements in the collection.")
* [arr-reduce](https://www.npmjs.com/package/arr-reduce): Fast array reduce that also loops over sparse elements. | [homepage](https://github.com/jonschlinkert/arr-reduce "Fast array reduce that also loops over sparse elements.")
* [arr-union](https://www.npmjs.com/package/arr-union): Combines a list of arrays, returning a single array with unique values, using strict equality… [more](https://github.com/jonschlinkert/arr-union) | [homepage](https://github.com/jonschlinkert/arr-union "Combines a list of arrays, returning a single array with unique values, using strict equality for comparisons.")
### Contributing
Pull requests and stars are always welcome. For bugs and feature requests, [please create an issue](../../issues/new).
### Building docs
_(This document was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme) (a [verb](https://github.com/verbose/verb) generator), please don't edit the readme directly. Any changes to the readme must be made in [.verb.md](.verb.md).)_
To generate the readme and API documentation with [verb](https://github.com/verbose/verb):
```sh
$ npm install -g verb verb-generate-readme && verb
```
### Running tests
Install dev dependencies:
```sh
$ npm install -d && npm test
```
### Author
**Jon Schlinkert**
* [github/jonschlinkert](https://github.com/jonschlinkert)
* [twitter/jonschlinkert](http://twitter.com/jonschlinkert)
### License
Copyright © 2016, [Jon Schlinkert](https://github.com/jonschlinkert).
Released under the [MIT license](https://github.com/jonschlinkert/array-unique/blob/master/LICENSE).
***
_This file was generated by [verb-generate-readme](https://github.com/verbose/verb-generate-readme), v0.1.28, on July 31, 2016._
+43
View File
@@ -0,0 +1,43 @@
/*!
* array-unique <https://github.com/jonschlinkert/array-unique>
*
* Copyright (c) 2014-2015, Jon Schlinkert.
* Licensed under the MIT License.
*/
'use strict';
module.exports = function unique(arr) {
if (!Array.isArray(arr)) {
throw new TypeError('array-unique expects an array.');
}
var len = arr.length;
var i = -1;
while (i++ < len) {
var j = i + 1;
for (; j < arr.length; ++j) {
if (arr[i] === arr[j]) {
arr.splice(j--, 1);
}
}
}
return arr;
};
module.exports.immutable = function uniqueImmutable(arr) {
if (!Array.isArray(arr)) {
throw new TypeError('array-unique expects an array.');
}
var arrLen = arr.length;
var newArr = new Array(arrLen);
for (var i = 0; i < arrLen; i++) {
newArr[i] = arr[i];
}
return module.exports(newArr);
};
@@ -0,0 +1,93 @@
{
"_from": "array-unique@^0.3.2",
"_id": "array-unique@0.3.2",
"_inBundle": false,
"_integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
"_location": "/array-unique",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "array-unique@^0.3.2",
"name": "array-unique",
"escapedName": "array-unique",
"rawSpec": "^0.3.2",
"saveSpec": null,
"fetchSpec": "^0.3.2"
},
"_requiredBy": [
"/"
],
"_resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
"_shasum": "a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428",
"_spec": "array-unique@^0.3.2",
"_where": "/home/pi/MagicMirror/modules/MMM-PublicTransportHafas",
"author": {
"name": "Jon Schlinkert",
"url": "https://github.com/jonschlinkert"
},
"bugs": {
"url": "https://github.com/jonschlinkert/array-unique/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "Remove duplicate values from an array. Fastest ES5 implementation.",
"devDependencies": {
"array-uniq": "^1.0.2",
"benchmarked": "^0.1.3",
"gulp-format-md": "^0.1.9",
"mocha": "^2.5.3",
"should": "^10.0.0"
},
"engines": {
"node": ">=0.10.0"
},
"files": [
"index.js",
"LICENSE",
"README.md"
],
"homepage": "https://github.com/jonschlinkert/array-unique",
"keywords": [
"array",
"unique"
],
"license": "MIT",
"main": "index.js",
"name": "array-unique",
"repository": {
"type": "git",
"url": "git+https://github.com/jonschlinkert/array-unique.git"
},
"scripts": {
"test": "mocha"
},
"verb": {
"toc": false,
"layout": "default",
"tasks": [
"readme"
],
"plugins": [
"gulp-format-md"
],
"related": {
"list": [
"arr-diff",
"arr-union",
"arr-flatten",
"arr-reduce",
"arr-map",
"arr-pluck"
]
},
"reflinks": [
"verb",
"verb-generate-readme"
],
"lint": {
"reflinks": true
}
},
"version": "0.3.2"
}
@@ -0,0 +1 @@
coverage/
+17
View File
@@ -0,0 +1,17 @@
{
"root": true,
"extends": "@ljharb",
"rules": {
"func-name-matching": 0,
"id-length": 0,
"new-cap": [2, {
"capIsNewExceptions": [
"GetIntrinsic",
],
}],
"no-magic-numbers": 0,
"operator-linebreak": [2, "before"],
},
}
@@ -0,0 +1,12 @@
# These are supported funding model platforms
github: [ljharb]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: npm/call-bind
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
+13
View File
@@ -0,0 +1,13 @@
{
"all": true,
"check-coverage": false,
"reporter": ["text-summary", "text", "html", "json"],
"lines": 86,
"statements": 85.93,
"functions": 82.43,
"branches": 76.06,
"exclude": [
"coverage",
"test"
]
}
+42
View File
@@ -0,0 +1,42 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [v1.0.2](https://github.com/ljharb/call-bind/compare/v1.0.1...v1.0.2) - 2021-01-11
### Commits
- [Fix] properly include the receiver in the bound length [`dbae7bc`](https://github.com/ljharb/call-bind/commit/dbae7bc676c079a0d33c0a43e9ef92cb7b01345d)
## [v1.0.1](https://github.com/ljharb/call-bind/compare/v1.0.0...v1.0.1) - 2021-01-08
### Commits
- [Tests] migrate tests to Github Actions [`b6db284`](https://github.com/ljharb/call-bind/commit/b6db284c36f8ccd195b88a6764fe84b7223a0da1)
- [meta] do not publish github action workflow files [`ec7fe46`](https://github.com/ljharb/call-bind/commit/ec7fe46e60cfa4764ee943d2755f5e5a366e578e)
- [Fix] preserve original function’s length when possible [`adbceaa`](https://github.com/ljharb/call-bind/commit/adbceaa3cac4b41ea78bb19d7ccdbaaf7e0bdadb)
- [Tests] gather coverage data on every job [`d69e23c`](https://github.com/ljharb/call-bind/commit/d69e23cc65f101ba1d4c19bb07fa8eb0ec624be8)
- [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `aud`, `tape` [`2fd3586`](https://github.com/ljharb/call-bind/commit/2fd3586c5d47b335364c14293114c6b625ae1f71)
- [Deps] update `get-intrinsic` [`f23e931`](https://github.com/ljharb/call-bind/commit/f23e9318cc271c2add8bb38cfded85ee7baf8eee)
- [Deps] update `get-intrinsic` [`72d9f44`](https://github.com/ljharb/call-bind/commit/72d9f44e184465ba8dd3fb48260bbcff234985f2)
- [meta] fix FUNDING.yml [`e723573`](https://github.com/ljharb/call-bind/commit/e723573438c5a68dcec31fb5d96ea6b7e4a93be8)
- [eslint] ignore coverage output [`15e76d2`](https://github.com/ljharb/call-bind/commit/15e76d28a5f43e504696401e5b31ebb78ee1b532)
- [meta] add Automatic Rebase and Require Allow Edits workflows [`8fa4dab`](https://github.com/ljharb/call-bind/commit/8fa4dabb23ba3dd7bb92c9571c1241c08b56e4b6)
## v1.0.0 - 2020-10-30
### Commits
- Initial commit [`306cf98`](https://github.com/ljharb/call-bind/commit/306cf98c7ec9e7ef66b653ec152277ac1381eb50)
- Tests [`e10d0bb`](https://github.com/ljharb/call-bind/commit/e10d0bbdadc7a10ecedc9a1c035112d3e368b8df)
- Implementation [`43852ed`](https://github.com/ljharb/call-bind/commit/43852eda0f187327b7fad2423ca972149a52bd65)
- npm init [`408f860`](https://github.com/ljharb/call-bind/commit/408f860b773a2f610805fd3613d0d71bac1b6249)
- [meta] add Automatic Rebase and Require Allow Edits workflows [`fb349b2`](https://github.com/ljharb/call-bind/commit/fb349b2e48defbec8b5ec8a8395cc8f69f220b13)
- [meta] add `auto-changelog` [`c4001fc`](https://github.com/ljharb/call-bind/commit/c4001fc43031799ef908211c98d3b0fb2b60fde4)
- [meta] add "funding"; create `FUNDING.yml` [`d4d6d29`](https://github.com/ljharb/call-bind/commit/d4d6d2974a14bc2e98830468eda7fe6d6a776717)
- [Tests] add `npm run lint` [`dedfb98`](https://github.com/ljharb/call-bind/commit/dedfb98bd0ecefb08ddb9a94061bd10cde4332af)
- Only apps should have lockfiles [`54ac776`](https://github.com/ljharb/call-bind/commit/54ac77653db45a7361dc153d2f478e743f110650)
- [meta] add `safe-publish-latest` [`9ea8e43`](https://github.com/ljharb/call-bind/commit/9ea8e435b950ce9b705559cd651039f9bf40140f)
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 Jordan Harband
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+2
View File
@@ -0,0 +1,2 @@
# call-bind
Robustly `.call.bind()` a function.
+15
View File
@@ -0,0 +1,15 @@
'use strict';
var GetIntrinsic = require('get-intrinsic');
var callBind = require('./');
var $indexOf = callBind(GetIntrinsic('String.prototype.indexOf'));
module.exports = function callBoundIntrinsic(name, allowMissing) {
var intrinsic = GetIntrinsic(name, !!allowMissing);
if (typeof intrinsic === 'function' && $indexOf(name, '.prototype.') > -1) {
return callBind(intrinsic);
}
return intrinsic;
};
+47
View File
@@ -0,0 +1,47 @@
'use strict';
var bind = require('function-bind');
var GetIntrinsic = require('get-intrinsic');
var $apply = GetIntrinsic('%Function.prototype.apply%');
var $call = GetIntrinsic('%Function.prototype.call%');
var $reflectApply = GetIntrinsic('%Reflect.apply%', true) || bind.call($call, $apply);
var $gOPD = GetIntrinsic('%Object.getOwnPropertyDescriptor%', true);
var $defineProperty = GetIntrinsic('%Object.defineProperty%', true);
var $max = GetIntrinsic('%Math.max%');
if ($defineProperty) {
try {
$defineProperty({}, 'a', { value: 1 });
} catch (e) {
// IE 8 has a broken defineProperty
$defineProperty = null;
}
}
module.exports = function callBind(originalFunction) {
var func = $reflectApply(bind, $call, arguments);
if ($gOPD && $defineProperty) {
var desc = $gOPD(func, 'length');
if (desc.configurable) {
// original length, plus the receiver, minus any additional arguments (after the receiver)
$defineProperty(
func,
'length',
{ value: 1 + $max(0, originalFunction.length - (arguments.length - 1)) }
);
}
}
return func;
};
var applyBind = function applyBind() {
return $reflectApply(bind, $apply, arguments);
};
if ($defineProperty) {
$defineProperty(module.exports, 'apply', { value: applyBind });
} else {
module.exports.apply = applyBind;
}
+108
View File
@@ -0,0 +1,108 @@
{
"_from": "call-bind@^1.0.0",
"_id": "call-bind@1.0.2",
"_inBundle": false,
"_integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
"_location": "/call-bind",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "call-bind@^1.0.0",
"name": "call-bind",
"escapedName": "call-bind",
"rawSpec": "^1.0.0",
"saveSpec": null,
"fetchSpec": "^1.0.0"
},
"_requiredBy": [
"/side-channel"
],
"_resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
"_shasum": "b1d4e89e688119c3c9a903ad30abb2f6a919be3c",
"_spec": "call-bind@^1.0.0",
"_where": "/home/pi/MagicMirror/modules/MMM-PublicTransportHafas/node_modules/side-channel",
"author": {
"name": "Jordan Harband",
"email": "ljharb@gmail.com"
},
"auto-changelog": {
"output": "CHANGELOG.md",
"template": "keepachangelog",
"unreleased": false,
"commitLimit": false,
"backfillLimit": false,
"hideCredit": true
},
"bugs": {
"url": "https://github.com/ljharb/call-bind/issues"
},
"bundleDependencies": false,
"dependencies": {
"function-bind": "^1.1.1",
"get-intrinsic": "^1.0.2"
},
"deprecated": false,
"description": "Robustly `.call.bind()` a function",
"devDependencies": {
"@ljharb/eslint-config": "^17.3.0",
"aud": "^1.1.3",
"auto-changelog": "^2.2.1",
"eslint": "^7.17.0",
"nyc": "^10.3.2",
"safe-publish-latest": "^1.1.4",
"tape": "^5.1.1"
},
"exports": {
".": [
{
"default": "./index.js"
},
"./index.js"
],
"./callBound": [
{
"default": "./callBound.js"
},
"./callBound.js"
],
"./package.json": "./package.json"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
},
"homepage": "https://github.com/ljharb/call-bind#readme",
"keywords": [
"javascript",
"ecmascript",
"es",
"js",
"callbind",
"callbound",
"call",
"bind",
"bound",
"call-bind",
"call-bound",
"function",
"es-abstract"
],
"license": "MIT",
"main": "index.js",
"name": "call-bind",
"repository": {
"type": "git",
"url": "git+https://github.com/ljharb/call-bind.git"
},
"scripts": {
"lint": "eslint --ext=.js,.mjs .",
"posttest": "aud --production",
"postversion": "auto-changelog && git add CHANGELOG.md && git commit --no-edit --amend && git tag -f \"v$(node -e \"console.log(require('./package.json').version)\")\"",
"prepublish": "safe-publish-latest",
"pretest": "npm run lint",
"test": "npm run tests-only",
"tests-only": "nyc tape 'test/*'",
"version": "auto-changelog && git add CHANGELOG.md"
},
"version": "1.0.2"
}
@@ -0,0 +1,55 @@
'use strict';
var test = require('tape');
var callBound = require('../callBound');
test('callBound', function (t) {
// static primitive
t.equal(callBound('Array.length'), Array.length, 'Array.length yields itself');
t.equal(callBound('%Array.length%'), Array.length, '%Array.length% yields itself');
// static non-function object
t.equal(callBound('Array.prototype'), Array.prototype, 'Array.prototype yields itself');
t.equal(callBound('%Array.prototype%'), Array.prototype, '%Array.prototype% yields itself');
t.equal(callBound('Array.constructor'), Array.constructor, 'Array.constructor yields itself');
t.equal(callBound('%Array.constructor%'), Array.constructor, '%Array.constructor% yields itself');
// static function
t.equal(callBound('Date.parse'), Date.parse, 'Date.parse yields itself');
t.equal(callBound('%Date.parse%'), Date.parse, '%Date.parse% yields itself');
// prototype primitive
t.equal(callBound('Error.prototype.message'), Error.prototype.message, 'Error.prototype.message yields itself');
t.equal(callBound('%Error.prototype.message%'), Error.prototype.message, '%Error.prototype.message% yields itself');
// prototype function
t.notEqual(callBound('Object.prototype.toString'), Object.prototype.toString, 'Object.prototype.toString does not yield itself');
t.notEqual(callBound('%Object.prototype.toString%'), Object.prototype.toString, '%Object.prototype.toString% does not yield itself');
t.equal(callBound('Object.prototype.toString')(true), Object.prototype.toString.call(true), 'call-bound Object.prototype.toString calls into the original');
t.equal(callBound('%Object.prototype.toString%')(true), Object.prototype.toString.call(true), 'call-bound %Object.prototype.toString% calls into the original');
t['throws'](
function () { callBound('does not exist'); },
SyntaxError,
'nonexistent intrinsic throws'
);
t['throws'](
function () { callBound('does not exist', true); },
SyntaxError,
'allowMissing arg still throws for unknown intrinsic'
);
/* globals WeakRef: false */
t.test('real but absent intrinsic', { skip: typeof WeakRef !== 'undefined' }, function (st) {
st['throws'](
function () { callBound('WeakRef'); },
TypeError,
'real but absent intrinsic throws'
);
st.equal(callBound('WeakRef', true), undefined, 'allowMissing arg avoids exception');
st.end();
});
t.end();
});
+66
View File
@@ -0,0 +1,66 @@
'use strict';
var callBind = require('../');
var bind = require('function-bind');
var test = require('tape');
/*
* older engines have length nonconfigurable
* in io.js v3, it is configurable except on bound functions, hence the .bind()
*/
var functionsHaveConfigurableLengths = !!(
Object.getOwnPropertyDescriptor
&& Object.getOwnPropertyDescriptor(bind.call(function () {}), 'length').configurable
);
test('callBind', function (t) {
var sentinel = { sentinel: true };
var func = function (a, b) {
// eslint-disable-next-line no-invalid-this
return [this, a, b];
};
t.equal(func.length, 2, 'original function length is 2');
t.deepEqual(func(), [undefined, undefined, undefined], 'unbound func with too few args');
t.deepEqual(func(1, 2), [undefined, 1, 2], 'unbound func with right args');
t.deepEqual(func(1, 2, 3), [undefined, 1, 2], 'unbound func with too many args');
var bound = callBind(func);
t.equal(bound.length, func.length + 1, 'function length is preserved', { skip: !functionsHaveConfigurableLengths });
t.deepEqual(bound(), [undefined, undefined, undefined], 'bound func with too few args');
t.deepEqual(bound(1, 2), [1, 2, undefined], 'bound func with right args');
t.deepEqual(bound(1, 2, 3), [1, 2, 3], 'bound func with too many args');
var boundR = callBind(func, sentinel);
t.equal(boundR.length, func.length, 'function length is preserved', { skip: !functionsHaveConfigurableLengths });
t.deepEqual(boundR(), [sentinel, undefined, undefined], 'bound func with receiver, with too few args');
t.deepEqual(boundR(1, 2), [sentinel, 1, 2], 'bound func with receiver, with right args');
t.deepEqual(boundR(1, 2, 3), [sentinel, 1, 2], 'bound func with receiver, with too many args');
var boundArg = callBind(func, sentinel, 1);
t.equal(boundArg.length, func.length - 1, 'function length is preserved', { skip: !functionsHaveConfigurableLengths });
t.deepEqual(boundArg(), [sentinel, 1, undefined], 'bound func with receiver and arg, with too few args');
t.deepEqual(boundArg(2), [sentinel, 1, 2], 'bound func with receiver and arg, with right arg');
t.deepEqual(boundArg(2, 3), [sentinel, 1, 2], 'bound func with receiver and arg, with too many args');
t.test('callBind.apply', function (st) {
var aBound = callBind.apply(func);
st.deepEqual(aBound(sentinel), [sentinel, undefined, undefined], 'apply-bound func with no args');
st.deepEqual(aBound(sentinel, [1], 4), [sentinel, 1, undefined], 'apply-bound func with too few args');
st.deepEqual(aBound(sentinel, [1, 2], 4), [sentinel, 1, 2], 'apply-bound func with right args');
var aBoundArg = callBind.apply(func);
st.deepEqual(aBoundArg(sentinel, [1, 2, 3], 4), [sentinel, 1, 2], 'apply-bound func with too many args');
st.deepEqual(aBoundArg(sentinel, [1, 2], 4), [sentinel, 1, 2], 'apply-bound func with right args');
st.deepEqual(aBoundArg(sentinel, [1], 4), [sentinel, 1, undefined], 'apply-bound func with too few args');
var aBoundR = callBind.apply(func, sentinel);
st.deepEqual(aBoundR([1, 2, 3], 4), [sentinel, 1, 2], 'apply-bound func with receiver and too many args');
st.deepEqual(aBoundR([1, 2], 4), [sentinel, 1, 2], 'apply-bound func with receiver and right args');
st.deepEqual(aBoundR([1], 4), [sentinel, 1, undefined], 'apply-bound func with receiver and too few args');
st.end();
});
t.end();
});
@@ -0,0 +1,18 @@
'use strict';
module.exports = Error.captureStackTrace || function (error) {
var container = new Error();
Object.defineProperty(error, 'stack', {
configurable: true,
get: function getStack() {
var stack = container.stack;
Object.defineProperty(this, 'stack', {
value: stack
});
return stack;
}
});
};
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) Vsevolod Strukchinsky <floatdrop@gmail.com> (github.com/floatdrop)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -0,0 +1,61 @@
{
"_from": "capture-stack-trace@^1.0.0",
"_id": "capture-stack-trace@1.0.1",
"_inBundle": false,
"_integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==",
"_location": "/capture-stack-trace",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "capture-stack-trace@^1.0.0",
"name": "capture-stack-trace",
"escapedName": "capture-stack-trace",
"rawSpec": "^1.0.0",
"saveSpec": null,
"fetchSpec": "^1.0.0"
},
"_requiredBy": [
"/hafas-client"
],
"_resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz",
"_shasum": "a6c0bbe1f38f3aa0b92238ecb6ff42c344d4135d",
"_spec": "capture-stack-trace@^1.0.0",
"_where": "/home/pi/MagicMirror/modules/MMM-PublicTransportHafas/node_modules/hafas-client",
"author": {
"name": "Vsevolod Strukchinsky",
"email": "floatdrop@gmail.com",
"url": "github.com/floatdrop"
},
"bugs": {
"url": "https://github.com/floatdrop/capture-stack-trace/issues"
},
"bundleDependencies": false,
"dependencies": {},
"deprecated": false,
"description": "Error.captureStackTrace ponyfill",
"devDependencies": {
"mocha": "*"
},
"engines": {
"node": ">=0.10.0"
},
"files": [
"index.js"
],
"homepage": "https://github.com/floatdrop/capture-stack-trace#readme",
"keywords": [
"Error",
"captureStackTrace"
],
"license": "MIT",
"name": "capture-stack-trace",
"repository": {
"type": "git",
"url": "git+https://github.com/floatdrop/capture-stack-trace.git"
},
"scripts": {
"test": "mocha"
},
"version": "1.0.1"
}
@@ -0,0 +1,36 @@
# capture-stack-trace [![Build Status](https://travis-ci.org/floatdrop/capture-stack-trace.svg?branch=master)](https://travis-ci.org/floatdrop/capture-stack-trace)
> Ponyfill for Error.captureStackTrace
## Install
```
$ npm install --save capture-stack-trace
```
## Usage
```js
var captureStackTrace = require('capture-stack-trace');
captureStackTrace({});
// => {stack: ...}
```
## API
### captureStackTrace(error)
#### error
*Required*
Type: `Object`
Target Object, that will recieve stack property.
## License
MIT © [Vsevolod Strukchinsky](http://github.com/floatdrop)
+3
View File
@@ -0,0 +1,3 @@
{
"extends": ["standard"]
}
+1
View File
@@ -0,0 +1 @@
node_modules
@@ -0,0 +1,6 @@
language: node_js
node_js:
- "0.11"
- "0.10"
- "0.12"
- "iojs"
+21
View File
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2017 crypto-browserify contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+17
View File
@@ -0,0 +1,17 @@
cipher-base
===
[![Build Status](https://travis-ci.org/crypto-browserify/cipher-base.svg)](https://travis-ci.org/crypto-browserify/cipher-base)
Abstract base class to inherit from if you want to create streams implementing
the same api as node crypto streams.
Requires you to implement 2 methods `_final` and `_update`. `_update` takes a
buffer and should return a buffer, `_final` takes no arguments and should return
a buffer.
The constructor takes one argument and that is a string which if present switches
it into hash mode, i.e. the object you get from crypto.createHash or
crypto.createSign, this switches the name of the final method to be the string
you passed instead of `final` and returns `this` from update.
+99
View File
@@ -0,0 +1,99 @@
var Buffer = require('safe-buffer').Buffer
var Transform = require('stream').Transform
var StringDecoder = require('string_decoder').StringDecoder
var inherits = require('inherits')
function CipherBase (hashMode) {
Transform.call(this)
this.hashMode = typeof hashMode === 'string'
if (this.hashMode) {
this[hashMode] = this._finalOrDigest
} else {
this.final = this._finalOrDigest
}
if (this._final) {
this.__final = this._final
this._final = null
}
this._decoder = null
this._encoding = null
}
inherits(CipherBase, Transform)
CipherBase.prototype.update = function (data, inputEnc, outputEnc) {
if (typeof data === 'string') {
data = Buffer.from(data, inputEnc)
}
var outData = this._update(data)
if (this.hashMode) return this
if (outputEnc) {
outData = this._toString(outData, outputEnc)
}
return outData
}
CipherBase.prototype.setAutoPadding = function () {}
CipherBase.prototype.getAuthTag = function () {
throw new Error('trying to get auth tag in unsupported state')
}
CipherBase.prototype.setAuthTag = function () {
throw new Error('trying to set auth tag in unsupported state')
}
CipherBase.prototype.setAAD = function () {
throw new Error('trying to set aad in unsupported state')
}
CipherBase.prototype._transform = function (data, _, next) {
var err
try {
if (this.hashMode) {
this._update(data)
} else {
this.push(this._update(data))
}
} catch (e) {
err = e
} finally {
next(err)
}
}
CipherBase.prototype._flush = function (done) {
var err
try {
this.push(this.__final())
} catch (e) {
err = e
}
done(err)
}
CipherBase.prototype._finalOrDigest = function (outputEnc) {
var outData = this.__final() || Buffer.alloc(0)
if (outputEnc) {
outData = this._toString(outData, outputEnc, true)
}
return outData
}
CipherBase.prototype._toString = function (value, enc, fin) {
if (!this._decoder) {
this._decoder = new StringDecoder(enc)
this._encoding = enc
}
if (this._encoding !== enc) throw new Error('can\'t switch encodings')
var out = this._decoder.write(value)
if (fin) {
out += this._decoder.end()
}
return out
}
module.exports = CipherBase
+60
View File
@@ -0,0 +1,60 @@
{
"_from": "cipher-base@^1.0.1",
"_id": "cipher-base@1.0.4",
"_inBundle": false,
"_integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
"_location": "/cipher-base",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "cipher-base@^1.0.1",
"name": "cipher-base",
"escapedName": "cipher-base",
"rawSpec": "^1.0.1",
"saveSpec": null,
"fetchSpec": "^1.0.1"
},
"_requiredBy": [
"/create-hash"
],
"_resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
"_shasum": "8760e4ecc272f4c363532f926d874aae2c1397de",
"_spec": "cipher-base@^1.0.1",
"_where": "/home/pi/MagicMirror/modules/MMM-PublicTransportHafas/node_modules/create-hash",
"author": {
"name": "Calvin Metcalf",
"email": "calvin.metcalf@gmail.com"
},
"bugs": {
"url": "https://github.com/crypto-browserify/cipher-base/issues"
},
"bundleDependencies": false,
"dependencies": {
"inherits": "^2.0.1",
"safe-buffer": "^5.0.1"
},
"deprecated": false,
"description": "abstract base class for crypto-streams",
"devDependencies": {
"standard": "^10.0.2",
"tap-spec": "^4.1.0",
"tape": "^4.2.0"
},
"homepage": "https://github.com/crypto-browserify/cipher-base#readme",
"keywords": [
"cipher",
"stream"
],
"license": "MIT",
"main": "index.js",
"name": "cipher-base",
"repository": {
"type": "git",
"url": "git+https://github.com/crypto-browserify/cipher-base.git"
},
"scripts": {
"test": "node test.js | tspec"
},
"version": "1.0.4"
}
+111
View File
@@ -0,0 +1,111 @@
var Buffer = require('safe-buffer').Buffer
var CipherBase = require('./')
var test = require('tape')
var inherits = require('inherits')
test('basic version', function (t) {
function Cipher () {
CipherBase.call(this)
}
inherits(Cipher, CipherBase)
Cipher.prototype._update = function (input) {
t.ok(Buffer.isBuffer(input))
return input
}
Cipher.prototype._final = function () {
// noop
}
var cipher = new Cipher()
var utf8 = 'abc123abcd'
var update = cipher.update(utf8, 'utf8', 'base64') + cipher.final('base64')
var string = (Buffer.from(update, 'base64')).toString()
t.equals(utf8, string)
t.end()
})
test('hash mode', function (t) {
function Cipher () {
CipherBase.call(this, 'finalName')
this._cache = []
}
inherits(Cipher, CipherBase)
Cipher.prototype._update = function (input) {
t.ok(Buffer.isBuffer(input))
this._cache.push(input)
}
Cipher.prototype._final = function () {
return Buffer.concat(this._cache)
}
var cipher = new Cipher()
var utf8 = 'abc123abcd'
var update = cipher.update(utf8, 'utf8').finalName('base64')
var string = (Buffer.from(update, 'base64')).toString()
t.equals(utf8, string)
t.end()
})
test('hash mode as stream', function (t) {
function Cipher () {
CipherBase.call(this, 'finalName')
this._cache = []
}
inherits(Cipher, CipherBase)
Cipher.prototype._update = function (input) {
t.ok(Buffer.isBuffer(input))
this._cache.push(input)
}
Cipher.prototype._final = function () {
return Buffer.concat(this._cache)
}
var cipher = new Cipher()
cipher.on('error', function (e) {
t.notOk(e)
})
var utf8 = 'abc123abcd'
cipher.end(utf8, 'utf8')
var update = cipher.read().toString('base64')
var string = (Buffer.from(update, 'base64')).toString()
t.equals(utf8, string)
t.end()
})
test('encodings', function (t) {
inherits(Cipher, CipherBase)
function Cipher () {
CipherBase.call(this)
}
Cipher.prototype._update = function (input) {
return input
}
Cipher.prototype._final = function () {
// noop
}
t.test('mix and match encoding', function (t) {
t.plan(2)
var cipher = new Cipher()
cipher.update('foo', 'utf8', 'utf8')
t.throws(function () {
cipher.update('foo', 'utf8', 'base64')
})
cipher = new Cipher()
cipher.update('foo', 'utf8', 'base64')
t.doesNotThrow(function () {
cipher.update('foo', 'utf8')
cipher.final('base64')
})
})
t.test('handle long uft8 plaintexts', function (t) {
t.plan(1)
var txt = 'ふっかつ あきる すぶり はやい つける まゆげ たんさん みんぞく ねほりはほり せまい たいまつばな ひはん'
var cipher = new Cipher()
var decipher = new Cipher()
var enc = decipher.update(cipher.update(txt, 'utf8', 'base64'), 'base64', 'utf8')
enc += decipher.update(cipher.final('base64'), 'base64', 'utf8')
enc += decipher.final('utf8')
t.equals(txt, enc)
})
})
+24
View File
@@ -0,0 +1,24 @@
1.0.4 / 2017-09-11
==================
* perf: skip parameter parsing when no parameters
1.0.3 / 2017-09-10
==================
* perf: remove argument reassignment
1.0.2 / 2016-05-09
==================
* perf: enable strict mode
1.0.1 / 2015-02-13
==================
* Improve missing `Content-Type` header error message
1.0.0 / 2015-02-01
==================
* Initial implementation, derived from `media-typer@0.3.0`
+22
View File
@@ -0,0 +1,22 @@
(The MIT License)
Copyright (c) 2015 Douglas Christopher Wilson
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+92
View File
@@ -0,0 +1,92 @@
# content-type
[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
[![Node.js Version][node-version-image]][node-version-url]
[![Build Status][travis-image]][travis-url]
[![Test Coverage][coveralls-image]][coveralls-url]
Create and parse HTTP Content-Type header according to RFC 7231
## Installation
```sh
$ npm install content-type
```
## API
```js
var contentType = require('content-type')
```
### contentType.parse(string)
```js
var obj = contentType.parse('image/svg+xml; charset=utf-8')
```
Parse a content type string. This will return an object with the following
properties (examples are shown for the string `'image/svg+xml; charset=utf-8'`):
- `type`: The media type (the type and subtype, always lower case).
Example: `'image/svg+xml'`
- `parameters`: An object of the parameters in the media type (name of parameter
always lower case). Example: `{charset: 'utf-8'}`
Throws a `TypeError` if the string is missing or invalid.
### contentType.parse(req)
```js
var obj = contentType.parse(req)
```
Parse the `content-type` header from the given `req`. Short-cut for
`contentType.parse(req.headers['content-type'])`.
Throws a `TypeError` if the `Content-Type` header is missing or invalid.
### contentType.parse(res)
```js
var obj = contentType.parse(res)
```
Parse the `content-type` header set on the given `res`. Short-cut for
`contentType.parse(res.getHeader('content-type'))`.
Throws a `TypeError` if the `Content-Type` header is missing or invalid.
### contentType.format(obj)
```js
var str = contentType.format({type: 'image/svg+xml'})
```
Format an object into a content type string. This will return a string of the
content type for the given object with the following properties (examples are
shown that produce the string `'image/svg+xml; charset=utf-8'`):
- `type`: The media type (will be lower-cased). Example: `'image/svg+xml'`
- `parameters`: An object of the parameters in the media type (name of the
parameter will be lower-cased). Example: `{charset: 'utf-8'}`
Throws a `TypeError` if the object contains an invalid type or parameter names.
## License
[MIT](LICENSE)
[npm-image]: https://img.shields.io/npm/v/content-type.svg
[npm-url]: https://npmjs.org/package/content-type
[node-version-image]: https://img.shields.io/node/v/content-type.svg
[node-version-url]: http://nodejs.org/download/
[travis-image]: https://img.shields.io/travis/jshttp/content-type/master.svg
[travis-url]: https://travis-ci.org/jshttp/content-type
[coveralls-image]: https://img.shields.io/coveralls/jshttp/content-type/master.svg
[coveralls-url]: https://coveralls.io/r/jshttp/content-type
[downloads-image]: https://img.shields.io/npm/dm/content-type.svg
[downloads-url]: https://npmjs.org/package/content-type
+222
View File
@@ -0,0 +1,222 @@
/*!
* content-type
* Copyright(c) 2015 Douglas Christopher Wilson
* MIT Licensed
*/
'use strict'
/**
* RegExp to match *( ";" parameter ) in RFC 7231 sec 3.1.1.1
*
* parameter = token "=" ( token / quoted-string )
* token = 1*tchar
* tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*"
* / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~"
* / DIGIT / ALPHA
* ; any VCHAR, except delimiters
* quoted-string = DQUOTE *( qdtext / quoted-pair ) DQUOTE
* qdtext = HTAB / SP / %x21 / %x23-5B / %x5D-7E / obs-text
* obs-text = %x80-FF
* quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )
*/
var PARAM_REGEXP = /; *([!#$%&'*+.^_`|~0-9A-Za-z-]+) *= *("(?:[\u000b\u0020\u0021\u0023-\u005b\u005d-\u007e\u0080-\u00ff]|\\[\u000b\u0020-\u00ff])*"|[!#$%&'*+.^_`|~0-9A-Za-z-]+) */g
var TEXT_REGEXP = /^[\u000b\u0020-\u007e\u0080-\u00ff]+$/
var TOKEN_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/
/**
* RegExp to match quoted-pair in RFC 7230 sec 3.2.6
*
* quoted-pair = "\" ( HTAB / SP / VCHAR / obs-text )
* obs-text = %x80-FF
*/
var QESC_REGEXP = /\\([\u000b\u0020-\u00ff])/g
/**
* RegExp to match chars that must be quoted-pair in RFC 7230 sec 3.2.6
*/
var QUOTE_REGEXP = /([\\"])/g
/**
* RegExp to match type in RFC 7231 sec 3.1.1.1
*
* media-type = type "/" subtype
* type = token
* subtype = token
*/
var TYPE_REGEXP = /^[!#$%&'*+.^_`|~0-9A-Za-z-]+\/[!#$%&'*+.^_`|~0-9A-Za-z-]+$/
/**
* Module exports.
* @public
*/
exports.format = format
exports.parse = parse
/**
* Format object to media type.
*
* @param {object} obj
* @return {string}
* @public
*/
function format (obj) {
if (!obj || typeof obj !== 'object') {
throw new TypeError('argument obj is required')
}
var parameters = obj.parameters
var type = obj.type
if (!type || !TYPE_REGEXP.test(type)) {
throw new TypeError('invalid type')
}
var string = type
// append parameters
if (parameters && typeof parameters === 'object') {
var param
var params = Object.keys(parameters).sort()
for (var i = 0; i < params.length; i++) {
param = params[i]
if (!TOKEN_REGEXP.test(param)) {
throw new TypeError('invalid parameter name')
}
string += '; ' + param + '=' + qstring(parameters[param])
}
}
return string
}
/**
* Parse media type to object.
*
* @param {string|object} string
* @return {Object}
* @public
*/
function parse (string) {
if (!string) {
throw new TypeError('argument string is required')
}
// support req/res-like objects as argument
var header = typeof string === 'object'
? getcontenttype(string)
: string
if (typeof header !== 'string') {
throw new TypeError('argument string is required to be a string')
}
var index = header.indexOf(';')
var type = index !== -1
? header.substr(0, index).trim()
: header.trim()
if (!TYPE_REGEXP.test(type)) {
throw new TypeError('invalid media type')
}
var obj = new ContentType(type.toLowerCase())
// parse parameters
if (index !== -1) {
var key
var match
var value
PARAM_REGEXP.lastIndex = index
while ((match = PARAM_REGEXP.exec(header))) {
if (match.index !== index) {
throw new TypeError('invalid parameter format')
}
index += match[0].length
key = match[1].toLowerCase()
value = match[2]
if (value[0] === '"') {
// remove quotes and escapes
value = value
.substr(1, value.length - 2)
.replace(QESC_REGEXP, '$1')
}
obj.parameters[key] = value
}
if (index !== header.length) {
throw new TypeError('invalid parameter format')
}
}
return obj
}
/**
* Get content-type from req/res objects.
*
* @param {object}
* @return {Object}
* @private
*/
function getcontenttype (obj) {
var header
if (typeof obj.getHeader === 'function') {
// res-like
header = obj.getHeader('content-type')
} else if (typeof obj.headers === 'object') {
// req-like
header = obj.headers && obj.headers['content-type']
}
if (typeof header !== 'string') {
throw new TypeError('content-type header is missing from object')
}
return header
}
/**
* Quote a string if necessary.
*
* @param {string} val
* @return {string}
* @private
*/
function qstring (val) {
var str = String(val)
// no need to quote tokens
if (TOKEN_REGEXP.test(str)) {
return str
}
if (str.length > 0 && !TEXT_REGEXP.test(str)) {
throw new TypeError('invalid parameter value')
}
return '"' + str.replace(QUOTE_REGEXP, '\\$1') + '"'
}
/**
* Class to represent a content type.
* @private
*/
function ContentType (type) {
this.parameters = Object.create(null)
this.type = type
}
@@ -0,0 +1,75 @@
{
"_from": "content-type@^1.0.4",
"_id": "content-type@1.0.4",
"_inBundle": false,
"_integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
"_location": "/content-type",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "content-type@^1.0.4",
"name": "content-type",
"escapedName": "content-type",
"rawSpec": "^1.0.4",
"saveSpec": null,
"fetchSpec": "^1.0.4"
},
"_requiredBy": [
"/hafas-client"
],
"_resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
"_shasum": "e138cc75e040c727b1966fe5e5f8c9aee256fe3b",
"_spec": "content-type@^1.0.4",
"_where": "/home/pi/MagicMirror/modules/MMM-PublicTransportHafas/node_modules/hafas-client",
"author": {
"name": "Douglas Christopher Wilson",
"email": "doug@somethingdoug.com"
},
"bugs": {
"url": "https://github.com/jshttp/content-type/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "Create and parse HTTP Content-Type header",
"devDependencies": {
"eslint": "3.19.0",
"eslint-config-standard": "10.2.1",
"eslint-plugin-import": "2.7.0",
"eslint-plugin-node": "5.1.1",
"eslint-plugin-promise": "3.5.0",
"eslint-plugin-standard": "3.0.1",
"istanbul": "0.4.5",
"mocha": "~1.21.5"
},
"engines": {
"node": ">= 0.6"
},
"files": [
"LICENSE",
"HISTORY.md",
"README.md",
"index.js"
],
"homepage": "https://github.com/jshttp/content-type#readme",
"keywords": [
"content-type",
"http",
"req",
"res",
"rfc7231"
],
"license": "MIT",
"name": "content-type",
"repository": {
"type": "git",
"url": "git+https://github.com/jshttp/content-type.git"
},
"scripts": {
"lint": "eslint .",
"test": "mocha --reporter spec --check-leaks --bail test/",
"test-ci": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --check-leaks test/",
"test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --check-leaks test/"
},
"version": "1.0.4"
}
+17
View File
@@ -0,0 +1,17 @@
sudo: false
language: node_js
before_install:
- "npm install npm -g"
node_js:
- "4"
- "5"
- "6"
- "7"
env:
matrix:
- TEST_SUITE=unit
matrix:
include:
- node_js: "7"
env: TEST_SUITE=standard
script: npm run $TEST_SUITE
+21
View File
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2017 crypto-browserify contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+19
View File
@@ -0,0 +1,19 @@
# create-hash
[![Build Status](https://travis-ci.org/crypto-browserify/createHash.svg)](https://travis-ci.org/crypto-browserify/createHash)
Node style hashes for use in the browser, with native hash functions in node.
API is the same as hashes in node:
```js
var createHash = require('create-hash')
var hash = createHash('sha224')
hash.update('synchronous write') // optional encoding parameter
hash.digest() // synchronously get result with optional encoding parameter
hash.write('write to it as a stream')
hash.end() // remember it's a stream
hash.read() // only if you ended it as a stream though
```
To get the JavaScript version even in node do `require('create-hash/browser')`
+30
View File
@@ -0,0 +1,30 @@
'use strict'
var inherits = require('inherits')
var MD5 = require('md5.js')
var RIPEMD160 = require('ripemd160')
var sha = require('sha.js')
var Base = require('cipher-base')
function Hash (hash) {
Base.call(this, 'digest')
this._hash = hash
}
inherits(Hash, Base)
Hash.prototype._update = function (data) {
this._hash.update(data)
}
Hash.prototype._final = function () {
return this._hash.digest()
}
module.exports = function createHash (alg) {
alg = alg.toLowerCase()
if (alg === 'md5') return new MD5()
if (alg === 'rmd160' || alg === 'ripemd160') return new RIPEMD160()
return new Hash(sha(alg))
}
+1
View File
@@ -0,0 +1 @@
module.exports = require('crypto').createHash
+5
View File
@@ -0,0 +1,5 @@
var MD5 = require('md5.js')
module.exports = function (buffer) {
return new MD5().update(buffer).digest()
}
+64
View File
@@ -0,0 +1,64 @@
{
"_from": "create-hash@^1.2.0",
"_id": "create-hash@1.2.0",
"_inBundle": false,
"_integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
"_location": "/create-hash",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "create-hash@^1.2.0",
"name": "create-hash",
"escapedName": "create-hash",
"rawSpec": "^1.2.0",
"saveSpec": null,
"fetchSpec": "^1.2.0"
},
"_requiredBy": [
"/hafas-client"
],
"_resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
"_shasum": "889078af11a63756bcfb59bd221996be3a9ef196",
"_spec": "create-hash@^1.2.0",
"_where": "/home/pi/MagicMirror/modules/MMM-PublicTransportHafas/node_modules/hafas-client",
"author": "",
"browser": "browser.js",
"bugs": {
"url": "https://github.com/crypto-browserify/createHash/issues"
},
"bundleDependencies": false,
"dependencies": {
"cipher-base": "^1.0.1",
"inherits": "^2.0.1",
"md5.js": "^1.3.4",
"ripemd160": "^2.0.1",
"sha.js": "^2.4.0"
},
"deprecated": false,
"description": "create hashes for browserify",
"devDependencies": {
"hash-test-vectors": "^1.3.2",
"safe-buffer": "^5.0.1",
"standard": "^10.0.2",
"tap-spec": "^2.1.2",
"tape": "^4.6.3"
},
"homepage": "https://github.com/crypto-browserify/createHash",
"keywords": [
"crypto"
],
"license": "MIT",
"main": "index.js",
"name": "create-hash",
"repository": {
"type": "git",
"url": "git+ssh://git@github.com/crypto-browserify/createHash.git"
},
"scripts": {
"standard": "standard",
"test": "npm run-script standard && npm run-script unit",
"unit": "node test.js | tspec"
},
"version": "1.2.0"
}
+41
View File
@@ -0,0 +1,41 @@
var test = require('tape')
var Buffer = require('safe-buffer').Buffer
var algorithms = ['sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'md5', 'rmd160', 'ripemd160']
var encodings = ['hex', 'base64'] // ignore binary
var vectors = require('hash-test-vectors')
vectors.forEach(function (vector) {
vector.ripemd160 = vector.rmd160
})
var createHash = require('./browser')
algorithms.forEach(function (algorithm) {
test('test ' + algorithm + ' against test vectors', function (t) {
vectors.forEach(function (obj, i) {
var input = Buffer.from(obj.input, 'base64')
var node = obj[algorithm]
var js = createHash(algorithm).update(input).digest('hex')
t.equal(js, node, algorithm + '(testVector[' + i + ']) == ' + node)
})
encodings.forEach(function (encoding) {
vectors.forEach(function (obj, i) {
var input = Buffer.from(obj.input, 'base64').toString(encoding)
var node = obj[algorithm]
var js = createHash(algorithm).update(input, encoding).digest('hex')
t.equal(js, node, algorithm + '(testVector[' + i + '], ' + encoding + ') == ' + node)
})
})
vectors.forEach(function (obj, i) {
var input = Buffer.from(obj.input, 'base64')
var node = obj[algorithm]
var hash = createHash(algorithm)
hash.end(input)
var js = hash.read().toString('hex')
t.equal(js, node, algorithm + '(testVector[' + i + ']) == ' + node)
})
t.end()
})
})
+19
View File
@@ -0,0 +1,19 @@
(The MIT License)
Copyright (c) 2014 TJ Holowaychuk <tj@vision-media.ca>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
and associated documentation files (the 'Software'), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+455
View File
@@ -0,0 +1,455 @@
# debug
[![Build Status](https://travis-ci.org/visionmedia/debug.svg?branch=master)](https://travis-ci.org/visionmedia/debug) [![Coverage Status](https://coveralls.io/repos/github/visionmedia/debug/badge.svg?branch=master)](https://coveralls.io/github/visionmedia/debug?branch=master) [![Slack](https://visionmedia-community-slackin.now.sh/badge.svg)](https://visionmedia-community-slackin.now.sh/) [![OpenCollective](https://opencollective.com/debug/backers/badge.svg)](#backers)
[![OpenCollective](https://opencollective.com/debug/sponsors/badge.svg)](#sponsors)
<img width="647" src="https://user-images.githubusercontent.com/71256/29091486-fa38524c-7c37-11e7-895f-e7ec8e1039b6.png">
A tiny JavaScript debugging utility modelled after Node.js core's debugging
technique. Works in Node.js and web browsers.
## Installation
```bash
$ npm install debug
```
## Usage
`debug` exposes a function; simply pass this function the name of your module, and it will return a decorated version of `console.error` for you to pass debug statements to. This will allow you to toggle the debug output for different parts of your module as well as the module as a whole.
Example [_app.js_](./examples/node/app.js):
```js
var debug = require('debug')('http')
, http = require('http')
, name = 'My App';
// fake app
debug('booting %o', name);
http.createServer(function(req, res){
debug(req.method + ' ' + req.url);
res.end('hello\n');
}).listen(3000, function(){
debug('listening');
});
// fake worker of some kind
require('./worker');
```
Example [_worker.js_](./examples/node/worker.js):
```js
var a = require('debug')('worker:a')
, b = require('debug')('worker:b');
function work() {
a('doing lots of uninteresting work');
setTimeout(work, Math.random() * 1000);
}
work();
function workb() {
b('doing some work');
setTimeout(workb, Math.random() * 2000);
}
workb();
```
The `DEBUG` environment variable is then used to enable these based on space or
comma-delimited names.
Here are some examples:
<img width="647" alt="screen shot 2017-08-08 at 12 53 04 pm" src="https://user-images.githubusercontent.com/71256/29091703-a6302cdc-7c38-11e7-8304-7c0b3bc600cd.png">
<img width="647" alt="screen shot 2017-08-08 at 12 53 38 pm" src="https://user-images.githubusercontent.com/71256/29091700-a62a6888-7c38-11e7-800b-db911291ca2b.png">
<img width="647" alt="screen shot 2017-08-08 at 12 53 25 pm" src="https://user-images.githubusercontent.com/71256/29091701-a62ea114-7c38-11e7-826a-2692bedca740.png">
#### Windows command prompt notes
##### CMD
On Windows the environment variable is set using the `set` command.
```cmd
set DEBUG=*,-not_this
```
Example:
```cmd
set DEBUG=* & node app.js
```
##### PowerShell (VS Code default)
PowerShell uses different syntax to set environment variables.
```cmd
$env:DEBUG = "*,-not_this"
```
Example:
```cmd
$env:DEBUG='app';node app.js
```
Then, run the program to be debugged as usual.
npm script example:
```js
"windowsDebug": "@powershell -Command $env:DEBUG='*';node app.js",
```
## Namespace Colors
Every debug instance has a color generated for it based on its namespace name.
This helps when visually parsing the debug output to identify which debug instance
a debug line belongs to.
#### Node.js
In Node.js, colors are enabled when stderr is a TTY. You also _should_ install
the [`supports-color`](https://npmjs.org/supports-color) module alongside debug,
otherwise debug will only use a small handful of basic colors.
<img width="521" src="https://user-images.githubusercontent.com/71256/29092181-47f6a9e6-7c3a-11e7-9a14-1928d8a711cd.png">
#### Web Browser
Colors are also enabled on "Web Inspectors" that understand the `%c` formatting
option. These are WebKit web inspectors, Firefox ([since version
31](https://hacks.mozilla.org/2014/05/editable-box-model-multiple-selection-sublime-text-keys-much-more-firefox-developer-tools-episode-31/))
and the Firebug plugin for Firefox (any version).
<img width="524" src="https://user-images.githubusercontent.com/71256/29092033-b65f9f2e-7c39-11e7-8e32-f6f0d8e865c1.png">
## Millisecond diff
When actively developing an application it can be useful to see when the time spent between one `debug()` call and the next. Suppose for example you invoke `debug()` before requesting a resource, and after as well, the "+NNNms" will show you how much time was spent between calls.
<img width="647" src="https://user-images.githubusercontent.com/71256/29091486-fa38524c-7c37-11e7-895f-e7ec8e1039b6.png">
When stdout is not a TTY, `Date#toISOString()` is used, making it more useful for logging the debug information as shown below:
<img width="647" src="https://user-images.githubusercontent.com/71256/29091956-6bd78372-7c39-11e7-8c55-c948396d6edd.png">
## Conventions
If you're using this in one or more of your libraries, you _should_ use the name of your library so that developers may toggle debugging as desired without guessing names. If you have more than one debuggers you _should_ prefix them with your library name and use ":" to separate features. For example "bodyParser" from Connect would then be "connect:bodyParser". If you append a "*" to the end of your name, it will always be enabled regardless of the setting of the DEBUG environment variable. You can then use it for normal output as well as debug output.
## Wildcards
The `*` character may be used as a wildcard. Suppose for example your library has
debuggers named "connect:bodyParser", "connect:compress", "connect:session",
instead of listing all three with
`DEBUG=connect:bodyParser,connect:compress,connect:session`, you may simply do
`DEBUG=connect:*`, or to run everything using this module simply use `DEBUG=*`.
You can also exclude specific debuggers by prefixing them with a "-" character.
For example, `DEBUG=*,-connect:*` would include all debuggers except those
starting with "connect:".
## Environment Variables
When running through Node.js, you can set a few environment variables that will
change the behavior of the debug logging:
| Name | Purpose |
|-----------|-------------------------------------------------|
| `DEBUG` | Enables/disables specific debugging namespaces. |
| `DEBUG_HIDE_DATE` | Hide date from debug output (non-TTY). |
| `DEBUG_COLORS`| Whether or not to use colors in the debug output. |
| `DEBUG_DEPTH` | Object inspection depth. |
| `DEBUG_SHOW_HIDDEN` | Shows hidden properties on inspected objects. |
__Note:__ The environment variables beginning with `DEBUG_` end up being
converted into an Options object that gets used with `%o`/`%O` formatters.
See the Node.js documentation for
[`util.inspect()`](https://nodejs.org/api/util.html#util_util_inspect_object_options)
for the complete list.
## Formatters
Debug uses [printf-style](https://wikipedia.org/wiki/Printf_format_string) formatting.
Below are the officially supported formatters:
| Formatter | Representation |
|-----------|----------------|
| `%O` | Pretty-print an Object on multiple lines. |
| `%o` | Pretty-print an Object all on a single line. |
| `%s` | String. |
| `%d` | Number (both integer and float). |
| `%j` | JSON. Replaced with the string '[Circular]' if the argument contains circular references. |
| `%%` | Single percent sign ('%'). This does not consume an argument. |
### Custom formatters
You can add custom formatters by extending the `debug.formatters` object.
For example, if you wanted to add support for rendering a Buffer as hex with
`%h`, you could do something like:
```js
const createDebug = require('debug')
createDebug.formatters.h = (v) => {
return v.toString('hex')
}
// …elsewhere
const debug = createDebug('foo')
debug('this is hex: %h', new Buffer('hello world'))
// foo this is hex: 68656c6c6f20776f726c6421 +0ms
```
## Browser Support
You can build a browser-ready script using [browserify](https://github.com/substack/node-browserify),
or just use the [browserify-as-a-service](https://wzrd.in/) [build](https://wzrd.in/standalone/debug@latest),
if you don't want to build it yourself.
Debug's enable state is currently persisted by `localStorage`.
Consider the situation shown below where you have `worker:a` and `worker:b`,
and wish to debug both. You can enable this using `localStorage.debug`:
```js
localStorage.debug = 'worker:*'
```
And then refresh the page.
```js
a = debug('worker:a');
b = debug('worker:b');
setInterval(function(){
a('doing some work');
}, 1000);
setInterval(function(){
b('doing some work');
}, 1200);
```
## Output streams
By default `debug` will log to stderr, however this can be configured per-namespace by overriding the `log` method:
Example [_stdout.js_](./examples/node/stdout.js):
```js
var debug = require('debug');
var error = debug('app:error');
// by default stderr is used
error('goes to stderr!');
var log = debug('app:log');
// set this namespace to log via console.log
log.log = console.log.bind(console); // don't forget to bind to console!
log('goes to stdout');
error('still goes to stderr!');
// set all output to go via console.info
// overrides all per-namespace log settings
debug.log = console.info.bind(console);
error('now goes to stdout via console.info');
log('still goes to stdout, but via console.info now');
```
## Extend
You can simply extend debugger
```js
const log = require('debug')('auth');
//creates new debug instance with extended namespace
const logSign = log.extend('sign');
const logLogin = log.extend('login');
log('hello'); // auth hello
logSign('hello'); //auth:sign hello
logLogin('hello'); //auth:login hello
```
## Set dynamically
You can also enable debug dynamically by calling the `enable()` method :
```js
let debug = require('debug');
console.log(1, debug.enabled('test'));
debug.enable('test');
console.log(2, debug.enabled('test'));
debug.disable();
console.log(3, debug.enabled('test'));
```
print :
```
1 false
2 true
3 false
```
Usage :
`enable(namespaces)`
`namespaces` can include modes separated by a colon and wildcards.
Note that calling `enable()` completely overrides previously set DEBUG variable :
```
$ DEBUG=foo node -e 'var dbg = require("debug"); dbg.enable("bar"); console.log(dbg.enabled("foo"))'
=> false
```
`disable()`
Will disable all namespaces. The functions returns the namespaces currently
enabled (and skipped). This can be useful if you want to disable debugging
temporarily without knowing what was enabled to begin with.
For example:
```js
let debug = require('debug');
debug.enable('foo:*,-foo:bar');
let namespaces = debug.disable();
debug.enable(namespaces);
```
Note: There is no guarantee that the string will be identical to the initial
enable string, but semantically they will be identical.
## Checking whether a debug target is enabled
After you've created a debug instance, you can determine whether or not it is
enabled by checking the `enabled` property:
```javascript
const debug = require('debug')('http');
if (debug.enabled) {
// do stuff...
}
```
You can also manually toggle this property to force the debug instance to be
enabled or disabled.
## Authors
- TJ Holowaychuk
- Nathan Rajlich
- Andrew Rhyne
## Backers
Support us with a monthly donation and help us continue our activities. [[Become a backer](https://opencollective.com/debug#backer)]
<a href="https://opencollective.com/debug/backer/0/website" target="_blank"><img src="https://opencollective.com/debug/backer/0/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/1/website" target="_blank"><img src="https://opencollective.com/debug/backer/1/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/2/website" target="_blank"><img src="https://opencollective.com/debug/backer/2/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/3/website" target="_blank"><img src="https://opencollective.com/debug/backer/3/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/4/website" target="_blank"><img src="https://opencollective.com/debug/backer/4/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/5/website" target="_blank"><img src="https://opencollective.com/debug/backer/5/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/6/website" target="_blank"><img src="https://opencollective.com/debug/backer/6/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/7/website" target="_blank"><img src="https://opencollective.com/debug/backer/7/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/8/website" target="_blank"><img src="https://opencollective.com/debug/backer/8/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/9/website" target="_blank"><img src="https://opencollective.com/debug/backer/9/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/10/website" target="_blank"><img src="https://opencollective.com/debug/backer/10/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/11/website" target="_blank"><img src="https://opencollective.com/debug/backer/11/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/12/website" target="_blank"><img src="https://opencollective.com/debug/backer/12/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/13/website" target="_blank"><img src="https://opencollective.com/debug/backer/13/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/14/website" target="_blank"><img src="https://opencollective.com/debug/backer/14/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/15/website" target="_blank"><img src="https://opencollective.com/debug/backer/15/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/16/website" target="_blank"><img src="https://opencollective.com/debug/backer/16/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/17/website" target="_blank"><img src="https://opencollective.com/debug/backer/17/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/18/website" target="_blank"><img src="https://opencollective.com/debug/backer/18/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/19/website" target="_blank"><img src="https://opencollective.com/debug/backer/19/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/20/website" target="_blank"><img src="https://opencollective.com/debug/backer/20/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/21/website" target="_blank"><img src="https://opencollective.com/debug/backer/21/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/22/website" target="_blank"><img src="https://opencollective.com/debug/backer/22/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/23/website" target="_blank"><img src="https://opencollective.com/debug/backer/23/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/24/website" target="_blank"><img src="https://opencollective.com/debug/backer/24/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/25/website" target="_blank"><img src="https://opencollective.com/debug/backer/25/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/26/website" target="_blank"><img src="https://opencollective.com/debug/backer/26/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/27/website" target="_blank"><img src="https://opencollective.com/debug/backer/27/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/28/website" target="_blank"><img src="https://opencollective.com/debug/backer/28/avatar.svg"></a>
<a href="https://opencollective.com/debug/backer/29/website" target="_blank"><img src="https://opencollective.com/debug/backer/29/avatar.svg"></a>
## Sponsors
Become a sponsor and get your logo on our README on Github with a link to your site. [[Become a sponsor](https://opencollective.com/debug#sponsor)]
<a href="https://opencollective.com/debug/sponsor/0/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/0/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/1/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/1/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/2/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/2/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/3/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/3/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/4/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/4/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/5/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/5/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/6/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/6/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/7/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/7/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/8/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/8/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/9/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/9/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/10/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/10/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/11/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/11/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/12/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/12/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/13/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/13/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/14/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/14/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/15/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/15/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/16/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/16/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/17/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/17/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/18/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/18/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/19/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/19/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/20/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/20/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/21/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/21/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/22/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/22/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/23/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/23/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/24/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/24/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/25/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/25/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/26/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/26/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/27/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/27/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/28/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/28/avatar.svg"></a>
<a href="https://opencollective.com/debug/sponsor/29/website" target="_blank"><img src="https://opencollective.com/debug/sponsor/29/avatar.svg"></a>
## License
(The MIT License)
Copyright (c) 2014-2017 TJ Holowaychuk &lt;tj@vision-media.ca&gt;
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+102
View File
@@ -0,0 +1,102 @@
{
"_from": "debug@4",
"_id": "debug@4.3.2",
"_inBundle": false,
"_integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
"_location": "/debug",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "debug@4",
"name": "debug",
"escapedName": "debug",
"rawSpec": "4",
"saveSpec": null,
"fetchSpec": "4"
},
"_requiredBy": [
"/agent-base",
"/https-proxy-agent"
],
"_resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
"_shasum": "f0a49c18ac8779e31d4a0c6029dfb76873c7428b",
"_spec": "debug@4",
"_where": "/home/pi/MagicMirror/modules/MMM-PublicTransportHafas/node_modules/https-proxy-agent",
"author": {
"name": "TJ Holowaychuk",
"email": "tj@vision-media.ca"
},
"browser": "./src/browser.js",
"bugs": {
"url": "https://github.com/visionmedia/debug/issues"
},
"bundleDependencies": false,
"contributors": [
{
"name": "Nathan Rajlich",
"email": "nathan@tootallnate.net",
"url": "http://n8.io"
},
{
"name": "Andrew Rhyne",
"email": "rhyneandrew@gmail.com"
},
{
"name": "Josh Junon",
"email": "josh@junon.me"
}
],
"dependencies": {
"ms": "2.1.2"
},
"deprecated": false,
"description": "small debugging utility",
"devDependencies": {
"brfs": "^2.0.1",
"browserify": "^16.2.3",
"coveralls": "^3.0.2",
"istanbul": "^0.4.5",
"karma": "^3.1.4",
"karma-browserify": "^6.0.0",
"karma-chrome-launcher": "^2.2.0",
"karma-mocha": "^1.3.0",
"mocha": "^5.2.0",
"mocha-lcov-reporter": "^1.2.0",
"xo": "^0.23.0"
},
"engines": {
"node": ">=6.0"
},
"files": [
"src",
"LICENSE",
"README.md"
],
"homepage": "https://github.com/visionmedia/debug#readme",
"keywords": [
"debug",
"log",
"debugger"
],
"license": "MIT",
"main": "./src/index.js",
"name": "debug",
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
},
"repository": {
"type": "git",
"url": "git://github.com/visionmedia/debug.git"
},
"scripts": {
"lint": "xo",
"test": "npm run test:node && npm run test:browser && npm run lint",
"test:browser": "karma start --single-run",
"test:coverage": "cat ./coverage/lcov.info | coveralls",
"test:node": "istanbul cover _mocha -- test.js"
},
"version": "4.3.2"
}
+269
View File
@@ -0,0 +1,269 @@
/* eslint-env browser */
/**
* This is the web browser implementation of `debug()`.
*/
exports.formatArgs = formatArgs;
exports.save = save;
exports.load = load;
exports.useColors = useColors;
exports.storage = localstorage();
exports.destroy = (() => {
let warned = false;
return () => {
if (!warned) {
warned = true;
console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.');
}
};
})();
/**
* Colors.
*/
exports.colors = [
'#0000CC',
'#0000FF',
'#0033CC',
'#0033FF',
'#0066CC',
'#0066FF',
'#0099CC',
'#0099FF',
'#00CC00',
'#00CC33',
'#00CC66',
'#00CC99',
'#00CCCC',
'#00CCFF',
'#3300CC',
'#3300FF',
'#3333CC',
'#3333FF',
'#3366CC',
'#3366FF',
'#3399CC',
'#3399FF',
'#33CC00',
'#33CC33',
'#33CC66',
'#33CC99',
'#33CCCC',
'#33CCFF',
'#6600CC',
'#6600FF',
'#6633CC',
'#6633FF',
'#66CC00',
'#66CC33',
'#9900CC',
'#9900FF',
'#9933CC',
'#9933FF',
'#99CC00',
'#99CC33',
'#CC0000',
'#CC0033',
'#CC0066',
'#CC0099',
'#CC00CC',
'#CC00FF',
'#CC3300',
'#CC3333',
'#CC3366',
'#CC3399',
'#CC33CC',
'#CC33FF',
'#CC6600',
'#CC6633',
'#CC9900',
'#CC9933',
'#CCCC00',
'#CCCC33',
'#FF0000',
'#FF0033',
'#FF0066',
'#FF0099',
'#FF00CC',
'#FF00FF',
'#FF3300',
'#FF3333',
'#FF3366',
'#FF3399',
'#FF33CC',
'#FF33FF',
'#FF6600',
'#FF6633',
'#FF9900',
'#FF9933',
'#FFCC00',
'#FFCC33'
];
/**
* Currently only WebKit-based Web Inspectors, Firefox >= v31,
* and the Firebug extension (any Firefox version) are known
* to support "%c" CSS customizations.
*
* TODO: add a `localStorage` variable to explicitly enable/disable colors
*/
// eslint-disable-next-line complexity
function useColors() {
// NB: In an Electron preload script, document will be defined but not fully
// initialized. Since we know we're in Chrome, we'll just detect this case
// explicitly
if (typeof window !== 'undefined' && window.process && (window.process.type === 'renderer' || window.process.__nwjs)) {
return true;
}
// Internet Explorer and Edge do not support colors.
if (typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/)) {
return false;
}
// Is webkit? http://stackoverflow.com/a/16459606/376773
// document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||
// Is firebug? http://stackoverflow.com/a/398120/376773
(typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||
// Is firefox >= v31?
// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
(typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||
// Double check webkit in userAgent just in case we are in a worker
(typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
}
/**
* Colorize log arguments if enabled.
*
* @api public
*/
function formatArgs(args) {
args[0] = (this.useColors ? '%c' : '') +
this.namespace +
(this.useColors ? ' %c' : ' ') +
args[0] +
(this.useColors ? '%c ' : ' ') +
'+' + module.exports.humanize(this.diff);
if (!this.useColors) {
return;
}
const c = 'color: ' + this.color;
args.splice(1, 0, c, 'color: inherit');
// The final "%c" is somewhat tricky, because there could be other
// arguments passed either before or after the %c, so we need to
// figure out the correct index to insert the CSS into
let index = 0;
let lastC = 0;
args[0].replace(/%[a-zA-Z%]/g, match => {
if (match === '%%') {
return;
}
index++;
if (match === '%c') {
// We only are interested in the *last* %c
// (the user may have provided their own)
lastC = index;
}
});
args.splice(lastC, 0, c);
}
/**
* Invokes `console.debug()` when available.
* No-op when `console.debug` is not a "function".
* If `console.debug` is not available, falls back
* to `console.log`.
*
* @api public
*/
exports.log = console.debug || console.log || (() => {});
/**
* Save `namespaces`.
*
* @param {String} namespaces
* @api private
*/
function save(namespaces) {
try {
if (namespaces) {
exports.storage.setItem('debug', namespaces);
} else {
exports.storage.removeItem('debug');
}
} catch (error) {
// Swallow
// XXX (@Qix-) should we be logging these?
}
}
/**
* Load `namespaces`.
*
* @return {String} returns the previously persisted debug modes
* @api private
*/
function load() {
let r;
try {
r = exports.storage.getItem('debug');
} catch (error) {
// Swallow
// XXX (@Qix-) should we be logging these?
}
// If debug isn't set in LS, and we're in Electron, try to load $DEBUG
if (!r && typeof process !== 'undefined' && 'env' in process) {
r = process.env.DEBUG;
}
return r;
}
/**
* Localstorage attempts to return the localstorage.
*
* This is necessary because safari throws
* when a user disables cookies/localstorage
* and you attempt to access it.
*
* @return {LocalStorage}
* @api private
*/
function localstorage() {
try {
// TVMLKit (Apple TV JS Runtime) does not have a window object, just localStorage in the global context
// The Browser also has localStorage in the global context.
return localStorage;
} catch (error) {
// Swallow
// XXX (@Qix-) should we be logging these?
}
}
module.exports = require('./common')(exports);
const {formatters} = module.exports;
/**
* Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
*/
formatters.j = function (v) {
try {
return JSON.stringify(v);
} catch (error) {
return '[UnexpectedJSONParseError]: ' + error.message;
}
};
+274
View File
@@ -0,0 +1,274 @@
/**
* This is the common logic for both the Node.js and web browser
* implementations of `debug()`.
*/
function setup(env) {
createDebug.debug = createDebug;
createDebug.default = createDebug;
createDebug.coerce = coerce;
createDebug.disable = disable;
createDebug.enable = enable;
createDebug.enabled = enabled;
createDebug.humanize = require('ms');
createDebug.destroy = destroy;
Object.keys(env).forEach(key => {
createDebug[key] = env[key];
});
/**
* The currently active debug mode names, and names to skip.
*/
createDebug.names = [];
createDebug.skips = [];
/**
* Map of special "%n" handling functions, for the debug "format" argument.
*
* Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
*/
createDebug.formatters = {};
/**
* Selects a color for a debug namespace
* @param {String} namespace The namespace string for the for the debug instance to be colored
* @return {Number|String} An ANSI color code for the given namespace
* @api private
*/
function selectColor(namespace) {
let hash = 0;
for (let i = 0; i < namespace.length; i++) {
hash = ((hash << 5) - hash) + namespace.charCodeAt(i);
hash |= 0; // Convert to 32bit integer
}
return createDebug.colors[Math.abs(hash) % createDebug.colors.length];
}
createDebug.selectColor = selectColor;
/**
* Create a debugger with the given `namespace`.
*
* @param {String} namespace
* @return {Function}
* @api public
*/
function createDebug(namespace) {
let prevTime;
let enableOverride = null;
let namespacesCache;
let enabledCache;
function debug(...args) {
// Disabled?
if (!debug.enabled) {
return;
}
const self = debug;
// Set `diff` timestamp
const curr = Number(new Date());
const ms = curr - (prevTime || curr);
self.diff = ms;
self.prev = prevTime;
self.curr = curr;
prevTime = curr;
args[0] = createDebug.coerce(args[0]);
if (typeof args[0] !== 'string') {
// Anything else let's inspect with %O
args.unshift('%O');
}
// Apply any `formatters` transformations
let index = 0;
args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => {
// If we encounter an escaped % then don't increase the array index
if (match === '%%') {
return '%';
}
index++;
const formatter = createDebug.formatters[format];
if (typeof formatter === 'function') {
const val = args[index];
match = formatter.call(self, val);
// Now we need to remove `args[index]` since it's inlined in the `format`
args.splice(index, 1);
index--;
}
return match;
});
// Apply env-specific formatting (colors, etc.)
createDebug.formatArgs.call(self, args);
const logFn = self.log || createDebug.log;
logFn.apply(self, args);
}
debug.namespace = namespace;
debug.useColors = createDebug.useColors();
debug.color = createDebug.selectColor(namespace);
debug.extend = extend;
debug.destroy = createDebug.destroy; // XXX Temporary. Will be removed in the next major release.
Object.defineProperty(debug, 'enabled', {
enumerable: true,
configurable: false,
get: () => {
if (enableOverride !== null) {
return enableOverride;
}
if (namespacesCache !== createDebug.namespaces) {
namespacesCache = createDebug.namespaces;
enabledCache = createDebug.enabled(namespace);
}
return enabledCache;
},
set: v => {
enableOverride = v;
}
});
// Env-specific initialization logic for debug instances
if (typeof createDebug.init === 'function') {
createDebug.init(debug);
}
return debug;
}
function extend(namespace, delimiter) {
const newDebug = createDebug(this.namespace + (typeof delimiter === 'undefined' ? ':' : delimiter) + namespace);
newDebug.log = this.log;
return newDebug;
}
/**
* Enables a debug mode by namespaces. This can include modes
* separated by a colon and wildcards.
*
* @param {String} namespaces
* @api public
*/
function enable(namespaces) {
createDebug.save(namespaces);
createDebug.namespaces = namespaces;
createDebug.names = [];
createDebug.skips = [];
let i;
const split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/);
const len = split.length;
for (i = 0; i < len; i++) {
if (!split[i]) {
// ignore empty strings
continue;
}
namespaces = split[i].replace(/\*/g, '.*?');
if (namespaces[0] === '-') {
createDebug.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
} else {
createDebug.names.push(new RegExp('^' + namespaces + '$'));
}
}
}
/**
* Disable debug output.
*
* @return {String} namespaces
* @api public
*/
function disable() {
const namespaces = [
...createDebug.names.map(toNamespace),
...createDebug.skips.map(toNamespace).map(namespace => '-' + namespace)
].join(',');
createDebug.enable('');
return namespaces;
}
/**
* Returns true if the given mode name is enabled, false otherwise.
*
* @param {String} name
* @return {Boolean}
* @api public
*/
function enabled(name) {
if (name[name.length - 1] === '*') {
return true;
}
let i;
let len;
for (i = 0, len = createDebug.skips.length; i < len; i++) {
if (createDebug.skips[i].test(name)) {
return false;
}
}
for (i = 0, len = createDebug.names.length; i < len; i++) {
if (createDebug.names[i].test(name)) {
return true;
}
}
return false;
}
/**
* Convert regexp to namespace
*
* @param {RegExp} regxep
* @return {String} namespace
* @api private
*/
function toNamespace(regexp) {
return regexp.toString()
.substring(2, regexp.toString().length - 2)
.replace(/\.\*\?$/, '*');
}
/**
* Coerce `val`.
*
* @param {Mixed} val
* @return {Mixed}
* @api private
*/
function coerce(val) {
if (val instanceof Error) {
return val.stack || val.message;
}
return val;
}
/**
* XXX DO NOT USE. This is a temporary stub function.
* XXX It WILL be removed in the next major release.
*/
function destroy() {
console.warn('Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`.');
}
createDebug.enable(createDebug.load());
return createDebug;
}
module.exports = setup;

Some files were not shown because too many files have changed in this diff Show More