diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e30c4ac..61e9025 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -11,15 +11,15 @@ jobs: matrix: node-version: - 16 - - 14 + - 18 + - latest steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} - run: npm install - run: npm test - - uses: codecov/codecov-action@v1 - if: matrix.node-version == 14 + - uses: codecov/codecov-action@v3 with: - fail_ci_if_error: true \ No newline at end of file + token: ${{ secrets.CODECOV_TOKEN }} diff --git a/__tests__/builds/cjs-module.test.js b/__tests__/builds/cjs-module.test.js new file mode 100644 index 0000000..c319675 --- /dev/null +++ b/__tests__/builds/cjs-module.test.js @@ -0,0 +1,10 @@ +/* istanbul ignore file */ +/* eslint-disable unicorn/prefer-module */ +const getVideoId = require('../../dist/get-video-id.js'); + +describe('bundled CJS module', () => { + test('has the expected API', () => { + expect(typeof getVideoId).toBe('function'); + expect(getVideoId('https://www.youtube.com/watch?v=1234').id).toBe('1234'); + }); +}); diff --git a/__tests__/builds/index.html b/__tests__/builds/index.html index c548cc2..22b8b3a 100644 --- a/__tests__/builds/index.html +++ b/__tests__/builds/index.html @@ -14,7 +14,7 @@ - + + ``` ###### Download @@ -48,18 +48,18 @@ Simply supply the module with a url or embed string matching any of the [pattern ```js import getVideoId from 'get-video-id'; -getVideoId('https://www.youtube.com/watch?v=8rSH8-pbHZ0'); -//=> { id: '8rSH8-pbHZ0', service: 'youtube' } +getVideoId('https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +//=> { id: 'dQw4w9WgXcQ', service: 'youtube' } -const { id } = getVideoId('https://www.youtube.com/watch?v=8rSH8-pbHZ0'); -//=> '8rSH8-pbHZ0' +const { id } = getVideoId('https://www.youtube.com/watch?v=dQw4w9WgXcQ'); +//=> 'dQw4w9WgXcQ' ``` get-video-id can also find the video buried in a Google redirection URL if it contains a reference to any of the supported URL patterns. ```js -getVideoId('https://www.google.cz/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0ahUKEwj30L2MvpDVAhUFZVAKHb8CBaYQuAIIIjAA&url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DeG1uDU0rSLw&usg=AFQjCNECyDn3DQL7U6VW2CnXQQjB0gNKqA'); -//=> { id: 'eG1uDU0rSLw', service: 'youtube' } +getVideoId('https://www.google.cz/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0ahUKEwj30L2MvpDVAhUFZVAKHb8CBaYQuAIIIjAA&url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DdQw4w9WgXcQ'); +//=> { id: 'dQw4w9WgXcQ', service: 'youtube' } ``` ## API @@ -79,7 +79,7 @@ Returns a metadata `Object` with the video `id` and `service` name: Type: `String` -The url (or embed code) from which you want to find the video id. See the +The url (or embed code, or google redirect url) from which you want to find the video id. See the [Patterns section](https://github.com/radiovisual/get-video-id#patterns) to see the formats that can be supplied. ## Patterns @@ -167,6 +167,13 @@ http://www.youtube.com/attribution_link?u=/watch?v=* http://www.youtube.com/attribution_link?/watch?v=* ``` +**YouTube live URLs** +``` +https://www.youtube.com/live/* +https://youtube.com/live/* +https://youtube.com/live/*? +``` + **Google Redirection to YouTube** ``` diff --git a/rollup.config.js b/rollup.config.js index 464c3f6..80a24de 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,70 +1,93 @@ -import resolve from 'rollup-plugin-node-resolve'; -import cleaner from 'rollup-plugin-cleaner'; -import babel from 'rollup-plugin-babel'; -import commonjs from 'rollup-plugin-commonjs'; -import {terser} from 'rollup-plugin-terser'; -import pkg from './package.json'; +import {readFile} from 'node:fs/promises'; +import nodeResolve from '@rollup/plugin-node-resolve'; +import babel from '@rollup/plugin-babel'; +import commonjs from '@rollup/plugin-commonjs'; +import terser from '@rollup/plugin-terser'; -const minified = file => file.replace(/.js/, '.min.js'); +// Remove these 2-lines to import JSON once with { type: 'json' } has official support. https://github.com/eslint/eslint/discussions/15305 +const fileUrl = new URL('package.json', import.meta.url); +const pkg = JSON.parse(await readFile(fileUrl, 'utf8')); -const banner = `/*! get-video-id v${pkg.version} | @license MIT © Michael Wuergler | https://github.com/radiovisual/get-video-id */`; +const minifiedExtension = file => file.replace(/.js/, '.min.js'); + +const babelRuntimeVersion = pkg.dependencies['@babel/runtime'].replace( + /^\D*/, + '', +); + +/** + * Used for generating external dependencies + * See: https://github.com/rollup/rollup-plugin-babel/issues/148#issuecomment-399696316 + */ +const makeExternalPredicate = externalArray => { + if (externalArray.length === 0) { + return () => false; + } + + const pattern = new RegExp(`^(${externalArray.join('|')})($|/)`); + + return id => pattern.test(id); +}; + +const outputOptions = { + sourcemap: true, + banner: `/*! get-video-id v${pkg.version} | @license MIT © Michael Wuergler | https://github.com/radiovisual/get-video-id */`, +}; const config = { input: './src/index.js', output: [ { file: pkg.main, - format: 'umd', - sourcemap: true, - name: 'getVideoId', - banner, + format: 'cjs', + ...outputOptions, }, { - file: minified(pkg.main), - format: 'umd', - sourcemap: true, - name: 'getVideoId', - banner, + file: minifiedExtension(pkg.main), + format: 'cjs', + plugins: [terser()], + ...outputOptions, }, { file: pkg.module, format: 'esm', - sourcemap: true, - banner, + ...outputOptions, }, { - file: minified(pkg.module), + file: minifiedExtension(pkg.module), format: 'esm', - sourcemap: true, - banner, + plugins: [terser()], + ...outputOptions, + }, + { + file: minifiedExtension('dist/get-video-id.umd.js'), + format: 'umd', + name: 'getVideoId', + plugins: [terser()], + ...outputOptions, + }, + { + file: 'dist/get-video-id.umd.js', + format: 'umd', + name: 'getVideoId', + ...outputOptions, }, ], - preserveModules: false, + external: makeExternalPredicate([ + // Handles both dependencies and peer dependencies so we don't have to manually maintain a list + ...Object.keys(pkg.dependencies || {}), + ...Object.keys(pkg.peerDependencies || {}), + ]), plugins: [ - cleaner({ - targets: ['dist'], - }), - resolve({ - mainFields: ['module', 'main'], - }), + nodeResolve(), commonjs(), babel({ - exclude: 'node_modules/**', - babelrc: false, - presets: [ - [ - '@babel/preset-env', - { - modules: false, - }, - ], + babelHelpers: 'runtime', + exclude: /node_modules/, + plugins: [ + ['@babel/plugin-transform-runtime', {version: babelRuntimeVersion}], ], - }), - terser({ - output: { - comments: 'some', - }, - include: [/^.+\.min\.js$/], + presets: [['@babel/preset-env', {targets: 'defaults'}]], }), ], }; diff --git a/src/index.js b/src/index.js index d521096..88753db 100644 --- a/src/index.js +++ b/src/index.js @@ -5,7 +5,8 @@ import videopress from './videopress.js'; import microsoftStream from './microsoftstream.js'; import tiktok from './tiktok.js'; import dailymotion from './dailymotion.js'; -import getSrc from './utils/get-src.js'; +import sanitizeUrl from './utils/sanitize-url.js'; +import extractGoogleRedirectionUrl from './utils/extract-google-redirection-url.js'; /** * Get the id and service from a video url. @@ -17,71 +18,47 @@ function getVideoId(urlString) { throw new TypeError('get-video-id expects a string'); } - let string_ = urlString; - - if (/