AK-21/Graphite-Industrial-Intelligence
0
1// A derivative work based on:2// <https://github.com/browserify/path-browserify>.3// Which is licensed:4//5// MIT License6//7// Copyright (c) 2013 James Halliday8//9// Permission is hereby granted, free of charge, to any person obtaining a copy of10// this software and associated documentation files (the "Software"), to deal in11// the Software without restriction, including without limitation the rights to12// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of13// the Software, and to permit persons to whom the Software is furnished to do so,14// subject to the following conditions:15//16// The above copyright notice and this permission notice shall be included in all17// copies or substantial portions of the Software.18//19// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR20// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS21// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR22// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER23// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN24// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.25// A derivative work based on:26//27// Parts of that are extracted from Node’s internal `path` module:28// <https://github.com/nodejs/node/blob/master/lib/path.js>.29// Which is licensed:30//31// Copyright Joyent, Inc. and other Node contributors.32//33// Permission is hereby granted, free of charge, to any person obtaining a34// copy of this software and associated documentation files (the35// "Software"), to deal in the Software without restriction, including36// without limitation the rights to use, copy, modify, merge, publish,37// distribute, sublicense, and/or sell copies of the Software, and to permit38// persons to whom the Software is furnished to do so, subject to the39// following conditions:40//41// The above copyright notice and this permission notice shall be included42// in all copies or substantial portions of the Software.43//44// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS45// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF46// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN47// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,48// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR49// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE50// USE OR OTHER DEALINGS IN THE SOFTWARE.51 52export const minpath = {basename, dirname, extname, join, sep: '/'}53 54/* eslint-disable max-depth, complexity */55 56/**57 * Get the basename from a path.58 *59 * @param {string} path60 * File path.61 * @param {string | null | undefined} [extname]62 * Extension to strip.63 * @returns {string}64 * Stem or basename.65 */66function basename(path, extname) {67 if (extname !== undefined && typeof extname !== 'string') {68 throw new TypeError('"ext" argument must be a string')69 }70 71 assertPath(path)72 let start = 073 let end = -174 let index = path.length75 /** @type {boolean | undefined} */76 let seenNonSlash77 78 if (79 extname === undefined ||80 extname.length === 0 ||81 extname.length > path.length82 ) {83 while (index--) {84 if (path.codePointAt(index) === 47 /* `/` */) {85 // If we reached a path separator that was not part of a set of path86 // separators at the end of the string, stop now.87 if (seenNonSlash) {88 start = index + 189 break90 }91 } else if (end < 0) {92 // We saw the first non-path separator, mark this as the end of our93 // path component.94 seenNonSlash = true95 end = index + 196 }97 }98 99 return end < 0 ? '' : path.slice(start, end)100 }101 102 if (extname === path) {103 return ''104 }105 106 let firstNonSlashEnd = -1107 let extnameIndex = extname.length - 1108 109 while (index--) {110 if (path.codePointAt(index) === 47 /* `/` */) {111 // If we reached a path separator that was not part of a set of path112 // separators at the end of the string, stop now.113 if (seenNonSlash) {114 start = index + 1115 break116 }117 } else {118 if (firstNonSlashEnd < 0) {119 // We saw the first non-path separator, remember this index in case120 // we need it if the extension ends up not matching.121 seenNonSlash = true122 firstNonSlashEnd = index + 1123 }124 125 if (extnameIndex > -1) {126 // Try to match the explicit extension.127 if (path.codePointAt(index) === extname.codePointAt(extnameIndex--)) {128 if (extnameIndex < 0) {129 // We matched the extension, so mark this as the end of our path130 // component131 end = index132 }133 } else {134 // Extension does not match, so our result is the entire path135 // component136 extnameIndex = -1137 end = firstNonSlashEnd138 }139 }140 }141 }142 143 if (start === end) {144 end = firstNonSlashEnd145 } else if (end < 0) {146 end = path.length147 }148 149 return path.slice(start, end)150}151 152/**153 * Get the dirname from a path.154 *155 * @param {string} path156 * File path.157 * @returns {string}158 * File path.159 */160function dirname(path) {161 assertPath(path)162 163 if (path.length === 0) {164 return '.'165 }166 167 let end = -1168 let index = path.length169 /** @type {boolean | undefined} */170 let unmatchedSlash171 172 // Prefix `--` is important to not run on `0`.173 while (--index) {174 if (path.codePointAt(index) === 47 /* `/` */) {175 if (unmatchedSlash) {176 end = index177 break178 }179 } else if (!unmatchedSlash) {180 // We saw the first non-path separator181 unmatchedSlash = true182 }183 }184 185 return end < 0186 ? path.codePointAt(0) === 47 /* `/` */187 ? '/'188 : '.'189 : end === 1 && path.codePointAt(0) === 47 /* `/` */190 ? '//'191 : path.slice(0, end)192}193 194/**195 * Get an extname from a path.196 *197 * @param {string} path198 * File path.199 * @returns {string}200 * Extname.201 */202function extname(path) {203 assertPath(path)204 205 let index = path.length206 207 let end = -1208 let startPart = 0209 let startDot = -1210 // Track the state of characters (if any) we see before our first dot and211 // after any path separator we find.212 let preDotState = 0213 /** @type {boolean | undefined} */214 let unmatchedSlash215 216 while (index--) {217 const code = path.codePointAt(index)218 219 if (code === 47 /* `/` */) {220 // If we reached a path separator that was not part of a set of path221 // separators at the end of the string, stop now.222 if (unmatchedSlash) {223 startPart = index + 1224 break225 }226 227 continue228 }229 230 if (end < 0) {231 // We saw the first non-path separator, mark this as the end of our232 // extension.233 unmatchedSlash = true234 end = index + 1235 }236 237 if (code === 46 /* `.` */) {238 // If this is our first dot, mark it as the start of our extension.239 if (startDot < 0) {240 startDot = index241 } else if (preDotState !== 1) {242 preDotState = 1243 }244 } else if (startDot > -1) {245 // We saw a non-dot and non-path separator before our dot, so we should246 // have a good chance at having a non-empty extension.247 preDotState = -1248 }249 }250 251 if (252 startDot < 0 ||253 end < 0 ||254 // We saw a non-dot character immediately before the dot.255 preDotState === 0 ||256 // The (right-most) trimmed path component is exactly `..`.257 (preDotState === 1 && startDot === end - 1 && startDot === startPart + 1)258 ) {259 return ''260 }261 262 return path.slice(startDot, end)263}264 265/**266 * Join segments from a path.267 *268 * @param {Array<string>} segments269 * Path segments.270 * @returns {string}271 * File path.272 */273function join(...segments) {274 let index = -1275 /** @type {string | undefined} */276 let joined277 278 while (++index < segments.length) {279 assertPath(segments[index])280 281 if (segments[index]) {282 joined =283 joined === undefined ? segments[index] : joined + '/' + segments[index]284 }285 }286 287 return joined === undefined ? '.' : normalize(joined)288}289 290/**291 * Normalize a basic file path.292 *293 * @param {string} path294 * File path.295 * @returns {string}296 * File path.297 */298// Note: `normalize` is not exposed as `path.normalize`, so some code is299// manually removed from it.300function normalize(path) {301 assertPath(path)302 303 const absolute = path.codePointAt(0) === 47 /* `/` */304 305 // Normalize the path according to POSIX rules.306 let value = normalizeString(path, !absolute)307 308 if (value.length === 0 && !absolute) {309 value = '.'310 }311 312 if (value.length > 0 && path.codePointAt(path.length - 1) === 47 /* / */) {313 value += '/'314 }315 316 return absolute ? '/' + value : value317}318 319/**320 * Resolve `.` and `..` elements in a path with directory names.321 *322 * @param {string} path323 * File path.324 * @param {boolean} allowAboveRoot325 * Whether `..` can move above root.326 * @returns {string}327 * File path.328 */329function normalizeString(path, allowAboveRoot) {330 let result = ''331 let lastSegmentLength = 0332 let lastSlash = -1333 let dots = 0334 let index = -1335 /** @type {number | undefined} */336 let code337 /** @type {number} */338 let lastSlashIndex339 340 while (++index <= path.length) {341 if (index < path.length) {342 code = path.codePointAt(index)343 } else if (code === 47 /* `/` */) {344 break345 } else {346 code = 47 /* `/` */347 }348 349 if (code === 47 /* `/` */) {350 if (lastSlash === index - 1 || dots === 1) {351 // Empty.352 } else if (lastSlash !== index - 1 && dots === 2) {353 if (354 result.length < 2 ||355 lastSegmentLength !== 2 ||356 result.codePointAt(result.length - 1) !== 46 /* `.` */ ||357 result.codePointAt(result.length - 2) !== 46 /* `.` */358 ) {359 if (result.length > 2) {360 lastSlashIndex = result.lastIndexOf('/')361 362 if (lastSlashIndex !== result.length - 1) {363 if (lastSlashIndex < 0) {364 result = ''365 lastSegmentLength = 0366 } else {367 result = result.slice(0, lastSlashIndex)368 lastSegmentLength = result.length - 1 - result.lastIndexOf('/')369 }370 371 lastSlash = index372 dots = 0373 continue374 }375 } else if (result.length > 0) {376 result = ''377 lastSegmentLength = 0378 lastSlash = index379 dots = 0380 continue381 }382 }383 384 if (allowAboveRoot) {385 result = result.length > 0 ? result + '/..' : '..'386 lastSegmentLength = 2387 }388 } else {389 if (result.length > 0) {390 result += '/' + path.slice(lastSlash + 1, index)391 } else {392 result = path.slice(lastSlash + 1, index)393 }394 395 lastSegmentLength = index - lastSlash - 1396 }397 398 lastSlash = index399 dots = 0400 } else if (code === 46 /* `.` */ && dots > -1) {401 dots++402 } else {403 dots = -1404 }405 }406 407 return result408}409 410/**411 * Make sure `path` is a string.412 *413 * @param {string} path414 * File path.415 * @returns {asserts path is string}416 * Nothing.417 */418function assertPath(path) {419 if (typeof path !== 'string') {420 throw new TypeError(421 'Path must be a string. Received ' + JSON.stringify(path)422 )423 }424}425 426/* eslint-enable max-depth, complexity */427 