{"_id":"@activediscourse/podcast-parser","_rev":"2-46d958a8f55951b24791090314b339fa","name":"@activediscourse/podcast-parser","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@activediscourse/podcast-parser","version":"1.0.0","description":"Parse XML podcast feeds into objects","license":"MIT","author":{"name":"Bo Lingen","email":"lingenbw@gmail.com","url":"https://github.com/citycide"},"contributors":[{"name":"Antti Kupila","email":"akupila@gmail.com"}],"repository":{"type":"git","url":"git+https://github.com/activediscourse/podcast-parser.git"},"homepage":"https://github.com/activediscourse/podcast-parser","bugs":{"url":"https://github.com/activediscourse/podcast-parser/issues"},"engines":{"node":">=10.10.0"},"main":"src/index.js","keywords":["podcast","node","browser","rss","feed","parse","parser","xml"],"scripts":{"lint":"eslint src test","test":"ava","prepublishOnly":"npm run lint && npm run test"},"dependencies":{"sax":"1.2.4"},"devDependencies":{"ava":"^3.1.0","eslint":"^6.8.0","eslint-config-standard":"^14.1.0","eslint-plugin-import":"^2.20.0","eslint-plugin-node":"^11.0.0","eslint-plugin-promise":"^4.2.1","eslint-plugin-standard":"^4.0.1"},"gitHead":"6f6724065fb609c9a32efb83404a2a923d170563","_id":"@activediscourse/podcast-parser@1.0.0","_nodeVersion":"13.7.0","_npmVersion":"6.13.6","dist":{"integrity":"sha512-2eCAVlY1eLMgS6eszJb7gJDESQFyqErT3Dsl6Zez4yFiEx1G9ExtqJNWpZoVs34AG1ONItznSgVi9JK8bR8aCg==","shasum":"9de6eaae1be05ecd4613a5604ea365bf0c1e85f2","tarball":"https://registry.npmjs.org/@activediscourse/podcast-parser/-/podcast-parser-1.0.0.tgz","fileCount":5,"unpackedSize":12967,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeNk6YCRA9TVsSAnZWagAAPr0P/3iswFJ/Pou/vjk25+b5\ngW2k7ut9RVSfeeg8uyIbR3DNGj37YzgEAmBPBPZPjmhHlaOHTALULMlluCVg\np6/nhzlpLSHVabr8veqoDSVAmvwYjYskc4GQ8Ptxr0v8QYxFg+/9vg00A+lI\nK9x6qYViUriALhltczS3ber/BYZl4O9NDysLRRTsv1dWCQHYoC9K3I+VTKt4\n76H7tUCuFSuc7ArXTFjGcbajwU6K42k2Grv1YcI2tKohfK5Urc+uiJynFRLw\n2gEci9yXm9bFTbJseuWIsldiSW1/ql2jrgIyk3ycupzty8luxZz0db2vhVfE\n7JpulGxFx6W9cM/cEn3msnF9qwGAFbm4HwISKDYpH475laQs7vuV/ftijmYg\n8B+jDy2F8g4UehzdC6IAiBRL42pZwrvNL/401/wSB/VD5LCBQqBfPV+8OeXD\nRiREWBjYIMgN9ZPA21tghVPYZ/h/+q3T4WlibPxxSpDK0yjn+sJ9m1MD88EF\nAbC+Ogqze9zztD22BIi7IfzMPWnt/TZ7aXpsGqjm5Ll2T4oOuwoF/riBbI6b\nTx4ztwmp4WjK9KtPAGasX08PYkCI3xJSImNwdSrdAe7XZUDrDtf4+st90XGd\nlp5oiNSXAUHzWk/yR2XAFAosEdNRVRYHLmzzKVDgdPu3lE1Ju1AkAcRIya3Q\ndvva\r\n=pLKi\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDiHxKmC6AbFc44gIWgKqAnoiUIf2UaqaM6/j0ylrBQDQIgdXBq+HT5fC7f7dlneUEaD1TuzRx1SGmKQ2fJfUjMssk="}]},"maintainers":[{"name":"citycide","email":"lingenbw@gmail.com"}],"_npmUser":{"name":"citycide","email":"lingenbw@gmail.com"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/podcast-parser_1.0.0_1580617368192_0.4929766748386031"},"_hasShrinkwrap":false}},"time":{"created":"2020-02-02T04:22:47.927Z","1.0.0":"2020-02-02T04:22:48.331Z","modified":"2022-04-04T11:17:50.213Z"},"maintainers":[{"email":"bo@lingen.life","name":"haltcase"},{"email":"lingenbw@gmail.com","name":"citycide"}],"description":"Parse XML podcast feeds into objects","homepage":"https://github.com/activediscourse/podcast-parser","keywords":["podcast","node","browser","rss","feed","parse","parser","xml"],"repository":{"type":"git","url":"git+https://github.com/activediscourse/podcast-parser.git"},"contributors":[{"name":"Antti Kupila","email":"akupila@gmail.com"}],"author":{"name":"Bo Lingen","email":"lingenbw@gmail.com","url":"https://github.com/citycide"},"bugs":{"url":"https://github.com/activediscourse/podcast-parser/issues"},"license":"MIT","readme":"# podcast-parser\r\n\r\nParse XML podcast RSS feeds into standardized objects.\r\n\r\n## installation\r\n\r\n```\r\nyarn add @activediscourse/podcast-parser\r\n```\r\n\r\n## usage\r\n\r\nPass a string containing XML source:\r\n\r\n```js\r\nconst parsePodcast = require(\"@activediscourse/podcast-parser\")\r\n\r\nparsePodcast(\"<podcast xml>\")\r\n  .then(feed => console.log(feed))\r\n  .catch(e => console.error(e))\r\n```\r\n\r\nThis library only handles parsing, so you'll need to fetch the feed\r\nseparately first. For example, using [node-fetch][node-fetch] (or\r\n[fetch][fetch] in the browser):\r\n\r\n```js\r\nconst fetch = require(\"node-fetch\")\r\nconst parsePodcast = require(\"@activediscourse/podcast-parser\")\r\n\r\n;(async () => {\r\n  const response = await fetch(\"https://pinecast.com/feed/activediscourse\")\r\n  const xml = await response.text()\r\n  const feed = await parsePodcast(xml)\r\n\r\n  return feed\r\n})()\r\n  .then(feed => console.log(feed))\r\n  .catch(e => console.error(e))\r\n```\r\n\r\n## output format\r\n\r\nThe output is opinionated with the goal of normalizing results across feeds:\r\n\r\n```json\r\n{\r\n  \"title\": \"<Podcast title>\",\r\n  \"description\": {\r\n    \"short\": \"<Podcast subtitle>\",\r\n    \"long\": \"<Podcast description>\"\r\n  },\r\n  \"link\": \"<Podcast link (usually website for podcast)>\",\r\n  \"image\": \"<Podcast image>\",\r\n  \"language\": \"<ISO 639 language>\",\r\n  \"copyright\": \"<Podcast copyright>\",\r\n  \"updated\": \"<pubDate or latest episode pubDate>\",\r\n  \"explicit\": \"<Podcast is explicit, true/false>\",\r\n  \"categories\": [\r\n    \"Category>Subcategory\"\r\n  ],\r\n  \"author\": \"<Author name>\",\r\n  \"owner\": {\r\n    \"name\":  \"<Owner name>\",\r\n    \"email\": \"<Owner email>\"\r\n  },\r\n  \"episodes\": [\r\n    {\r\n      \"guid\": \"<Unique id>\",\r\n      \"title\": \"<Episode title>\",\r\n      \"subtitle\": \"<Episode subtitle>\",\r\n      \"description\": \"<Episode description>\",\r\n      \"rawDescription\": \"<Episode description stripped of HTML tags>\",\r\n      \"explicit\": \"<Episode is is explicit, true/false>\",\r\n      \"image\": \"<Episode image>\",\r\n      \"published\": \"<date>\",\r\n      \"duration\": 120,\r\n      \"categories\": [\r\n        \"Category\"\r\n      ],\r\n      \"enclosure\": {\r\n        \"filesize\": 5650889,\r\n        \"type\": \"audio/mpeg\",\r\n        \"url\": \"<mp3 file>\"\r\n      }\r\n    }\r\n  ]\r\n}\r\n```\r\n\r\n## notes\r\n\r\n### language\r\n\r\nMany podcasts have the language set something like `en`. A best effort attempt\r\nis made to normalize language strings to an [IETF language code][IETF], so for\r\nexample `en` will be converted to `en-us`. Non-English languages will be presented\r\nfor example as `de-DE`.\r\n\r\n### normalization\r\n\r\nNot all feeds can be guaranteed to contain all properties, so they are simply\r\nommited from the output in that case.\r\n\r\nEpisode categories are included as an empty array if the podcast isn't\r\nassigned any categories.\r\n\r\nEpisodes are sorted in descending order by publish date.\r\n\r\n## development\r\n\r\n1. Clone the repo: `git clone https://github.com/activediscourse/podcast-parser.git`\r\n2. Move into the new directory: `cd podcast-parser`\r\n3. Install dependencies: `yarn`\r\n4. Build the source: `yarn build`\r\n5. Run tests: `yarn test`\r\n\r\n## license\r\n\r\nMIT © Bo Lingen / citycide\r\n\r\nBased on [`node-podcast-parser`][node-podcast-parser], also MIT, © Antti Kupila.\r\n\r\nSee [license](license)\r\n\r\n[fetch]: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch\r\n[node-fetch]: https://github.com/node-fetch/node-fetch\r\n[node-podcast-parser]: https://github.com/akupila/node-podcast-parser\r\n[IETF]: https://en.wikipedia.org/wiki/IETF_language_tag\r\n","readmeFilename":"readme.md"}