Merge pull request #12638 from iptv-org/patch-2023.04.48

Add "format" script
This commit is contained in:
Aleksandr Statciuk 2023-05-01 01:06:03 +03:00 committed by GitHub
commit 116c589ed1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 157 additions and 54 deletions

View File

@ -1,14 +1,11 @@
# IPTV
[![auto-update](https://github.com/iptv-org/iptv/actions/workflows/auto-update.yml/badge.svg)](https://github.com/iptv-org/iptv/actions/workflows/auto-update.yml)
Collection of publicly available IPTV (Internet Protocol television) channels from all over the world.
## Table of contents
- 🚀 [How to use?](#how-to-use)
- 📺 [Playlists](#playlists)
- 🗓 [EPG](#epg)
- 🗄 [Database](#database)
- 👨‍💻 [API](#api)
- 📚 [Resources](#resources)

View File

@ -5,14 +5,16 @@
"api:generate": "node scripts/commands/api/generate.js",
"api:deploy": "npx gh-pages -a -m \"Deploy to iptv-org/api\" -d .api -r https://$GITHUB_TOKEN@github.com/iptv-org/api.git -x",
"db:create": "node scripts/commands/database/create.js",
"playlist:format": "node scripts/commands/playlist/format.js",
"playlist:generate": "node scripts/commands/playlist/generate.js",
"playlist:validate": "node scripts/commands/playlist/validate.js",
"playlist:lint": "npx m3u-linter -c m3u-linter.json",
"playlist:deploy": "npx gh-pages -a -m \"Deploy to GitHub Pages\" -d .gh-pages -r https://$GITHUB_TOKEN@github.com/iptv-org/iptv.git -x",
"readme:update": "node scripts/commands/readme/update.js",
"format": "npm run db:create && npm run playlist:format",
"check": "npm run api:load && npm run playlist:lint && npm run playlist:validate",
"update": "npm run api:load && npm run db:create && npm run playlist:generate && npm run api:generate && npm run readme:update",
"deploy": "npm run playlist:deploy && npm run api:deploy",
"check": "npm run api:load && npm run playlist:lint && npm run playlist:validate",
"test": "jest --runInBand"
},
"jest": {

2
scripts/.gitignore vendored
View File

@ -1,2 +0,0 @@
/logs/
/database/

View File

@ -1,10 +1,10 @@
#!/bin/bash
mkdir -p scripts/data
curl -L -o scripts/data/blocklist.json https://iptv-org.github.io/api/blocklist.json
curl -L -o scripts/data/categories.json https://iptv-org.github.io/api/categories.json
curl -L -o scripts/data/channels.json https://iptv-org.github.io/api/channels.json
curl -L -o scripts/data/countries.json https://iptv-org.github.io/api/countries.json
curl -L -o scripts/data/languages.json https://iptv-org.github.io/api/languages.json
curl -L -o scripts/data/regions.json https://iptv-org.github.io/api/regions.json
curl -L -o scripts/data/subdivisions.json https://iptv-org.github.io/api/subdivisions.json
mkdir -p scripts/tmp/data
curl -L -o scripts/tmp/data/blocklist.json https://iptv-org.github.io/api/blocklist.json
curl -L -o scripts/tmp/data/categories.json https://iptv-org.github.io/api/categories.json
curl -L -o scripts/tmp/data/channels.json https://iptv-org.github.io/api/channels.json
curl -L -o scripts/tmp/data/countries.json https://iptv-org.github.io/api/countries.json
curl -L -o scripts/tmp/data/languages.json https://iptv-org.github.io/api/languages.json
curl -L -o scripts/tmp/data/regions.json https://iptv-org.github.io/api/regions.json
curl -L -o scripts/tmp/data/subdivisions.json https://iptv-org.github.io/api/subdivisions.json

View File

@ -1,4 +1,4 @@
const { db, file, parser, store, logger, api } = require('../../core')
const { db, file, parser, store, logger } = require('../../core')
const { program } = require('commander')
const _ = require('lodash')
@ -8,21 +8,7 @@ const options = program
.opts()
async function main() {
logger.info('starting...')
await saveToDatabase(await findStreams())
}
main()
async function findStreams() {
logger.info(`loading channels...`)
await api.channels.load()
const channels = _.keyBy(await api.channels.all(), 'id')
logger.info(`looking for streams...`)
await db.streams.load()
const streams = []
const files = await file.list(`${options.inputDir}/**/*.m3u`)
for (const filepath of files) {
@ -31,9 +17,8 @@ async function findStreams() {
item.filepath = filepath
const stream = store.create()
const channel = channels[item.tvg.id]
stream.set('channel', { channel: channel ? channel.id : null })
stream.set('channel', { channel: item.tvg.id })
stream.set('title', { title: item.name })
stream.set('filepath', { filepath: item.filepath })
stream.set('url', { url: item.url })
@ -45,13 +30,11 @@ async function findStreams() {
}
logger.info(`found ${streams.length} streams`)
return streams
}
async function saveToDatabase(streams = []) {
logger.info('saving to the database...')
await db.streams.load()
await db.streams.reset()
const data = streams.map(stream => stream.data())
await db.streams.insert(data)
}
main()

View File

@ -0,0 +1,26 @@
const { create: createPlaylist } = require('../../core/playlist')
const { db, logger, file } = require('../../core')
const { orderBy } = require('natural-orderby')
const _ = require('lodash')
async function main() {
logger.info('loading streams...')
await db.streams.load()
let streams = await db.streams.find({})
logger.info('sorting links...')
streams = orderBy(
streams,
['channel', s => (s.channel ? '' : s.title), 'url'],
['asc', 'asc', 'asc']
)
logger.info('saving...')
const files = _.groupBy(streams, 'filepath')
for (const filepath in files) {
const playlist = createPlaylist(files[filepath], { public: false })
await file.create(filepath, playlist.toString())
}
}
main()

View File

@ -2,7 +2,7 @@ const { file, markdown, parser, logger, api } = require('../../core')
const { create: createTable } = require('../../core/table')
const { program } = require('commander')
const LOGS_DIR = process.env.LOGS_DIR || 'scripts/logs/generators'
const LOGS_DIR = process.env.LOGS_DIR || 'scripts/tmp/logs/generators'
const options = program
.option('-c, --config <config>', 'Set path to config file', '.readme/config.json')

View File

@ -1,7 +1,7 @@
const _ = require('lodash')
const file = require('./file')
const DATA_DIR = process.env.DATA_DIR || './scripts/data'
const DATA_DIR = process.env.DATA_DIR || './scripts/tmp/data'
class API {
constructor(filepath) {

View File

@ -1,7 +1,7 @@
const nedb = require('nedb-promises')
const file = require('./file')
const DB_DIR = process.env.DB_DIR || './scripts/database'
const DB_DIR = process.env.DB_DIR || './scripts/tmp/database'
class Database {
constructor(filepath) {

View File

@ -4,7 +4,7 @@ const logger = require('./logger')
const file = require('./file')
const PUBLIC_DIR = process.env.PUBLIC_DIR || '.gh-pages'
const LOGS_DIR = process.env.LOGS_DIR || 'scripts/logs/generators'
const LOGS_DIR = process.env.LOGS_DIR || 'scripts/tmp/logs/generators'
const generator = {}

View File

@ -1,2 +1,2 @@
*
*
!.gitignore

View File

@ -1,14 +1,11 @@
# IPTV
[![auto-update](https://github.com/iptv-org/iptv/actions/workflows/auto-update.yml/badge.svg)](https://github.com/iptv-org/iptv/actions/workflows/auto-update.yml)
Collection of publicly available IPTV (Internet Protocol television) channels from all over the world.
## Table of contents
- 🚀 [How to use?](#how-to-use)
- 📺 [Playlists](#playlists)
- 🗓 [EPG](#epg)
- 🗄 [Database](#database)
- 👨‍💻 [API](#api)
- 📚 [Resources](#resources)
@ -454,10 +451,6 @@ Same thing, but split up into separate files:
</details>
## EPG
The playlists already contain links to all guides, so players with support the `x-tvg-url` tag should load it automatically. Otherwise, you can choose one of the guides featured in the [iptv-org/epg](https://github.com/iptv-org/epg) repository.
## Database
All channel data is taken from the [iptv-org/database](https://github.com/iptv-org/database) repository. If you find any errors please open a new [issue](https://github.com/iptv-org/database/issues) there.

View File

@ -1,6 +1,7 @@
{"channel":null,"title":"TVN","filepath":"tests/__data__/input/streams/us_blocked.m3u","url":"https://example.com/playlist2.m3u8","http_referrer":null,"user_agent":null,"_id":"UAYbCvjOWvqXHH95"}
{"channel":"LibyasChannel.ly","title":"Libyas Channel","filepath":"tests/__data__/input/streams/ly.m3u","url":"https://master.starmena-cloud.com/hls/libyas.m3u8","http_referrer":null,"user_agent":null,"_id":"I0rJlwp3rZEy2SnG"}
{"channel":"EverydayHeroes.us","title":"Everyday Heroes (720p)","filepath":"tests/__data__/input/streams/us_blocked.m3u","url":"https://a.jsrdn.com/broadcast/7b1451fa52/+0000/c.m3u8","http_referrer":null,"user_agent":null,"_id":"tdzk1IN7wLJxfGab"}
{"channel":null,"title":"ATV (720p) [Offline]","filepath":"tests/__data__/input/streams/ad.m3u","url":"https://iptv-all.lanesh4d0w.repl.co/andorra/atv","http_referrer":"http://imn.iq","user_agent":"Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148","_id":"3evMHt3nFsZjhzas"}
{"channel":null,"title":"ABC (720p)","filepath":"tests/__data__/input/streams/wrong_id.m3u","url":"https://example.com/playlist2.m3u8","http_referrer":null,"user_agent":null,"_id":"agJlTEr8wwpbWgw0"}
{"channel":null,"title":"Fox Sports 2 Asia (Thai) (720p)","filepath":"tests/__data__/input/streams/us_blocked.m3u","url":"https://example.com/playlist.m3u8","http_referrer":null,"user_agent":null,"_id":"FpMhoWjtpnVuYlO9"}
{"channel":"ATV.ad","title":"ATV (720p) [Offline]","filepath":"tests/__data__/input/streams/ad.m3u","url":"https://iptv-all.lanesh4d0w.repl.co/andorra/atv","http_referrer":"http://imn.iq","user_agent":"Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148","_id":"k4XpZHQAyqyTbcf0"}
{"channel":"LibyasChannel.ly","title":"Libyas Channel","filepath":"tests/__data__/input/streams/ly.m3u","url":"https://master.starmena-cloud.com/hls/libyas.m3u8","http_referrer":null,"user_agent":null,"_id":"ki4YjAoNNoIY8sSm"}
{"channel":null,"title":"1A Network (720p)","filepath":"tests/__data__/input/streams/unsorted.m3u","url":"https://simultv.s.llnwi.net/n4s4/2ANetwork/interlink.m3u8","http_referrer":null,"user_agent":null,"_id":"IZpCJjjWPaBYh7Dr"}
{"channel":null,"title":"Fox Sports 2 Asia (Thai) (720p)","filepath":"tests/__data__/input/streams/us_blocked.m3u","url":"https://example.com/playlist.m3u8","http_referrer":null,"user_agent":null,"_id":"6c4J4vs8K69wMJ7S"}
{"channel":null,"title":"TVN","filepath":"tests/__data__/input/streams/us_blocked.m3u","url":"https://example.com/playlist2.m3u8","http_referrer":null,"user_agent":null,"_id":"xEmbX384v3t3F5Wg"}
{"channel":"EverydayHeroes.us","title":"Everyday Heroes (720p)","filepath":"tests/__data__/input/streams/us_blocked.m3u","url":"https://a.jsrdn.com/broadcast/7b1451fa52/+0000/c.m3u8","http_referrer":null,"user_agent":null,"_id":"BZsRPt8VS4kIJnfi"}
{"channel":"qib22lAq1L.us","title":"ABC (720p)","filepath":"tests/__data__/input/streams/wrong_id.m3u","url":"https://example.com/playlist2.m3u8","http_referrer":null,"user_agent":null,"_id":"eFUlUnST5zJSBWAF"}

View File

@ -0,0 +1,5 @@
#EXTM3U
#EXTINF:-1 tvg-id="AndorraTV.ad" user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148",ATV (720p) [Offline]
#EXTVLCOPT:http-referrer=http://imn.iq
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148
https://iptv-all.lanesh4d0w.repl.co/andorra/atv

View File

@ -0,0 +1,5 @@
#EXTM3U
#EXTINF:-1 tvg-id="KayhanTV.af",Kayhan TV
http://208.93.117.113/live/Stream1/playlist.m3u8
#EXTINF:-1 tvg-id="Sharq.af",Sharq
http://51.210.199.50/hls/stream.m3u8

View File

@ -0,0 +1,6 @@
#EXTM3U
#EXTINF:-1 tvg-id="Telearuba.aw",Telearuba (720p)
http://cdn.setar.aw:1935/Telearuba/smil:telearuba.smil/playlist.m3u8
#EXTINF:-1 tvg-id="Telearuba.aw" user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36",Telearuba (480p) [Not 24/7]
#EXTVLCOPT:http-user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36
https://backend-server-dot-telearuba-app.appspot.com/media/livestream13/playlist.m3u8

View File

@ -0,0 +1,7 @@
#EXTM3U
#EXTINF:-1 tvg-id="",Caillou
https://dhx-caillou-1-es.samsung.wurl.tv/playlist.m3u8
#EXTINF:-1 tvg-id="",iHola Play
https://rakuten-hola-2-es.samsung.wurl.tv/playlist.m3u8
#EXTINF:-1 tvg-id="",Planeta Junior TV
https://deaplaneta-planetakidz-1-es.samsung.wurl.tv/playlist.m3u8

View File

@ -0,0 +1,11 @@
#EXTM3U
#EXTINF:-1 tvg-id="NPO1.nl",NPO 1 (342p) [Geo-blocked]
http://resolver.streaming.api.nos.nl/livestream?url=/live/npo/tvlive/npo1/npo1.isml/.m3u8
#EXTINF:-1 tvg-id="NPO1.nl",NPO 1 (1080p) [Geo-blocked]
http://stream.tvtap.net:8081/live/nl-npo1.stream/30fps.m3u8
#EXTINF:-1 tvg-id="NPO1.nl",NPO 1 (1080p) [Geo-blocked]
http://stream.tvtap.net:8081/live/nl-npo1.stream/60fps.m3u8
#EXTINF:-1 tvg-id="NPO2.nl",NPO 2 (342p)
http://resolver.streaming.api.nos.nl/livestream?url=/live/npo/tvlive/npo2/npo2.isml/.m3u8
#EXTINF:-1 tvg-id="NPO2.nl",NPO 2 (302p) [Geo-blocked]
http://stream.tvtap.net:8081/live/nl-npo2.stream/playlist.m3u8

View File

@ -0,0 +1,3 @@
#EXTM3U
#EXTINF:-1 tvg-id="Tele2000.pe",Tele 2000
https://servilive.com:3126/live/tele2000live.m3u8

View File

@ -0,0 +1,9 @@
#EXTM3U
#EXTINF:-1 tvg-id="LDPRTV.ru",ЛДПР ТВ (1080p)
http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8
#EXTINF:-1 tvg-id="LDPRTV.ru",ЛДПР ТВ (1080p)
http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8
#EXTINF:-1 tvg-id="LDPRTV.ru",ЛДПР ТВ (1080p)
http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8
#EXTINF:-1 tvg-id="LDPRTV.ru",ЛДПР ТВ (1080p)
http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8

View File

@ -0,0 +1,5 @@
#EXTM3U
#EXTINF:-1 tvg-id="BBCNews.uk",BBC News HD (720p) [Not 24/7]
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8
#EXTINF:-1 tvg-id="BBCNews.uk",BBC News HD (480p) [Geo-blocked]
http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/playlist.m3u8

View File

@ -0,0 +1,20 @@
{"title":"ЛДПР ТВ (1080p)","channel":"LDPRTV.ru","filepath":"tests/__data__/output/streams/ru.m3u","url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8","http_referrer":null,"user_agent":null,"_id":"2ST8btby3mmsgPF3"}
{"title":"ЛДПР ТВ (1080p)","channel":"LDPRTV.ru","filepath":"tests/__data__/output/streams/ru.m3u","url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8","http_referrer":null,"user_agent":null,"_id":"2ST8btby3mmsgPF0"}
{"title":"ЛДПР ТВ (1080p)","channel":"LDPRTV.ru","filepath":"tests/__data__/output/streams/ru.m3u","url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8","http_referrer":null,"user_agent":null,"_id":"2ST8btby3mmsgPF1"}
{"title":"ЛДПР ТВ (1080p)","channel":"LDPRTV.ru","filepath":"tests/__data__/output/streams/ru.m3u","url":"http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8","http_referrer":null,"user_agent":null,"_id":"2ST8btby3mmsgPF2"}
{"title":"BBC News HD (720p) [Not 24/7]","channel":"BBCNews.uk","filepath":"tests/__data__/output/streams/uk.m3u","url":"http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/index.m3u8","http_referrer":null,"user_agent":null,"_id":"3TbieV1ptnZVCIdn"}
{"title":"ATV (720p) [Offline]","channel":"AndorraTV.ad","filepath":"tests/__data__/output/streams/ad.m3u","url":"https://iptv-all.lanesh4d0w.repl.co/andorra/atv","http_referrer":"http://imn.iq","user_agent":"Mozilla/5.0 (iPhone; CPU iPhone OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148","_id":"I6cjG2xCBRFFP4sz"}
{"title":"BBC News HD (480p) [Geo-blocked]","channel":"BBCNews.uk","filepath":"tests/__data__/output/streams/uk.m3u","url":"http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/playlist.m3u8","http_referrer":null,"user_agent":null,"_id":"WTbieV1ptnZVCIdn"}
{"title":"Kayhan TV","channel":"KayhanTV.af","filepath":"tests/__data__/output/streams/af.m3u","url":"http://208.93.117.113/live/Stream1/playlist.m3u8","http_referrer":null,"user_agent":null,"_id":"cFFpFVzSn6xFMUF3"}
{"title":"Sharq","channel":"Sharq.af","filepath":"tests/__data__/output/streams/af.m3u","url":"http://51.210.199.50/hls/stream.m3u8","http_referrer":null,"user_agent":null,"_id":"u7iyA6cjtf1iWWAZ"}
{"channel":"NPO1.nl","title":"NPO 1 (342p) [Geo-blocked]","filepath":"tests/__data__/output/streams/nl.m3u","url":"http://resolver.streaming.api.nos.nl/livestream?url=/live/npo/tvlive/npo1/npo1.isml/.m3u8","http_referrer":null,"user_agent":null,"_id":"mvUyDVuS5gc8gLJV"}
{"channel":"NPO1.nl","title":"NPO 1 (1080p) [Geo-blocked]","filepath":"tests/__data__/output/streams/nl.m3u","url":"http://stream.tvtap.net:8081/live/nl-npo1.stream/30fps.m3u8","http_referrer":null,"user_agent":null,"_id":"8WVbsxsYeOL7kHQl"}
{"channel":"NPO1.nl","title":"NPO 1 (1080p) [Geo-blocked]","filepath":"tests/__data__/output/streams/nl.m3u","url":"http://stream.tvtap.net:8081/live/nl-npo1.stream/60fps.m3u8","http_referrer":null,"user_agent":null,"_id":"8WVbsxsYeOL7kHQB"}
{"channel":"NPO2.nl","title":"NPO 2 (342p)","filepath":"tests/__data__/output/streams/nl.m3u","url":"http://resolver.streaming.api.nos.nl/livestream?url=/live/npo/tvlive/npo2/npo2.isml/.m3u8","http_referrer":null,"user_agent":null,"_id":"2p1TNGO0mF0MJOGy"}
{"channel":"NPO2.nl","title":"NPO 2 (302p) [Geo-blocked]","filepath":"tests/__data__/output/streams/nl.m3u","url":"http://stream.tvtap.net:8081/live/nl-npo2.stream/playlist.m3u8","http_referrer":null,"user_agent":null,"_id":"nhL85BL7YM5OR7cn"}
{"title":"Tele 2000","channel":"Tele2000.pe","filepath":"tests/__data__/output/streams/pe.m3u","url":"https://servilive.com:3126/live/tele2000live.m3u8","http_referrer":null,"user_agent":null,"_id":"cF0pFVzSn6xFMUF3"}
{"title":"Planeta Junior TV","channel":"","filepath":"tests/__data__/output/streams/es.m3u","url":"https://deaplaneta-planetakidz-1-es.samsung.wurl.tv/playlist.m3u8","http_referrer":null,"user_agent":null,"_id":"1BT8btby3mmsgPF0"}
{"title":"Caillou","channel":"","filepath":"tests/__data__/output/streams/es.m3u","url":"https://dhx-caillou-1-es.samsung.wurl.tv/playlist.m3u8","http_referrer":null,"user_agent":null,"_id":"3BT8btby3mmsgPF0"}
{"title":"iHola Play","channel":"","filepath":"tests/__data__/output/streams/es.m3u","url":"https://rakuten-hola-2-es.samsung.wurl.tv/playlist.m3u8","http_referrer":null,"user_agent":null,"_id":"2BT8btby3mmsgPF0"}
{"title":"Telearuba (720p)","channel":"Telearuba.aw","filepath":"tests/__data__/output/streams/aw.m3u","url":"http://cdn.setar.aw:1935/Telearuba/smil:telearuba.smil/playlist.m3u8","http_referrer":null,"user_agent":null,"_id":"6BT8btby3mmsgPF0"}
{"title":"Telearuba (480p) [Not 24/7]","channel":"Telearuba.aw","filepath":"tests/__data__/output/streams/aw.m3u","url":"https://backend-server-dot-telearuba-app.appspot.com/media/livestream13/playlist.m3u8","http_referrer":null,"user_agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36","_id":"4BT8btby3mmsgPF0"}

View File

@ -0,0 +1,32 @@
const { execSync } = require('child_process')
const fs = require('fs-extra')
const path = require('path')
const glob = require('glob')
beforeEach(() => {
fs.emptyDirSync('tests/__data__/output')
fs.copyFileSync(
'tests/__data__/input/database/playlist_format.streams.db',
'tests/__data__/output/streams.db'
)
const stdout = execSync('DB_DIR=tests/__data__/output npm run playlist:format', {
encoding: 'utf8'
})
})
it('can format playlists', () => {
const files = glob
.sync('tests/__data__/expected/streams/*.m3u')
.map(f => f.replace('tests/__data__/expected/', ''))
files.forEach(filepath => {
expect(content(`output/${filepath}`), filepath).toBe(content(`expected/${filepath}`))
})
})
function content(filepath) {
return fs.readFileSync(`tests/__data__/${filepath}`, {
encoding: 'utf8'
})
}