1082815dcSEvan Bacon"use strict"; 2082815dcSEvan Bacon 3082815dcSEvan BaconObject.defineProperty(exports, "__esModule", { 4082815dcSEvan Bacon value: true 5082815dcSEvan Bacon}); 6082815dcSEvan Baconexports.addBuildSourceFileToGroup = addBuildSourceFileToGroup; 7082815dcSEvan Baconexports.addFileToGroupAndLink = addFileToGroupAndLink; 8082815dcSEvan Baconexports.addFramework = addFramework; 9082815dcSEvan Baconexports.addResourceFileToGroup = addResourceFileToGroup; 10082815dcSEvan Baconexports.ensureGroupRecursively = ensureGroupRecursively; 11082815dcSEvan Baconexports.getApplicationNativeTarget = getApplicationNativeTarget; 12082815dcSEvan Baconexports.getBuildConfigurationForListIdAndName = getBuildConfigurationForListIdAndName; 13082815dcSEvan Baconexports.getBuildConfigurationsForListId = getBuildConfigurationsForListId; 14082815dcSEvan Baconexports.getHackyProjectName = getHackyProjectName; 15082815dcSEvan Baconexports.getPbxproj = getPbxproj; 16082815dcSEvan Baconexports.getProductName = getProductName; 17082815dcSEvan Baconexports.getProjectName = getProjectName; 18082815dcSEvan Baconexports.getProjectSection = getProjectSection; 19082815dcSEvan Baconexports.getXCConfigurationListEntries = getXCConfigurationListEntries; 20082815dcSEvan Baconexports.isBuildConfig = isBuildConfig; 21082815dcSEvan Baconexports.isNotComment = isNotComment; 22082815dcSEvan Baconexports.isNotTestHost = isNotTestHost; 23082815dcSEvan Baconexports.resolvePathOrProject = resolvePathOrProject; 24082815dcSEvan Baconexports.sanitizedName = sanitizedName; 25082815dcSEvan Baconexports.unquote = unquote; 26082815dcSEvan Baconfunction _assert() { 27082815dcSEvan Bacon const data = _interopRequireDefault(require("assert")); 28082815dcSEvan Bacon _assert = function () { 29082815dcSEvan Bacon return data; 30082815dcSEvan Bacon }; 31082815dcSEvan Bacon return data; 32082815dcSEvan Bacon} 33082815dcSEvan Baconfunction _path() { 34082815dcSEvan Bacon const data = _interopRequireDefault(require("path")); 35082815dcSEvan Bacon _path = function () { 36082815dcSEvan Bacon return data; 37082815dcSEvan Bacon }; 38082815dcSEvan Bacon return data; 39082815dcSEvan Bacon} 40082815dcSEvan Baconfunction _slugify() { 41082815dcSEvan Bacon const data = _interopRequireDefault(require("slugify")); 42082815dcSEvan Bacon _slugify = function () { 43082815dcSEvan Bacon return data; 44082815dcSEvan Bacon }; 45082815dcSEvan Bacon return data; 46082815dcSEvan Bacon} 47082815dcSEvan Baconfunction _xcode() { 48082815dcSEvan Bacon const data = _interopRequireDefault(require("xcode")); 49082815dcSEvan Bacon _xcode = function () { 50082815dcSEvan Bacon return data; 51082815dcSEvan Bacon }; 52082815dcSEvan Bacon return data; 53082815dcSEvan Bacon} 54082815dcSEvan Baconfunction _pbxFile() { 55082815dcSEvan Bacon const data = _interopRequireDefault(require("xcode/lib/pbxFile")); 56082815dcSEvan Bacon _pbxFile = function () { 57082815dcSEvan Bacon return data; 58082815dcSEvan Bacon }; 59082815dcSEvan Bacon return data; 60082815dcSEvan Bacon} 61*8a424bebSJames Idefunction _string() { 62*8a424bebSJames Ide const data = require("./string"); 63*8a424bebSJames Ide _string = function () { 64*8a424bebSJames Ide return data; 65*8a424bebSJames Ide }; 66*8a424bebSJames Ide return data; 67*8a424bebSJames Ide} 68082815dcSEvan Baconfunction _warnings() { 69082815dcSEvan Bacon const data = require("../../utils/warnings"); 70082815dcSEvan Bacon _warnings = function () { 71082815dcSEvan Bacon return data; 72082815dcSEvan Bacon }; 73082815dcSEvan Bacon return data; 74082815dcSEvan Bacon} 75082815dcSEvan Baconfunction Paths() { 76082815dcSEvan Bacon const data = _interopRequireWildcard(require("../Paths")); 77082815dcSEvan Bacon Paths = function () { 78082815dcSEvan Bacon return data; 79082815dcSEvan Bacon }; 80082815dcSEvan Bacon return data; 81082815dcSEvan Bacon} 82082815dcSEvan Baconfunction _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } 83082815dcSEvan Baconfunction _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } 84082815dcSEvan Baconfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 85082815dcSEvan Baconfunction getProjectName(projectRoot) { 86082815dcSEvan Bacon const sourceRoot = Paths().getSourceRoot(projectRoot); 87082815dcSEvan Bacon return _path().default.basename(sourceRoot); 88082815dcSEvan Bacon} 89082815dcSEvan Baconfunction resolvePathOrProject(projectRootOrProject) { 90082815dcSEvan Bacon if (typeof projectRootOrProject === 'string') { 91082815dcSEvan Bacon try { 92082815dcSEvan Bacon return getPbxproj(projectRootOrProject); 93082815dcSEvan Bacon } catch { 94082815dcSEvan Bacon return null; 95082815dcSEvan Bacon } 96082815dcSEvan Bacon } 97082815dcSEvan Bacon return projectRootOrProject; 98ee216927STomasz Sapeta} 99082815dcSEvan Bacon 100ee216927STomasz Sapeta// TODO: come up with a better solution for using app.json expo.name in various places 101082815dcSEvan Baconfunction sanitizedName(name) { 102082815dcSEvan Bacon // Default to the name `app` when every safe character has been sanitized 103082815dcSEvan Bacon return sanitizedNameForProjects(name) || sanitizedNameForProjects((0, _slugify().default)(name)) || 'app'; 104082815dcSEvan Bacon} 105082815dcSEvan Baconfunction sanitizedNameForProjects(name) { 106082815dcSEvan Bacon return name.replace(/[\W_]+/g, '').normalize('NFD').replace(/[\u0300-\u036f]/g, ''); 107ee216927STomasz Sapeta} 108ee216927STomasz Sapeta 109ee216927STomasz Sapeta// TODO: it's silly and kind of fragile that we look at app config to determine 110082815dcSEvan Bacon// the ios project paths. Overall this function needs to be revamped, just a 111082815dcSEvan Bacon// placeholder for now! Make this more robust when we support applying config 112082815dcSEvan Bacon// at any time (currently it's only applied on eject). 113082815dcSEvan Baconfunction getHackyProjectName(projectRoot, config) { 114082815dcSEvan Bacon // Attempt to get the current ios folder name (apply). 115082815dcSEvan Bacon try { 116082815dcSEvan Bacon return getProjectName(projectRoot); 117082815dcSEvan Bacon } catch { 118082815dcSEvan Bacon // If no iOS project exists then create a new one (eject). 119082815dcSEvan Bacon const projectName = config.name; 120082815dcSEvan Bacon (0, _assert().default)(projectName, 'Your project needs a name in app.json/app.config.js.'); 121082815dcSEvan Bacon return sanitizedName(projectName); 122082815dcSEvan Bacon } 123082815dcSEvan Bacon} 124082815dcSEvan Baconfunction createProjectFileForGroup({ 125082815dcSEvan Bacon filepath, 126082815dcSEvan Bacon group 127082815dcSEvan Bacon}) { 128082815dcSEvan Bacon const file = new (_pbxFile().default)(filepath); 129082815dcSEvan Bacon const conflictingFile = group.children.find(child => child.comment === file.basename); 130082815dcSEvan Bacon if (conflictingFile) { 131082815dcSEvan Bacon // This can happen when a file like the GoogleService-Info.plist needs to be added and the eject command is run twice. 132082815dcSEvan Bacon // Not much we can do here since it might be a conflicting file. 133082815dcSEvan Bacon return null; 134082815dcSEvan Bacon } 135082815dcSEvan Bacon return file; 136082815dcSEvan Bacon} 137ee216927STomasz Sapeta 138082815dcSEvan Bacon/** 139082815dcSEvan Bacon * Add a resource file (ex: `SplashScreen.storyboard`, `Images.xcassets`) to an Xcode project. 140082815dcSEvan Bacon * This is akin to creating a new code file in Xcode with `⌘+n`. 141082815dcSEvan Bacon */ 142082815dcSEvan Baconfunction addResourceFileToGroup({ 143082815dcSEvan Bacon filepath, 144082815dcSEvan Bacon groupName, 145082815dcSEvan Bacon // Should add to `PBXBuildFile Section` 146082815dcSEvan Bacon isBuildFile, 147082815dcSEvan Bacon project, 148082815dcSEvan Bacon verbose, 149082815dcSEvan Bacon targetUuid 150082815dcSEvan Bacon}) { 151082815dcSEvan Bacon return addFileToGroupAndLink({ 152082815dcSEvan Bacon filepath, 153082815dcSEvan Bacon groupName, 154082815dcSEvan Bacon project, 155082815dcSEvan Bacon verbose, 156082815dcSEvan Bacon targetUuid, 157082815dcSEvan Bacon addFileToProject({ 158082815dcSEvan Bacon project, 159082815dcSEvan Bacon file 160082815dcSEvan Bacon }) { 161082815dcSEvan Bacon project.addToPbxFileReferenceSection(file); 162082815dcSEvan Bacon if (isBuildFile) { 163082815dcSEvan Bacon project.addToPbxBuildFileSection(file); 164082815dcSEvan Bacon } 165082815dcSEvan Bacon project.addToPbxResourcesBuildPhase(file); 166082815dcSEvan Bacon } 167082815dcSEvan Bacon }); 168082815dcSEvan Bacon} 169ee216927STomasz Sapeta 170082815dcSEvan Bacon/** 171082815dcSEvan Bacon * Add a build source file (ex: `AppDelegate.m`, `ViewController.swift`) to an Xcode project. 172082815dcSEvan Bacon * This is akin to creating a new code file in Xcode with `⌘+n`. 173082815dcSEvan Bacon */ 174082815dcSEvan Baconfunction addBuildSourceFileToGroup({ 175082815dcSEvan Bacon filepath, 176082815dcSEvan Bacon groupName, 177082815dcSEvan Bacon project, 178082815dcSEvan Bacon verbose, 179082815dcSEvan Bacon targetUuid 180082815dcSEvan Bacon}) { 181082815dcSEvan Bacon return addFileToGroupAndLink({ 182082815dcSEvan Bacon filepath, 183082815dcSEvan Bacon groupName, 184082815dcSEvan Bacon project, 185082815dcSEvan Bacon verbose, 186082815dcSEvan Bacon targetUuid, 187082815dcSEvan Bacon addFileToProject({ 188082815dcSEvan Bacon project, 189082815dcSEvan Bacon file 190082815dcSEvan Bacon }) { 191082815dcSEvan Bacon project.addToPbxFileReferenceSection(file); 192082815dcSEvan Bacon project.addToPbxBuildFileSection(file); 193082815dcSEvan Bacon project.addToPbxSourcesBuildPhase(file); 194082815dcSEvan Bacon } 195082815dcSEvan Bacon }); 196ee216927STomasz Sapeta} 197ee216927STomasz Sapeta 198ee216927STomasz Sapeta// TODO(brentvatne): I couldn't figure out how to do this with an existing 199082815dcSEvan Bacon// higher level function exposed by the xcode library, but we should find out how to do 200082815dcSEvan Bacon// that and replace this with it 201082815dcSEvan Baconfunction addFileToGroupAndLink({ 202082815dcSEvan Bacon filepath, 203082815dcSEvan Bacon groupName, 204082815dcSEvan Bacon project, 205082815dcSEvan Bacon verbose, 206082815dcSEvan Bacon addFileToProject, 207082815dcSEvan Bacon targetUuid 208082815dcSEvan Bacon}) { 209082815dcSEvan Bacon const group = pbxGroupByPathOrAssert(project, groupName); 210082815dcSEvan Bacon const file = createProjectFileForGroup({ 211082815dcSEvan Bacon filepath, 212082815dcSEvan Bacon group 213082815dcSEvan Bacon }); 214082815dcSEvan Bacon if (!file) { 215082815dcSEvan Bacon if (verbose) { 216082815dcSEvan Bacon // This can happen when a file like the GoogleService-Info.plist needs to be added and the eject command is run twice. 217082815dcSEvan Bacon // Not much we can do here since it might be a conflicting file. 218082815dcSEvan Bacon (0, _warnings().addWarningIOS)('ios-xcode-project', `Skipped adding duplicate file "${filepath}" to PBXGroup named "${groupName}"`); 219082815dcSEvan Bacon } 220082815dcSEvan Bacon return project; 221082815dcSEvan Bacon } 222082815dcSEvan Bacon if (targetUuid != null) { 223082815dcSEvan Bacon file.target = targetUuid; 224082815dcSEvan Bacon } else { 225082815dcSEvan Bacon const applicationNativeTarget = project.getTarget('com.apple.product-type.application'); 226082815dcSEvan Bacon file.target = applicationNativeTarget === null || applicationNativeTarget === void 0 ? void 0 : applicationNativeTarget.uuid; 227082815dcSEvan Bacon } 228082815dcSEvan Bacon file.uuid = project.generateUuid(); 229082815dcSEvan Bacon file.fileRef = project.generateUuid(); 230082815dcSEvan Bacon addFileToProject({ 231082815dcSEvan Bacon project, 232082815dcSEvan Bacon file 233082815dcSEvan Bacon }); 234082815dcSEvan Bacon group.children.push({ 235082815dcSEvan Bacon value: file.fileRef, 236082815dcSEvan Bacon comment: file.basename 237082815dcSEvan Bacon }); 238082815dcSEvan Bacon return project; 239082815dcSEvan Bacon} 240082815dcSEvan Baconfunction getApplicationNativeTarget({ 241082815dcSEvan Bacon project, 242082815dcSEvan Bacon projectName 243082815dcSEvan Bacon}) { 244082815dcSEvan Bacon const applicationNativeTarget = project.getTarget('com.apple.product-type.application'); 245082815dcSEvan Bacon (0, _assert().default)(applicationNativeTarget, `Couldn't locate application PBXNativeTarget in '.xcodeproj' file.`); 246082815dcSEvan Bacon (0, _assert().default)(String(applicationNativeTarget.target.name) === projectName, `Application native target name mismatch. Expected ${projectName}, but found ${applicationNativeTarget.target.name}.`); 247082815dcSEvan Bacon return applicationNativeTarget; 248082815dcSEvan Bacon} 249ee216927STomasz Sapeta 250082815dcSEvan Bacon/** 251082815dcSEvan Bacon * Add a framework to the default app native target. 252082815dcSEvan Bacon * 253082815dcSEvan Bacon * @param projectName Name of the PBX project. 254082815dcSEvan Bacon * @param framework String ending in `.framework`, i.e. `StoreKit.framework` 255082815dcSEvan Bacon */ 256082815dcSEvan Baconfunction addFramework({ 257082815dcSEvan Bacon project, 258082815dcSEvan Bacon projectName, 259082815dcSEvan Bacon framework 260082815dcSEvan Bacon}) { 261082815dcSEvan Bacon const target = getApplicationNativeTarget({ 262082815dcSEvan Bacon project, 263082815dcSEvan Bacon projectName 264082815dcSEvan Bacon }); 265082815dcSEvan Bacon return project.addFramework(framework, { 266082815dcSEvan Bacon target: target.uuid 267082815dcSEvan Bacon }); 268082815dcSEvan Bacon} 269082815dcSEvan Baconfunction splitPath(path) { 270082815dcSEvan Bacon // TODO: Should we account for other platforms that may not use `/` 271082815dcSEvan Bacon return path.split('/'); 272082815dcSEvan Bacon} 273082815dcSEvan Baconconst findGroup = (group, name) => { 274082815dcSEvan Bacon if (!group) { 275082815dcSEvan Bacon return undefined; 276082815dcSEvan Bacon } 277082815dcSEvan Bacon return group.children.find(group => group.comment === name); 278082815dcSEvan Bacon}; 279082815dcSEvan Baconfunction findGroupInsideGroup(project, group, name) { 280082815dcSEvan Bacon const foundGroup = findGroup(group, name); 281082815dcSEvan Bacon if (foundGroup) { 282082815dcSEvan Bacon var _project$getPBXGroupB; 283082815dcSEvan Bacon return (_project$getPBXGroupB = project.getPBXGroupByKey(foundGroup.value)) !== null && _project$getPBXGroupB !== void 0 ? _project$getPBXGroupB : null; 284082815dcSEvan Bacon } 285082815dcSEvan Bacon return null; 286082815dcSEvan Bacon} 287082815dcSEvan Baconfunction pbxGroupByPathOrAssert(project, path) { 288082815dcSEvan Bacon const { 289082815dcSEvan Bacon firstProject 290082815dcSEvan Bacon } = project.getFirstProject(); 291082815dcSEvan Bacon let group = project.getPBXGroupByKey(firstProject.mainGroup); 292082815dcSEvan Bacon const components = splitPath(path); 293082815dcSEvan Bacon for (const name of components) { 294082815dcSEvan Bacon const nextGroup = findGroupInsideGroup(project, group, name); 295082815dcSEvan Bacon if (nextGroup) { 296082815dcSEvan Bacon group = nextGroup; 297082815dcSEvan Bacon } else { 298082815dcSEvan Bacon break; 299082815dcSEvan Bacon } 300082815dcSEvan Bacon } 301082815dcSEvan Bacon if (!group) { 302082815dcSEvan Bacon throw Error(`Xcode PBXGroup with name "${path}" could not be found in the Xcode project.`); 303082815dcSEvan Bacon } 304082815dcSEvan Bacon return group; 305082815dcSEvan Bacon} 306082815dcSEvan Baconfunction ensureGroupRecursively(project, filepath) { 307082815dcSEvan Bacon var _topMostGroup; 308082815dcSEvan Bacon const components = splitPath(filepath); 309082815dcSEvan Bacon const hasChild = (group, name) => group.children.find(({ 310082815dcSEvan Bacon comment 311082815dcSEvan Bacon }) => comment === name); 312082815dcSEvan Bacon const { 313082815dcSEvan Bacon firstProject 314082815dcSEvan Bacon } = project.getFirstProject(); 315082815dcSEvan Bacon let topMostGroup = project.getPBXGroupByKey(firstProject.mainGroup); 316082815dcSEvan Bacon for (const pathComponent of components) { 317082815dcSEvan Bacon if (topMostGroup && !hasChild(topMostGroup, pathComponent)) { 318082815dcSEvan Bacon topMostGroup.children.push({ 319082815dcSEvan Bacon comment: pathComponent, 320082815dcSEvan Bacon value: project.pbxCreateGroup(pathComponent, '""') 321082815dcSEvan Bacon }); 322082815dcSEvan Bacon } 323082815dcSEvan Bacon topMostGroup = project.pbxGroupByName(pathComponent); 324082815dcSEvan Bacon } 325082815dcSEvan Bacon return (_topMostGroup = topMostGroup) !== null && _topMostGroup !== void 0 ? _topMostGroup : null; 326082815dcSEvan Bacon} 327ee216927STomasz Sapeta 328082815dcSEvan Bacon/** 329082815dcSEvan Bacon * Get the pbxproj for the given path 330082815dcSEvan Bacon */ 331082815dcSEvan Baconfunction getPbxproj(projectRoot) { 332082815dcSEvan Bacon const projectPath = Paths().getPBXProjectPath(projectRoot); 333082815dcSEvan Bacon const project = _xcode().default.project(projectPath); 334082815dcSEvan Bacon project.parseSync(); 335082815dcSEvan Bacon return project; 336082815dcSEvan Bacon} 337ee216927STomasz Sapeta 338082815dcSEvan Bacon/** 339082815dcSEvan Bacon * Get the productName for a project, if the name is using a variable `$(TARGET_NAME)`, then attempt to get the value of that variable. 340082815dcSEvan Bacon * 341082815dcSEvan Bacon * @param project 342082815dcSEvan Bacon */ 343082815dcSEvan Baconfunction getProductName(project) { 344082815dcSEvan Bacon let productName = '$(TARGET_NAME)'; 345082815dcSEvan Bacon try { 346082815dcSEvan Bacon // If the product name is numeric, this will fail (it's a getter). 347082815dcSEvan Bacon // If the bundle identifier' final component is only numeric values, then the PRODUCT_NAME 348082815dcSEvan Bacon // will be a numeric value, this results in a bug where the product name isn't useful, 349082815dcSEvan Bacon // i.e. `com.bacon.001` -> `1` -- in this case, use the first target name. 350082815dcSEvan Bacon productName = project.productName; 351082815dcSEvan Bacon } catch {} 352082815dcSEvan Bacon if (productName === '$(TARGET_NAME)') { 353082815dcSEvan Bacon var _project$getFirstTarg, _project$getFirstTarg2; 354082815dcSEvan Bacon const targetName = (_project$getFirstTarg = project.getFirstTarget()) === null || _project$getFirstTarg === void 0 ? void 0 : (_project$getFirstTarg2 = _project$getFirstTarg.firstTarget) === null || _project$getFirstTarg2 === void 0 ? void 0 : _project$getFirstTarg2.productName; 355082815dcSEvan Bacon productName = targetName !== null && targetName !== void 0 ? targetName : productName; 356082815dcSEvan Bacon } 357082815dcSEvan Bacon return productName; 358082815dcSEvan Bacon} 359082815dcSEvan Baconfunction getProjectSection(project) { 360082815dcSEvan Bacon return project.pbxProjectSection(); 361082815dcSEvan Bacon} 362082815dcSEvan Baconfunction getXCConfigurationListEntries(project) { 363082815dcSEvan Bacon const lists = project.pbxXCConfigurationList(); 364082815dcSEvan Bacon return Object.entries(lists).filter(isNotComment); 365082815dcSEvan Bacon} 366082815dcSEvan Baconfunction getBuildConfigurationsForListId(project, configurationListId) { 367082815dcSEvan Bacon const configurationListEntries = getXCConfigurationListEntries(project); 368082815dcSEvan Bacon const [, configurationList] = configurationListEntries.find(([key]) => key === configurationListId); 369082815dcSEvan Bacon const buildConfigurations = configurationList.buildConfigurations.map(i => i.value); 370082815dcSEvan Bacon return Object.entries(project.pbxXCBuildConfigurationSection()).filter(isNotComment).filter(isBuildConfig).filter(([key]) => buildConfigurations.includes(key)); 371082815dcSEvan Bacon} 372082815dcSEvan Baconfunction getBuildConfigurationForListIdAndName(project, { 373082815dcSEvan Bacon configurationListId, 374082815dcSEvan Bacon buildConfiguration 375082815dcSEvan Bacon}) { 376082815dcSEvan Bacon const xcBuildConfigurationEntry = getBuildConfigurationsForListId(project, configurationListId).find(i => (0, _string().trimQuotes)(i[1].name) === buildConfiguration); 377082815dcSEvan Bacon if (!xcBuildConfigurationEntry) { 378082815dcSEvan Bacon throw new Error(`Build configuration '${buildConfiguration}' does not exist in list with id '${configurationListId}'`); 379082815dcSEvan Bacon } 380082815dcSEvan Bacon return xcBuildConfigurationEntry; 381082815dcSEvan Bacon} 382082815dcSEvan Baconfunction isBuildConfig([, sectionItem]) { 383082815dcSEvan Bacon return sectionItem.isa === 'XCBuildConfiguration'; 384082815dcSEvan Bacon} 385082815dcSEvan Baconfunction isNotTestHost([, sectionItem]) { 386082815dcSEvan Bacon return !sectionItem.buildSettings.TEST_HOST; 387082815dcSEvan Bacon} 388082815dcSEvan Baconfunction isNotComment([key]) { 389082815dcSEvan Bacon return !key.endsWith(`_comment`); 390ee216927STomasz Sapeta} 391082815dcSEvan Bacon 392ee216927STomasz Sapeta// Remove surrounding double quotes if they exist. 393082815dcSEvan Baconfunction unquote(value) { 394082815dcSEvan Bacon var _value$match$, _value$match; 395082815dcSEvan Bacon // projects with numeric names will fail due to a bug in the xcode package. 396082815dcSEvan Bacon if (typeof value === 'number') { 397082815dcSEvan Bacon value = String(value); 398082815dcSEvan Bacon } 399082815dcSEvan Bacon return (_value$match$ = (_value$match = value.match(/^"(.*)"$/)) === null || _value$match === void 0 ? void 0 : _value$match[1]) !== null && _value$match$ !== void 0 ? _value$match$ : value; 400082815dcSEvan Bacon} 401082815dcSEvan Bacon//# sourceMappingURL=Xcodeproj.js.map