123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- const { URL, domainToUnicode } = require('url')
- const CHAR_LOWERCASE_A = 97
- const CHAR_LOWERCASE_Z = 122
- const isWindows = process.platform === 'win32'
- class ERR_INVALID_FILE_URL_HOST extends TypeError {
- constructor (platform) {
- super(`File URL host must be "localhost" or empty on ${platform}`)
- this.code = 'ERR_INVALID_FILE_URL_HOST'
- }
- toString () {
- return `${this.name} [${this.code}]: ${this.message}`
- }
- }
- class ERR_INVALID_FILE_URL_PATH extends TypeError {
- constructor (msg) {
- super(`File URL path ${msg}`)
- this.code = 'ERR_INVALID_FILE_URL_PATH'
- }
- toString () {
- return `${this.name} [${this.code}]: ${this.message}`
- }
- }
- class ERR_INVALID_ARG_TYPE extends TypeError {
- constructor (name, actual) {
- super(`The "${name}" argument must be one of type string or an instance ` +
- `of URL. Received type ${typeof actual} ${actual}`)
- this.code = 'ERR_INVALID_ARG_TYPE'
- }
- toString () {
- return `${this.name} [${this.code}]: ${this.message}`
- }
- }
- class ERR_INVALID_URL_SCHEME extends TypeError {
- constructor (expected) {
- super(`The URL must be of scheme ${expected}`)
- this.code = 'ERR_INVALID_URL_SCHEME'
- }
- toString () {
- return `${this.name} [${this.code}]: ${this.message}`
- }
- }
- const isURLInstance = (input) => {
- return input != null && input.href && input.origin
- }
- const getPathFromURLWin32 = (url) => {
- const hostname = url.hostname
- let pathname = url.pathname
- for (let n = 0; n < pathname.length; n++) {
- if (pathname[n] === '%') {
- const third = pathname.codePointAt(n + 2) | 0x20
- if ((pathname[n + 1] === '2' && third === 102) ||
- (pathname[n + 1] === '5' && third === 99)) {
- throw new ERR_INVALID_FILE_URL_PATH('must not include encoded \\ or / characters')
- }
- }
- }
- pathname = pathname.replace(/\//g, '\\')
- pathname = decodeURIComponent(pathname)
- if (hostname !== '') {
- return `\\\\${domainToUnicode(hostname)}${pathname}`
- }
- const letter = pathname.codePointAt(1) | 0x20
- const sep = pathname[2]
- if (letter < CHAR_LOWERCASE_A || letter > CHAR_LOWERCASE_Z ||
- (sep !== ':')) {
- throw new ERR_INVALID_FILE_URL_PATH('must be absolute')
- }
- return pathname.slice(1)
- }
- const getPathFromURLPosix = (url) => {
- if (url.hostname !== '') {
- throw new ERR_INVALID_FILE_URL_HOST(process.platform)
- }
- const pathname = url.pathname
- for (let n = 0; n < pathname.length; n++) {
- if (pathname[n] === '%') {
- const third = pathname.codePointAt(n + 2) | 0x20
- if (pathname[n + 1] === '2' && third === 102) {
- throw new ERR_INVALID_FILE_URL_PATH('must not include encoded / characters')
- }
- }
- }
- return decodeURIComponent(pathname)
- }
- const fileURLToPath = (path) => {
- if (typeof path === 'string') {
- path = new URL(path)
- } else if (!isURLInstance(path)) {
- throw new ERR_INVALID_ARG_TYPE('path', ['string', 'URL'], path)
- }
- if (path.protocol !== 'file:') {
- throw new ERR_INVALID_URL_SCHEME('file')
- }
- return isWindows
- ? getPathFromURLWin32(path)
- : getPathFromURLPosix(path)
- }
- module.exports = fileURLToPath
|