path.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. // Copyright 2010 The Closure Library Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. /**
  15. * @fileoverview Utilities for dealing with POSIX path strings. Based on
  16. * Python's os.path and posixpath.
  17. * @author nnaze@google.com (Nathan Naze)
  18. */
  19. goog.provide('goog.string.path');
  20. goog.require('goog.array');
  21. goog.require('goog.string');
  22. /**
  23. * Returns the final component of a pathname.
  24. * See http://docs.python.org/library/os.path.html#os.path.basename
  25. * @param {string} path A pathname.
  26. * @return {string} path The final component of a pathname, i.e. everything
  27. * after the final slash.
  28. */
  29. goog.string.path.baseName = function(path) {
  30. var i = path.lastIndexOf('/') + 1;
  31. return path.slice(i);
  32. };
  33. /**
  34. * Alias to goog.string.path.baseName.
  35. * @param {string} path A pathname.
  36. * @return {string} path The final component of a pathname.
  37. * @deprecated Use goog.string.path.baseName.
  38. */
  39. goog.string.path.basename = goog.string.path.baseName;
  40. /**
  41. * Returns the directory component of a pathname.
  42. * See http://docs.python.org/library/os.path.html#os.path.dirname
  43. * @param {string} path A pathname.
  44. * @return {string} The directory component of a pathname, i.e. everything
  45. * leading up to the final slash.
  46. */
  47. goog.string.path.dirname = function(path) {
  48. var i = path.lastIndexOf('/') + 1;
  49. var head = path.slice(0, i);
  50. // If the path isn't all forward slashes, trim the trailing slashes.
  51. if (!/^\/+$/.test(head)) {
  52. head = head.replace(/\/+$/, '');
  53. }
  54. return head;
  55. };
  56. /**
  57. * Extracts the extension part of a pathname.
  58. * @param {string} path The path name to process.
  59. * @return {string} The extension if any, otherwise the empty string.
  60. */
  61. goog.string.path.extension = function(path) {
  62. var separator = '.';
  63. // Combining all adjacent periods in the basename to a single period.
  64. var baseName = goog.string.path.baseName(path).replace(/\.+/g, separator);
  65. var separatorIndex = baseName.lastIndexOf(separator);
  66. return separatorIndex <= 0 ? '' : baseName.substr(separatorIndex + 1);
  67. };
  68. /**
  69. * Joins one or more path components (e.g. 'foo/' and 'bar' make 'foo/bar').
  70. * An absolute component will discard all previous component.
  71. * See http://docs.python.org/library/os.path.html#os.path.join
  72. * @param {...string} var_args One of more path components.
  73. * @return {string} The path components joined.
  74. */
  75. goog.string.path.join = function(var_args) {
  76. var path = arguments[0];
  77. for (var i = 1; i < arguments.length; i++) {
  78. var arg = arguments[i];
  79. if (goog.string.startsWith(arg, '/')) {
  80. path = arg;
  81. } else if (path == '' || goog.string.endsWith(path, '/')) {
  82. path += arg;
  83. } else {
  84. path += '/' + arg;
  85. }
  86. }
  87. return path;
  88. };
  89. /**
  90. * Normalizes a pathname by collapsing duplicate separators, parent directory
  91. * references ('..'), and current directory references ('.').
  92. * See http://docs.python.org/library/os.path.html#os.path.normpath
  93. * @param {string} path One or more path components.
  94. * @return {string} The path after normalization.
  95. */
  96. goog.string.path.normalizePath = function(path) {
  97. if (path == '') {
  98. return '.';
  99. }
  100. var initialSlashes = '';
  101. // POSIX will keep two slashes, but three or more will be collapsed to one.
  102. if (goog.string.startsWith(path, '/')) {
  103. initialSlashes = '/';
  104. if (goog.string.startsWith(path, '//') &&
  105. !goog.string.startsWith(path, '///')) {
  106. initialSlashes = '//';
  107. }
  108. }
  109. var parts = path.split('/');
  110. var newParts = [];
  111. for (var i = 0; i < parts.length; i++) {
  112. var part = parts[i];
  113. // '' and '.' don't change the directory, ignore.
  114. if (part == '' || part == '.') {
  115. continue;
  116. }
  117. // A '..' should pop a directory unless this is not an absolute path and
  118. // we're at the root, or we've travelled upwards relatively in the last
  119. // iteration.
  120. if (part != '..' || (!initialSlashes && !newParts.length) ||
  121. goog.array.peek(newParts) == '..') {
  122. newParts.push(part);
  123. } else {
  124. newParts.pop();
  125. }
  126. }
  127. var returnPath = initialSlashes + newParts.join('/');
  128. return returnPath || '.';
  129. };
  130. /**
  131. * Splits a pathname into "dirname" and "baseName" components, where "baseName"
  132. * is everything after the final slash. Either part may return an empty string.
  133. * See http://docs.python.org/library/os.path.html#os.path.split
  134. * @param {string} path A pathname.
  135. * @return {!Array<string>} An array of [dirname, basename].
  136. */
  137. goog.string.path.split = function(path) {
  138. var head = goog.string.path.dirname(path);
  139. var tail = goog.string.path.baseName(path);
  140. return [head, tail];
  141. };
  142. // TODO(nnaze): Implement other useful functions from os.path