정민혁

백과사전 구현시도(실패), 네이버 트랜드검색api를 대신 도입- response 값 parsing에 문제가 있어서 카카오톡으로는 response값을 그대로 출력하도록 설정

Showing 118 changed files with 3757 additions and 0 deletions
1 +sudo: true
2 +language: node_js
3 +node_js:
4 + - 8
5 +script: npm run coveralls
1 +Copyright (c) Felix Böhm
2 +All rights reserved.
3 +
4 +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
5 +
6 +Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7 +
8 +Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9 +
10 +THIS IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS,
11 +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1 +var encode = require("./lib/encode.js"),
2 + decode = require("./lib/decode.js");
3 +
4 +exports.decode = function(data, level) {
5 + return (!level || level <= 0 ? decode.XML : decode.HTML)(data);
6 +};
7 +
8 +exports.decodeStrict = function(data, level) {
9 + return (!level || level <= 0 ? decode.XML : decode.HTMLStrict)(data);
10 +};
11 +
12 +exports.encode = function(data, level) {
13 + return (!level || level <= 0 ? encode.XML : encode.HTML)(data);
14 +};
15 +
16 +exports.encodeXML = encode.XML;
17 +
18 +exports.encodeHTML4 = exports.encodeHTML5 = exports.encodeHTML = encode.HTML;
19 +
20 +exports.decodeXML = exports.decodeXMLStrict = decode.XML;
21 +
22 +exports.decodeHTML4 = exports.decodeHTML5 = exports.decodeHTML = decode.HTML;
23 +
24 +exports.decodeHTML4Strict = exports.decodeHTML5Strict = exports.decodeHTMLStrict = decode.HTMLStrict;
25 +
26 +exports.escape = encode.escape;
1 +var entityMap = require("../maps/entities.json"),
2 + legacyMap = require("../maps/legacy.json"),
3 + xmlMap = require("../maps/xml.json"),
4 + decodeCodePoint = require("./decode_codepoint.js");
5 +
6 +var decodeXMLStrict = getStrictDecoder(xmlMap),
7 + decodeHTMLStrict = getStrictDecoder(entityMap);
8 +
9 +function getStrictDecoder(map) {
10 + var keys = Object.keys(map).join("|"),
11 + replace = getReplacer(map);
12 +
13 + keys += "|#[xX][\\da-fA-F]+|#\\d+";
14 +
15 + var re = new RegExp("&(?:" + keys + ");", "g");
16 +
17 + return function(str) {
18 + return String(str).replace(re, replace);
19 + };
20 +}
21 +
22 +var decodeHTML = (function() {
23 + var legacy = Object.keys(legacyMap).sort(sorter);
24 +
25 + var keys = Object.keys(entityMap).sort(sorter);
26 +
27 + for (var i = 0, j = 0; i < keys.length; i++) {
28 + if (legacy[j] === keys[i]) {
29 + keys[i] += ";?";
30 + j++;
31 + } else {
32 + keys[i] += ";";
33 + }
34 + }
35 +
36 + var re = new RegExp("&(?:" + keys.join("|") + "|#[xX][\\da-fA-F]+;?|#\\d+;?)", "g"),
37 + replace = getReplacer(entityMap);
38 +
39 + function replacer(str) {
40 + if (str.substr(-1) !== ";") str += ";";
41 + return replace(str);
42 + }
43 +
44 + //TODO consider creating a merged map
45 + return function(str) {
46 + return String(str).replace(re, replacer);
47 + };
48 +})();
49 +
50 +function sorter(a, b) {
51 + return a < b ? 1 : -1;
52 +}
53 +
54 +function getReplacer(map) {
55 + return function replace(str) {
56 + if (str.charAt(1) === "#") {
57 + if (str.charAt(2) === "X" || str.charAt(2) === "x") {
58 + return decodeCodePoint(parseInt(str.substr(3), 16));
59 + }
60 + return decodeCodePoint(parseInt(str.substr(2), 10));
61 + }
62 + return map[str.slice(1, -1)];
63 + };
64 +}
65 +
66 +module.exports = {
67 + XML: decodeXMLStrict,
68 + HTML: decodeHTML,
69 + HTMLStrict: decodeHTMLStrict
70 +};
1 +var decodeMap = require("../maps/decode.json");
2 +
3 +module.exports = decodeCodePoint;
4 +
5 +// modified version of https://github.com/mathiasbynens/he/blob/master/src/he.js#L94-L119
6 +function decodeCodePoint(codePoint) {
7 + if ((codePoint >= 0xd800 && codePoint <= 0xdfff) || codePoint > 0x10ffff) {
8 + return "\uFFFD";
9 + }
10 +
11 + if (codePoint in decodeMap) {
12 + codePoint = decodeMap[codePoint];
13 + }
14 +
15 + var output = "";
16 +
17 + if (codePoint > 0xffff) {
18 + codePoint -= 0x10000;
19 + output += String.fromCharCode(((codePoint >>> 10) & 0x3ff) | 0xd800);
20 + codePoint = 0xdc00 | (codePoint & 0x3ff);
21 + }
22 +
23 + output += String.fromCharCode(codePoint);
24 + return output;
25 +}
1 +var inverseXML = getInverseObj(require("../maps/xml.json")),
2 + xmlReplacer = getInverseReplacer(inverseXML);
3 +
4 +exports.XML = getInverse(inverseXML, xmlReplacer);
5 +
6 +var inverseHTML = getInverseObj(require("../maps/entities.json")),
7 + htmlReplacer = getInverseReplacer(inverseHTML);
8 +
9 +exports.HTML = getInverse(inverseHTML, htmlReplacer);
10 +
11 +function getInverseObj(obj) {
12 + return Object.keys(obj)
13 + .sort()
14 + .reduce(function(inverse, name) {
15 + inverse[obj[name]] = "&" + name + ";";
16 + return inverse;
17 + }, {});
18 +}
19 +
20 +function getInverseReplacer(inverse) {
21 + var single = [],
22 + multiple = [];
23 +
24 + Object.keys(inverse).forEach(function(k) {
25 + if (k.length === 1) {
26 + single.push("\\" + k);
27 + } else {
28 + multiple.push(k);
29 + }
30 + });
31 +
32 + //TODO add ranges
33 + multiple.unshift("[" + single.join("") + "]");
34 +
35 + return new RegExp(multiple.join("|"), "g");
36 +}
37 +
38 +var re_nonASCII = /[^\0-\x7F]/g,
39 + re_astralSymbols = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
40 +
41 +function singleCharReplacer(c) {
42 + return (
43 + "&#x" +
44 + c
45 + .charCodeAt(0)
46 + .toString(16)
47 + .toUpperCase() +
48 + ";"
49 + );
50 +}
51 +
52 +function astralReplacer(c) {
53 + // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
54 + var high = c.charCodeAt(0);
55 + var low = c.charCodeAt(1);
56 + var codePoint = (high - 0xd800) * 0x400 + low - 0xdc00 + 0x10000;
57 + return "&#x" + codePoint.toString(16).toUpperCase() + ";";
58 +}
59 +
60 +function getInverse(inverse, re) {
61 + function func(name) {
62 + return inverse[name];
63 + }
64 +
65 + return function(data) {
66 + return data
67 + .replace(re, func)
68 + .replace(re_astralSymbols, astralReplacer)
69 + .replace(re_nonASCII, singleCharReplacer);
70 + };
71 +}
72 +
73 +var re_xmlChars = getInverseReplacer(inverseXML);
74 +
75 +function escapeXML(data) {
76 + return data
77 + .replace(re_xmlChars, singleCharReplacer)
78 + .replace(re_astralSymbols, astralReplacer)
79 + .replace(re_nonASCII, singleCharReplacer);
80 +}
81 +
82 +exports.escape = escapeXML;
1 +{"0":65533,"128":8364,"130":8218,"131":402,"132":8222,"133":8230,"134":8224,"135":8225,"136":710,"137":8240,"138":352,"139":8249,"140":338,"142":381,"145":8216,"146":8217,"147":8220,"148":8221,"149":8226,"150":8211,"151":8212,"152":732,"153":8482,"154":353,"155":8250,"156":339,"158":382,"159":376}
...\ No newline at end of file ...\ No newline at end of file
This diff is collapsed. Click to expand it.
1 +{"Aacute":"\u00C1","aacute":"\u00E1","Acirc":"\u00C2","acirc":"\u00E2","acute":"\u00B4","AElig":"\u00C6","aelig":"\u00E6","Agrave":"\u00C0","agrave":"\u00E0","amp":"&","AMP":"&","Aring":"\u00C5","aring":"\u00E5","Atilde":"\u00C3","atilde":"\u00E3","Auml":"\u00C4","auml":"\u00E4","brvbar":"\u00A6","Ccedil":"\u00C7","ccedil":"\u00E7","cedil":"\u00B8","cent":"\u00A2","copy":"\u00A9","COPY":"\u00A9","curren":"\u00A4","deg":"\u00B0","divide":"\u00F7","Eacute":"\u00C9","eacute":"\u00E9","Ecirc":"\u00CA","ecirc":"\u00EA","Egrave":"\u00C8","egrave":"\u00E8","ETH":"\u00D0","eth":"\u00F0","Euml":"\u00CB","euml":"\u00EB","frac12":"\u00BD","frac14":"\u00BC","frac34":"\u00BE","gt":">","GT":">","Iacute":"\u00CD","iacute":"\u00ED","Icirc":"\u00CE","icirc":"\u00EE","iexcl":"\u00A1","Igrave":"\u00CC","igrave":"\u00EC","iquest":"\u00BF","Iuml":"\u00CF","iuml":"\u00EF","laquo":"\u00AB","lt":"<","LT":"<","macr":"\u00AF","micro":"\u00B5","middot":"\u00B7","nbsp":"\u00A0","not":"\u00AC","Ntilde":"\u00D1","ntilde":"\u00F1","Oacute":"\u00D3","oacute":"\u00F3","Ocirc":"\u00D4","ocirc":"\u00F4","Ograve":"\u00D2","ograve":"\u00F2","ordf":"\u00AA","ordm":"\u00BA","Oslash":"\u00D8","oslash":"\u00F8","Otilde":"\u00D5","otilde":"\u00F5","Ouml":"\u00D6","ouml":"\u00F6","para":"\u00B6","plusmn":"\u00B1","pound":"\u00A3","quot":"\"","QUOT":"\"","raquo":"\u00BB","reg":"\u00AE","REG":"\u00AE","sect":"\u00A7","shy":"\u00AD","sup1":"\u00B9","sup2":"\u00B2","sup3":"\u00B3","szlig":"\u00DF","THORN":"\u00DE","thorn":"\u00FE","times":"\u00D7","Uacute":"\u00DA","uacute":"\u00FA","Ucirc":"\u00DB","ucirc":"\u00FB","Ugrave":"\u00D9","ugrave":"\u00F9","uml":"\u00A8","Uuml":"\u00DC","uuml":"\u00FC","Yacute":"\u00DD","yacute":"\u00FD","yen":"\u00A5","yuml":"\u00FF"}
...\ No newline at end of file ...\ No newline at end of file
1 +{"amp":"&","apos":"'","gt":">","lt":"<","quot":"\""}
1 +{
2 + "_from": "entities@^1.1.1",
3 + "_id": "entities@1.1.2",
4 + "_inBundle": false,
5 + "_integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==",
6 + "_location": "/entities",
7 + "_phantomChildren": {},
8 + "_requested": {
9 + "type": "range",
10 + "registry": true,
11 + "raw": "entities@^1.1.1",
12 + "name": "entities",
13 + "escapedName": "entities",
14 + "rawSpec": "^1.1.1",
15 + "saveSpec": null,
16 + "fetchSpec": "^1.1.1"
17 + },
18 + "_requiredBy": [
19 + "/rss-parser"
20 + ],
21 + "_resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
22 + "_shasum": "bdfa735299664dfafd34529ed4f8522a275fea56",
23 + "_spec": "entities@^1.1.1",
24 + "_where": "C:\\Users\\정민채\\Desktop\\TermProject\\2017104024정민혁KakaoBot\\node_modules\\rss-parser",
25 + "author": {
26 + "name": "Felix Boehm",
27 + "email": "me@feedic.com"
28 + },
29 + "bugs": {
30 + "url": "https://github.com/fb55/entities/issues"
31 + },
32 + "bundleDependencies": false,
33 + "deprecated": false,
34 + "description": "Encode & decode XML/HTML entities with ease",
35 + "devDependencies": {
36 + "coveralls": "*",
37 + "istanbul": "*",
38 + "jshint": "2",
39 + "mocha": "^5.0.1",
40 + "mocha-lcov-reporter": "*"
41 + },
42 + "directories": {
43 + "test": "test"
44 + },
45 + "homepage": "https://github.com/fb55/entities#readme",
46 + "jshintConfig": {
47 + "eqeqeq": true,
48 + "freeze": true,
49 + "latedef": "nofunc",
50 + "noarg": true,
51 + "nonbsp": true,
52 + "quotmark": "double",
53 + "undef": true,
54 + "unused": true,
55 + "trailing": true,
56 + "eqnull": true,
57 + "proto": true,
58 + "smarttabs": true,
59 + "node": true,
60 + "globals": {
61 + "describe": true,
62 + "it": true
63 + }
64 + },
65 + "keywords": [
66 + "html",
67 + "xml",
68 + "entity",
69 + "decoding",
70 + "encoding"
71 + ],
72 + "license": "BSD-2-Clause",
73 + "main": "./index.js",
74 + "name": "entities",
75 + "prettier": {
76 + "tabWidth": 4
77 + },
78 + "repository": {
79 + "type": "git",
80 + "url": "git://github.com/fb55/entities.git"
81 + },
82 + "scripts": {
83 + "coveralls": "npm run lint && npm run lcov && (cat coverage/lcov.info | coveralls || exit 0)",
84 + "lcov": "istanbul cover _mocha --report lcovonly -- -R spec",
85 + "lint": "jshint index.js lib/*.js test/*.js",
86 + "test": "mocha && npm run lint"
87 + },
88 + "version": "1.1.2"
89 +}
1 +# entities [![NPM version](http://img.shields.io/npm/v/entities.svg)](https://npmjs.org/package/entities) [![Downloads](https://img.shields.io/npm/dm/entities.svg)](https://npmjs.org/package/entities) [![Build Status](http://img.shields.io/travis/fb55/entities.svg)](http://travis-ci.org/fb55/entities) [![Coverage](http://img.shields.io/coveralls/fb55/entities.svg)](https://coveralls.io/r/fb55/entities)
2 +
3 +En- & decoder for XML/HTML entities.
4 +
5 +## How to…
6 +
7 +### …install `entities`
8 +
9 + npm i entities
10 +
11 +### …use `entities`
12 +
13 +```javascript
14 +var entities = require("entities");
15 +//encoding
16 +entities.encodeXML("&#38;"); // "&amp;#38;"
17 +entities.encodeHTML("&#38;"); // "&amp;&num;38&semi;"
18 +//decoding
19 +entities.decodeXML("asdf &amp; &#xFF; &#xFC; &apos;"); // "asdf & ÿ ü '"
20 +entities.decodeHTML("asdf &amp; &yuml; &uuml; &apos;"); // "asdf & ÿ ü '"
21 +```
22 +
23 +<!-- TODO extend API -->
24 +
25 +---
26 +
27 +License: BSD-2-Clause
1 +--check-leaks
2 +--reporter spec
1 +var assert = require("assert"),
2 + path = require("path"),
3 + entities = require("../");
4 +
5 +describe("Encode->decode test", function() {
6 + var testcases = [
7 + {
8 + input: "asdf & ÿ ü '",
9 + xml: "asdf &amp; &#xFF; &#xFC; &apos;",
10 + html: "asdf &amp; &yuml; &uuml; &apos;"
11 + },
12 + {
13 + input: "&#38;",
14 + xml: "&amp;#38;",
15 + html: "&amp;&num;38&semi;"
16 + }
17 + ];
18 + testcases.forEach(function(tc) {
19 + var encodedXML = entities.encodeXML(tc.input);
20 + it("should XML encode " + tc.input, function() {
21 + assert.equal(encodedXML, tc.xml);
22 + });
23 + it("should default to XML encode " + tc.input, function() {
24 + assert.equal(entities.encode(tc.input), tc.xml);
25 + });
26 + it("should XML decode " + encodedXML, function() {
27 + assert.equal(entities.decodeXML(encodedXML), tc.input);
28 + });
29 + it("should default to XML encode " + encodedXML, function() {
30 + assert.equal(entities.decode(encodedXML), tc.input);
31 + });
32 + it("should default strict to XML encode " + encodedXML, function() {
33 + assert.equal(entities.decodeStrict(encodedXML), tc.input);
34 + });
35 +
36 + var encodedHTML5 = entities.encodeHTML5(tc.input);
37 + it("should HTML5 encode " + tc.input, function() {
38 + assert.equal(encodedHTML5, tc.html);
39 + });
40 + it("should HTML5 decode " + encodedHTML5, function() {
41 + assert.equal(entities.decodeHTML(encodedHTML5), tc.input);
42 + });
43 + });
44 +
45 + it("should encode data URIs (issue 16)", function() {
46 + var data = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAALAAABAAEAAAIBRAA7";
47 + assert.equal(entities.decode(entities.encode(data)), data);
48 + });
49 +});
50 +
51 +describe("Decode test", function() {
52 + var testcases = [
53 + { input: "&amp;amp;", output: "&amp;" },
54 + { input: "&amp;#38;", output: "&#38;" },
55 + { input: "&amp;#x26;", output: "&#x26;" },
56 + { input: "&amp;#X26;", output: "&#X26;" },
57 + { input: "&#38;#38;", output: "&#38;" },
58 + { input: "&#x26;#38;", output: "&#38;" },
59 + { input: "&#X26;#38;", output: "&#38;" },
60 + { input: "&#x3a;", output: ":" },
61 + { input: "&#x3A;", output: ":" },
62 + { input: "&#X3a;", output: ":" },
63 + { input: "&#X3A;", output: ":" }
64 + ];
65 + testcases.forEach(function(tc) {
66 + it("should XML decode " + tc.input, function() {
67 + assert.equal(entities.decodeXML(tc.input), tc.output);
68 + });
69 + it("should HTML4 decode " + tc.input, function() {
70 + assert.equal(entities.decodeHTML(tc.input), tc.output);
71 + });
72 + it("should HTML5 decode " + tc.input, function() {
73 + assert.equal(entities.decodeHTML(tc.input), tc.output);
74 + });
75 + });
76 +});
77 +
78 +var levels = ["xml", "entities"];
79 +
80 +describe("Documents", function() {
81 + levels
82 + .map(function(n) {
83 + return path.join("..", "maps", n);
84 + })
85 + .map(require)
86 + .forEach(function(doc, i) {
87 + describe("Decode", function() {
88 + it(levels[i], function() {
89 + Object.keys(doc).forEach(function(e) {
90 + for (var l = i; l < levels.length; l++) {
91 + assert.equal(entities.decode("&" + e + ";", l), doc[e]);
92 + }
93 + });
94 + });
95 + });
96 +
97 + describe("Decode strict", function() {
98 + it(levels[i], function() {
99 + Object.keys(doc).forEach(function(e) {
100 + for (var l = i; l < levels.length; l++) {
101 + assert.equal(entities.decodeStrict("&" + e + ";", l), doc[e]);
102 + }
103 + });
104 + });
105 + });
106 +
107 + describe("Encode", function() {
108 + it(levels[i], function() {
109 + Object.keys(doc).forEach(function(e) {
110 + for (var l = i; l < levels.length; l++) {
111 + assert.equal(entities.decode(entities.encode(doc[e], l), l), doc[e]);
112 + }
113 + });
114 + });
115 + });
116 + });
117 +
118 + var legacy = require("../maps/legacy.json");
119 +
120 + describe("Legacy", function() {
121 + it("should decode", runLegacy);
122 + });
123 +
124 + function runLegacy() {
125 + Object.keys(legacy).forEach(function(e) {
126 + assert.equal(entities.decodeHTML("&" + e), legacy[e]);
127 + });
128 + }
129 +});
130 +
131 +var astral = {
132 + "1D306": "\uD834\uDF06",
133 + "1D11E": "\uD834\uDD1E"
134 +};
135 +
136 +var astralSpecial = {
137 + "80": "\u20AC",
138 + "110000": "\uFFFD"
139 +};
140 +
141 +describe("Astral entities", function() {
142 + Object.keys(astral).forEach(function(c) {
143 + it("should decode " + astral[c], function() {
144 + assert.equal(entities.decode("&#x" + c + ";"), astral[c]);
145 + });
146 +
147 + it("should encode " + astral[c], function() {
148 + assert.equal(entities.encode(astral[c]), "&#x" + c + ";");
149 + });
150 +
151 + it("should escape " + astral[c], function() {
152 + assert.equal(entities.escape(astral[c]), "&#x" + c + ";");
153 + });
154 + });
155 +
156 + Object.keys(astralSpecial).forEach(function(c) {
157 + it("special should decode \\u" + c, function() {
158 + assert.equal(entities.decode("&#x" + c + ";"), astralSpecial[c]);
159 + });
160 + });
161 +});
162 +
163 +describe("Escape", function() {
164 + it("should always decode ASCII chars", function() {
165 + for (var i = 0; i < 0x7f; i++) {
166 + var c = String.fromCharCode(i);
167 + assert.equal(entities.decodeXML(entities.escape(c)), c);
168 + }
169 + });
170 +});
1 +dist: trusty
2 +
3 +language: node_js
4 +node_js:
5 + - "8"
6 +
7 +before_script:
8 + - npm install -g mocha
9 +script: npm test
10 +
11 +addons:
12 + apt:
13 + packages:
14 + - libnss3
1 +MIT License
2 +
3 +Copyright (c) 2016 Bobby Brennan
4 +
5 +Permission is hereby granted, free of charge, to any person obtaining a copy
6 +of this software and associated documentation files (the "Software"), to deal
7 +in the Software without restriction, including without limitation the rights
8 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 +copies of the Software, and to permit persons to whom the Software is
10 +furnished to do so, subject to the following conditions:
11 +
12 +The above copyright notice and this permission notice shall be included in all
13 +copies or substantial portions of the Software.
14 +
15 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 +SOFTWARE.
1 +# rss-parser
2 +
3 +[![Version][npm-image]][npm-link]
4 +[![Build Status][build-image]][build-link]
5 +[![Downloads][downloads-image]][npm-link]
6 +
7 +[downloads-image]: https://img.shields.io/npm/dm/rss-parser.svg
8 +[npm-image]: https://img.shields.io/npm/v/rss-parser.svg
9 +[npm-link]: https://npmjs.org/package/rss-parser
10 +[build-image]: https://travis-ci.org/bobby-brennan/rss-parser.svg?branch=master
11 +[build-link]: https://travis-ci.org/bobby-brennan/rss-parser
12 +
13 +A small library for turning RSS XML feeds into JavaScript objects.
14 +
15 +## Installation
16 +```bash
17 +npm install --save rss-parser
18 +```
19 +
20 +## Usage
21 +You can parse RSS from a URL (`parser.parseURL`) or an XML string (`parser.parseString`).
22 +
23 +Both callbacks and Promises are supported.
24 +
25 +### NodeJS
26 +Here's an example in NodeJS using Promises with async/await:
27 +
28 +```js
29 +let Parser = require('rss-parser');
30 +let parser = new Parser();
31 +
32 +(async () => {
33 +
34 + let feed = await parser.parseURL('https://www.reddit.com/.rss');
35 + console.log(feed.title);
36 +
37 + feed.items.forEach(item => {
38 + console.log(item.title + ':' + item.link)
39 + });
40 +
41 +})();
42 +```
43 +
44 +### Web
45 +> We recommend using a bundler like [webpack](https://webpack.js.org/), but we also provide
46 +> pre-built browser distributions in the `dist/` folder. If you use the pre-built distribution,
47 +> you'll need a [polyfill](https://github.com/taylorhakes/promise-polyfill) for Promise support.
48 +
49 +Here's an example in the browser using callbacks:
50 +
51 +```html
52 +<script src="/node_modules/rss-parser/dist/rss-parser.min.js"></script>
53 +<script>
54 +
55 +// Note: some RSS feeds can't be loaded in the browser due to CORS security.
56 +// To get around this, you can use a proxy.
57 +const CORS_PROXY = "https://cors-anywhere.herokuapp.com/"
58 +
59 +let parser = new RSSParser();
60 +parser.parseURL(CORS_PROXY + 'https://www.reddit.com/.rss', function(err, feed) {
61 + console.log(feed.title);
62 + feed.items.forEach(function(entry) {
63 + console.log(entry.title + ':' + entry.link);
64 + })
65 +})
66 +
67 +</script>
68 +```
69 +
70 +### Upgrading from v2 to v3
71 +A few minor breaking changes were made in v3. Here's what you need to know:
72 +
73 +* You need to construct a `new Parser()` before calling `parseString` or `parseURL`
74 +* `parseFile` is no longer available (for better browser support)
75 +* `options` are now passed to the Parser constructor
76 +* `parsed.feed` is now just `feed` (top-level object removed)
77 +* `feed.entries` is now `feed.items` (to better match RSS XML)
78 +
79 +
80 +## Output
81 +Check out the full output format in [test/output/reddit.json](test/output/reddit.json)
82 +
83 +```yaml
84 +feedUrl: 'https://www.reddit.com/.rss'
85 +title: 'reddit: the front page of the internet'
86 +description: ""
87 +link: 'https://www.reddit.com/'
88 +items:
89 + - title: 'The water is too deep, so he improvises'
90 + link: 'https://www.reddit.com/r/funny/comments/3skxqc/the_water_is_too_deep_so_he_improvises/'
91 + pubDate: 'Thu, 12 Nov 2015 21:16:39 +0000'
92 + creator: "John Doe"
93 + content: '<a href="http://example.com">this is a link</a> &amp; <b>this is bold text</b>'
94 + contentSnippet: 'this is a link & this is bold text'
95 + guid: 'https://www.reddit.com/r/funny/comments/3skxqc/the_water_is_too_deep_so_he_improvises/'
96 + categories:
97 + - funny
98 + isoDate: '2015-11-12T21:16:39.000Z'
99 +```
100 +
101 +##### Notes:
102 +* The `contentSnippet` field strips out HTML tags and unescapes HTML entities
103 +* The `dc:` prefix will be removed from all fields
104 +* Both `dc:date` and `pubDate` will be available in ISO 8601 format as `isoDate`
105 +* If `author` is specified, but not `dc:creator`, `creator` will be set to `author` ([see article](http://www.lowter.com/blogs/2008/2/9/rss-dccreator-author))
106 +* Atom's `updated` becomes `lastBuildDate` for consistency
107 +
108 +## Options
109 +
110 +### Custom Fields
111 +If your RSS feed contains fields that aren't currently returned, you can access them using the `customFields` option.
112 +
113 +```js
114 +let parser = new Parser({
115 + customFields: {
116 + feed: ['otherTitle', 'extendedDescription'],
117 + item: ['coAuthor','subtitle'],
118 + }
119 +});
120 +
121 +parser.parseURL('https://www.reddit.com/.rss', function(err, feed) {
122 + console.log(feed.extendedDescription);
123 +
124 + feed.items.forEach(function(entry) {
125 + console.log(entry.coAuthor + ':' + entry.subtitle);
126 + })
127 +})
128 +```
129 +
130 +To rename fields, you can pass in an array with two items, in the format `[fromField, toField]`:
131 +
132 +```js
133 +let parser = new Parser({
134 + customFields: {
135 + item: [
136 + ['dc:coAuthor', 'coAuthor'],
137 + ]
138 + }
139 +})
140 +```
141 +
142 +To pass additional flags, provide an object as the third array item. Currently there is one such flag:
143 +
144 +* `keepArray`: `true` to return *all* values for fields that can have multiple entries. Default: return the first item only.
145 +
146 +```js
147 +let parser = new Parser({
148 + customFields: {
149 + item: [
150 + ['media:content', 'media:content', {keepArray: true}],
151 + ]
152 + }
153 +})
154 +```
155 +
156 +### Default RSS version
157 +If your RSS Feed doesn't contain a `<rss>` tag with a `version` attribute,
158 +you can pass a `defaultRSS` option for the Parser to use:
159 +```js
160 +let parser = new Parser({
161 + defaultRSS: 2.0
162 +});
163 +```
164 +
165 +
166 +### xml2js passthrough
167 +`rss-parser` uses [xml2js](https://github.com/Leonidas-from-XIV/node-xml2js)
168 +to parse XML. You can pass [these options](https://github.com/Leonidas-from-XIV/node-xml2js#options)
169 +to `new xml2js.Parser()` by specifying `options.xml2js`:
170 +
171 +```js
172 +let parser = new Parser({
173 + xml2js: {
174 + emptyTag: '--EMPTY--',
175 + }
176 +});
177 +```
178 +
179 +### Headers
180 +You can pass headers to the HTTP request:
181 +```js
182 +let parser = new Parser({
183 + headers: {'User-Agent': 'something different'},
184 +});
185 +```
186 +
187 +### Redirects
188 +By default, `parseURL` will follow up to five redirects. You can change this
189 +with `options.maxRedirects`.
190 +
191 +```js
192 +let parser = new Parser({maxRedirects: 100});
193 +```
194 +
195 +
196 +## Contributing
197 +Contributions are welcome! If you are adding a feature or fixing a bug, please be sure to add a [test case](https://github.com/bobby-brennan/rss-parser/tree/master/test/input)
198 +
199 +### Running Tests
200 +The tests run the RSS parser for several sample RSS feeds in `test/input` and outputs the resulting JSON into `test/output`. If there are any changes to the output files the tests will fail.
201 +
202 +To check if your changes affect the output of any test cases, run
203 +
204 +`npm test`
205 +
206 +To update the output files with your changes, run
207 +
208 +`WRITE_GOLDEN=true npm test`
209 +
210 +### Publishing Releases
211 +```bash
212 +npm run build
213 +git commit -a -m "Build distribution"
214 +npm version minor # or major/patch
215 +npm publish
216 +git push --follow-tags
217 +```
1 +{
2 + "name": "rss-parser",
3 + "description": "",
4 + "version": "1.1.0",
5 + "main": "dist/rss-parser.js",
6 + "authors": [
7 + "Bobby Brennan"
8 + ],
9 + "license": "MIT",
10 + "homepage": "https://github.com/bobby-brennan/rss-parser",
11 + "moduleType": [
12 + "node"
13 + ],
14 + "ignore": [
15 + "**/.*",
16 + "node_modules",
17 + "bower_components",
18 + "test",
19 + "tests"
20 + ]
21 +}
1 +window.RSSParser = require('./index');
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
1 +import { Options } from 'xml2js';
2 +
3 +interface Headers
4 +{
5 + readonly Accept: string;
6 + readonly 'User-Agent': string;
7 +}
8 +
9 +interface CustomFields
10 +{
11 + readonly feed?: string[];
12 + readonly item?: string[] | string[][];
13 +}
14 +
15 +interface ParserOptions
16 +{
17 + readonly xml2js?: Options;
18 + readonly headers?: Headers;
19 + readonly defaultRSS?: number;
20 + readonly maxRedirects?: number;
21 + readonly customFields?: CustomFields;
22 +}
23 +
24 +interface Items
25 +{
26 + readonly link: string;
27 + readonly guid: string;
28 + readonly title: string;
29 + readonly pubDate: string;
30 + readonly creator: string;
31 + readonly content: string;
32 + readonly isoDate: string;
33 + readonly categories: string[];
34 + readonly contentSnippet: string;
35 +}
36 +
37 +interface Output
38 +{
39 + readonly link: string;
40 + readonly title: string;
41 + readonly items: Items[];
42 + readonly feedUrl: string;
43 + readonly description: string;
44 + readonly itunes: {
45 + image: string;
46 + owner: {
47 + name: string;
48 + email: string;
49 + };
50 + author: string;
51 + summary: string;
52 + explicit: string;
53 + };
54 +}
55 +
56 +/**
57 + * Class that handles all parsing or URL, or even XML, RSS feed to JSON.
58 + */
59 +declare const Parser: {
60 + /**
61 + * @param options - Parser options.
62 + */
63 + new(options?: ParserOptions): {
64 + /**
65 + * Parse XML content to JSON.
66 + *
67 + * @param xml - The xml to be parsed.
68 + * @param callback - Traditional callback.
69 + *
70 + * @returns Promise that has the same Output as the callback.
71 + */
72 + parseString(xml: string, callback?: (err: Error, feed: Output) => void): Promise<Output>;
73 +
74 + /**
75 + * Parse URL content to JSON.
76 + *
77 + * @param feedUrl - The url that needs to be parsed to JSON.
78 + * @param callback - Traditional callback.
79 + * @param redirectCount - Max of redirects, default is set to five.
80 + *
81 + * @example
82 + * await parseURL('https://www.reddit.com/.rss');
83 + * parseURL('https://www.reddit.com/.rss', (err, feed) => { ... });
84 + *
85 + * @returns Promise that has the same Output as the callback.
86 + */
87 + parseURL(feedUrl: string, callback?: (err: Error, feed: Output) => void, redirectCount?: number): Promise<Output>;
88 + };
89 +}
90 +export = Parser
1 +'use strict';
2 +
3 +module.exports = require('./lib/parser');
4 +
1 +const fields = module.exports = {};
2 +
3 +fields.feed = [
4 + ['author', 'creator'],
5 + ['dc:publisher', 'publisher'],
6 + ['dc:creator', 'creator'],
7 + ['dc:source', 'source'],
8 + ['dc:title', 'title'],
9 + ['dc:type', 'type'],
10 + 'title',
11 + 'description',
12 + 'author',
13 + 'pubDate',
14 + 'webMaster',
15 + 'managingEditor',
16 + 'generator',
17 + 'link',
18 + 'language',
19 + 'copyright',
20 + 'lastBuildDate',
21 + 'docs',
22 + 'generator',
23 + 'ttl',
24 + 'rating',
25 + 'skipHours',
26 + 'skipDays',
27 +];
28 +
29 +fields.item = [
30 + ['author', 'creator'],
31 + ['dc:creator', 'creator'],
32 + ['dc:date', 'date'],
33 + ['dc:language', 'language'],
34 + ['dc:rights', 'rights'],
35 + ['dc:source', 'source'],
36 + ['dc:title', 'title'],
37 + 'title',
38 + 'link',
39 + 'pubDate',
40 + 'author',
41 + 'content:encoded',
42 + 'enclosure',
43 + 'dc:creator',
44 + 'dc:date',
45 + 'comments',
46 +];
47 +
48 +var mapItunesField = function(f) {
49 + return ['itunes:' + f, f];
50 +}
51 +
52 +fields.podcastFeed = ([
53 + 'author',
54 + 'subtitle',
55 + 'summary',
56 + 'explicit'
57 +]).map(mapItunesField);
58 +
59 +fields.podcastItem = ([
60 + 'author',
61 + 'subtitle',
62 + 'summary',
63 + 'explicit',
64 + 'duration',
65 + 'image',
66 + 'episode',
67 + 'image',
68 + 'season',
69 + 'keywords',
70 +]).map(mapItunesField);
71 +
1 +"use strict";
2 +const http = require('http');
3 +const https = require('https');
4 +const xml2js = require('xml2js');
5 +const url = require('url');
6 +
7 +const fields = require('./fields');
8 +const utils = require('./utils');
9 +
10 +const DEFAULT_HEADERS = {
11 + 'User-Agent': 'rss-parser',
12 + 'Accept': 'application/rss+xml',
13 +}
14 +const DEFAULT_MAX_REDIRECTS = 5;
15 +
16 +class Parser {
17 + constructor(options={}) {
18 + options.headers = options.headers || {};
19 + options.xml2js = options.xml2js || {};
20 + options.customFields = options.customFields || {};
21 + options.customFields.item = options.customFields.item || [];
22 + options.customFields.feed = options.customFields.feed || [];
23 + if (!options.maxRedirects) options.maxRedirects = DEFAULT_MAX_REDIRECTS;
24 + this.options = options;
25 + this.xmlParser = new xml2js.Parser(this.options.xml2js);
26 + }
27 +
28 + parseString(xml, callback) {
29 + let prom = new Promise((resolve, reject) => {
30 + this.xmlParser.parseString(xml, (err, result) => {
31 + if (err) return reject(err);
32 + if (!result) {
33 + return reject(new Error('Unable to parse XML.'));
34 + }
35 + let feed = null;
36 + if (result.feed) {
37 + feed = this.buildAtomFeed(result);
38 + } else if (result.rss && result.rss.$ && result.rss.$.version && result.rss.$.version.match(/^2/)) {
39 + feed = this.buildRSS2(result);
40 + } else if (result['rdf:RDF']) {
41 + feed = this.buildRSS1(result);
42 + } else if (result.rss && result.rss.$ && result.rss.$.version && result.rss.$.version.match(/0\.9/)) {
43 + feed = this.buildRSS0_9(result);
44 + } else if (result.rss && this.options.defaultRSS) {
45 + switch(this.options.defaultRSS) {
46 + case 0.9:
47 + feed = this.buildRSS0_9(result);
48 + break;
49 + case 1:
50 + feed = this.buildRSS1(result);
51 + break;
52 + case 2:
53 + feed = this.buildRSS2(result);
54 + break;
55 + default:
56 + return reject(new Error("default RSS version not recognized."))
57 + }
58 + } else {
59 + return reject(new Error("Feed not recognized as RSS 1 or 2."))
60 + }
61 + resolve(feed);
62 + });
63 + });
64 + prom = utils.maybePromisify(callback, prom);
65 + return prom;
66 + }
67 +
68 + parseURL(feedUrl, callback, redirectCount=0) {
69 + let xml = '';
70 + let get = feedUrl.indexOf('https') === 0 ? https.get : http.get;
71 + let urlParts = url.parse(feedUrl);
72 + let headers = Object.assign({}, DEFAULT_HEADERS, this.options.headers);
73 + let prom = new Promise((resolve, reject) => {
74 + let req = get({
75 + headers,
76 + auth: urlParts.auth,
77 + protocol: urlParts.protocol,
78 + hostname: urlParts.hostname,
79 + port: urlParts.port,
80 + path: urlParts.path,
81 + }, (res) => {
82 + if (this.options.maxRedirects && res.statusCode >= 300 && res.statusCode < 400 && res.headers['location']) {
83 + if (redirectCount === this.options.maxRedirects) {
84 + return reject(new Error("Too many redirects"));
85 + } else {
86 + return this.parseURL(res.headers['location'], null, redirectCount + 1).then(resolve, reject);
87 + }
88 + } else if (res.statusCode >= 300) {
89 + return reject(new Error("Status code " + res.statusCode))
90 + }
91 + let encoding = utils.getEncodingFromContentType(res.headers['content-type']);
92 + res.setEncoding(encoding);
93 + res.on('data', (chunk) => {
94 + xml += chunk;
95 + });
96 + res.on('end', () => {
97 + return this.parseString(xml).then(resolve, reject);
98 + });
99 + })
100 + req.on('error', reject);
101 + });
102 + prom = utils.maybePromisify(callback, prom);
103 + return prom;
104 + }
105 +
106 + buildAtomFeed(xmlObj) {
107 + let feed = {items: []};
108 + utils.copyFromXML(xmlObj.feed, feed, this.options.customFields.feed);
109 + if (xmlObj.feed.link) {
110 + feed.link = utils.getLink(xmlObj.feed.link, 'alternate', 0);
111 + feed.feedUrl = utils.getLink(xmlObj.feed.link, 'self', 1);
112 + }
113 + if (xmlObj.feed.title) {
114 + let title = xmlObj.feed.title[0] || '';
115 + if (title._) title = title._
116 + if (title) feed.title = title;
117 + }
118 + if (xmlObj.feed.updated) {
119 + feed.lastBuildDate = xmlObj.feed.updated[0];
120 + }
121 + (xmlObj.feed.entry || []).forEach(entry => {
122 + let item = {};
123 + utils.copyFromXML(entry, item, this.options.customFields.item);
124 + if (entry.title) {
125 + let title = entry.title[0] || '';
126 + if (title._) title = title._;
127 + if (title) item.title = title;
128 + }
129 + if (entry.link && entry.link.length) {
130 + item.link = utils.getLink(entry.link, 'alternate', 0);
131 + }
132 + if (entry.published && entry.published.length && entry.published[0].length) item.pubDate = new Date(entry.published[0]).toISOString();
133 + if (!item.pubDate && entry.updated && entry.updated.length && entry.updated[0].length) item.pubDate = new Date(entry.updated[0]).toISOString();
134 + if (entry.author && entry.author.length) item.author = entry.author[0].name[0];
135 + if (entry.content && entry.content.length) {
136 + item.content = utils.getContent(entry.content[0]);
137 + item.contentSnippet = utils.getSnippet(item.content)
138 + }
139 + if (entry.id) {
140 + item.id = entry.id[0];
141 + }
142 + this.setISODate(item);
143 + feed.items.push(item);
144 + });
145 + return feed;
146 + }
147 +
148 + buildRSS0_9(xmlObj) {
149 + var channel = xmlObj.rss.channel[0];
150 + var items = channel.item;
151 + return this.buildRSS(channel, items);
152 + }
153 +
154 + buildRSS1(xmlObj) {
155 + xmlObj = xmlObj['rdf:RDF'];
156 + let channel = xmlObj.channel[0];
157 + let items = xmlObj.item;
158 + return this.buildRSS(channel, items);
159 + }
160 +
161 + buildRSS2(xmlObj) {
162 + let channel = xmlObj.rss.channel[0];
163 + let items = channel.item;
164 + let feed = this.buildRSS(channel, items);
165 + if (xmlObj.rss.$ && xmlObj.rss.$['xmlns:itunes']) {
166 + this.decorateItunes(feed, channel);
167 + }
168 + return feed;
169 + }
170 +
171 + buildRSS(channel, items) {
172 + items = items || [];
173 + let feed = {items: []};
174 + let feedFields = fields.feed.concat(this.options.customFields.feed);
175 + let itemFields = fields.item.concat(this.options.customFields.item);
176 + if (channel['atom:link']) feed.feedUrl = channel['atom:link'][0].$.href;
177 + if (channel.image && channel.image[0] && channel.image[0].url) {
178 + feed.image = {};
179 + let image = channel.image[0];
180 + if (image.link) feed.image.link = image.link[0];
181 + if (image.url) feed.image.url = image.url[0];
182 + if (image.title) feed.image.title = image.title[0];
183 + if (image.width) feed.image.width = image.width[0];
184 + if (image.height) feed.image.height = image.height[0];
185 + }
186 + utils.copyFromXML(channel, feed, feedFields);
187 + items.forEach(xmlItem => {
188 + let item = {};
189 + utils.copyFromXML(xmlItem, item, itemFields);
190 + if (xmlItem.enclosure) {
191 + item.enclosure = xmlItem.enclosure[0].$;
192 + }
193 + if (xmlItem.description) {
194 + item.content = utils.getContent(xmlItem.description[0]);
195 + item.contentSnippet = utils.getSnippet(item.content);
196 + }
197 + if (xmlItem.guid) {
198 + item.guid = xmlItem.guid[0];
199 + if (item.guid._) item.guid = item.guid._;
200 + }
201 + if (xmlItem.category) item.categories = xmlItem.category;
202 + this.setISODate(item);
203 + feed.items.push(item);
204 + });
205 + return feed;
206 + }
207 +
208 + /**
209 + * Add iTunes specific fields from XML to extracted JSON
210 + *
211 + * @access public
212 + * @param {object} feed extracted
213 + * @param {object} channel parsed XML
214 + */
215 + decorateItunes(feed, channel) {
216 + let items = channel.item || [],
217 + entry = {};
218 + feed.itunes = {}
219 +
220 + if (channel['itunes:owner']) {
221 + let owner = {},
222 + image;
223 +
224 + if(channel['itunes:owner'][0]['itunes:name']) {
225 + owner.name = channel['itunes:owner'][0]['itunes:name'][0];
226 + }
227 + if(channel['itunes:owner'][0]['itunes:email']) {
228 + owner.email = channel['itunes:owner'][0]['itunes:email'][0];
229 + }
230 + if(channel['itunes:image']) {
231 + let hasImageHref = (channel['itunes:image'][0] &&
232 + channel['itunes:image'][0].$ &&
233 + channel['itunes:image'][0].$.href);
234 + image = hasImageHref ? channel['itunes:image'][0].$.href : null;
235 + }
236 +
237 + if(image) {
238 + feed.itunes.image = image;
239 + }
240 + feed.itunes.owner = owner;
241 + }
242 +
243 + utils.copyFromXML(channel, feed.itunes, fields.podcastFeed);
244 + items.forEach((item, index) => {
245 + let entry = feed.items[index];
246 + entry.itunes = {};
247 + utils.copyFromXML(item, entry.itunes, fields.podcastItem);
248 + let image = item['itunes:image'];
249 + if (image && image[0] && image[0].$ && image[0].$.href) {
250 + entry.itunes.image = image[0].$.href;
251 + }
252 + });
253 + }
254 +
255 + setISODate(item) {
256 + let date = item.pubDate || item.date;
257 + if (date) {
258 + try {
259 + item.isoDate = new Date(date.trim()).toISOString();
260 + } catch (e) {
261 + // Ignore bad date format
262 + }
263 + }
264 + }
265 +}
266 +
267 +module.exports = Parser;
1 +const utils = module.exports = {};
2 +const entities = require('entities');
3 +const xml2js = require('xml2js');
4 +
5 +utils.stripHtml = function(str) {
6 + return str.replace(/<(?:.|\n)*?>/gm, '');
7 +}
8 +
9 +utils.getSnippet = function(str) {
10 + return entities.decode(utils.stripHtml(str)).trim();
11 +}
12 +
13 +utils.getLink = function(links, rel, fallbackIdx) {
14 + if (!links) return;
15 + for (let i = 0; i < links.length; ++i) {
16 + if (links[i].$.rel === rel) return links[i].$.href;
17 + }
18 + if (links[fallbackIdx]) return links[fallbackIdx].$.href;
19 +}
20 +
21 +utils.getContent = function(content) {
22 + if (typeof content._ === 'string') {
23 + return content._;
24 + } else if (typeof content === 'object') {
25 + let builder = new xml2js.Builder({headless: true, explicitRoot: true, rootName: 'div', renderOpts: {pretty: false}});
26 + return builder.buildObject(content);
27 + } else {
28 + return content;
29 + }
30 +}
31 +
32 +utils.copyFromXML = function(xml, dest, fields) {
33 + fields.forEach(function(f) {
34 + let from = f;
35 + let to = f;
36 + let options = {};
37 + if (Array.isArray(f)) {
38 + from = f[0];
39 + to = f[1];
40 + if (f.length > 2) {
41 + options = f[2];
42 + }
43 + }
44 + const { keepArray } = options;
45 + if (xml[from] !== undefined)
46 + dest[to] = keepArray ? xml[from] : xml[from][0];
47 + })
48 +}
49 +
50 +utils.maybePromisify = function(callback, promise) {
51 + if (!callback) return promise;
52 + return promise.then(
53 + data => setTimeout(() => callback(null, data)),
54 + err => setTimeout(() => callback(err))
55 + );
56 +}
57 +
58 +const DEFAULT_ENCODING = 'utf8';
59 +const ENCODING_REGEX = /(encoding|charset)\s*=\s*(\S+)/;
60 +const SUPPORTED_ENCODINGS = ['ascii', 'utf8', 'utf16le', 'ucs2', 'base64', 'latin1', 'binary', 'hex'];
61 +const ENCODING_ALIASES = {
62 + 'utf-8': 'utf8',
63 + 'iso-8859-1': 'latin1',
64 +}
65 +
66 +utils.getEncodingFromContentType = function(contentType) {
67 + contentType = contentType || '';
68 + let match = contentType.match(ENCODING_REGEX);
69 + let encoding = (match || [])[2] || '';
70 + encoding = encoding.toLowerCase();
71 + encoding = ENCODING_ALIASES[encoding] || encoding;
72 + if (!encoding || SUPPORTED_ENCODINGS.indexOf(encoding) === -1) {
73 + encoding = DEFAULT_ENCODING;
74 + }
75 + return encoding;
76 +}
1 +{
2 + "_from": "rss-parser",
3 + "_id": "rss-parser@3.5.4",
4 + "_inBundle": false,
5 + "_integrity": "sha512-dC7wHtz/p8QWQnsGgCB+HEYE01Dk8/AHMzSk0ZvoV3S0mhBqQNO/yi3H2fPh3qV2NNLNNEBg+8ZDSipKxjR5tQ==",
6 + "_location": "/rss-parser",
7 + "_phantomChildren": {},
8 + "_requested": {
9 + "type": "tag",
10 + "registry": true,
11 + "raw": "rss-parser",
12 + "name": "rss-parser",
13 + "escapedName": "rss-parser",
14 + "rawSpec": "",
15 + "saveSpec": null,
16 + "fetchSpec": "latest"
17 + },
18 + "_requiredBy": [
19 + "#USER",
20 + "/"
21 + ],
22 + "_resolved": "https://registry.npmjs.org/rss-parser/-/rss-parser-3.5.4.tgz",
23 + "_shasum": "3b267d96c57bdc22ff5cc847ef9bcd3dce4ae2cc",
24 + "_spec": "rss-parser",
25 + "_where": "C:\\Users\\정민채\\Desktop\\TermProject\\2017104024정민혁KakaoBot",
26 + "author": {
27 + "name": "Bobby Brennan"
28 + },
29 + "bugs": {
30 + "url": "https://github.com/bobby-brennan/rss-parser/issues"
31 + },
32 + "bundleDependencies": false,
33 + "dependencies": {
34 + "entities": "^1.1.1",
35 + "xml2js": "^0.4.19"
36 + },
37 + "deprecated": false,
38 + "description": "A lightweight RSS parser, for Node and the browser",
39 + "devDependencies": {
40 + "@types/xml2js": "^0.4.3",
41 + "babel-core": "^6.26.3",
42 + "babel-loader": "^7.1.5",
43 + "babel-preset-env": "^1.7.0",
44 + "chai": "^3.4.1",
45 + "express": "^4.16.3",
46 + "mocha": "^5.2.0",
47 + "puppeteer": "^1.8.0",
48 + "webpack": "^3.12.0"
49 + },
50 + "directories": {
51 + "test": "test"
52 + },
53 + "homepage": "https://github.com/bobby-brennan/rss-parser#readme",
54 + "keywords": [
55 + "RSS",
56 + "RSS to JSON",
57 + "RSS reader",
58 + "RSS parser",
59 + "RSS to JS",
60 + "Feed reader"
61 + ],
62 + "license": "MIT",
63 + "main": "index.js",
64 + "name": "rss-parser",
65 + "repository": {
66 + "type": "git",
67 + "url": "git+https://github.com/bobby-brennan/rss-parser.git"
68 + },
69 + "scripts": {
70 + "build": "./scripts/build.sh",
71 + "test": "mocha --exit"
72 + },
73 + "types": "index.d.ts",
74 + "version": "3.5.4"
75 +}
1 +set -e
2 +webpack
3 +cp dist/rss-parser.min.js dist/rss-parser.js
4 +webpack -p
1 +"use strict";
2 +
3 +const express = require('express');
4 +const expect = require('chai').expect;
5 +const Browser = require('puppeteer');
6 +
7 +let browser = null;
8 +let page = null;
9 +
10 +const PORT = 3333;
11 +const PARSE_TIMEOUT = 1000;
12 +
13 +describe('Browser', function() {
14 + if (process.env.SKIP_BROWSER_TESTS) {
15 + console.log('skipping browser tests');
16 + return;
17 + }
18 +
19 + before(function(done) {
20 + this.timeout(5000);
21 + let app = express();
22 + app.use(express.static(__dirname));
23 + app.use('/dist', express.static(__dirname + '/../dist'));
24 + app.listen(PORT, err => {
25 + if (err) return done(err);
26 + Browser.launch({args: ['--no-sandbox']})
27 + .then(b => browser = b)
28 + .then(_ => browser.newPage())
29 + .then(p => {
30 + page = p;
31 + return page.goto('http://localhost:3333/index.html');
32 + })
33 + .then(_ => done())
34 + .catch(e => done(e));
35 + });
36 + });
37 +
38 + after(() => browser.close());
39 +
40 + it('should have window.RSSParser', () => {
41 + return page.evaluate(() => {
42 + return typeof window.RSSParser;
43 + }).then(type => {
44 + expect(type).to.equal('function');
45 + })
46 + });
47 +
48 + it('should parse reddit', function() {
49 + this.timeout(PARSE_TIMEOUT + 1000);
50 + return page.evaluate(() => {
51 + var parser = new RSSParser();
52 + parser.parseURL('http://localhost:3333/input/reddit.rss', function(err, data) {
53 + window.error = err;
54 + window.reddit = data;
55 + })
56 + })
57 + .then(_ => {
58 + return new Promise(resolve => setTimeout(resolve, PARSE_TIMEOUT))
59 + })
60 + .then(_ => page.evaluate(() => {
61 + return window.error;
62 + }))
63 + .then(err => {
64 + expect(err).to.equal(null);
65 + })
66 + .then(_ => page.evaluate(() => {
67 + return window.reddit.title;
68 + }))
69 + .then(title => {
70 + expect(title).to.equal('reddit: the front page of the internet');
71 + })
72 + })
73 +})
1 +<script src="dist/rss-parser.min.js"></script>
2 +
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<feed xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xml:lang="en-US">
3 + <id>tag:github.com,2008:https://github.com/gulpjs/gulp/releases</id>
4 + <link type="text/html" rel="alternate" href="https://github.com/gulpjs/gulp/releases"/>
5 + <link type="application/atom+xml" rel="self" href="https://github.com/gulpjs/gulp/releases.atom"/>
6 + <title>Release notes from gulp</title>
7 + <updated>2015-06-01T23:49:41+02:00</updated>
8 + <entry>
9 + <id>tag:github.com,2008:Repository/11167738/v3.9.0</id>
10 + <updated>2015-06-01T23:49:41+02:00</updated>
11 + <link rel="alternate" type="text/html" href="/gulpjs/gulp/releases/tag/v3.9.0"/>
12 + <title>v3.9.0</title>
13 + <content type="html">&lt;p&gt;3.9.0&lt;/p&gt;</content>
14 + <author>
15 + <name>contra</name>
16 + </author>
17 + <media:thumbnail height="30" width="30" url="https://avatars3.githubusercontent.com/u/425716?v=3&amp;s=60"/>
18 + </entry>
19 + <entry>
20 + <id>tag:github.com,2008:Repository/11167738/v3.8.11</id>
21 + <updated>2015-02-09T21:37:28+01:00</updated>
22 + <link rel="alternate" type="text/html" href="/gulpjs/gulp/releases/tag/v3.8.11"/>
23 + <title>v3.8.11</title>
24 + <content type="html">&lt;p&gt;3.8.11&lt;/p&gt;</content>
25 + <author>
26 + <name>contra</name>
27 + </author>
28 + <media:thumbnail height="30" width="30" url="https://avatars3.githubusercontent.com/u/425716?v=3&amp;s=60"/>
29 + </entry>
30 + <entry>
31 + <id>tag:github.com,2008:Repository/11167738/v3.8.10</id>
32 + <updated>2014-11-04T01:11:30+01:00</updated>
33 + <link rel="alternate" type="text/html" href="/gulpjs/gulp/releases/tag/v3.8.10"/>
34 + <title>v3.8.10</title>
35 + <content type="html">&lt;p&gt;3.8.10&lt;/p&gt;</content>
36 + <author>
37 + <name>contra</name>
38 + </author>
39 + <media:thumbnail height="30" width="30" url="https://avatars3.githubusercontent.com/u/425716?v=3&amp;s=60"/>
40 + </entry>
41 + <entry>
42 + <id>tag:github.com,2008:Repository/11167738/v3.8.9</id>
43 + <updated>2014-10-22T08:55:20+02:00</updated>
44 + <link rel="alternate" type="text/html" href="/gulpjs/gulp/releases/tag/v3.8.9"/>
45 + <title>v3.8.9</title>
46 + <content type="html">&lt;p&gt;3.8.9&lt;/p&gt;</content>
47 + <author>
48 + <name>contra</name>
49 + </author>
50 + <media:thumbnail height="30" width="30" url="https://avatars3.githubusercontent.com/u/425716?v=3&amp;s=60"/>
51 + </entry>
52 + <entry>
53 + <id>tag:github.com,2008:Repository/11167738/v3.8.8</id>
54 + <updated>2014-09-07T22:20:11+02:00</updated>
55 + <link rel="alternate" type="text/html" href="/gulpjs/gulp/releases/tag/v3.8.8"/>
56 + <title>v3.8.8</title>
57 + <content type="html">&lt;p&gt;3.8.8&lt;/p&gt;</content>
58 + <author>
59 + <name>contra</name>
60 + </author>
61 + <media:thumbnail height="30" width="30" url="https://avatars3.githubusercontent.com/u/425716?v=3&amp;s=60"/>
62 + </entry>
63 + <entry>
64 + <id>tag:github.com,2008:Repository/11167738/v3.8.7</id>
65 + <updated>2014-08-02T06:58:19+02:00</updated>
66 + <link rel="alternate" type="text/html" href="/gulpjs/gulp/releases/tag/v3.8.7"/>
67 + <title>v3.8.7</title>
68 + <content type="html">&lt;p&gt;3.8.7&lt;/p&gt;</content>
69 + <author>
70 + <name>contra</name>
71 + </author>
72 + <media:thumbnail height="30" width="30" url="https://avatars3.githubusercontent.com/u/425716?v=3&amp;s=60"/>
73 + </entry>
74 + <entry>
75 + <id>tag:github.com,2008:Repository/11167738/v3.8.6</id>
76 + <updated>2014-07-10T00:06:50+02:00</updated>
77 + <link rel="alternate" type="text/html" href="/gulpjs/gulp/releases/tag/v3.8.6"/>
78 + <title>v3.8.6</title>
79 + <content type="html">&lt;p&gt;3.8.6&lt;/p&gt;</content>
80 + <author>
81 + <name>contra</name>
82 + </author>
83 + <media:thumbnail height="30" width="30" url="https://avatars3.githubusercontent.com/u/425716?v=3&amp;s=60"/>
84 + </entry>
85 + <entry>
86 + <id>tag:github.com,2008:Repository/11167738/v3.8.5</id>
87 + <updated>2014-06-27T08:53:54+02:00</updated>
88 + <link rel="alternate" type="text/html" href="/gulpjs/gulp/releases/tag/v3.8.5"/>
89 + <title>v3.8.5</title>
90 + <content type="html">&lt;p&gt;3.8.5&lt;/p&gt;</content>
91 + <author>
92 + <name>contra</name>
93 + </author>
94 + <media:thumbnail height="30" width="30" url="https://avatars3.githubusercontent.com/u/425716?v=3&amp;s=60"/>
95 + </entry>
96 + <entry>
97 + <id>tag:github.com,2008:Repository/11167738/v3.8.4</id>
98 + <updated>2014-06-27T08:38:43+02:00</updated>
99 + <link rel="alternate" type="text/html" href="/gulpjs/gulp/releases/tag/v3.8.4"/>
100 + <title>v3.8.4</title>
101 + <content type="html">&lt;p&gt;3.8.4&lt;/p&gt;</content>
102 + <author>
103 + <name>contra</name>
104 + </author>
105 + <media:thumbnail height="30" width="30" url="https://avatars3.githubusercontent.com/u/425716?v=3&amp;s=60"/>
106 + </entry>
107 + <entry>
108 + <id>tag:github.com,2008:Repository/11167738/v3.8.3</id>
109 + <updated>2014-06-26T23:17:51+02:00</updated>
110 + <link rel="alternate" type="text/html" href="/gulpjs/gulp/releases/tag/v3.8.3"/>
111 + <title>v3.8.3</title>
112 + <content type="html">&lt;p&gt;3.8.3&lt;/p&gt;</content>
113 + <author>
114 + <name>contra</name>
115 + </author>
116 + <media:thumbnail height="30" width="30" url="https://avatars3.githubusercontent.com/u/425716?v=3&amp;s=60"/>
117 + </entry>
118 +</feed>
This diff is collapsed. Click to expand it.
1 +<?xml version="1.0" encoding="ISO-8859-1" ?>
2 +<rss version="0.92">
3 +<channel>
4 + <title>RSS0.92 Example</title>
5 + <link>http://www.oreilly.com/example/index.html</link>
6 + <description>This is an example RSS0.91 feed</description>
7 + <language>en-gb</language>
8 + <copyright>Copyright 2002, Oreilly and Associates.</copyright>
9 + <managingEditor>editor@oreilly.com</managingEditor>
10 + <webMaster>webmaster@oreilly.com</webMaster>
11 + <rating>5</rating>
12 + <pubDate>03 Apr 02 1500 GMT</pubDate>
13 + <lastBuildDate>03 Apr 02 1500 GMT</lastBuildDate>
14 + <item>
15 + <title>The First Item</title>
16 + <link>http://www.oreilly.com/example/001.html</link>
17 + <description>This is the first item.</description>
18 + <source url="http://www.anothersite.com/index.xml">Another Site</source>
19 + <enclosure url="http://www.oreilly.com/001.mp3" length="54321" type="audio/mpeg"/>
20 + <category domain="http://www.dmoz.org">Business/Industries/Publishing/Publishers/Nonfiction/</category>
21 + </item>
22 + <item>
23 + <title>The Second Item</title>
24 + <link>http://www.oreilly.com/example/002.html</link>
25 + <description>This is the second item.</description>
26 + <source url="http://www.anothersite.com/index.xml">Another Site</source>
27 + <enclosure url="http://www.oreilly.com/002.mp3" length="54321" type="audio/mpeg"/>
28 + <category domain="http://www.dmoz.org">Business/Industries/Publishing/Publishers/Nonfiction/</category>
29 + </item>
30 +</channel>
31 +</rss>
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
3 + <channel>
4 + <title>Instant Article Test</title>
5 + <link>https://localhost:8000</link>
6 + <description>1, 2, 1, 2… check the mic!</description>
7 + <language>en</language>
8 + <pubDate>Fri, 13 May 2016 15:14:05 GMT</pubDate>
9 + <dc:date>2016-05-13T15:14:05Z</dc:date>
10 + <dc:language>en</dc:language>
11 + <item>
12 + <title>My first Instant Article</title>
13 + <link>https://localhost:8000</link>
14 + <description>Lorem ipsum</description>
15 + <content:encoded>&lt;b&gt;Lorem&lt;/b&gt; ipsum</content:encoded>
16 + <pubDate>Wed, 04 May 2016 06:53:45 GMT</pubDate>
17 + <guid>https://localhost:8000</guid>
18 + <dc:creator>tobi</dc:creator>
19 + <dc:date>2016-05-04T06:53:45Z</dc:date>
20 + </item>
21 + </channel>
22 +</rss>
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<feed xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xml:lang="en-US">
3 + <entry>
4 + <id>tag:github.com,2008:Repository/11167738/v3.9.0</id>
5 + </entry>
6 +</feed>
1 +<?xml version="1.0" encoding="UTF-8"?>
2 +<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" version="2.0">
3 + <channel>
4 + <title>foobar on Narro</title>
5 + <link>http://on.narro.co/f</link>
6 + <description>foobar uses Narro to create a podcast of articles transcribed to audio.</description>
7 + <language>en</language>
8 + <copyright>All article content copyright of respective source authors.</copyright>
9 + <managingEditor>foobar@gmail.com</managingEditor>
10 + <webMaster>josh@narro.co</webMaster>
11 + <pubDate>Fri, 08 Jul 2016 13:40:00 UTC</pubDate>
12 + <generator>gopod - http://github.com/jbckmn/gopod</generator>
13 + <ttl>20</ttl>
14 + <itunes:author>foobar@gmail.com</itunes:author>
15 + <itunes:subtitle>foobar uses Narro to create a podcast of articles transcribed to audio.</itunes:subtitle>
16 + <itunes:summary>foobar uses Narro to create a podcast of articles transcribed to audio.</itunes:summary>
17 + <itunes:explicit>no</itunes:explicit>
18 + <itunes:owner>
19 + <itunes:name>foobar</itunes:name>
20 + <itunes:email>foobar@gmail.com</itunes:email>
21 + </itunes:owner>
22 + <itunes:image href="https://www.narro.co/images/narro-icon-lg.png"></itunes:image>
23 + <atom:link href="http://on.narro.co/f" rel="self" type="application/rss+xml"></atom:link>
24 + <item>
25 + <link>https://www.narro.co/article/54e703933058540300000069</link>
26 + <description>Listen to your reading list anywhere. Narro will take your bookmarked articles and read them back to you as a podcast.&lt;br/&gt; http://www.narro.co/faq&lt;br/&gt; &lt;ul class=&#34;linkList&#34;&gt;&lt;/ul&gt;</description>
27 + <title>FAQ for Narro</title>
28 + <pubDate>Fri, 20 Feb 2015 09:51:15 UTC</pubDate>
29 + <author>foobar@gmail.com</author>
30 + <guid>https://www.narro.co/article/54e703933058540300000069</guid>
31 + <itunes:author>foobar@gmail.com</itunes:author>
32 + <itunes:subtitle>FAQ for Narro</itunes:subtitle>
33 + <itunes:summary>Listen to your reading list anywhere. Narro will take your bookmarked articles and read them back to you as a podcast. ... http://www.narro.co/faq ... &lt;ul class=&#34;linkList&#34;&gt;&lt;/ul&gt;</itunes:summary>
34 + <itunes:explicit>no</itunes:explicit>
35 + <itunes:duration>74</itunes:duration>
36 + <itunes:image href="http://example.com/someImage.jpg"/>
37 + <enclosure url="https://s3.amazonaws.com/nareta-articles/audio/54d046c293f79c0300000003/7e2d2b00-a945-441a-f49b-063786a319a4.mp3" length="74" type="audio/mpeg"></enclosure>
38 + </item>
39 + </channel>
40 +</rss>
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
1 +<head><title>Document Moved</title></head>
2 +<body><h1>Object Moved</h1>This document may be found <a HREF="http://fishhawk2.marketwatch.com/rss/pf/">here</a></body>
...\ No newline at end of file ...\ No newline at end of file
1 +<rss>
2 + <channel>
3 + <title>UOL Noticias</title>
4 + <link>http://noticias.uol.com.br/</link>
5 + <description>Últimas Notícias</description>
6 + <language></language>
7 + <category>Notícias</category>
8 + <copyright></copyright>
9 + <image>
10 + <title>UOL Noticias - Últimas Notícias</title>
11 + <url>http://rss.i.uol.com.br/uol_rss.gif</url>
12 + <link>http://noticias.uol.com.br/ultimas/</link>
13 + </image>
14 + <item>
15 + <title><![CDATA[Ibope: Bolsonaro perde de Haddad, Ciro e Alckmin em simulações de 2º turno]]></title>
16 + <link><![CDATA[https://noticias.uol.com.br/politica/eleicoes/2018/noticias/2018/09/24/ibope-bolsonaro-perde-de-haddad-ciro-e-alckmin-em-simulacoes-de-2-turno.htm]]></link>
17 + <description><![CDATA[<img src='https://conteudo.imguol.com.br/c/noticias/5f/2018/09/17/presidenciaveis-1537211917356_142x100.jpg' align="left" /> Líder na pesquisa Ibope de intenção de voto para o primeiro turno divulgada nesta segunda-feira (24), o candidato do PSL a presidente, Jair Bolsonaro, não tem o mesmo desempenho nas simulações de segundo turno feitas pela empresa no mesmo levantamento. ]]></description>
18 + <pubDate>Seg, 24 Set 2018 19:42:40 -0300</pubDate>
19 + </item>
20 + <item>
21 + <title><![CDATA[Promotoria abre inquérito para apurar suspeita de improbidade de Skaf no Sebrae-SP]]></title>
22 + <link><![CDATA[https://www1.folha.uol.com.br/poder/2018/09/promotoria-abre-inquerito-para-apurar-suspeita-de-improbidade-de-skaf-no-sebrae-sp.shtml]]></link>
23 + <description></description>
24 + <pubDate>Seg, 24 Set 2018 19:38:00 -0300</pubDate>
25 + </item>
26 + <item>
27 + <title><![CDATA[Apucarana garante continuidade do Pré Aprendiz; ano vai fechar com 13 mil pessoas qualificadas]]></title>
28 + <link><![CDATA[https://tnonline.uol.com.br/noticias/apucarana/45,470927,24,09,apucarana-garante-continuidade-do-pre-aprendiz-ano-vai-fechar-com-13-mil-pessoas-qualificadas]]></link>
29 + <description><![CDATA[<img src='https://m1.tnonline.com.br/entre/2018/09/24/tn_4017f330b2_preapre.jpg' align="left" /> Programa Pré Aprendiz, que é realizado pela Secretaria Municipal de Assistência Social de Apucarana em parceria com o Serviço Social do Comércio (Sesc), terá continuidade em 2019. O termo de renovaç... ]]></description>
30 + <pubDate>Seg, 24 Set 2018 19:35:07 -0300</pubDate>
31 + </item>
32 + <item>
33 + <title><![CDATA[Dow Jones fecha em baixa de 0,68%]]></title>
34 + <link><![CDATA[https://economia.uol.com.br/noticias/efe/2018/09/24/dow-jones-fecha-em-baixa-de-068.htm]]></link>
35 + <description><![CDATA[ Nova York, 24 set (EFE).- O índice Dow Jones Industrial fechou nesta segunda-feira em baixa de 0,68% em mais um pregão marcado pela disputa comercial entre Estados Unidos e China e por especulações sobre a possível renúncia de Rod Rosenstein ao cargo de procurador-geral adjunto dos Estados Unidos. ]]></description>
36 + <pubDate>Seg, 24 Set 2018 19:32:00 -0300</pubDate>
37 + </item>
38 + <item>
39 + <title><![CDATA[Rival de Putin é condenado a mais 20 dias de prisão]]></title>
40 + <link><![CDATA[https://noticias.uol.com.br/ultimas-noticias/ansa/2018/09/24/rival-de-putin-e-condenado-a-mais-20-dias-de-prisao.htm]]></link>
41 + <description><![CDATA[ MOSCOU, 24 SET (ANSA) - O líder de oposição russo Alexei Navalny foi condenado na noite desta segunda-feira (24) a mais 20 dias de prisão por organizar manifestações não autorizadas contra o governo de Vladimir Putin, informou a mídia russa. Navalny foi preso nesta manhã pouco tempo depois de ser libertado da cadeia após cumprir outra sentença de 30 dias.    ]]></description>
42 + <pubDate>Seg, 24 Set 2018 19:32:00 -0300</pubDate>
43 + </item>
44 + <item>
45 + <title><![CDATA[Em entrevista, Bolsonaro chama proposta de Paulo Guedes para imposto de renda de "ousada"]]></title>
46 + <link><![CDATA[https://noticias.uol.com.br/ultimas-noticias/reuters/2018/09/24/em-entrevista-bolsonaro-chama-proposta-de-paulo-guedes-para-imposto-de-renda-de-ousada.htm]]></link>
47 + <description><![CDATA[ BRASÍLIA (Reuters) - O candidato do PSL à Presidência, Jair Bolsonaro, classificou nesta segunda-feira a proposta do seu principal assessor econômico, Paulo Guedes, para a mudança na forma de cobrança do imposto de renda para pessoa física de "ousada". ]]></description>
48 + <pubDate>Seg, 24 Set 2018 19:30:42 -0300</pubDate>
49 + </item>
50 + <item>
51 + <title><![CDATA[Relatório do governo dos EUA acusa militares de Mianmar de atrocidades contra muçulmanos rohingyas]]></title>
52 + <link><![CDATA[https://noticias.uol.com.br/ultimas-noticias/reuters/2018/09/24/relatorio-do-governo-dos-eua-acusa-militares-de-mianmar-de-atrocidades-contra-muculmanos-rohingyas.htm]]></link>
53 + <description><![CDATA[ Por Matt Spetalnick e Jason Szep ]]></description>
54 + <pubDate>Seg, 24 Set 2018 19:29:18 -0300</pubDate>
55 + </item>
56 + <item>
57 + <title><![CDATA[Enfermeira de Chávez alega 'perseguição' em Corte espanhola]]></title>
58 + <link><![CDATA[https://noticias.uol.com.br/ultimas-noticias/ansa/2018/09/24/enfermeira-de-chavez-alega-perseguicao-em-corte-espanhola.htm]]></link>
59 + <description><![CDATA[ MADRI, 24 SET (ANSA) - A ex-enfermeira do falecido Hugo Chávez, ex-presidente venezuelano, prestou depoimento hoje (24) na Corte Nacional da Espanha e alegou sofrer perseguiç... ]]></description>
60 + <pubDate>Seg, 24 Set 2018 19:25:00 -0300</pubDate>
61 + </item>
62 + <item>
63 + <title><![CDATA[Match Eleitoral já soma mais de 500 mil testes completos; ache seu candidato]]></title>
64 + <link><![CDATA[https://www1.folha.uol.com.br/poder/2018/09/match-eleitoral-ja-soma-mais-de-500-mil-testes-completos-ache-seu-candidato.shtml]]></link>
65 + <description></description>
66 + <pubDate>Seg, 24 Set 2018 19:22:00 -0300</pubDate>
67 + </item>
68 + <item>
69 + <title><![CDATA[Match Eleitoral já soma mais de 500 mil testes completos; ache seu candidato]]></title>
70 + <link><![CDATA[https://redir.folha.com.br/redir/online/poder/eleicoes-2018/rss091/*https://www1.folha.uol.com.br/poder/2018/09/match-eleitoral-ja-soma-mais-de-500-mil-testes-completos-ache-seu-candidato.shtml]]></link>
71 + <description><![CDATA[ Já são mais de 500 mil testes completos no Match Eleitoral, ferramenta criada pela Folha e pelo Datafolha para ajudar o eleitor a escolher seu deputado federal por São Paulo, Minas Gerais e Rio de Janeiro, além de senadores por São Paulo. Leia mais (09/24/2018 - 19h22) ]]></description>
72 + <pubDate>Seg, 24 Set 2018 19:22:00 -0300</pubDate>
73 + </item>
74 + <item>
75 + <title><![CDATA[Acordo adicional da Argentina com FMI está "perto de acontecer", diz Macri]]></title>
76 + <link><![CDATA[https://www1.folha.uol.com.br/mercado/2018/09/acordo-adicional-da-argentina-com-fmi-esta-perto-de-acontecer-diz-macri.shtml]]></link>
77 + <description></description>
78 + <pubDate>Seg, 24 Set 2018 19:22:00 -0300</pubDate>
79 + </item>
80 + <item>
81 + <title><![CDATA[Fernanda Melchionna: a Primavera Feminista vai derrotar Bolsonaro nas ruas e nas urnas!]]></title>
82 + <link><![CDATA[https://agoraequesaoelas.blogfolha.uol.com.br/?p=1609]]></link>
83 + <description></description>
84 + <pubDate>Seg, 24 Set 2018 19:21:00 -0300</pubDate>
85 + </item>
86 + <item>
87 + <title><![CDATA[Ibope: Bolsonaro estaciona na liderança; Haddad segue avançando]]></title>
88 + <link><![CDATA[https://congressoemfoco.uol.com.br/eleicoes/ibope-bolsonaro-estaciona-na-lideranca-haddad-segue-avancando/]]></link>
89 + <description><![CDATA[<img src='https://static.congressoemfoco.uol.com.br/2018/09/bolsonaro-haddad.jpg' align="left" /> Em nova pesquisa Ibope divulgada nesta segunda-feira (24), o candidato do PSL à Presidência, Jair Bolsonaro, continua líder com 28% das intenções de voto, sem apresentar crescimento em relação à última pesquisa, quando teve a mesma pontuação. O candidato do PT, Fernando Haddad, aproxima-se de Bolsonaro com 22%, uma diferença de 3 pontos percentuais em [?] ]]></description>
90 + <pubDate>Seg, 24 Set 2018 19:20:08 -0300</pubDate>
91 + </item>
92 + <item>
93 + <title><![CDATA[Assange chegou a renunciar a asilo do Equador, segundo carta privada]]></title>
94 + <link><![CDATA[https://noticias.uol.com.br/ultimas-noticias/afp/2018/09/24/assange-chegou-a-renunciar-a-asilo-do-equador-segundo-carta-privada.htm]]></link>
95 + <description><![CDATA[ Quito, 24 Set 2018 (AFP) - O fundador do WikiLeaks, Julian Assange, refugiado na embaixada equatoriana em Londres há seis anos, chegou a renunciar ao asilo concedido por Quito, segundo uma carta assinada por ele em dezembro passado à qual a AFP teve acesso. ]]></description>
96 + <pubDate>Seg, 24 Set 2018 19:20:00 -0300</pubDate>
97 + </item>
98 + <item>
99 + <title><![CDATA[Fama "A" é campeã da Primeira Divisão da Copa Cidade Alta de Futebol Suíço]]></title>
100 + <link><![CDATA[https://tnonline.uol.com.br/noticias/apucarana/45,470926,24,09,fama-a-e-campea-da-primeira-divisao-da-copa-cidade-alta-de-futebol-suico]]></link>
101 + <description><![CDATA[<img src='https://m1.tnonline.com.br/entre/2018/09/24/tn_563c48a591_fama-ajpg.jpg' align="left" /> om a Arena Fama lotada, a equipe da Molas Fama/Multividros "A" foi campeã neste sábado da Primeira Divisão da 10ª edição da Copa Cidade Alta de Futebol Suíço, categoria livre, ao vencer a Estamparia ... ]]></description>
102 + <pubDate>Seg, 24 Set 2018 19:18:49 -0300</pubDate>
103 + </item>
104 +</channel>
105 +</rss>
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
1 +{
2 + "feed": {
3 + "items": [
4 + {
5 + "title": "v3.9.0",
6 + "link": "/gulpjs/gulp/releases/tag/v3.9.0",
7 + "pubDate": "2015-06-01T21:49:41.000Z",
8 + "author": "contra",
9 + "content": "<p>3.9.0</p>",
10 + "contentSnippet": "3.9.0",
11 + "id": "tag:github.com,2008:Repository/11167738/v3.9.0",
12 + "isoDate": "2015-06-01T21:49:41.000Z"
13 + },
14 + {
15 + "title": "v3.8.11",
16 + "link": "/gulpjs/gulp/releases/tag/v3.8.11",
17 + "pubDate": "2015-02-09T20:37:28.000Z",
18 + "author": "contra",
19 + "content": "<p>3.8.11</p>",
20 + "contentSnippet": "3.8.11",
21 + "id": "tag:github.com,2008:Repository/11167738/v3.8.11",
22 + "isoDate": "2015-02-09T20:37:28.000Z"
23 + },
24 + {
25 + "title": "v3.8.10",
26 + "link": "/gulpjs/gulp/releases/tag/v3.8.10",
27 + "pubDate": "2014-11-04T00:11:30.000Z",
28 + "author": "contra",
29 + "content": "<p>3.8.10</p>",
30 + "contentSnippet": "3.8.10",
31 + "id": "tag:github.com,2008:Repository/11167738/v3.8.10",
32 + "isoDate": "2014-11-04T00:11:30.000Z"
33 + },
34 + {
35 + "title": "v3.8.9",
36 + "link": "/gulpjs/gulp/releases/tag/v3.8.9",
37 + "pubDate": "2014-10-22T06:55:20.000Z",
38 + "author": "contra",
39 + "content": "<p>3.8.9</p>",
40 + "contentSnippet": "3.8.9",
41 + "id": "tag:github.com,2008:Repository/11167738/v3.8.9",
42 + "isoDate": "2014-10-22T06:55:20.000Z"
43 + },
44 + {
45 + "title": "v3.8.8",
46 + "link": "/gulpjs/gulp/releases/tag/v3.8.8",
47 + "pubDate": "2014-09-07T20:20:11.000Z",
48 + "author": "contra",
49 + "content": "<p>3.8.8</p>",
50 + "contentSnippet": "3.8.8",
51 + "id": "tag:github.com,2008:Repository/11167738/v3.8.8",
52 + "isoDate": "2014-09-07T20:20:11.000Z"
53 + },
54 + {
55 + "title": "v3.8.7",
56 + "link": "/gulpjs/gulp/releases/tag/v3.8.7",
57 + "pubDate": "2014-08-02T04:58:19.000Z",
58 + "author": "contra",
59 + "content": "<p>3.8.7</p>",
60 + "contentSnippet": "3.8.7",
61 + "id": "tag:github.com,2008:Repository/11167738/v3.8.7",
62 + "isoDate": "2014-08-02T04:58:19.000Z"
63 + },
64 + {
65 + "title": "v3.8.6",
66 + "link": "/gulpjs/gulp/releases/tag/v3.8.6",
67 + "pubDate": "2014-07-09T22:06:50.000Z",
68 + "author": "contra",
69 + "content": "<p>3.8.6</p>",
70 + "contentSnippet": "3.8.6",
71 + "id": "tag:github.com,2008:Repository/11167738/v3.8.6",
72 + "isoDate": "2014-07-09T22:06:50.000Z"
73 + },
74 + {
75 + "title": "v3.8.5",
76 + "link": "/gulpjs/gulp/releases/tag/v3.8.5",
77 + "pubDate": "2014-06-27T06:53:54.000Z",
78 + "author": "contra",
79 + "content": "<p>3.8.5</p>",
80 + "contentSnippet": "3.8.5",
81 + "id": "tag:github.com,2008:Repository/11167738/v3.8.5",
82 + "isoDate": "2014-06-27T06:53:54.000Z"
83 + },
84 + {
85 + "title": "v3.8.4",
86 + "link": "/gulpjs/gulp/releases/tag/v3.8.4",
87 + "pubDate": "2014-06-27T06:38:43.000Z",
88 + "author": "contra",
89 + "content": "<p>3.8.4</p>",
90 + "contentSnippet": "3.8.4",
91 + "id": "tag:github.com,2008:Repository/11167738/v3.8.4",
92 + "isoDate": "2014-06-27T06:38:43.000Z"
93 + },
94 + {
95 + "title": "v3.8.3",
96 + "link": "/gulpjs/gulp/releases/tag/v3.8.3",
97 + "pubDate": "2014-06-26T21:17:51.000Z",
98 + "author": "contra",
99 + "content": "<p>3.8.3</p>",
100 + "contentSnippet": "3.8.3",
101 + "id": "tag:github.com,2008:Repository/11167738/v3.8.3",
102 + "isoDate": "2014-06-26T21:17:51.000Z"
103 + }
104 + ],
105 + "link": "https://github.com/gulpjs/gulp/releases",
106 + "feedUrl": "https://github.com/gulpjs/gulp/releases.atom",
107 + "title": "Release notes from gulp",
108 + "lastBuildDate": "2015-06-01T23:49:41+02:00"
109 + }
110 +}
...\ No newline at end of file ...\ No newline at end of file
This diff is collapsed. Click to expand it.
1 +{
2 + "feed": {
3 + "items": [
4 + {
5 + "title": "The First Item",
6 + "link": "http://www.oreilly.com/example/001.html",
7 + "enclosure": {
8 + "url": "http://www.oreilly.com/001.mp3",
9 + "length": "54321",
10 + "type": "audio/mpeg"
11 + },
12 + "content": "This is the first item.",
13 + "contentSnippet": "This is the first item.",
14 + "categories": [
15 + {
16 + "_": "Business/Industries/Publishing/Publishers/Nonfiction/",
17 + "$": {
18 + "domain": "http://www.dmoz.org"
19 + }
20 + }
21 + ]
22 + },
23 + {
24 + "title": "The Second Item",
25 + "link": "http://www.oreilly.com/example/002.html",
26 + "enclosure": {
27 + "url": "http://www.oreilly.com/002.mp3",
28 + "length": "54321",
29 + "type": "audio/mpeg"
30 + },
31 + "content": "This is the second item.",
32 + "contentSnippet": "This is the second item.",
33 + "categories": [
34 + {
35 + "_": "Business/Industries/Publishing/Publishers/Nonfiction/",
36 + "$": {
37 + "domain": "http://www.dmoz.org"
38 + }
39 + }
40 + ]
41 + }
42 + ],
43 + "title": "RSS0.92 Example",
44 + "description": "This is an example RSS0.91 feed",
45 + "pubDate": "03 Apr 02 1500 GMT",
46 + "webMaster": "webmaster@oreilly.com",
47 + "managingEditor": "editor@oreilly.com",
48 + "link": "http://www.oreilly.com/example/index.html",
49 + "language": "en-gb",
50 + "copyright": "Copyright 2002, Oreilly and Associates.",
51 + "lastBuildDate": "03 Apr 02 1500 GMT",
52 + "rating": "5"
53 + }
54 +}
...\ No newline at end of file ...\ No newline at end of file
1 +{
2 + "feed": {
3 + "items": [
4 + {
5 + "creator": "tobi",
6 + "date": "2016-05-04T06:53:45Z",
7 + "title": "My first Instant Article",
8 + "link": "https://localhost:8000",
9 + "pubDate": "Wed, 04 May 2016 06:53:45 GMT",
10 + "content:encoded": "<b>Lorem</b> ipsum",
11 + "dc:creator": "tobi",
12 + "dc:date": "2016-05-04T06:53:45Z",
13 + "content": "Lorem ipsum",
14 + "contentSnippet": "Lorem ipsum",
15 + "guid": "https://localhost:8000",
16 + "isoDate": "2016-05-04T06:53:45.000Z"
17 + }
18 + ],
19 + "title": "Instant Article Test",
20 + "description": "1, 2, 1, 2… check the mic!",
21 + "pubDate": "Fri, 13 May 2016 15:14:05 GMT",
22 + "link": "https://localhost:8000",
23 + "language": "en"
24 + }
25 +}
...\ No newline at end of file ...\ No newline at end of file
This diff could not be displayed because it is too large.
1 +{
2 + "feed": {
3 + "items": [
4 + {
5 + "id": "tag:github.com,2008:Repository/11167738/v3.9.0"
6 + }
7 + ]
8 + }
9 +}
...\ No newline at end of file ...\ No newline at end of file
1 +{
2 + "feed": {
3 + "items": [
4 + {
5 + "creator": "foobar@gmail.com",
6 + "title": "FAQ for Narro",
7 + "link": "https://www.narro.co/article/54e703933058540300000069",
8 + "pubDate": "Fri, 20 Feb 2015 09:51:15 UTC",
9 + "author": "foobar@gmail.com",
10 + "enclosure": {
11 + "url": "https://s3.amazonaws.com/nareta-articles/audio/54d046c293f79c0300000003/7e2d2b00-a945-441a-f49b-063786a319a4.mp3",
12 + "length": "74",
13 + "type": "audio/mpeg"
14 + },
15 + "content": "Listen to your reading list anywhere. Narro will take your bookmarked articles and read them back to you as a podcast.<br/> http://www.narro.co/faq<br/> <ul class=\"linkList\"></ul>",
16 + "contentSnippet": "Listen to your reading list anywhere. Narro will take your bookmarked articles and read them back to you as a podcast. http://www.narro.co/faq",
17 + "guid": "https://www.narro.co/article/54e703933058540300000069",
18 + "isoDate": "2015-02-20T09:51:15.000Z",
19 + "itunes": {
20 + "author": "foobar@gmail.com",
21 + "subtitle": "FAQ for Narro",
22 + "summary": "Listen to your reading list anywhere. Narro will take your bookmarked articles and read them back to you as a podcast. ... http://www.narro.co/faq ... <ul class=\"linkList\"></ul>",
23 + "explicit": "no",
24 + "duration": "74",
25 + "image": "http://example.com/someImage.jpg"
26 + }
27 + }
28 + ],
29 + "feedUrl": "http://on.narro.co/f",
30 + "title": "foobar on Narro",
31 + "description": "foobar uses Narro to create a podcast of articles transcribed to audio.",
32 + "pubDate": "Fri, 08 Jul 2016 13:40:00 UTC",
33 + "webMaster": "josh@narro.co",
34 + "managingEditor": "foobar@gmail.com",
35 + "generator": "gopod - http://github.com/jbckmn/gopod",
36 + "link": "http://on.narro.co/f",
37 + "language": "en",
38 + "copyright": "All article content copyright of respective source authors.",
39 + "ttl": "20",
40 + "itunes": {
41 + "image": "https://www.narro.co/images/narro-icon-lg.png",
42 + "owner": {
43 + "name": "foobar",
44 + "email": "foobar@gmail.com"
45 + },
46 + "author": "foobar@gmail.com",
47 + "subtitle": "foobar uses Narro to create a podcast of articles transcribed to audio.",
48 + "summary": "foobar uses Narro to create a podcast of articles transcribed to audio.",
49 + "explicit": "no"
50 + }
51 + }
52 +}
...\ No newline at end of file ...\ No newline at end of file
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
1 +"use strict";
2 +
3 +var fs = require('fs');
4 +var HTTP = require('http');
5 +
6 +var Parser = require('../index.js');
7 +
8 +var Expect = require('chai').expect;
9 +
10 +var IN_DIR = __dirname + '/input';
11 +var OUT_DIR = __dirname + '/output';
12 +
13 +describe('Parser', function() {
14 + var testParseForFile = function(name, ext, options, done) {
15 + if (typeof done === 'undefined') {
16 + done = options;
17 + options = {};
18 + }
19 + let parser = new Parser(options);
20 + let xml = fs.readFileSync(IN_DIR + '/' + name + '.' + ext, 'utf8');
21 + parser.parseString(xml, function(err, parsed) {
22 + if (err) console.log(err);
23 + Expect(err).to.equal(null);
24 + if (process.env.WRITE_GOLDEN) {
25 + fs.writeFileSync(OUT_DIR + '/' + name + '.json', JSON.stringify({feed: parsed}, null, 2));
26 + } else {
27 + var expected = fs.readFileSync(OUT_DIR + '/' + name + '.json', 'utf8')
28 + expected = JSON.parse(expected);
29 + Expect({feed: parsed}).to.deep.equal(expected);
30 + }
31 + done();
32 + })
33 + }
34 +
35 + it('should parse Reddit', function(done) {
36 + testParseForFile('reddit', 'rss', done);
37 + })
38 +
39 + it('should parse sciencemag.org (RSS 1.0)', function(done) {
40 + testParseForFile('rss-1', 'rss', done);
41 + })
42 +
43 + it('should parse craigslist (RSS 1.0)', function(done) {
44 + testParseForFile('craigslist', 'rss', done);
45 + })
46 +
47 + it('should parse atom', function(done) {
48 + testParseForFile('reddit-atom', 'rss', done);
49 + })
50 +
51 + it('should parse atom feed', function(done) {
52 + testParseForFile('gulp-atom', 'atom', done);
53 + })
54 +
55 + it('should parse reddits new feed', function(done) {
56 + testParseForFile('reddit-home', 'rss', done);
57 + })
58 +
59 + it('should parse with missing fields', function(done) {
60 + testParseForFile('missing-fields', 'atom', done)
61 + })
62 +
63 + it('should parse heise', function(done) {
64 + testParseForFile('heise', 'atom', done);
65 + })
66 +
67 + it('should parse heraldsun', function(done) {
68 + testParseForFile('heraldsun', 'rss', done);
69 + });
70 +
71 + it('should parse UOL Noticias', function(done) {
72 + testParseForFile('uolNoticias', 'rss', { defaultRSS: 2.0 }, done);
73 + });
74 +
75 + it('should NOT parse UOL Noticias, if no default RSS is provided', function(done) {
76 + function willFail() {
77 + testParseForFile('uolNoticias', 'rss', done);
78 + }
79 + Expect(willFail).to.throw;
80 + done();
81 + });
82 +
83 + it('should parse Instant Article', function(done) {
84 + testParseForFile('instant-article', 'rss', done);
85 + });
86 +
87 + it('should parse Feedburner', function(done) {
88 + testParseForFile('feedburner', 'atom', done);
89 + });
90 +
91 + it('should parse podcasts', function(done) {
92 + testParseForFile('narro', 'rss', done);
93 + });
94 +
95 + it('should parse multiple links', function(done) {
96 + testParseForFile('many-links', 'rss', done);
97 + });
98 +
99 + it('should pass xml2js options', function(done) {
100 + testParseForFile('xml2js-options', 'rss', {xml2js: {emptyTag: 'EMPTY'}}, done);
101 + });
102 +
103 + it('should throw error for unrecognized', function(done) {
104 + let parser = new Parser();
105 + let xml = fs.readFileSync(__dirname + '/input/unrecognized.rss', 'utf8');
106 + parser.parseString(xml, function(err, parsed) {
107 + Expect(err.message).to.contain('Feed not recognized as RSS');
108 + done();
109 + });
110 + });
111 +
112 + it('should omit iTunes image if none available during decoration', function(done) {
113 + const rssFeedWithMissingImage = __dirname + '/input/itunes-missing-image.rss';
114 + const xml = fs.readFileSync(rssFeedWithMissingImage, 'utf8');
115 + let parser = new Parser();
116 + parser.parseString(xml, function(err, parsed) {
117 + Expect(err).to.be.null;
118 + Expect(parsed).to.not.have.deep.property('feed.itunes.image');
119 + done();
120 + });
121 + });
122 +
123 + it('should parse custom fields', function(done) {
124 + var options = {
125 + customFields: {
126 + feed: ['language', 'copyright', 'nested-field'],
127 + item: ['subtitle']
128 + }
129 + };
130 + testParseForFile('customfields', 'rss', options, done);
131 + });
132 +
133 + it('should parse Atom feed custom fields', function(done) {
134 + var options = {
135 + customFields: {
136 + feed: ['totalViews'],
137 + item: ['media:group']
138 + }
139 + };
140 + testParseForFile('atom-customfields', 'atom', options, done);
141 + });
142 +
143 + it('should parse sibling custom fields', function(done) {
144 + var options = {
145 + customFields: {
146 + item: [['media:content', 'media:content', {keepArray: true}]]
147 + }
148 + };
149 + testParseForFile('guardian', 'rss', options, done);
150 + });
151 +
152 + it('should parse URL', function(done) {
153 + var INPUT_FILE = __dirname + '/input/reddit.rss';
154 + var OUTPUT_FILE = __dirname + '/output/reddit.json';
155 + var server = HTTP.createServer(function(req, res) {
156 + var file = fs.createReadStream(INPUT_FILE, 'utf8');
157 + file.pipe(res);
158 + });
159 + server.listen(function() {
160 + var port = server.address().port;
161 + var url = 'http://localhost:' + port;
162 + let parser = new Parser();
163 + parser.parseURL(url, function(err, parsed) {
164 + Expect(err).to.equal(null);
165 + if (process.env.WRITE_GOLDEN) {
166 + fs.writeFileSync(OUTPUT_FILE, JSON.stringify({feed: parsed}, null, 2));
167 + } else {
168 + var expected = JSON.parse(fs.readFileSync(OUTPUT_FILE, 'utf8'));
169 + Expect({feed: parsed}).to.deep.equal(expected);
170 + }
171 + server.close();
172 + done();
173 + });
174 + });
175 + });
176 +
177 + it('should use proper encoding', function(done) {
178 + var INPUT_FILE = __dirname + '/input/encoding.rss';
179 + var OUTPUT_FILE = __dirname + '/output/encoding.json';
180 + var ENCODING = 'latin1';
181 + var server = HTTP.createServer(function(req, res) {
182 + res.setHeader('Content-Type', 'text/xml; charset=' + ENCODING)
183 + var file = fs.readFileSync(INPUT_FILE, ENCODING);
184 + res.end(file, ENCODING);
185 + });
186 + server.listen(function() {
187 + var port = server.address().port;
188 + var url = 'http://localhost:' + port;
189 + var parser = new Parser();
190 + parser.parseURL(url, function(err, parsed) {
191 + Expect(err).to.equal(null);
192 + if (process.env.WRITE_GOLDEN) {
193 + fs.writeFileSync(OUTPUT_FILE, JSON.stringify({feed: parsed}, null, 2), {encoding: ENCODING});
194 + } else {
195 + var expected = JSON.parse(fs.readFileSync(OUTPUT_FILE, ENCODING));
196 + Expect({feed: parsed}).to.deep.equal(expected);
197 + }
198 + server.close();
199 + done();
200 + })
201 + })
202 + })
203 +})
1 +var webpack = require("webpack");
2 +module.exports = {
3 + entry: {
4 + "rss-parser": "./browser.js"
5 + },
6 + output: {
7 + path: __dirname,
8 + filename: "dist/[name].min.js"
9 + },
10 + resolve: {
11 + extensions: ['.js']
12 + },
13 + devtool: 'source-map',
14 + module: {
15 + loaders: [{
16 + test: /\.js$/,
17 + loader: 'babel-loader?presets[]=env',
18 + }]
19 + },
20 + node: {
21 + fs: "empty"
22 + }
23 +}
1 +The ISC License
2 +
3 +Copyright (c) Isaac Z. Schlueter and Contributors
4 +
5 +Permission to use, copy, modify, and/or distribute this software for any
6 +purpose with or without fee is hereby granted, provided that the above
7 +copyright notice and this permission notice appear in all copies.
8 +
9 +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
15 +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 +
17 +====
18 +
19 +`String.fromCodePoint` by Mathias Bynens used according to terms of MIT
20 +License, as follows:
21 +
22 + Copyright Mathias Bynens <https://mathiasbynens.be/>
23 +
24 + Permission is hereby granted, free of charge, to any person obtaining
25 + a copy of this software and associated documentation files (the
26 + "Software"), to deal in the Software without restriction, including
27 + without limitation the rights to use, copy, modify, merge, publish,
28 + distribute, sublicense, and/or sell copies of the Software, and to
29 + permit persons to whom the Software is furnished to do so, subject to
30 + the following conditions:
31 +
32 + The above copyright notice and this permission notice shall be
33 + included in all copies or substantial portions of the Software.
34 +
35 + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
36 + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
37 + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
38 + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
39 + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
40 + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
41 + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1 +# sax js
2 +
3 +A sax-style parser for XML and HTML.
4 +
5 +Designed with [node](http://nodejs.org/) in mind, but should work fine in
6 +the browser or other CommonJS implementations.
7 +
8 +## What This Is
9 +
10 +* A very simple tool to parse through an XML string.
11 +* A stepping stone to a streaming HTML parser.
12 +* A handy way to deal with RSS and other mostly-ok-but-kinda-broken XML
13 + docs.
14 +
15 +## What This Is (probably) Not
16 +
17 +* An HTML Parser - That's a fine goal, but this isn't it. It's just
18 + XML.
19 +* A DOM Builder - You can use it to build an object model out of XML,
20 + but it doesn't do that out of the box.
21 +* XSLT - No DOM = no querying.
22 +* 100% Compliant with (some other SAX implementation) - Most SAX
23 + implementations are in Java and do a lot more than this does.
24 +* An XML Validator - It does a little validation when in strict mode, but
25 + not much.
26 +* A Schema-Aware XSD Thing - Schemas are an exercise in fetishistic
27 + masochism.
28 +* A DTD-aware Thing - Fetching DTDs is a much bigger job.
29 +
30 +## Regarding `<!DOCTYPE`s and `<!ENTITY`s
31 +
32 +The parser will handle the basic XML entities in text nodes and attribute
33 +values: `&amp; &lt; &gt; &apos; &quot;`. It's possible to define additional
34 +entities in XML by putting them in the DTD. This parser doesn't do anything
35 +with that. If you want to listen to the `ondoctype` event, and then fetch
36 +the doctypes, and read the entities and add them to `parser.ENTITIES`, then
37 +be my guest.
38 +
39 +Unknown entities will fail in strict mode, and in loose mode, will pass
40 +through unmolested.
41 +
42 +## Usage
43 +
44 +```javascript
45 +var sax = require("./lib/sax"),
46 + strict = true, // set to false for html-mode
47 + parser = sax.parser(strict);
48 +
49 +parser.onerror = function (e) {
50 + // an error happened.
51 +};
52 +parser.ontext = function (t) {
53 + // got some text. t is the string of text.
54 +};
55 +parser.onopentag = function (node) {
56 + // opened a tag. node has "name" and "attributes"
57 +};
58 +parser.onattribute = function (attr) {
59 + // an attribute. attr has "name" and "value"
60 +};
61 +parser.onend = function () {
62 + // parser stream is done, and ready to have more stuff written to it.
63 +};
64 +
65 +parser.write('<xml>Hello, <who name="world">world</who>!</xml>').close();
66 +
67 +// stream usage
68 +// takes the same options as the parser
69 +var saxStream = require("sax").createStream(strict, options)
70 +saxStream.on("error", function (e) {
71 + // unhandled errors will throw, since this is a proper node
72 + // event emitter.
73 + console.error("error!", e)
74 + // clear the error
75 + this._parser.error = null
76 + this._parser.resume()
77 +})
78 +saxStream.on("opentag", function (node) {
79 + // same object as above
80 +})
81 +// pipe is supported, and it's readable/writable
82 +// same chunks coming in also go out.
83 +fs.createReadStream("file.xml")
84 + .pipe(saxStream)
85 + .pipe(fs.createWriteStream("file-copy.xml"))
86 +```
87 +
88 +
89 +## Arguments
90 +
91 +Pass the following arguments to the parser function. All are optional.
92 +
93 +`strict` - Boolean. Whether or not to be a jerk. Default: `false`.
94 +
95 +`opt` - Object bag of settings regarding string formatting. All default to `false`.
96 +
97 +Settings supported:
98 +
99 +* `trim` - Boolean. Whether or not to trim text and comment nodes.
100 +* `normalize` - Boolean. If true, then turn any whitespace into a single
101 + space.
102 +* `lowercase` - Boolean. If true, then lowercase tag names and attribute names
103 + in loose mode, rather than uppercasing them.
104 +* `xmlns` - Boolean. If true, then namespaces are supported.
105 +* `position` - Boolean. If false, then don't track line/col/position.
106 +* `strictEntities` - Boolean. If true, only parse [predefined XML
107 + entities](http://www.w3.org/TR/REC-xml/#sec-predefined-ent)
108 + (`&amp;`, `&apos;`, `&gt;`, `&lt;`, and `&quot;`)
109 +
110 +## Methods
111 +
112 +`write` - Write bytes onto the stream. You don't have to do this all at
113 +once. You can keep writing as much as you want.
114 +
115 +`close` - Close the stream. Once closed, no more data may be written until
116 +it is done processing the buffer, which is signaled by the `end` event.
117 +
118 +`resume` - To gracefully handle errors, assign a listener to the `error`
119 +event. Then, when the error is taken care of, you can call `resume` to
120 +continue parsing. Otherwise, the parser will not continue while in an error
121 +state.
122 +
123 +## Members
124 +
125 +At all times, the parser object will have the following members:
126 +
127 +`line`, `column`, `position` - Indications of the position in the XML
128 +document where the parser currently is looking.
129 +
130 +`startTagPosition` - Indicates the position where the current tag starts.
131 +
132 +`closed` - Boolean indicating whether or not the parser can be written to.
133 +If it's `true`, then wait for the `ready` event to write again.
134 +
135 +`strict` - Boolean indicating whether or not the parser is a jerk.
136 +
137 +`opt` - Any options passed into the constructor.
138 +
139 +`tag` - The current tag being dealt with.
140 +
141 +And a bunch of other stuff that you probably shouldn't touch.
142 +
143 +## Events
144 +
145 +All events emit with a single argument. To listen to an event, assign a
146 +function to `on<eventname>`. Functions get executed in the this-context of
147 +the parser object. The list of supported events are also in the exported
148 +`EVENTS` array.
149 +
150 +When using the stream interface, assign handlers using the EventEmitter
151 +`on` function in the normal fashion.
152 +
153 +`error` - Indication that something bad happened. The error will be hanging
154 +out on `parser.error`, and must be deleted before parsing can continue. By
155 +listening to this event, you can keep an eye on that kind of stuff. Note:
156 +this happens *much* more in strict mode. Argument: instance of `Error`.
157 +
158 +`text` - Text node. Argument: string of text.
159 +
160 +`doctype` - The `<!DOCTYPE` declaration. Argument: doctype string.
161 +
162 +`processinginstruction` - Stuff like `<?xml foo="blerg" ?>`. Argument:
163 +object with `name` and `body` members. Attributes are not parsed, as
164 +processing instructions have implementation dependent semantics.
165 +
166 +`sgmldeclaration` - Random SGML declarations. Stuff like `<!ENTITY p>`
167 +would trigger this kind of event. This is a weird thing to support, so it
168 +might go away at some point. SAX isn't intended to be used to parse SGML,
169 +after all.
170 +
171 +`opentagstart` - Emitted immediately when the tag name is available,
172 +but before any attributes are encountered. Argument: object with a
173 +`name` field and an empty `attributes` set. Note that this is the
174 +same object that will later be emitted in the `opentag` event.
175 +
176 +`opentag` - An opening tag. Argument: object with `name` and `attributes`.
177 +In non-strict mode, tag names are uppercased, unless the `lowercase`
178 +option is set. If the `xmlns` option is set, then it will contain
179 +namespace binding information on the `ns` member, and will have a
180 +`local`, `prefix`, and `uri` member.
181 +
182 +`closetag` - A closing tag. In loose mode, tags are auto-closed if their
183 +parent closes. In strict mode, well-formedness is enforced. Note that
184 +self-closing tags will have `closeTag` emitted immediately after `openTag`.
185 +Argument: tag name.
186 +
187 +`attribute` - An attribute node. Argument: object with `name` and `value`.
188 +In non-strict mode, attribute names are uppercased, unless the `lowercase`
189 +option is set. If the `xmlns` option is set, it will also contains namespace
190 +information.
191 +
192 +`comment` - A comment node. Argument: the string of the comment.
193 +
194 +`opencdata` - The opening tag of a `<![CDATA[` block.
195 +
196 +`cdata` - The text of a `<![CDATA[` block. Since `<![CDATA[` blocks can get
197 +quite large, this event may fire multiple times for a single block, if it
198 +is broken up into multiple `write()`s. Argument: the string of random
199 +character data.
200 +
201 +`closecdata` - The closing tag (`]]>`) of a `<![CDATA[` block.
202 +
203 +`opennamespace` - If the `xmlns` option is set, then this event will
204 +signal the start of a new namespace binding.
205 +
206 +`closenamespace` - If the `xmlns` option is set, then this event will
207 +signal the end of a namespace binding.
208 +
209 +`end` - Indication that the closed stream has ended.
210 +
211 +`ready` - Indication that the stream has reset, and is ready to be written
212 +to.
213 +
214 +`noscript` - In non-strict mode, `<script>` tags trigger a `"script"`
215 +event, and their contents are not checked for special xml characters.
216 +If you pass `noscript: true`, then this behavior is suppressed.
217 +
218 +## Reporting Problems
219 +
220 +It's best to write a failing test if you find an issue. I will always
221 +accept pull requests with failing tests if they demonstrate intended
222 +behavior, but it is very hard to figure out what issue you're describing
223 +without a test. Writing a test is also the best way for you yourself
224 +to figure out if you really understand the issue you think you have with
225 +sax-js.
This diff is collapsed. Click to expand it.
1 +{
2 + "_from": "sax@>=0.6.0",
3 + "_id": "sax@1.2.4",
4 + "_inBundle": false,
5 + "_integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
6 + "_location": "/sax",
7 + "_phantomChildren": {},
8 + "_requested": {
9 + "type": "range",
10 + "registry": true,
11 + "raw": "sax@>=0.6.0",
12 + "name": "sax",
13 + "escapedName": "sax",
14 + "rawSpec": ">=0.6.0",
15 + "saveSpec": null,
16 + "fetchSpec": ">=0.6.0"
17 + },
18 + "_requiredBy": [
19 + "/xml2js"
20 + ],
21 + "_resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
22 + "_shasum": "2816234e2378bddc4e5354fab5caa895df7100d9",
23 + "_spec": "sax@>=0.6.0",
24 + "_where": "C:\\Users\\정민채\\Desktop\\TermProject\\2017104024정민혁KakaoBot\\node_modules\\xml2js",
25 + "author": {
26 + "name": "Isaac Z. Schlueter",
27 + "email": "i@izs.me",
28 + "url": "http://blog.izs.me/"
29 + },
30 + "bugs": {
31 + "url": "https://github.com/isaacs/sax-js/issues"
32 + },
33 + "bundleDependencies": false,
34 + "deprecated": false,
35 + "description": "An evented streaming XML parser in JavaScript",
36 + "devDependencies": {
37 + "standard": "^8.6.0",
38 + "tap": "^10.5.1"
39 + },
40 + "files": [
41 + "lib/sax.js",
42 + "LICENSE",
43 + "README.md"
44 + ],
45 + "homepage": "https://github.com/isaacs/sax-js#readme",
46 + "license": "ISC",
47 + "main": "lib/sax.js",
48 + "name": "sax",
49 + "repository": {
50 + "type": "git",
51 + "url": "git://github.com/isaacs/sax-js.git"
52 + },
53 + "scripts": {
54 + "postpublish": "git push origin --all; git push origin --tags",
55 + "posttest": "standard -F test/*.js lib/*.js",
56 + "postversion": "npm publish",
57 + "preversion": "npm test",
58 + "test": "tap test/*.js --cov -j4"
59 + },
60 + "version": "1.2.4"
61 +}
1 +Copyright 2010, 2011, 2012, 2013. All rights reserved.
2 +
3 +Permission is hereby granted, free of charge, to any person obtaining a copy
4 +of this software and associated documentation files (the "Software"), to
5 +deal in the Software without restriction, including without limitation the
6 +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 +sell copies of the Software, and to permit persons to whom the Software is
8 +furnished to do so, subject to the following conditions:
9 +
10 +The above copyright notice and this permission notice shall be included in
11 +all copies or substantial portions of the Software.
12 +
13 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 +IN THE SOFTWARE.
This diff is collapsed. Click to expand it.
1 +// Generated by CoffeeScript 1.12.7
2 +(function() {
3 + "use strict";
4 + exports.stripBOM = function(str) {
5 + if (str[0] === '\uFEFF') {
6 + return str.substring(1);
7 + } else {
8 + return str;
9 + }
10 + };
11 +
12 +}).call(this);
1 +// Generated by CoffeeScript 1.12.7
2 +(function() {
3 + "use strict";
4 + var builder, defaults, escapeCDATA, requiresCDATA, wrapCDATA,
5 + hasProp = {}.hasOwnProperty;
6 +
7 + builder = require('xmlbuilder');
8 +
9 + defaults = require('./defaults').defaults;
10 +
11 + requiresCDATA = function(entry) {
12 + return typeof entry === "string" && (entry.indexOf('&') >= 0 || entry.indexOf('>') >= 0 || entry.indexOf('<') >= 0);
13 + };
14 +
15 + wrapCDATA = function(entry) {
16 + return "<![CDATA[" + (escapeCDATA(entry)) + "]]>";
17 + };
18 +
19 + escapeCDATA = function(entry) {
20 + return entry.replace(']]>', ']]]]><![CDATA[>');
21 + };
22 +
23 + exports.Builder = (function() {
24 + function Builder(opts) {
25 + var key, ref, value;
26 + this.options = {};
27 + ref = defaults["0.2"];
28 + for (key in ref) {
29 + if (!hasProp.call(ref, key)) continue;
30 + value = ref[key];
31 + this.options[key] = value;
32 + }
33 + for (key in opts) {
34 + if (!hasProp.call(opts, key)) continue;
35 + value = opts[key];
36 + this.options[key] = value;
37 + }
38 + }
39 +
40 + Builder.prototype.buildObject = function(rootObj) {
41 + var attrkey, charkey, render, rootElement, rootName;
42 + attrkey = this.options.attrkey;
43 + charkey = this.options.charkey;
44 + if ((Object.keys(rootObj).length === 1) && (this.options.rootName === defaults['0.2'].rootName)) {
45 + rootName = Object.keys(rootObj)[0];
46 + rootObj = rootObj[rootName];
47 + } else {
48 + rootName = this.options.rootName;
49 + }
50 + render = (function(_this) {
51 + return function(element, obj) {
52 + var attr, child, entry, index, key, value;
53 + if (typeof obj !== 'object') {
54 + if (_this.options.cdata && requiresCDATA(obj)) {
55 + element.raw(wrapCDATA(obj));
56 + } else {
57 + element.txt(obj);
58 + }
59 + } else if (Array.isArray(obj)) {
60 + for (index in obj) {
61 + if (!hasProp.call(obj, index)) continue;
62 + child = obj[index];
63 + for (key in child) {
64 + entry = child[key];
65 + element = render(element.ele(key), entry).up();
66 + }
67 + }
68 + } else {
69 + for (key in obj) {
70 + if (!hasProp.call(obj, key)) continue;
71 + child = obj[key];
72 + if (key === attrkey) {
73 + if (typeof child === "object") {
74 + for (attr in child) {
75 + value = child[attr];
76 + element = element.att(attr, value);
77 + }
78 + }
79 + } else if (key === charkey) {
80 + if (_this.options.cdata && requiresCDATA(child)) {
81 + element = element.raw(wrapCDATA(child));
82 + } else {
83 + element = element.txt(child);
84 + }
85 + } else if (Array.isArray(child)) {
86 + for (index in child) {
87 + if (!hasProp.call(child, index)) continue;
88 + entry = child[index];
89 + if (typeof entry === 'string') {
90 + if (_this.options.cdata && requiresCDATA(entry)) {
91 + element = element.ele(key).raw(wrapCDATA(entry)).up();
92 + } else {
93 + element = element.ele(key, entry).up();
94 + }
95 + } else {
96 + element = render(element.ele(key), entry).up();
97 + }
98 + }
99 + } else if (typeof child === "object") {
100 + element = render(element.ele(key), child).up();
101 + } else {
102 + if (typeof child === 'string' && _this.options.cdata && requiresCDATA(child)) {
103 + element = element.ele(key).raw(wrapCDATA(child)).up();
104 + } else {
105 + if (child == null) {
106 + child = '';
107 + }
108 + element = element.ele(key, child.toString()).up();
109 + }
110 + }
111 + }
112 + }
113 + return element;
114 + };
115 + })(this);
116 + rootElement = builder.create(rootName, this.options.xmldec, this.options.doctype, {
117 + headless: this.options.headless,
118 + allowSurrogateChars: this.options.allowSurrogateChars
119 + });
120 + return render(rootElement, rootObj).end(this.options.renderOpts);
121 + };
122 +
123 + return Builder;
124 +
125 + })();
126 +
127 +}).call(this);
1 +// Generated by CoffeeScript 1.12.7
2 +(function() {
3 + exports.defaults = {
4 + "0.1": {
5 + explicitCharkey: false,
6 + trim: true,
7 + normalize: true,
8 + normalizeTags: false,
9 + attrkey: "@",
10 + charkey: "#",
11 + explicitArray: false,
12 + ignoreAttrs: false,
13 + mergeAttrs: false,
14 + explicitRoot: false,
15 + validator: null,
16 + xmlns: false,
17 + explicitChildren: false,
18 + childkey: '@@',
19 + charsAsChildren: false,
20 + includeWhiteChars: false,
21 + async: false,
22 + strict: true,
23 + attrNameProcessors: null,
24 + attrValueProcessors: null,
25 + tagNameProcessors: null,
26 + valueProcessors: null,
27 + emptyTag: ''
28 + },
29 + "0.2": {
30 + explicitCharkey: false,
31 + trim: false,
32 + normalize: false,
33 + normalizeTags: false,
34 + attrkey: "$",
35 + charkey: "_",
36 + explicitArray: true,
37 + ignoreAttrs: false,
38 + mergeAttrs: false,
39 + explicitRoot: true,
40 + validator: null,
41 + xmlns: false,
42 + explicitChildren: false,
43 + preserveChildrenOrder: false,
44 + childkey: '$$',
45 + charsAsChildren: false,
46 + includeWhiteChars: false,
47 + async: false,
48 + strict: true,
49 + attrNameProcessors: null,
50 + attrValueProcessors: null,
51 + tagNameProcessors: null,
52 + valueProcessors: null,
53 + rootName: 'root',
54 + xmldec: {
55 + 'version': '1.0',
56 + 'encoding': 'UTF-8',
57 + 'standalone': true
58 + },
59 + doctype: null,
60 + renderOpts: {
61 + 'pretty': true,
62 + 'indent': ' ',
63 + 'newline': '\n'
64 + },
65 + headless: false,
66 + chunkSize: 10000,
67 + emptyTag: '',
68 + cdata: false
69 + }
70 + };
71 +
72 +}).call(this);
This diff is collapsed. Click to expand it.
1 +// Generated by CoffeeScript 1.12.7
2 +(function() {
3 + "use strict";
4 + var prefixMatch;
5 +
6 + prefixMatch = new RegExp(/(?!xmlns)^.*:/);
7 +
8 + exports.normalize = function(str) {
9 + return str.toLowerCase();
10 + };
11 +
12 + exports.firstCharLowerCase = function(str) {
13 + return str.charAt(0).toLowerCase() + str.slice(1);
14 + };
15 +
16 + exports.stripPrefix = function(str) {
17 + return str.replace(prefixMatch, '');
18 + };
19 +
20 + exports.parseNumbers = function(str) {
21 + if (!isNaN(str)) {
22 + str = str % 1 === 0 ? parseInt(str, 10) : parseFloat(str);
23 + }
24 + return str;
25 + };
26 +
27 + exports.parseBooleans = function(str) {
28 + if (/^(?:true|false)$/i.test(str)) {
29 + str = str.toLowerCase() === 'true';
30 + }
31 + return str;
32 + };
33 +
34 +}).call(this);
1 +// Generated by CoffeeScript 1.12.7
2 +(function() {
3 + "use strict";
4 + var builder, defaults, parser, processors,
5 + extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
6 + hasProp = {}.hasOwnProperty;
7 +
8 + defaults = require('./defaults');
9 +
10 + builder = require('./builder');
11 +
12 + parser = require('./parser');
13 +
14 + processors = require('./processors');
15 +
16 + exports.defaults = defaults.defaults;
17 +
18 + exports.processors = processors;
19 +
20 + exports.ValidationError = (function(superClass) {
21 + extend(ValidationError, superClass);
22 +
23 + function ValidationError(message) {
24 + this.message = message;
25 + }
26 +
27 + return ValidationError;
28 +
29 + })(Error);
30 +
31 + exports.Builder = builder.Builder;
32 +
33 + exports.Parser = parser.Parser;
34 +
35 + exports.parseString = parser.parseString;
36 +
37 +}).call(this);
1 +{
2 + "_from": "xml2js@^0.4.19",
3 + "_id": "xml2js@0.4.19",
4 + "_inBundle": false,
5 + "_integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==",
6 + "_location": "/xml2js",
7 + "_phantomChildren": {},
8 + "_requested": {
9 + "type": "range",
10 + "registry": true,
11 + "raw": "xml2js@^0.4.19",
12 + "name": "xml2js",
13 + "escapedName": "xml2js",
14 + "rawSpec": "^0.4.19",
15 + "saveSpec": null,
16 + "fetchSpec": "^0.4.19"
17 + },
18 + "_requiredBy": [
19 + "/rss-parser"
20 + ],
21 + "_resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz",
22 + "_shasum": "686c20f213209e94abf0d1bcf1efaa291c7827a7",
23 + "_spec": "xml2js@^0.4.19",
24 + "_where": "C:\\Users\\정민채\\Desktop\\TermProject\\2017104024정민혁KakaoBot\\node_modules\\rss-parser",
25 + "author": {
26 + "name": "Marek Kubica",
27 + "email": "marek@xivilization.net",
28 + "url": "https://xivilization.net"
29 + },
30 + "bugs": {
31 + "url": "https://github.com/Leonidas-from-XIV/node-xml2js/issues"
32 + },
33 + "bundleDependencies": false,
34 + "contributors": [
35 + {
36 + "name": "maqr",
37 + "email": "maqr.lollerskates@gmail.com",
38 + "url": "https://github.com/maqr"
39 + },
40 + {
41 + "name": "Ben Weaver",
42 + "url": "http://benweaver.com/"
43 + },
44 + {
45 + "name": "Jae Kwon",
46 + "url": "https://github.com/jaekwon"
47 + },
48 + {
49 + "name": "Jim Robert"
50 + },
51 + {
52 + "name": "Ștefan Rusu",
53 + "url": "http://www.saltwaterc.eu/"
54 + },
55 + {
56 + "name": "Carter Cole",
57 + "email": "carter.cole@cartercole.com",
58 + "url": "http://cartercole.com/"
59 + },
60 + {
61 + "name": "Kurt Raschke",
62 + "email": "kurt@kurtraschke.com",
63 + "url": "http://www.kurtraschke.com/"
64 + },
65 + {
66 + "name": "Contra",
67 + "email": "contra@australia.edu",
68 + "url": "https://github.com/Contra"
69 + },
70 + {
71 + "name": "Marcelo Diniz",
72 + "email": "marudiniz@gmail.com",
73 + "url": "https://github.com/mdiniz"
74 + },
75 + {
76 + "name": "Michael Hart",
77 + "url": "https://github.com/mhart"
78 + },
79 + {
80 + "name": "Zachary Scott",
81 + "email": "zachary@zacharyscott.net",
82 + "url": "http://zacharyscott.net/"
83 + },
84 + {
85 + "name": "Raoul Millais",
86 + "url": "https://github.com/raoulmillais"
87 + },
88 + {
89 + "name": "Salsita Software",
90 + "url": "http://www.salsitasoft.com/"
91 + },
92 + {
93 + "name": "Mike Schilling",
94 + "email": "mike@emotive.com",
95 + "url": "http://www.emotive.com/"
96 + },
97 + {
98 + "name": "Jackson Tian",
99 + "email": "shyvo1987@gmail.com",
100 + "url": "http://weibo.com/shyvo"
101 + },
102 + {
103 + "name": "Mikhail Zyatin",
104 + "email": "mikhail.zyatin@gmail.com",
105 + "url": "https://github.com/Sitin"
106 + },
107 + {
108 + "name": "Chris Tavares",
109 + "email": "ctavares@microsoft.com",
110 + "url": "https://github.com/christav"
111 + },
112 + {
113 + "name": "Frank Xu",
114 + "email": "yyfrankyy@gmail.com",
115 + "url": "http://f2e.us/"
116 + },
117 + {
118 + "name": "Guido D'Albore",
119 + "email": "guido@bitstorm.it",
120 + "url": "http://www.bitstorm.it/"
121 + },
122 + {
123 + "name": "Jack Senechal",
124 + "url": "http://jacksenechal.com/"
125 + },
126 + {
127 + "name": "Matthias Hölzl",
128 + "email": "tc@xantira.com",
129 + "url": "https://github.com/hoelzl"
130 + },
131 + {
132 + "name": "Camille Reynders",
133 + "email": "info@creynders.be",
134 + "url": "http://www.creynders.be/"
135 + },
136 + {
137 + "name": "Taylor Gautier",
138 + "url": "https://github.com/tsgautier"
139 + },
140 + {
141 + "name": "Todd Bryan",
142 + "url": "https://github.com/toddrbryan"
143 + },
144 + {
145 + "name": "Leore Avidar",
146 + "email": "leore.avidar@gmail.com",
147 + "url": "http://leoreavidar.com/"
148 + },
149 + {
150 + "name": "Dave Aitken",
151 + "email": "dave.aitken@gmail.com",
152 + "url": "http://www.actionshrimp.com/"
153 + },
154 + {
155 + "name": "Shaney Orrowe",
156 + "email": "shaney.orrowe@practiceweb.co.uk"
157 + },
158 + {
159 + "name": "Candle",
160 + "email": "candle@candle.me.uk"
161 + },
162 + {
163 + "name": "Jess Telford",
164 + "email": "hi@jes.st",
165 + "url": "http://jes.st"
166 + },
167 + {
168 + "name": "Tom Hughes",
169 + "email": "<tom@compton.nu",
170 + "url": "http://compton.nu/"
171 + },
172 + {
173 + "name": "Piotr Rochala",
174 + "url": "http://rocha.la/"
175 + },
176 + {
177 + "name": "Michael Avila",
178 + "url": "https://github.com/michaelavila"
179 + },
180 + {
181 + "name": "Ryan Gahl",
182 + "url": "https://github.com/ryedin"
183 + },
184 + {
185 + "name": "Eric Laberge",
186 + "email": "e.laberge@gmail.com",
187 + "url": "https://github.com/elaberge"
188 + },
189 + {
190 + "name": "Benjamin E. Coe",
191 + "email": "ben@npmjs.com",
192 + "url": "https://twitter.com/benjamincoe"
193 + },
194 + {
195 + "name": "Stephen Cresswell",
196 + "url": "https://github.com/cressie176"
197 + },
198 + {
199 + "name": "Pascal Ehlert",
200 + "email": "pascal@hacksrus.net",
201 + "url": "http://www.hacksrus.net/"
202 + },
203 + {
204 + "name": "Tom Spencer",
205 + "email": "fiznool@gmail.com",
206 + "url": "http://fiznool.com/"
207 + },
208 + {
209 + "name": "Tristian Flanagan",
210 + "email": "tflanagan@datacollaborative.com",
211 + "url": "https://github.com/tflanagan"
212 + },
213 + {
214 + "name": "Tim Johns",
215 + "email": "timjohns@yahoo.com",
216 + "url": "https://github.com/TimJohns"
217 + },
218 + {
219 + "name": "Bogdan Chadkin",
220 + "email": "trysound@yandex.ru",
221 + "url": "https://github.com/TrySound"
222 + },
223 + {
224 + "name": "David Wood",
225 + "email": "david.p.wood@gmail.com",
226 + "url": "http://codesleuth.co.uk/"
227 + },
228 + {
229 + "name": "Nicolas Maquet",
230 + "url": "https://github.com/nmaquet"
231 + },
232 + {
233 + "name": "Lovell Fuller",
234 + "url": "http://lovell.info/"
235 + },
236 + {
237 + "name": "d3adc0d3",
238 + "url": "https://github.com/d3adc0d3"
239 + }
240 + ],
241 + "dependencies": {
242 + "sax": ">=0.6.0",
243 + "xmlbuilder": "~9.0.1"
244 + },
245 + "deprecated": false,
246 + "description": "Simple XML to JavaScript object converter.",
247 + "devDependencies": {
248 + "coffee-script": ">=1.10.0",
249 + "coveralls": "^2.11.2",
250 + "diff": ">=1.0.8",
251 + "docco": ">=0.6.2",
252 + "nyc": ">=2.2.1",
253 + "zap": ">=0.2.9"
254 + },
255 + "directories": {
256 + "lib": "./lib"
257 + },
258 + "files": [
259 + "lib"
260 + ],
261 + "homepage": "https://github.com/Leonidas-from-XIV/node-xml2js",
262 + "keywords": [
263 + "xml",
264 + "json"
265 + ],
266 + "license": "MIT",
267 + "main": "./lib/xml2js",
268 + "name": "xml2js",
269 + "repository": {
270 + "type": "git",
271 + "url": "git+https://github.com/Leonidas-from-XIV/node-xml2js.git"
272 + },
273 + "scripts": {
274 + "coverage": "nyc npm test && nyc report",
275 + "coveralls": "nyc npm test && nyc report --reporter=text-lcov | coveralls",
276 + "test": "zap"
277 + },
278 + "version": "0.4.19"
279 +}
1 +.travis.yml
2 +src
3 +test
4 +perf
5 +coverage
This diff is collapsed. Click to expand it.
1 +The MIT License (MIT)
2 +
3 +Copyright (c) 2013 Ozgur Ozcitak
4 +
5 +Permission is hereby granted, free of charge, to any person obtaining a copy
6 +of this software and associated documentation files (the "Software"), to deal
7 +in the Software without restriction, including without limitation the rights
8 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 +copies of the Software, and to permit persons to whom the Software is
10 +furnished to do so, subject to the following conditions:
11 +
12 +The above copyright notice and this permission notice shall be included in
13 +all copies or substantial portions of the Software.
14 +
15 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 +THE SOFTWARE.
1 +# xmlbuilder-js
2 +
3 +An XML builder for [node.js](https://nodejs.org/) similar to
4 +[java-xmlbuilder](https://github.com/jmurty/java-xmlbuilder).
5 +
6 +[![License](http://img.shields.io/npm/l/xmlbuilder.svg?style=flat-square)](http://opensource.org/licenses/MIT)
7 +[![NPM Version](http://img.shields.io/npm/v/xmlbuilder.svg?style=flat-square)](https://npmjs.com/package/xmlbuilder)
8 +[![NPM Downloads](https://img.shields.io/npm/dm/xmlbuilder.svg?style=flat-square)](https://npmjs.com/package/xmlbuilder)
9 +
10 +[![Build Status](http://img.shields.io/travis/oozcitak/xmlbuilder-js.svg?style=flat-square)](http://travis-ci.org/oozcitak/xmlbuilder-js)
11 +[![Dev Dependency Status](http://img.shields.io/david/dev/oozcitak/xmlbuilder-js.svg?style=flat-square)](https://david-dm.org/oozcitak/xmlbuilder-js)
12 +[![Code Coverage](https://img.shields.io/coveralls/oozcitak/xmlbuilder-js.svg?style=flat-square)](https://coveralls.io/github/oozcitak/xmlbuilder-js)
13 +
14 +### Installation:
15 +
16 +``` sh
17 +npm install xmlbuilder
18 +```
19 +
20 +### Usage:
21 +
22 +``` js
23 +var builder = require('xmlbuilder');
24 +var xml = builder.create('root')
25 + .ele('xmlbuilder')
26 + .ele('repo', {'type': 'git'}, 'git://github.com/oozcitak/xmlbuilder-js.git')
27 + .end({ pretty: true});
28 +
29 +console.log(xml);
30 +```
31 +
32 +will result in:
33 +
34 +``` xml
35 +<?xml version="1.0"?>
36 +<root>
37 + <xmlbuilder>
38 + <repo type="git">git://github.com/oozcitak/xmlbuilder-js.git</repo>
39 + </xmlbuilder>
40 +</root>
41 +```
42 +
43 +It is also possible to convert objects into nodes:
44 +
45 +``` js
46 +builder.create({
47 + root: {
48 + xmlbuilder: {
49 + repo: {
50 + '@type': 'git', // attributes start with @
51 + '#text': 'git://github.com/oozcitak/xmlbuilder-js.git' // text node
52 + }
53 + }
54 + }
55 +});
56 +```
57 +
58 +If you need to do some processing:
59 +
60 +``` js
61 +var root = builder.create('squares');
62 +root.com('f(x) = x^2');
63 +for(var i = 1; i <= 5; i++)
64 +{
65 + var item = root.ele('data');
66 + item.att('x', i);
67 + item.att('y', i * i);
68 +}
69 +```
70 +
71 +This will result in:
72 +
73 +``` xml
74 +<?xml version="1.0"?>
75 +<squares>
76 + <!-- f(x) = x^2 -->
77 + <data x="1" y="1"/>
78 + <data x="2" y="4"/>
79 + <data x="3" y="9"/>
80 + <data x="4" y="16"/>
81 + <data x="5" y="25"/>
82 +</squares>
83 +```
84 +
85 +See the [wiki](https://github.com/oozcitak/xmlbuilder-js/wiki) for details and [examples](https://github.com/oozcitak/xmlbuilder-js/wiki/Examples) for more complex examples.
1 +// Generated by CoffeeScript 1.12.7
2 +(function() {
3 + var assign, isArray, isEmpty, isFunction, isObject, isPlainObject,
4 + slice = [].slice,
5 + hasProp = {}.hasOwnProperty;
6 +
7 + assign = function() {
8 + var i, key, len, source, sources, target;
9 + target = arguments[0], sources = 2 <= arguments.length ? slice.call(arguments, 1) : [];
10 + if (isFunction(Object.assign)) {
11 + Object.assign.apply(null, arguments);
12 + } else {
13 + for (i = 0, len = sources.length; i < len; i++) {
14 + source = sources[i];
15 + if (source != null) {
16 + for (key in source) {
17 + if (!hasProp.call(source, key)) continue;
18 + target[key] = source[key];
19 + }
20 + }
21 + }
22 + }
23 + return target;
24 + };
25 +
26 + isFunction = function(val) {
27 + return !!val && Object.prototype.toString.call(val) === '[object Function]';
28 + };
29 +
30 + isObject = function(val) {
31 + var ref;
32 + return !!val && ((ref = typeof val) === 'function' || ref === 'object');
33 + };
34 +
35 + isArray = function(val) {
36 + if (isFunction(Array.isArray)) {
37 + return Array.isArray(val);
38 + } else {
39 + return Object.prototype.toString.call(val) === '[object Array]';
40 + }
41 + };
42 +
43 + isEmpty = function(val) {
44 + var key;
45 + if (isArray(val)) {
46 + return !val.length;
47 + } else {
48 + for (key in val) {
49 + if (!hasProp.call(val, key)) continue;
50 + return false;
51 + }
52 + return true;
53 + }
54 + };
55 +
56 + isPlainObject = function(val) {
57 + var ctor, proto;
58 + return isObject(val) && (proto = Object.getPrototypeOf(val)) && (ctor = proto.constructor) && (typeof ctor === 'function') && (ctor instanceof ctor) && (Function.prototype.toString.call(ctor) === Function.prototype.toString.call(Object));
59 + };
60 +
61 + module.exports.assign = assign;
62 +
63 + module.exports.isFunction = isFunction;
64 +
65 + module.exports.isObject = isObject;
66 +
67 + module.exports.isArray = isArray;
68 +
69 + module.exports.isEmpty = isEmpty;
70 +
71 + module.exports.isPlainObject = isPlainObject;
72 +
73 +}).call(this);
1 +// Generated by CoffeeScript 1.12.7
2 +(function() {
3 + var XMLAttribute;
4 +
5 + module.exports = XMLAttribute = (function() {
6 + function XMLAttribute(parent, name, value) {
7 + this.options = parent.options;
8 + this.stringify = parent.stringify;
9 + if (name == null) {
10 + throw new Error("Missing attribute name of element " + parent.name);
11 + }
12 + if (value == null) {
13 + throw new Error("Missing attribute value for attribute " + name + " of element " + parent.name);
14 + }
15 + this.name = this.stringify.attName(name);
16 + this.value = this.stringify.attValue(value);
17 + }
18 +
19 + XMLAttribute.prototype.clone = function() {
20 + return Object.create(this);
21 + };
22 +
23 + XMLAttribute.prototype.toString = function(options) {
24 + return this.options.writer.set(options).attribute(this);
25 + };
26 +
27 + return XMLAttribute;
28 +
29 + })();
30 +
31 +}).call(this);
1 +// Generated by CoffeeScript 1.12.7
2 +(function() {
3 + var XMLCData, XMLNode,
4 + extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
5 + hasProp = {}.hasOwnProperty;
6 +
7 + XMLNode = require('./XMLNode');
8 +
9 + module.exports = XMLCData = (function(superClass) {
10 + extend(XMLCData, superClass);
11 +
12 + function XMLCData(parent, text) {
13 + XMLCData.__super__.constructor.call(this, parent);
14 + if (text == null) {
15 + throw new Error("Missing CDATA text");
16 + }
17 + this.text = this.stringify.cdata(text);
18 + }
19 +
20 + XMLCData.prototype.clone = function() {
21 + return Object.create(this);
22 + };
23 +
24 + XMLCData.prototype.toString = function(options) {
25 + return this.options.writer.set(options).cdata(this);
26 + };
27 +
28 + return XMLCData;
29 +
30 + })(XMLNode);
31 +
32 +}).call(this);
1 +// Generated by CoffeeScript 1.12.7
2 +(function() {
3 + var XMLComment, XMLNode,
4 + extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
5 + hasProp = {}.hasOwnProperty;
6 +
7 + XMLNode = require('./XMLNode');
8 +
9 + module.exports = XMLComment = (function(superClass) {
10 + extend(XMLComment, superClass);
11 +
12 + function XMLComment(parent, text) {
13 + XMLComment.__super__.constructor.call(this, parent);
14 + if (text == null) {
15 + throw new Error("Missing comment text");
16 + }
17 + this.text = this.stringify.comment(text);
18 + }
19 +
20 + XMLComment.prototype.clone = function() {
21 + return Object.create(this);
22 + };
23 +
24 + XMLComment.prototype.toString = function(options) {
25 + return this.options.writer.set(options).comment(this);
26 + };
27 +
28 + return XMLComment;
29 +
30 + })(XMLNode);
31 +
32 +}).call(this);
1 +// Generated by CoffeeScript 1.12.7
2 +(function() {
3 + var XMLDTDAttList, XMLNode,
4 + extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
5 + hasProp = {}.hasOwnProperty;
6 +
7 + XMLNode = require('./XMLNode');
8 +
9 + module.exports = XMLDTDAttList = (function(superClass) {
10 + extend(XMLDTDAttList, superClass);
11 +
12 + function XMLDTDAttList(parent, elementName, attributeName, attributeType, defaultValueType, defaultValue) {
13 + XMLDTDAttList.__super__.constructor.call(this, parent);
14 + if (elementName == null) {
15 + throw new Error("Missing DTD element name");
16 + }
17 + if (attributeName == null) {
18 + throw new Error("Missing DTD attribute name");
19 + }
20 + if (!attributeType) {
21 + throw new Error("Missing DTD attribute type");
22 + }
23 + if (!defaultValueType) {
24 + throw new Error("Missing DTD attribute default");
25 + }
26 + if (defaultValueType.indexOf('#') !== 0) {
27 + defaultValueType = '#' + defaultValueType;
28 + }
29 + if (!defaultValueType.match(/^(#REQUIRED|#IMPLIED|#FIXED|#DEFAULT)$/)) {
30 + throw new Error("Invalid default value type; expected: #REQUIRED, #IMPLIED, #FIXED or #DEFAULT");
31 + }
32 + if (defaultValue && !defaultValueType.match(/^(#FIXED|#DEFAULT)$/)) {
33 + throw new Error("Default value only applies to #FIXED or #DEFAULT");
34 + }
35 + this.elementName = this.stringify.eleName(elementName);
36 + this.attributeName = this.stringify.attName(attributeName);
37 + this.attributeType = this.stringify.dtdAttType(attributeType);
38 + this.defaultValue = this.stringify.dtdAttDefault(defaultValue);
39 + this.defaultValueType = defaultValueType;
40 + }
41 +
42 + XMLDTDAttList.prototype.toString = function(options) {
43 + return this.options.writer.set(options).dtdAttList(this);
44 + };
45 +
46 + return XMLDTDAttList;
47 +
48 + })(XMLNode);
49 +
50 +}).call(this);
1 +// Generated by CoffeeScript 1.12.7
2 +(function() {
3 + var XMLDTDElement, XMLNode,
4 + extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
5 + hasProp = {}.hasOwnProperty;
6 +
7 + XMLNode = require('./XMLNode');
8 +
9 + module.exports = XMLDTDElement = (function(superClass) {
10 + extend(XMLDTDElement, superClass);
11 +
12 + function XMLDTDElement(parent, name, value) {
13 + XMLDTDElement.__super__.constructor.call(this, parent);
14 + if (name == null) {
15 + throw new Error("Missing DTD element name");
16 + }
17 + if (!value) {
18 + value = '(#PCDATA)';
19 + }
20 + if (Array.isArray(value)) {
21 + value = '(' + value.join(',') + ')';
22 + }
23 + this.name = this.stringify.eleName(name);
24 + this.value = this.stringify.dtdElementValue(value);
25 + }
26 +
27 + XMLDTDElement.prototype.toString = function(options) {
28 + return this.options.writer.set(options).dtdElement(this);
29 + };
30 +
31 + return XMLDTDElement;
32 +
33 + })(XMLNode);
34 +
35 +}).call(this);
1 +// Generated by CoffeeScript 1.12.7
2 +(function() {
3 + var XMLDTDEntity, XMLNode, isObject,
4 + extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
5 + hasProp = {}.hasOwnProperty;
6 +
7 + isObject = require('./Utility').isObject;
8 +
9 + XMLNode = require('./XMLNode');
10 +
11 + module.exports = XMLDTDEntity = (function(superClass) {
12 + extend(XMLDTDEntity, superClass);
13 +
14 + function XMLDTDEntity(parent, pe, name, value) {
15 + XMLDTDEntity.__super__.constructor.call(this, parent);
16 + if (name == null) {
17 + throw new Error("Missing entity name");
18 + }
19 + if (value == null) {
20 + throw new Error("Missing entity value");
21 + }
22 + this.pe = !!pe;
23 + this.name = this.stringify.eleName(name);
24 + if (!isObject(value)) {
25 + this.value = this.stringify.dtdEntityValue(value);
26 + } else {
27 + if (!value.pubID && !value.sysID) {
28 + throw new Error("Public and/or system identifiers are required for an external entity");
29 + }
30 + if (value.pubID && !value.sysID) {
31 + throw new Error("System identifier is required for a public external entity");
32 + }
33 + if (value.pubID != null) {
34 + this.pubID = this.stringify.dtdPubID(value.pubID);
35 + }
36 + if (value.sysID != null) {
37 + this.sysID = this.stringify.dtdSysID(value.sysID);
38 + }
39 + if (value.nData != null) {
40 + this.nData = this.stringify.dtdNData(value.nData);
41 + }
42 + if (this.pe && this.nData) {
43 + throw new Error("Notation declaration is not allowed in a parameter entity");
44 + }
45 + }
46 + }
47 +
48 + XMLDTDEntity.prototype.toString = function(options) {
49 + return this.options.writer.set(options).dtdEntity(this);
50 + };
51 +
52 + return XMLDTDEntity;
53 +
54 + })(XMLNode);
55 +
56 +}).call(this);
1 +// Generated by CoffeeScript 1.12.7
2 +(function() {
3 + var XMLDTDNotation, XMLNode,
4 + extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
5 + hasProp = {}.hasOwnProperty;
6 +
7 + XMLNode = require('./XMLNode');
8 +
9 + module.exports = XMLDTDNotation = (function(superClass) {
10 + extend(XMLDTDNotation, superClass);
11 +
12 + function XMLDTDNotation(parent, name, value) {
13 + XMLDTDNotation.__super__.constructor.call(this, parent);
14 + if (name == null) {
15 + throw new Error("Missing notation name");
16 + }
17 + if (!value.pubID && !value.sysID) {
18 + throw new Error("Public or system identifiers are required for an external entity");
19 + }
20 + this.name = this.stringify.eleName(name);
21 + if (value.pubID != null) {
22 + this.pubID = this.stringify.dtdPubID(value.pubID);
23 + }
24 + if (value.sysID != null) {
25 + this.sysID = this.stringify.dtdSysID(value.sysID);
26 + }
27 + }
28 +
29 + XMLDTDNotation.prototype.toString = function(options) {
30 + return this.options.writer.set(options).dtdNotation(this);
31 + };
32 +
33 + return XMLDTDNotation;
34 +
35 + })(XMLNode);
36 +
37 +}).call(this);
1 +// Generated by CoffeeScript 1.12.7
2 +(function() {
3 + var XMLDeclaration, XMLNode, isObject,
4 + extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
5 + hasProp = {}.hasOwnProperty;
6 +
7 + isObject = require('./Utility').isObject;
8 +
9 + XMLNode = require('./XMLNode');
10 +
11 + module.exports = XMLDeclaration = (function(superClass) {
12 + extend(XMLDeclaration, superClass);
13 +
14 + function XMLDeclaration(parent, version, encoding, standalone) {
15 + var ref;
16 + XMLDeclaration.__super__.constructor.call(this, parent);
17 + if (isObject(version)) {
18 + ref = version, version = ref.version, encoding = ref.encoding, standalone = ref.standalone;
19 + }
20 + if (!version) {
21 + version = '1.0';
22 + }
23 + this.version = this.stringify.xmlVersion(version);
24 + if (encoding != null) {
25 + this.encoding = this.stringify.xmlEncoding(encoding);
26 + }
27 + if (standalone != null) {
28 + this.standalone = this.stringify.xmlStandalone(standalone);
29 + }
30 + }
31 +
32 + XMLDeclaration.prototype.toString = function(options) {
33 + return this.options.writer.set(options).declaration(this);
34 + };
35 +
36 + return XMLDeclaration;
37 +
38 + })(XMLNode);
39 +
40 +}).call(this);
1 +// Generated by CoffeeScript 1.12.7
2 +(function() {
3 + var XMLDTDAttList, XMLDTDElement, XMLDTDEntity, XMLDTDNotation, XMLDocType, XMLNode, isObject,
4 + extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
5 + hasProp = {}.hasOwnProperty;
6 +
7 + isObject = require('./Utility').isObject;
8 +
9 + XMLNode = require('./XMLNode');
10 +
11 + XMLDTDAttList = require('./XMLDTDAttList');
12 +
13 + XMLDTDEntity = require('./XMLDTDEntity');
14 +
15 + XMLDTDElement = require('./XMLDTDElement');
16 +
17 + XMLDTDNotation = require('./XMLDTDNotation');
18 +
19 + module.exports = XMLDocType = (function(superClass) {
20 + extend(XMLDocType, superClass);
21 +
22 + function XMLDocType(parent, pubID, sysID) {
23 + var ref, ref1;
24 + XMLDocType.__super__.constructor.call(this, parent);
25 + this.documentObject = parent;
26 + if (isObject(pubID)) {
27 + ref = pubID, pubID = ref.pubID, sysID = ref.sysID;
28 + }
29 + if (sysID == null) {
30 + ref1 = [pubID, sysID], sysID = ref1[0], pubID = ref1[1];
31 + }
32 + if (pubID != null) {
33 + this.pubID = this.stringify.dtdPubID(pubID);
34 + }
35 + if (sysID != null) {
36 + this.sysID = this.stringify.dtdSysID(sysID);
37 + }
38 + }
39 +
40 + XMLDocType.prototype.element = function(name, value) {
41 + var child;
42 + child = new XMLDTDElement(this, name, value);
43 + this.children.push(child);
44 + return this;
45 + };
46 +
47 + XMLDocType.prototype.attList = function(elementName, attributeName, attributeType, defaultValueType, defaultValue) {
48 + var child;
49 + child = new XMLDTDAttList(this, elementName, attributeName, attributeType, defaultValueType, defaultValue);
50 + this.children.push(child);
51 + return this;
52 + };
53 +
54 + XMLDocType.prototype.entity = function(name, value) {
55 + var child;
56 + child = new XMLDTDEntity(this, false, name, value);
57 + this.children.push(child);
58 + return this;
59 + };
60 +
61 + XMLDocType.prototype.pEntity = function(name, value) {
62 + var child;
63 + child = new XMLDTDEntity(this, true, name, value);
64 + this.children.push(child);
65 + return this;
66 + };
67 +
68 + XMLDocType.prototype.notation = function(name, value) {
69 + var child;
70 + child = new XMLDTDNotation(this, name, value);
71 + this.children.push(child);
72 + return this;
73 + };
74 +
75 + XMLDocType.prototype.toString = function(options) {
76 + return this.options.writer.set(options).docType(this);
77 + };
78 +
79 + XMLDocType.prototype.ele = function(name, value) {
80 + return this.element(name, value);
81 + };
82 +
83 + XMLDocType.prototype.att = function(elementName, attributeName, attributeType, defaultValueType, defaultValue) {
84 + return this.attList(elementName, attributeName, attributeType, defaultValueType, defaultValue);
85 + };
86 +
87 + XMLDocType.prototype.ent = function(name, value) {
88 + return this.entity(name, value);
89 + };
90 +
91 + XMLDocType.prototype.pent = function(name, value) {
92 + return this.pEntity(name, value);
93 + };
94 +
95 + XMLDocType.prototype.not = function(name, value) {
96 + return this.notation(name, value);
97 + };
98 +
99 + XMLDocType.prototype.up = function() {
100 + return this.root() || this.documentObject;
101 + };
102 +
103 + return XMLDocType;
104 +
105 + })(XMLNode);
106 +
107 +}).call(this);
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.