Merge remote-tracking branch 'origin/master' into scaffold
This commit is contained in:
commit
ad2ed05563
|
@ -1,7 +1,7 @@
|
|||
# https://help.github.com/en/github/automating-your-workflow-with-github-actions/workflow-syntax-for-github-actions#jobsjob_idname
|
||||
name: Checks
|
||||
|
||||
on: [push, pull_request]
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
swiftformat:
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
name: Fixture Generator
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- fixtures/fixture_generator/**/*
|
||||
- Sources/ProjectDescription/**/*
|
||||
- .github/workflows/fixture-generator.yml
|
||||
pull_request:
|
||||
paths:
|
||||
- fixtures/fixture_generator/**/*
|
||||
- Sources/ProjectDescription/**/*
|
||||
- .github/workflows/fixture-generator.yml
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Test
|
||||
runs-on: macOS-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Select Xcode 11.2.1
|
||||
run: sudo xcode-select -switch /Applications/Xcode_11.2.1.app
|
||||
- name: Build Package
|
||||
working-directory: ./fixtures/fixture_generator
|
||||
run: swift build
|
||||
- name: Generate Fixture
|
||||
working-directory: ./fixtures/fixture_generator
|
||||
run: swift run FixtureGenerator --projects 1 --targets 1 --sources 1
|
||||
- name: Build Tuist
|
||||
run: swift build
|
||||
- name: Generate Fixture Project
|
||||
run: swift run tuist generate --path ./fixtures/fixture_generator/Fixture
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
name: Tuist
|
||||
|
||||
on: ['push', 'pull_request']
|
||||
on: ['push']
|
||||
|
||||
jobs:
|
||||
unit_tests:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
name: Website
|
||||
|
||||
on: ['push', 'pull_request']
|
||||
on: ['push']
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
|
|
@ -1 +1 @@
|
|||
2.6.3
|
||||
2.6.5
|
13
CHANGELOG.md
13
CHANGELOG.md
|
@ -6,8 +6,20 @@ Please, check out guidelines: https://keepachangelog.com/en/1.0.0/
|
|||
|
||||
### Added
|
||||
|
||||
### Fixed
|
||||
|
||||
### Changed
|
||||
|
||||
## 1.2.0
|
||||
|
||||
### Added
|
||||
|
||||
- Best practices page to the documentation https://github.com/tuist/tuist/pull/843 by @pepibumur.
|
||||
- Fail CI if there are broken links on the website https://github.com/tuist/tuist/pull/917 by @pepibumur.
|
||||
- Excluding multiple files from a target https://github.com/tuist/tuist/pull/937 by @paciej00
|
||||
- Better SEO to the website https://github.com/tuist/tuist/pull/945 by @pepibumur.
|
||||
- Add fixture generator for stress testing Tuist https://github.com/tuist/tuist/pull/890 by @kwridan.
|
||||
|
||||
|
||||
### Fixed
|
||||
|
||||
|
@ -18,6 +30,7 @@ Please, check out guidelines: https://keepachangelog.com/en/1.0.0/
|
|||
- Fix project header attributes https://github.com/tuist/tuist/pull/895 by @kwridan
|
||||
- Excluding files from target doesn't work in all cases https://github.com/tuist/tuist/pull/913 by @vytis
|
||||
- Support for Core Data mapping modules https://github.com/tuist/tuist/pull/911 by @andreacipriani
|
||||
- Deep nested hierarchy in the project generated by `tuist edit` https://github.com/tuist/tuist/pull/923 by @pepibumur
|
||||
|
||||
### Changed
|
||||
- Turn models from `TuistCore` that are clases into structs https://github.com/tuist/tuist/pull/870 by @pepibumur.
|
||||
|
|
|
@ -16,7 +16,7 @@ GEM
|
|||
atomos (0.1.3)
|
||||
backports (3.11.4)
|
||||
builder (3.2.3)
|
||||
byebug (11.1.0)
|
||||
byebug (11.1.1)
|
||||
claide (1.0.3)
|
||||
cocoapods (1.8.4)
|
||||
activesupport (>= 4.0.2, < 5)
|
||||
|
|
|
@ -28,15 +28,6 @@
|
|||
"version": "1.0.2"
|
||||
}
|
||||
},
|
||||
{
|
||||
"package": "OpenCombine",
|
||||
"repositoryURL": "https://github.com/broadwaylamb/OpenCombine.git",
|
||||
"state": {
|
||||
"branch": null,
|
||||
"revision": "1496bab2724bf6f794cba8ac4d97d2a5013eeba7",
|
||||
"version": "0.8.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"package": "PathKit",
|
||||
"repositoryURL": "https://github.com/kylef/PathKit",
|
||||
|
|
|
@ -32,7 +32,6 @@ let package = Package(
|
|||
.package(url: "https://github.com/IBM-Swift/BlueSignals", .upToNextMajor(from: "1.0.21")),
|
||||
.package(url: "https://github.com/ReactiveX/RxSwift.git", .upToNextMajor(from: "5.0.1")),
|
||||
.package(url: "https://github.com/rnine/Checksum.git", .upToNextMajor(from: "1.0.2")),
|
||||
.package(url: "https://github.com/broadwaylamb/OpenCombine.git", .upToNextMajor(from: "0.8.0")),
|
||||
],
|
||||
targets: [
|
||||
.target(
|
||||
|
@ -53,7 +52,7 @@ let package = Package(
|
|||
),
|
||||
.target(
|
||||
name: "TuistKit",
|
||||
dependencies: ["XcodeProj", "SPMUtility", "TuistSupport", "TuistGenerator", "TuistGalaxy", "TuistAutomation", "ProjectDescription", "Signals", "RxSwift", "Checksum", "TuistLoader"]
|
||||
dependencies: ["XcodeProj", "SPMUtility", "TuistSupport", "TuistGenerator", "TuistCache", "TuistAutomation", "ProjectDescription", "Signals", "RxSwift", "Checksum", "TuistLoader"]
|
||||
),
|
||||
.testTarget(
|
||||
name: "TuistKitTests",
|
||||
|
@ -69,7 +68,7 @@ let package = Package(
|
|||
),
|
||||
.target(
|
||||
name: "TuistEnvKit",
|
||||
dependencies: ["SPMUtility", "TuistSupport", "OpenCombine", "OpenCombineFoundation"]
|
||||
dependencies: ["SPMUtility", "TuistSupport"]
|
||||
),
|
||||
.testTarget(
|
||||
name: "TuistEnvKitTests",
|
||||
|
@ -89,7 +88,7 @@ let package = Package(
|
|||
),
|
||||
.target(
|
||||
name: "TuistSupport",
|
||||
dependencies: ["SPMUtility", "RxSwift", "RxRelay", "OpenCombine", "OpenCombineDispatch"]
|
||||
dependencies: ["SPMUtility", "RxSwift", "RxRelay"]
|
||||
),
|
||||
.target(
|
||||
name: "TuistSupportTesting",
|
||||
|
@ -116,16 +115,16 @@ let package = Package(
|
|||
dependencies: ["TuistGenerator", "TuistSupportTesting"]
|
||||
),
|
||||
.target(
|
||||
name: "TuistGalaxy",
|
||||
name: "TuistCache",
|
||||
dependencies: ["XcodeProj", "SPMUtility", "TuistCore", "TuistSupport"]
|
||||
),
|
||||
.testTarget(
|
||||
name: "TuistGalaxyTests",
|
||||
dependencies: ["TuistGalaxy", "TuistSupportTesting", "TuistCoreTesting", "RxBlocking"]
|
||||
name: "TuistCacheTests",
|
||||
dependencies: ["TuistCache", "TuistSupportTesting", "TuistCoreTesting", "RxBlocking"]
|
||||
),
|
||||
.testTarget(
|
||||
name: "TuistGalaxyIntegrationTests",
|
||||
dependencies: ["TuistGalaxy", "TuistSupportTesting", "RxBlocking"]
|
||||
name: "TuistCacheIntegrationTests",
|
||||
dependencies: ["TuistCache", "TuistSupportTesting", "RxBlocking"]
|
||||
),
|
||||
.target(
|
||||
name: "TuistAutomation",
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
import Foundation
|
||||
|
||||
// MARK: - Galaxy
|
||||
|
||||
public struct Galaxy: Codable, Equatable {
|
||||
/// The project token to authenticate with the API.
|
||||
public let token: String
|
||||
|
||||
/// Initializes the Galaxy instance with its attributes.
|
||||
/// - Parameter token: The project token to authenticate with the API.
|
||||
public init(token: String) {
|
||||
self.token = token
|
||||
dumpIfNeeded(self)
|
||||
}
|
||||
}
|
|
@ -5,8 +5,8 @@ public struct SourceFileGlob: ExpressibleByStringLiteral, Codable, Equatable {
|
|||
/// Relative glob pattern.
|
||||
public let glob: Path
|
||||
|
||||
/// Relative glob pattern for excluded files
|
||||
public let excluding: Path?
|
||||
/// Relative glob patterns for excluded files.
|
||||
public let excluding: [Path]
|
||||
|
||||
/// Compiler flags.
|
||||
public let compilerFlags: String?
|
||||
|
@ -15,13 +15,19 @@ public struct SourceFileGlob: ExpressibleByStringLiteral, Codable, Equatable {
|
|||
///
|
||||
/// - Parameters:
|
||||
/// - glob: Relative glob pattern.
|
||||
/// - excluding: Relative glob patterns for excluded files.
|
||||
/// - compilerFlags: Compiler flags.
|
||||
public init(_ glob: Path, excluding: Path? = nil, compilerFlags: String? = nil) {
|
||||
public init(_ glob: Path, excluding: [Path] = [], compilerFlags: String? = nil) {
|
||||
self.glob = glob
|
||||
self.excluding = excluding
|
||||
self.compilerFlags = compilerFlags
|
||||
}
|
||||
|
||||
public init(_ glob: Path, excluding: Path?, compilerFlags: String? = nil) {
|
||||
let paths: [Path] = excluding.flatMap { [$0] } ?? []
|
||||
self.init(glob, excluding: paths, compilerFlags: compilerFlags)
|
||||
}
|
||||
|
||||
public init(stringLiteral value: String) {
|
||||
self.init(Path(value))
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
|
||||
// TuistAutomation placeholder
|
||||
|
|
|
@ -466,7 +466,9 @@ public class Graph: Graphing {
|
|||
return references
|
||||
}
|
||||
|
||||
public func findAll<T: GraphNode, S: GraphNode>(targetNode: TargetNode, test: (T) -> Bool = { _ in true }, skip: (S) -> Bool = { _ in false }) -> Set<T> {
|
||||
public func findAll<T: GraphNode, S: GraphNode>(targetNode: TargetNode,
|
||||
test: (T) -> Bool = { _ in true },
|
||||
skip: (S) -> Bool = { _ in false }) -> Set<T> {
|
||||
var stack = Stack<GraphNode>()
|
||||
|
||||
stack.push(targetNode)
|
||||
|
|
|
@ -4,7 +4,7 @@ import TuistSupport
|
|||
|
||||
public struct Target: Equatable, Hashable {
|
||||
public typealias SourceFile = (path: AbsolutePath, compilerFlags: String?)
|
||||
public typealias SourceFileGlob = (glob: String, excluding: String?, compilerFlags: String?)
|
||||
public typealias SourceFileGlob = (glob: String, excluding: [String], compilerFlags: String?)
|
||||
|
||||
// MARK: - Static
|
||||
|
||||
|
@ -115,10 +115,12 @@ public struct Target: Equatable, Hashable {
|
|||
let base = AbsolutePath(sourcePath.dirname)
|
||||
|
||||
// Paths that should be excluded from sources
|
||||
let excluded = source.excluding
|
||||
.map { AbsolutePath($0) }
|
||||
.map { excludePath in AbsolutePath(excludePath.dirname).glob(excludePath.basename) }
|
||||
?? []
|
||||
var excluded: [AbsolutePath] = []
|
||||
source.excluding.forEach { path in
|
||||
let absolute = AbsolutePath(path)
|
||||
let globs = AbsolutePath(absolute.dirname).glob(absolute.basename)
|
||||
excluded.append(contentsOf: globs)
|
||||
}
|
||||
|
||||
Set(base.glob(sourcePath.basename))
|
||||
.subtracting(excluded)
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
import Foundation
|
||||
import OpenCombine
|
||||
import OpenCombineFoundation
|
||||
|
||||
protocol URLSessionScheduling: AnyObject {
|
||||
/// Schedules an URLSession request and returns the result synchronously.
|
||||
|
@ -8,10 +6,6 @@ protocol URLSessionScheduling: AnyObject {
|
|||
/// - Parameter request: request to be executed.
|
||||
/// - Returns: request's response.
|
||||
func schedule(request: URLRequest) -> (error: Error?, data: Data?)
|
||||
|
||||
/// Returns a publisher that sends the given request. The publisher forwards the response data and error to the subscribers.
|
||||
/// - Parameter request: The request to be sent.
|
||||
func publisher(request: URLRequest) -> OpenCombine.AnyPublisher<(data: Data, response: URLResponse), URLError>
|
||||
}
|
||||
|
||||
final class URLSessionScheduler: URLSessionScheduling {
|
||||
|
@ -50,8 +44,4 @@ final class URLSessionScheduler: URLSessionScheduling {
|
|||
_ = semaphore.wait(timeout: .now() + 3)
|
||||
return (error: error, data: data)
|
||||
}
|
||||
|
||||
func publisher(request: URLRequest) -> OpenCombine.AnyPublisher<(data: Data, response: URLResponse), URLError> {
|
||||
URLSession.OCombine.DataTaskPublisher(request: request, session: session).eraseToAnyPublisher()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,11 +76,11 @@ final class ConfigGenerator: ConfigGenerating {
|
|||
let buildConfigurations = Set(projectBuildConfigurations).union(targetBuildConfigurations)
|
||||
let configurationsTuples: [(BuildConfiguration, Configuration?)] = buildConfigurations
|
||||
.map { buildConfiguration in
|
||||
if let configuration = target.settings?.configurations[buildConfiguration] {
|
||||
return (buildConfiguration, configuration)
|
||||
if let configuration = target.settings?.configurations[buildConfiguration] {
|
||||
return (buildConfiguration, configuration)
|
||||
}
|
||||
return (buildConfiguration, nil)
|
||||
}
|
||||
return (buildConfiguration, nil)
|
||||
}
|
||||
let configurations = Dictionary(uniqueKeysWithValues: configurationsTuples)
|
||||
let nonEmptyConfigurations = !configurations.isEmpty ? configurations : Settings.default.configurations
|
||||
let orderedConfigurations = nonEmptyConfigurations.sortedByBuildConfigurationName()
|
||||
|
|
|
@ -18,7 +18,9 @@ public protocol Generating {
|
|||
/// - Parameters:
|
||||
/// - project: The project to be generated.
|
||||
/// - graph: The dependencies graph.
|
||||
func generateProject(_ project: Project, graph: Graphing) throws -> AbsolutePath
|
||||
/// - sourceRootPath: The path all the files in the Xcode project will be realtived to. When it's nil, it's assumed that all the paths are relative to the directory that contains the manifest.
|
||||
/// - xcodeprojPath: Path where the .xcodeproj directory will be generated. When the attribute is nil, the project is generated in the manifest's directory.
|
||||
func generateProject(_ project: Project, graph: Graphing, sourceRootPath: AbsolutePath?, xcodeprojPath: AbsolutePath?) throws -> AbsolutePath
|
||||
|
||||
/// Generate an Xcode workspace for the project at a given path. All the project's dependencies will also be generated and included.
|
||||
///
|
||||
|
@ -97,10 +99,18 @@ public class Generator: Generating {
|
|||
self.environmentLinter = environmentLinter
|
||||
}
|
||||
|
||||
public func generateProject(_ project: Project, graph: Graphing) throws -> AbsolutePath {
|
||||
public func generateProject(_ project: Project,
|
||||
graph: Graphing,
|
||||
sourceRootPath: AbsolutePath? = nil,
|
||||
xcodeprojPath: AbsolutePath? = nil) throws -> AbsolutePath {
|
||||
/// When the source root path is not given, we assume paths
|
||||
/// are relative to the directory that contains the manifest.
|
||||
let sourceRootPath = sourceRootPath ?? project.path
|
||||
|
||||
let generatedProject = try projectGenerator.generate(project: project,
|
||||
graph: graph,
|
||||
sourceRootPath: project.path)
|
||||
sourceRootPath: sourceRootPath,
|
||||
xcodeprojPath: xcodeprojPath)
|
||||
return generatedProject.path
|
||||
}
|
||||
|
||||
|
@ -113,7 +123,8 @@ public class Generator: Generating {
|
|||
|
||||
let generatedProject = try projectGenerator.generate(project: project,
|
||||
graph: graph,
|
||||
sourceRootPath: path)
|
||||
sourceRootPath: path,
|
||||
xcodeprojPath: nil)
|
||||
return generatedProject.path
|
||||
}
|
||||
|
||||
|
|
|
@ -23,9 +23,16 @@ extension ProjectConstants {
|
|||
}
|
||||
|
||||
protocol ProjectGenerating: AnyObject {
|
||||
/// Generates the given project.
|
||||
/// - Parameters:
|
||||
/// - project: Project to be generated.
|
||||
/// - graph: Dependencies graph.
|
||||
/// - sourceRootPath: Directory where the files are relative to.
|
||||
/// - xcodeprojPath: Path to the Xcode project. When not given, the xcodeproj is generated at sourceRootPath.
|
||||
func generate(project: Project,
|
||||
graph: Graphing,
|
||||
sourceRootPath: AbsolutePath?) throws -> GeneratedProject
|
||||
sourceRootPath: AbsolutePath?,
|
||||
xcodeprojPath: AbsolutePath?) throws -> GeneratedProject
|
||||
}
|
||||
|
||||
final class ProjectGenerator: ProjectGenerating {
|
||||
|
@ -66,13 +73,15 @@ final class ProjectGenerator: ProjectGenerating {
|
|||
|
||||
func generate(project: Project,
|
||||
graph: Graphing,
|
||||
sourceRootPath: AbsolutePath? = nil) throws -> GeneratedProject {
|
||||
sourceRootPath: AbsolutePath? = nil,
|
||||
xcodeprojPath: AbsolutePath? = nil) throws -> GeneratedProject {
|
||||
Printer.shared.print("Generating project \(project.name)")
|
||||
|
||||
// Getting the path.
|
||||
let sourceRootPath = sourceRootPath ?? project.path
|
||||
|
||||
let xcodeprojPath = sourceRootPath.appending(component: "\(project.fileName).xcodeproj")
|
||||
// If the xcodeproj path is not given, we generate it under the source root path.
|
||||
let xcodeprojPath = xcodeprojPath ?? sourceRootPath.appending(component: "\(project.fileName).xcodeproj")
|
||||
|
||||
// Project and workspace.
|
||||
return try generateProjectAndWorkspace(project: project,
|
||||
|
@ -96,7 +105,7 @@ final class ProjectGenerator: ProjectGenerating {
|
|||
let pbxproj = PBXProj(objectVersion: projectConstants.objectVersion,
|
||||
archiveVersion: projectConstants.archiveVersion,
|
||||
classes: [:])
|
||||
let groups = ProjectGroups.generate(project: project, pbxproj: pbxproj, sourceRootPath: sourceRootPath)
|
||||
let groups = ProjectGroups.generate(project: project, pbxproj: pbxproj, xcodeprojPath: xcodeprojPath, sourceRootPath: sourceRootPath)
|
||||
let fileElements = ProjectFileElements()
|
||||
try fileElements.generateProjectFiles(project: project,
|
||||
graph: graph,
|
||||
|
|
|
@ -66,10 +66,11 @@ class ProjectGroups {
|
|||
|
||||
static func generate(project: Project,
|
||||
pbxproj: PBXProj,
|
||||
xcodeprojPath: AbsolutePath,
|
||||
sourceRootPath: AbsolutePath,
|
||||
playgrounds: Playgrounding = Playgrounds()) -> ProjectGroups {
|
||||
/// Main
|
||||
let projectRelativePath = project.path.relative(to: sourceRootPath).pathString
|
||||
let projectRelativePath = sourceRootPath.relative(to: xcodeprojPath.parentDirectory).pathString
|
||||
let mainGroup = PBXGroup(children: [],
|
||||
sourceTree: .group,
|
||||
path: (projectRelativePath != ".") ? projectRelativePath : nil)
|
||||
|
|
|
@ -96,7 +96,8 @@ final class WorkspaceGenerator: WorkspaceGenerating {
|
|||
try graph.projects.forEach { project in
|
||||
let generatedProject = try projectGenerator.generate(project: project,
|
||||
graph: graph,
|
||||
sourceRootPath: project.path)
|
||||
sourceRootPath: project.path,
|
||||
xcodeprojPath: nil)
|
||||
generatedProjects[project.path] = generatedProject
|
||||
}
|
||||
|
||||
|
|
|
@ -59,7 +59,9 @@ final class ProjectEditor: ProjectEditing {
|
|||
self.helpersDirectoryLocator = helpersDirectoryLocator
|
||||
}
|
||||
|
||||
func edit(at: AbsolutePath, in destinationDirectory: AbsolutePath) throws -> AbsolutePath {
|
||||
func edit(at: AbsolutePath, in dstDirectory: AbsolutePath) throws -> AbsolutePath {
|
||||
let xcodeprojPath = dstDirectory.appending(component: "Manifests.xcodeproj")
|
||||
|
||||
let projectDesciptionPath = try resourceLocator.projectDescription()
|
||||
let manifests = manifestFilesLocator.locate(at: at)
|
||||
var helpers: [AbsolutePath] = []
|
||||
|
@ -72,10 +74,13 @@ final class ProjectEditor: ProjectEditing {
|
|||
throw ProjectEditorError.noEditableFiles(at)
|
||||
}
|
||||
|
||||
let (project, graph) = projectEditorMapper.map(sourceRootPath: destinationDirectory,
|
||||
let (project, graph) = projectEditorMapper.map(sourceRootPath: at,
|
||||
manifests: manifests.map { $0.1 },
|
||||
helpers: helpers,
|
||||
projectDescriptionPath: projectDesciptionPath)
|
||||
return try generator.generateProject(project, graph: graph)
|
||||
return try generator.generateProject(project,
|
||||
graph: graph,
|
||||
sourceRootPath: project.path,
|
||||
xcodeprojPath: xcodeprojPath)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -292,10 +292,11 @@ extension TuistCore.Target {
|
|||
let entitlements = try manifest.entitlements.map { try generatorPaths.resolve(path: $0) }
|
||||
|
||||
let settings = try manifest.settings.map { try TuistCore.Settings.from(manifest: $0, path: path, generatorPaths: generatorPaths) }
|
||||
let sources = try TuistCore.Target.sources(projectPath: path, sources: manifest.sources?.globs.map {
|
||||
let glob = try generatorPaths.resolve(path: $0.glob).pathString
|
||||
let excluding = try $0.excluding.map { try generatorPaths.resolve(path: $0).pathString }
|
||||
return (glob: glob, excluding: excluding, compilerFlags: $0.compilerFlags)
|
||||
let sources = try TuistCore.Target.sources(projectPath: path,
|
||||
sources: manifest.sources?.globs.map { (glob: ProjectDescription.SourceFileGlob) in
|
||||
let globPath = try generatorPaths.resolve(path: glob.glob).pathString
|
||||
let excluding: [String] = try glob.excluding.compactMap { try generatorPaths.resolve(path: $0).pathString }
|
||||
return (glob: globPath, excluding: excluding, compilerFlags: glob.compilerFlags)
|
||||
} ?? [])
|
||||
|
||||
let resourceFilter = { (path: AbsolutePath) -> Bool in
|
||||
|
|
|
@ -58,13 +58,6 @@ public protocol ManifestLoading {
|
|||
/// - Throws: An error if the file has a syntax error.
|
||||
func loadTuistConfig(at path: AbsolutePath) throws -> ProjectDescription.TuistConfig
|
||||
|
||||
/// Loads the Galaxy.swift in the given directory.
|
||||
///
|
||||
/// - Parameter path: Path to the directory that contains the Galaxy.swift file.
|
||||
/// - Returns: Loaded Galaxy.swift file.
|
||||
/// - Throws: An error if the file has a syntax error.
|
||||
func loadGalaxy(at path: AbsolutePath) throws -> ProjectDescription.Galaxy
|
||||
|
||||
/// Loads the Project.swift in the given directory.
|
||||
/// - Parameter path: Path to the directory that contains the Project.swift.
|
||||
func loadProject(at path: AbsolutePath) throws -> ProjectDescription.Project
|
||||
|
@ -115,10 +108,6 @@ public class ManifestLoader: ManifestLoading {
|
|||
try loadManifest(.tuistConfig, at: path)
|
||||
}
|
||||
|
||||
public func loadGalaxy(at path: AbsolutePath) throws -> ProjectDescription.Galaxy {
|
||||
try loadManifest(.galaxy, at: path)
|
||||
}
|
||||
|
||||
public func loadProject(at path: AbsolutePath) throws -> ProjectDescription.Project {
|
||||
try loadManifest(.project, at: path)
|
||||
}
|
||||
|
|
|
@ -22,14 +22,6 @@ final class MockManifestLoader: ManifestLoading {
|
|||
var loadTuistConfigCount: UInt = 0
|
||||
var loadTuistConfigStub: ((AbsolutePath) throws -> ProjectDescription.TuistConfig)?
|
||||
|
||||
var loadGalaxyCount: UInt = 0
|
||||
var loadGalaxyStub: ((AbsolutePath) throws -> ProjectDescription.Galaxy)?
|
||||
|
||||
func loadGalaxy(at path: AbsolutePath) throws -> ProjectDescription.Galaxy {
|
||||
loadGalaxyCount += 1
|
||||
return try loadGalaxyStub?(path) ?? ProjectDescription.Galaxy.test()
|
||||
}
|
||||
|
||||
func loadProject(at path: AbsolutePath) throws -> ProjectDescription.Project {
|
||||
try loadProjectStub?(path) ?? ProjectDescription.Project.test()
|
||||
}
|
||||
|
|
|
@ -17,12 +17,6 @@ extension Workspace {
|
|||
}
|
||||
}
|
||||
|
||||
extension Galaxy {
|
||||
public static func test(token: String = "xyz") -> Galaxy {
|
||||
Galaxy(token: token)
|
||||
}
|
||||
}
|
||||
|
||||
extension Project {
|
||||
public static func test(name: String = "Project",
|
||||
settings: Settings? = nil,
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
import Foundation
|
||||
import OpenCombine
|
||||
|
||||
public extension OpenCombine.Publisher {
|
||||
/// Waits for the publisher to complete and then returns the values or the error.
|
||||
/// This method blocks the thread from which it's called from so it should be used cautiously.
|
||||
func wait() throws -> [Output] {
|
||||
var output: [Self.Output] = []
|
||||
var error: Self.Failure?
|
||||
|
||||
let semaphore = DispatchSemaphore(value: 0)
|
||||
_ = handleEvents(receiveOutput: { receivedOutput in
|
||||
output.append(receivedOutput)
|
||||
}, receiveCompletion: { completion in
|
||||
if case let .failure(receivedError) = completion {
|
||||
error = receivedError
|
||||
}
|
||||
semaphore.signal()
|
||||
}, receiveCancel: {
|
||||
semaphore.signal()
|
||||
})
|
||||
semaphore.wait()
|
||||
|
||||
if let error = error {
|
||||
throw error
|
||||
}
|
||||
return output
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@ public struct Constants {
|
|||
public static let binFolderName = ".tuist-bin"
|
||||
public static let binName = "tuist"
|
||||
public static let gitRepositoryURL = "https://github.com/tuist/tuist.git"
|
||||
public static let version = "1.1.0"
|
||||
public static let version = "1.2.0"
|
||||
public static let swiftVersion: String = "5.1"
|
||||
public static let bundleName: String = "tuist.zip"
|
||||
public static let trueValues: [String] = ["1", "true", "TRUE", "yes", "YES"]
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
import Foundation
|
||||
|
||||
public protocol CIChecking: AnyObject {
|
||||
/// Returns true when the environment in which the tuist process is running is a CI environment.
|
||||
func isCI() -> Bool
|
||||
}
|
||||
|
||||
public final class CIChecker: CIChecking {
|
||||
static let variables = [
|
||||
// GitHub: https://help.github.com/en/actions/automating-your-workflow-with-github-actions/using-environment-variables
|
||||
"GITHUB_RUN_ID",
|
||||
// CircleCI: https://circleci.com/docs/2.0/env-vars/
|
||||
// Bitrise: https://devcenter.bitrise.io/builds/available-environment-variables/
|
||||
// Buildkite: https://buildkite.com/docs/pipelines/environment-variables
|
||||
// Travis: https://docs.travis-ci.com/user/environment-variables/
|
||||
"CI",
|
||||
// Jenkins: https://wiki.jenkins.io/display/JENKINS/Building+a+software+project
|
||||
"BUILD_NUMBER",
|
||||
]
|
||||
|
||||
// MARK: - CIChecking
|
||||
|
||||
public func isCI() -> Bool {
|
||||
isCI(environment: ProcessInfo.processInfo.environment)
|
||||
}
|
||||
|
||||
// MARK: - Internal
|
||||
|
||||
func isCI(environment: [String: String]) -> Bool {
|
||||
environment.first(where: {
|
||||
CIChecker.variables.contains($0.key) && Constants.trueValues.contains($0.value)
|
||||
}) != nil
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
import Foundation
|
||||
import TuistSupport
|
||||
|
||||
public final class MockCIChecker: CIChecking {
|
||||
var isCIStub: Bool = false
|
||||
|
||||
public func isCI() -> Bool {
|
||||
isCIStub
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
import Foundation
|
||||
import TuistSupportTesting
|
||||
import XCTest
|
||||
|
||||
@testable import ProjectDescription
|
||||
|
||||
final class GalaxyTests: XCTestCase {
|
||||
func test_codable() throws {
|
||||
let subject = Galaxy(token: "token")
|
||||
XCTAssertCodable(subject)
|
||||
}
|
||||
}
|
|
@ -5,8 +5,8 @@ import SPMUtility
|
|||
import TuistCore
|
||||
import TuistSupport
|
||||
import XCTest
|
||||
@testable import TuistCache
|
||||
@testable import TuistCoreTesting
|
||||
@testable import TuistGalaxy
|
||||
@testable import TuistSupportTesting
|
||||
|
||||
final class CacheLocalStorageIntegrationTests: TuistTestCase {
|
|
@ -4,8 +4,8 @@ import SPMUtility
|
|||
import TuistCore
|
||||
import TuistSupport
|
||||
import XCTest
|
||||
@testable import TuistCache
|
||||
@testable import TuistCoreTesting
|
||||
@testable import TuistGalaxy
|
||||
@testable import TuistSupportTesting
|
||||
|
||||
final class XCFrameworkBuilderIntegrationTests: TuistTestCase {
|
|
@ -5,7 +5,7 @@ import TuistCoreTesting
|
|||
import TuistSupport
|
||||
import XCTest
|
||||
|
||||
@testable import TuistGalaxy
|
||||
@testable import TuistCache
|
||||
@testable import TuistSupportTesting
|
||||
|
||||
final class ContentHashingIntegrationTests: TuistTestCase {
|
|
@ -1,7 +1,7 @@
|
|||
import Foundation
|
||||
import XCTest
|
||||
|
||||
@testable import TuistGalaxy
|
||||
@testable import TuistCache
|
||||
@testable import TuistSupportTesting
|
||||
|
||||
final class CacheLocalStorageErrorTests: TuistUnitTestCase {
|
|
@ -3,7 +3,7 @@ import Foundation
|
|||
import TuistCore
|
||||
import TuistCoreTesting
|
||||
import XCTest
|
||||
@testable import TuistGalaxy
|
||||
@testable import TuistCache
|
||||
|
||||
final class GraphContentHasherTests: XCTestCase {
|
||||
private var sut: GraphContentHasher!
|
|
@ -61,8 +61,8 @@ final class TargetTests: TuistUnitTestCase {
|
|||
// When
|
||||
let sources = try Target.sources(projectPath: temporaryPath,
|
||||
sources: [
|
||||
(glob: temporaryPath.appending(RelativePath("sources/**")).pathString, excluding: nil, compilerFlags: nil),
|
||||
(glob: temporaryPath.appending(RelativePath("sources/**")).pathString, excluding: nil, compilerFlags: nil),
|
||||
(glob: temporaryPath.appending(RelativePath("sources/**")).pathString, excluding: [], compilerFlags: nil),
|
||||
(glob: temporaryPath.appending(RelativePath("sources/**")).pathString, excluding: [], compilerFlags: nil),
|
||||
])
|
||||
|
||||
// Then
|
||||
|
@ -92,11 +92,52 @@ final class TargetTests: TuistUnitTestCase {
|
|||
|
||||
// When
|
||||
let sources = try Target.sources(projectPath: temporaryPath,
|
||||
sources: [(
|
||||
glob: temporaryPath.appending(RelativePath("sources/**")).pathString,
|
||||
excluding: temporaryPath.appending(RelativePath("sources/**/*Tests.swift")).pathString,
|
||||
compilerFlags: nil
|
||||
)])
|
||||
sources: [
|
||||
(glob: temporaryPath.appending(RelativePath("sources/**")).pathString,
|
||||
excluding: [temporaryPath.appending(RelativePath("sources/**/*Tests.swift")).pathString],
|
||||
compilerFlags: nil),
|
||||
])
|
||||
|
||||
// Then
|
||||
let relativeSources = sources.map { $0.path.relative(to: temporaryPath).pathString }
|
||||
|
||||
XCTAssertEqual(Set(relativeSources), Set([
|
||||
"sources/a.swift",
|
||||
"sources/b.swift",
|
||||
"sources/c/c.swift",
|
||||
]))
|
||||
}
|
||||
|
||||
func test_sources_excluding_multiple_paths() throws {
|
||||
// Given
|
||||
let temporaryPath = try self.temporaryPath()
|
||||
try createFiles([
|
||||
"sources/a.swift",
|
||||
"sources/b.swift",
|
||||
"sources/aTests.swift",
|
||||
"sources/c/cType+Fake.swift",
|
||||
"sources/aType+Fake.swift",
|
||||
"sources/bTests.swift",
|
||||
"sources/kTests.kt",
|
||||
"sources/c/c.swift",
|
||||
"sources/c/cTests.swift",
|
||||
"sources/d.h",
|
||||
"sources/d.m",
|
||||
"sources/d/d.m",
|
||||
])
|
||||
let excluding: [String] = [
|
||||
temporaryPath.appending(RelativePath("sources/**/*Tests.swift")).pathString,
|
||||
temporaryPath.appending(RelativePath("sources/**/*Fake.swift")).pathString,
|
||||
temporaryPath.appending(RelativePath("sources/**/*.m")).pathString,
|
||||
]
|
||||
|
||||
// When
|
||||
let sources = try Target.sources(projectPath: temporaryPath,
|
||||
sources: [
|
||||
(glob: temporaryPath.appending(RelativePath("sources/**")).pathString,
|
||||
excluding: excluding,
|
||||
compilerFlags: nil),
|
||||
])
|
||||
|
||||
// Then
|
||||
let relativeSources = sources.map { $0.path.relative(to: temporaryPath).pathString }
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import Foundation
|
||||
import OpenCombine
|
||||
@testable import TuistEnvKit
|
||||
|
||||
final class MockURLSessionScheduler: URLSessionScheduling {
|
||||
|
@ -14,28 +13,9 @@ final class MockURLSessionScheduler: URLSessionScheduling {
|
|||
}
|
||||
|
||||
func schedule(request: URLRequest) -> (error: Error?, data: Data?) {
|
||||
guard let stub = self.stubs[request] else {
|
||||
guard let stub = stubs[request] else {
|
||||
return (error: nil, data: nil)
|
||||
}
|
||||
return stub
|
||||
}
|
||||
|
||||
func publisher(request: URLRequest) -> OpenCombine.AnyPublisher<(data: Data, response: URLResponse), URLError> {
|
||||
guard let stub = self.stubs[request] else {
|
||||
return OpenCombine.Fail<(data: Data, response: URLResponse), URLError>(error: URLError(.badServerResponse))
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
if let data = stub.data {
|
||||
let response = URLResponse()
|
||||
return OpenCombine.Just<(data: Data, response: URLResponse)>.init((data: data, response: response))
|
||||
.setFailureType(to: URLError.self)
|
||||
.eraseToAnyPublisher()
|
||||
} else if let error = stub.error {
|
||||
return OpenCombine.Fail<(data: Data, response: URLResponse), URLError>(error: error)
|
||||
.eraseToAnyPublisher()
|
||||
} else {
|
||||
return OpenCombine.Fail<(data: Data, response: URLResponse), URLError>(error: URLError(.badServerResponse))
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -345,7 +345,10 @@ final class ConfigGeneratorTests: TuistUnitTestCase {
|
|||
settings: .default,
|
||||
targets: [target])
|
||||
let fileElements = ProjectFileElements()
|
||||
let groups = ProjectGroups.generate(project: project, pbxproj: pbxproj, sourceRootPath: dir.path)
|
||||
let groups = ProjectGroups.generate(project: project,
|
||||
pbxproj: pbxproj,
|
||||
xcodeprojPath: project.path.appending(component: "\(project.fileName).xcodeproj"),
|
||||
sourceRootPath: dir.path)
|
||||
let graph = Graph.test()
|
||||
try fileElements.generateProjectFiles(project: project,
|
||||
graph: graph,
|
||||
|
|
|
@ -7,12 +7,13 @@ import TuistSupport
|
|||
|
||||
final class MockProjectGenerator: ProjectGenerating {
|
||||
var generatedProjects: [Project] = []
|
||||
var generateStub: ((Project, Graphing, AbsolutePath?) throws -> GeneratedProject)?
|
||||
var generateStub: ((Project, Graphing, AbsolutePath?, AbsolutePath?) throws -> GeneratedProject)?
|
||||
|
||||
func generate(project: Project,
|
||||
graph: Graphing,
|
||||
sourceRootPath: AbsolutePath?) throws -> GeneratedProject {
|
||||
sourceRootPath: AbsolutePath?,
|
||||
xcodeprojPath: AbsolutePath?) throws -> GeneratedProject {
|
||||
generatedProjects.append(project)
|
||||
return try generateStub?(project, graph, sourceRootPath) ?? GeneratedProject.test()
|
||||
return try generateStub?(project, graph, sourceRootPath, xcodeprojPath) ?? GeneratedProject.test()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ final class ProjectFileElementsTests: TuistUnitTestCase {
|
|||
pbxproj = PBXProj()
|
||||
groups = ProjectGroups.generate(project: .test(),
|
||||
pbxproj: pbxproj,
|
||||
xcodeprojPath: "/path/Project.xcodeproj",
|
||||
sourceRootPath: "/path",
|
||||
playgrounds: MockPlaygrounds())
|
||||
|
||||
|
@ -314,6 +315,7 @@ final class ProjectFileElementsTests: TuistUnitTestCase {
|
|||
let graph = Graph.test()
|
||||
let groups = ProjectGroups.generate(project: project,
|
||||
pbxproj: pbxproj,
|
||||
xcodeprojPath: project.path.appending(component: "\(project.fileName).xcodeproj"),
|
||||
sourceRootPath: project.path)
|
||||
|
||||
// When
|
||||
|
@ -348,6 +350,7 @@ final class ProjectFileElementsTests: TuistUnitTestCase {
|
|||
let graph = Graph.test()
|
||||
let groups = ProjectGroups.generate(project: project,
|
||||
pbxproj: pbxproj,
|
||||
xcodeprojPath: project.path.appending(component: "\(project.fileName).xcodeproj"),
|
||||
sourceRootPath: project.path)
|
||||
|
||||
// When
|
||||
|
@ -378,6 +381,7 @@ final class ProjectFileElementsTests: TuistUnitTestCase {
|
|||
let graph = Graph.test()
|
||||
let groups = ProjectGroups.generate(project: project,
|
||||
pbxproj: pbxproj,
|
||||
xcodeprojPath: project.path.appending(component: "\(project.fileName).xcodeproj"),
|
||||
sourceRootPath: project.path)
|
||||
|
||||
// When
|
||||
|
@ -401,6 +405,7 @@ final class ProjectFileElementsTests: TuistUnitTestCase {
|
|||
let project = Project.test(path: AbsolutePath("/"), filesGroup: projectGroup, targets: [target])
|
||||
let groups = ProjectGroups.generate(project: project,
|
||||
pbxproj: pbxproj,
|
||||
xcodeprojPath: project.path.appending(component: "\(project.fileName).xcodeproj"),
|
||||
sourceRootPath: sourceRootPath)
|
||||
var dependencies: Set<GraphDependencyReference> = Set()
|
||||
let precompiledNode = GraphDependencyReference.absolute(project.path.appending(component: "waka.framework"))
|
||||
|
@ -427,6 +432,7 @@ final class ProjectFileElementsTests: TuistUnitTestCase {
|
|||
let sourceRootPath = AbsolutePath("/a/project/")
|
||||
let groups = ProjectGroups.generate(project: project,
|
||||
pbxproj: pbxproj,
|
||||
xcodeprojPath: project.path.appending(component: "\(project.fileName).xcodeproj"),
|
||||
sourceRootPath: sourceRootPath)
|
||||
|
||||
// When
|
||||
|
@ -534,6 +540,7 @@ final class ProjectFileElementsTests: TuistUnitTestCase {
|
|||
let project = Project.test(path: temporaryPath)
|
||||
let groups = ProjectGroups.generate(project: project,
|
||||
pbxproj: pbxproj,
|
||||
xcodeprojPath: project.path.appending(component: "\(project.fileName).xcodeproj"),
|
||||
sourceRootPath: temporaryPath,
|
||||
playgrounds: playgrounds)
|
||||
|
||||
|
@ -599,6 +606,7 @@ final class ProjectFileElementsTests: TuistUnitTestCase {
|
|||
let sourceRootPath = AbsolutePath("/a/project/")
|
||||
let groups = ProjectGroups.generate(project: project,
|
||||
pbxproj: pbxproj,
|
||||
xcodeprojPath: project.path.appending(component: "\(project.fileName).xcodeproj"),
|
||||
sourceRootPath: sourceRootPath)
|
||||
|
||||
let sdk = try SDKNode(name: "ARKit.framework",
|
||||
|
@ -633,6 +641,7 @@ final class ProjectFileElementsTests: TuistUnitTestCase {
|
|||
packages: [.remote(url: "url", requirement: .branch("master"))])
|
||||
let groups = ProjectGroups.generate(project: .test(),
|
||||
pbxproj: pbxproj,
|
||||
xcodeprojPath: project.path.appending(component: "\(project.fileName).xcodeproj"),
|
||||
sourceRootPath: project.path)
|
||||
|
||||
let package = PackageProductNode(product: "A", path: "/packages/url")
|
||||
|
|
|
@ -44,6 +44,7 @@ final class ProjectGroupsTests: XCTestCase {
|
|||
}
|
||||
subject = ProjectGroups.generate(project: project,
|
||||
pbxproj: pbxproj,
|
||||
xcodeprojPath: project.path.appending(component: "\(project.fileName).xcodeproj"),
|
||||
sourceRootPath: sourceRootPath,
|
||||
playgrounds: playgrounds)
|
||||
|
||||
|
@ -81,7 +82,11 @@ final class ProjectGroupsTests: XCTestCase {
|
|||
playgrounds.pathsStub = { _ in
|
||||
[]
|
||||
}
|
||||
subject = ProjectGroups.generate(project: project, pbxproj: pbxproj, sourceRootPath: sourceRootPath, playgrounds: playgrounds)
|
||||
subject = ProjectGroups.generate(project: project,
|
||||
pbxproj: pbxproj,
|
||||
xcodeprojPath: project.path.appending(component: "\(project.fileName).xcodeproj"),
|
||||
sourceRootPath: sourceRootPath,
|
||||
playgrounds: playgrounds)
|
||||
|
||||
XCTAssertNil(subject.playgrounds)
|
||||
}
|
||||
|
@ -99,7 +104,11 @@ final class ProjectGroupsTests: XCTestCase {
|
|||
targets: [target1, target2, target3, target4])
|
||||
|
||||
// When
|
||||
subject = ProjectGroups.generate(project: project, pbxproj: pbxproj, sourceRootPath: sourceRootPath, playgrounds: playgrounds)
|
||||
subject = ProjectGroups.generate(project: project,
|
||||
pbxproj: pbxproj,
|
||||
xcodeprojPath: project.path.appending(component: "\(project.fileName).xcodeproj"),
|
||||
sourceRootPath: sourceRootPath,
|
||||
playgrounds: playgrounds)
|
||||
|
||||
// Then
|
||||
let paths = subject.main.children.compactMap { $0.nameOrPath }
|
||||
|
@ -115,7 +124,11 @@ final class ProjectGroupsTests: XCTestCase {
|
|||
}
|
||||
|
||||
func test_targetFrameworks() throws {
|
||||
subject = ProjectGroups.generate(project: project, pbxproj: pbxproj, sourceRootPath: sourceRootPath, playgrounds: playgrounds)
|
||||
subject = ProjectGroups.generate(project: project,
|
||||
pbxproj: pbxproj,
|
||||
xcodeprojPath: project.path.appending(component: "\(project.fileName).xcodeproj"),
|
||||
sourceRootPath: sourceRootPath,
|
||||
playgrounds: playgrounds)
|
||||
|
||||
let got = try subject.targetFrameworks(target: "Test")
|
||||
XCTAssertEqual(got.name, "Test")
|
||||
|
@ -125,7 +138,11 @@ final class ProjectGroupsTests: XCTestCase {
|
|||
|
||||
func test_projectGroup_unknownProjectGroups() throws {
|
||||
// Given
|
||||
subject = ProjectGroups.generate(project: project, pbxproj: pbxproj, sourceRootPath: sourceRootPath, playgrounds: playgrounds)
|
||||
subject = ProjectGroups.generate(project: project,
|
||||
pbxproj: pbxproj,
|
||||
xcodeprojPath: project.path.appending(component: "\(project.fileName).xcodeproj"),
|
||||
sourceRootPath: sourceRootPath,
|
||||
playgrounds: playgrounds)
|
||||
|
||||
// When / Then
|
||||
XCTAssertThrowsSpecific(try subject.projectGroup(named: "abc"),
|
||||
|
@ -140,7 +157,11 @@ final class ProjectGroupsTests: XCTestCase {
|
|||
let project = Project.test(filesGroup: .group(name: "P"),
|
||||
targets: [target1, target2, target3])
|
||||
|
||||
subject = ProjectGroups.generate(project: project, pbxproj: pbxproj, sourceRootPath: sourceRootPath, playgrounds: playgrounds)
|
||||
subject = ProjectGroups.generate(project: project,
|
||||
pbxproj: pbxproj,
|
||||
xcodeprojPath: project.path.appending(component: "\(project.fileName).xcodeproj"),
|
||||
sourceRootPath: sourceRootPath,
|
||||
playgrounds: playgrounds)
|
||||
|
||||
// When / Then
|
||||
XCTAssertNotNil(try? subject.projectGroup(named: "A"))
|
||||
|
|
|
@ -45,6 +45,7 @@ final class TargetGeneratorTests: XCTestCase {
|
|||
let graph = Graph.test()
|
||||
let groups = ProjectGroups.generate(project: project,
|
||||
pbxproj: pbxproj,
|
||||
xcodeprojPath: project.path.appending(component: "\(project.fileName).xcodeproj"),
|
||||
sourceRootPath: path,
|
||||
playgrounds: MockPlaygrounds())
|
||||
try fileElements.generateProjectFiles(project: project,
|
||||
|
@ -121,6 +122,7 @@ final class TargetGeneratorTests: XCTestCase {
|
|||
let project = Project.test(path: path, targets: [target])
|
||||
let groups = ProjectGroups.generate(project: project,
|
||||
pbxproj: pbxproj,
|
||||
xcodeprojPath: project.path.appending(component: "\(project.fileName).xcodeproj"),
|
||||
sourceRootPath: path,
|
||||
playgrounds: MockPlaygrounds())
|
||||
try fileElements.generateProjectFiles(project: project,
|
||||
|
|
|
@ -9,9 +9,9 @@ class MockGenerator: Generating {
|
|||
try generateProjectAtStub?(path) ?? AbsolutePath("/test")
|
||||
}
|
||||
|
||||
var generateProjectStub: ((Project) throws -> AbsolutePath)?
|
||||
func generateProject(_ project: Project, graph _: Graphing) throws -> AbsolutePath {
|
||||
try generateProjectStub?(project) ?? AbsolutePath("/test")
|
||||
var generateProjectStub: ((Project, AbsolutePath?, AbsolutePath?) throws -> AbsolutePath)?
|
||||
func generateProject(_ project: Project, graph _: Graphing, sourceRootPath: AbsolutePath?, xcodeprojPath: AbsolutePath?) throws -> AbsolutePath {
|
||||
try generateProjectStub?(project, sourceRootPath, xcodeprojPath) ?? AbsolutePath("/test")
|
||||
}
|
||||
|
||||
var generateProjectWorkspaceStub: ((AbsolutePath, [AbsolutePath]) throws -> AbsolutePath)?
|
||||
|
|
|
@ -68,7 +68,7 @@ final class ProjectEditorTests: TuistUnitTestCase {
|
|||
helpersDirectoryLocator.locateStub = helpersDirectory
|
||||
projectEditorMapper.mapStub = (project, graph)
|
||||
var generatedProject: Project?
|
||||
generator.generateProjectStub = { project in
|
||||
generator.generateProjectStub = { project, _, _ in
|
||||
generatedProject = project
|
||||
return directory.appending(component: "Edit.xcodeproj")
|
||||
}
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
import Foundation
|
||||
import XCTest
|
||||
@testable import TuistSupport
|
||||
|
||||
final class CICheckerTests: XCTestCase {
|
||||
var subject: CIChecker!
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
subject = CIChecker()
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
subject = nil
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
func testIsCI_when_isCI() {
|
||||
// Given
|
||||
let env = ["CI": "1"]
|
||||
|
||||
// When
|
||||
let got = subject.isCI(environment: env)
|
||||
|
||||
// Then
|
||||
XCTAssertTrue(got)
|
||||
}
|
||||
|
||||
func testIsCI_when_isNotCI() {
|
||||
// Given
|
||||
let env: [String: String] = [:]
|
||||
|
||||
// When
|
||||
let got = subject.isCI(environment: env)
|
||||
|
||||
// Then
|
||||
XCTAssertFalse(got)
|
||||
}
|
||||
}
|
|
@ -3,6 +3,10 @@
|
|||
This folder contains sample projects we use in the integration and acceptance tests.
|
||||
Please keep this keep in alphabetical order.
|
||||
|
||||
## fixture_generator
|
||||
|
||||
This is a Swift Package that generates a large application / workspace to stress test Tuist. The generated fixture itself is not checked in as it can vary based on the test being conducted.
|
||||
|
||||
## invalid_workspace_manifest_name
|
||||
|
||||
Contains a single file `Workspac.swift`, incorrectly named workspace manifest file.
|
||||
|
@ -297,3 +301,4 @@ e.g. `ios_app_with_xcframeworks/Frameworks/MyFramework/build.sh`
|
|||
## ios_app_with_coredate
|
||||
|
||||
A simple iOS app with a Core Data model and Mapping Model (.xcmappingmodel)
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
.DS_Store
|
||||
/.build
|
||||
/Packages
|
||||
/*.xcodeproj
|
||||
xcuserdata/
|
||||
Fixture
|
||||
.swiftpm
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"object": {
|
||||
"pins": [
|
||||
{
|
||||
"package": "llbuild",
|
||||
"repositoryURL": "https://github.com/apple/swift-llbuild.git",
|
||||
"state": {
|
||||
"branch": null,
|
||||
"revision": "f73b84bc1525998e5e267f9d830c1411487ac65e",
|
||||
"version": "0.2.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"package": "SwiftPM",
|
||||
"repositoryURL": "https://github.com/apple/swift-package-manager",
|
||||
"state": {
|
||||
"branch": null,
|
||||
"revision": "9abcc2260438177cecd7cf5185b144d13e74122b",
|
||||
"version": "0.5.0"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"version": 1
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
// swift-tools-version:5.1
|
||||
// The swift-tools-version declares the minimum version of Swift required to build this package.
|
||||
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "FixtureGenerator",
|
||||
dependencies: [
|
||||
// Dependencies declare other packages that this package depends on.
|
||||
.package(url: "https://github.com/apple/swift-package-manager", from: "0.5.0"),
|
||||
],
|
||||
targets: [
|
||||
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
|
||||
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
|
||||
.target(
|
||||
name: "FixtureGenerator",
|
||||
dependencies: [
|
||||
"SPMUtility",
|
||||
]
|
||||
),
|
||||
]
|
||||
)
|
|
@ -0,0 +1,24 @@
|
|||
# Fixture Generator
|
||||
|
||||
A tool to generate large fixtures for the purposes of stress testing Tuist,
|
||||
|
||||
# Usage
|
||||
|
||||
```sh
|
||||
swift run FixtureGenerator --projects 10 --targets 10 --sources 500
|
||||
```
|
||||
|
||||
Options:
|
||||
|
||||
- `projects`: Number of projects to generate
|
||||
- `targets`: Number of targets to generate
|
||||
- `sources`: Number of sources to generate
|
||||
|
||||
# Features
|
||||
|
||||
- [x] Control number of projects
|
||||
- [x] Control number of targets
|
||||
- [x] Control number of sources
|
||||
- [ ] Add pre-compiled libraries
|
||||
- [ ] Add pre-compiled frameworks
|
||||
- [ ] Add pre-compiled xcframeworks
|
|
@ -0,0 +1,64 @@
|
|||
|
||||
import Basic
|
||||
import Foundation
|
||||
import SPMUtility
|
||||
|
||||
enum GenerateCommandError: Error {
|
||||
case invalidPath
|
||||
}
|
||||
|
||||
final class GenerateCommand {
|
||||
private let pathArgument: OptionArgument<String>
|
||||
private let projectsArgument: OptionArgument<Int>
|
||||
private let targetsArgument: OptionArgument<Int>
|
||||
private let sourcesArgument: OptionArgument<Int>
|
||||
|
||||
private let fileSystem: FileSystem
|
||||
|
||||
init(fileSystem: FileSystem,
|
||||
parser: ArgumentParser) {
|
||||
self.fileSystem = fileSystem
|
||||
|
||||
pathArgument = parser.add(option: "--path",
|
||||
kind: String.self,
|
||||
usage: "The path where the fixture will be generated.",
|
||||
completion: .filename)
|
||||
projectsArgument = parser.add(option: "--projects",
|
||||
shortName: "-s",
|
||||
kind: Int.self,
|
||||
usage: "Number of projects to generate.")
|
||||
targetsArgument = parser.add(option: "--targets",
|
||||
shortName: "-t",
|
||||
kind: Int.self,
|
||||
usage: "Number of targets to generate within each project.")
|
||||
sourcesArgument = parser.add(option: "--sources",
|
||||
shortName: "-s",
|
||||
kind: Int.self,
|
||||
usage: "Number of sources to generate within each target.")
|
||||
}
|
||||
|
||||
func run(with arguments: ArgumentParser.Result) throws {
|
||||
let defaultConfig = GeneratorConfig.default
|
||||
|
||||
let path = try determineFixturePath(using: arguments)
|
||||
let projects = arguments.get(projectsArgument) ?? defaultConfig.projects
|
||||
let targets = arguments.get(targetsArgument) ?? defaultConfig.targets
|
||||
let sources = arguments.get(sourcesArgument) ?? defaultConfig.sources
|
||||
|
||||
let config = GeneratorConfig(projects: projects, targets: targets, sources: sources)
|
||||
let generator = Generator(fileSystem: fileSystem, config: config)
|
||||
|
||||
try generator.generate(at: path)
|
||||
}
|
||||
|
||||
private func determineFixturePath(using arguments: ArgumentParser.Result) throws -> AbsolutePath {
|
||||
guard let currentPath = fileSystem.currentWorkingDirectory else {
|
||||
throw GenerateCommandError.invalidPath
|
||||
}
|
||||
|
||||
guard let path = arguments.get(pathArgument) else {
|
||||
return currentPath
|
||||
}
|
||||
return AbsolutePath(path, relativeTo: currentPath)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
|
||||
import Basic
|
||||
import Foundation
|
||||
class Generator {
|
||||
private let fileSystem: FileSystem
|
||||
private let config: GeneratorConfig
|
||||
private let sourceTemplate: SourceTemplate
|
||||
private let manifestTemplate: ManifestTemplate
|
||||
|
||||
init(fileSystem: FileSystem, config: GeneratorConfig) {
|
||||
self.fileSystem = fileSystem
|
||||
self.config = config
|
||||
|
||||
sourceTemplate = SourceTemplate()
|
||||
manifestTemplate = ManifestTemplate()
|
||||
}
|
||||
|
||||
func generate(at path: AbsolutePath) throws {
|
||||
let rootPath = path.appending(component: "Fixture")
|
||||
let projects = (1 ... config.projects).map { "Project\($0)" }
|
||||
|
||||
try fileSystem.createDirectory(rootPath)
|
||||
try initWorkspaceManifest(at: rootPath,
|
||||
name: "Workspace",
|
||||
projects: projects)
|
||||
|
||||
try projects.forEach {
|
||||
try initProject(at: rootPath,
|
||||
name: $0)
|
||||
}
|
||||
}
|
||||
|
||||
private func initWorkspaceManifest(at path: AbsolutePath,
|
||||
name: String,
|
||||
projects: [String]) throws {
|
||||
let manifestPath = path.appending(component: "Workspace.swift")
|
||||
|
||||
let manifest = manifestTemplate.generate(workspaceName: name,
|
||||
projects: projects)
|
||||
try fileSystem.writeFileContents(manifestPath,
|
||||
bytes: ByteString(encodingAsUTF8: manifest))
|
||||
}
|
||||
|
||||
private func initProject(at path: AbsolutePath,
|
||||
name: String) throws {
|
||||
let projectPath = path.appending(component: name)
|
||||
let targets = (1 ... config.targets).map { "Target\($0)" }
|
||||
|
||||
try fileSystem.createDirectory(projectPath)
|
||||
try initProjectManifest(at: projectPath, name: name, targets: targets)
|
||||
|
||||
try targets.forEach {
|
||||
try initTarget(at: projectPath, name: $0)
|
||||
}
|
||||
}
|
||||
|
||||
private func initProjectManifest(at path: AbsolutePath,
|
||||
name: String,
|
||||
targets: [String]) throws {
|
||||
let manifestPath = path.appending(component: "Project.swift")
|
||||
|
||||
let manifest = manifestTemplate.generate(projectName: name,
|
||||
targets: targets)
|
||||
try fileSystem.writeFileContents(manifestPath,
|
||||
bytes: ByteString(encodingAsUTF8: manifest))
|
||||
}
|
||||
|
||||
private func initTarget(at path: AbsolutePath, name: String) throws {
|
||||
let targetPath = path.appending(component: name)
|
||||
|
||||
try fileSystem.createDirectory(targetPath)
|
||||
try initSources(at: targetPath, targetName: name)
|
||||
}
|
||||
|
||||
private func initSources(at path: AbsolutePath, targetName: String) throws {
|
||||
let sourcesPath = path.appending(component: "Sources")
|
||||
|
||||
try fileSystem.createDirectory(sourcesPath)
|
||||
try (1 ... config.sources).forEach {
|
||||
let sourceName = "Source\($0).swift"
|
||||
let source = sourceTemplate.generate(frameworkName: targetName, number: $0)
|
||||
try fileSystem.writeFileContents(sourcesPath.appending(component: sourceName),
|
||||
bytes: ByteString(encodingAsUTF8: source))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
struct GeneratorConfig {
|
||||
var projects: Int
|
||||
var targets: Int
|
||||
var sources: Int
|
||||
}
|
||||
|
||||
extension GeneratorConfig {
|
||||
static var `default`: GeneratorConfig {
|
||||
return GeneratorConfig(projects: 5, targets: 10, sources: 50)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
class ManifestTemplate {
|
||||
private let workspaceTemplate = """
|
||||
import ProjectDescription
|
||||
|
||||
let workspace = Workspace(
|
||||
name: "{WorkspaceName}",
|
||||
projects: [
|
||||
{Projects}
|
||||
])
|
||||
"""
|
||||
|
||||
private let workspaceProjectTemplate = """
|
||||
"{Project}"
|
||||
"""
|
||||
|
||||
private let projectTemplate = """
|
||||
import ProjectDescription
|
||||
|
||||
let project = Project(
|
||||
name: "{ProjectName}",
|
||||
targets: [
|
||||
{Targets}
|
||||
])
|
||||
|
||||
"""
|
||||
|
||||
private let targetTemplate = """
|
||||
Target(
|
||||
name: "{TargetName}",
|
||||
platform: .iOS,
|
||||
product: .framework,
|
||||
bundleId: "io.tuist.{TargetName}",
|
||||
infoPlist: .default,
|
||||
sources: [
|
||||
"{TargetName}/Sources/**"
|
||||
],
|
||||
resources: [
|
||||
|
||||
],
|
||||
dependencies: [
|
||||
])
|
||||
"""
|
||||
|
||||
func generate(workspaceName: String, projects: [String]) -> String {
|
||||
return workspaceTemplate
|
||||
.replacingOccurrences(of: "{WorkspaceName}", with: workspaceName)
|
||||
.replacingOccurrences(of: "{Projects}", with: generate(projects: projects))
|
||||
}
|
||||
|
||||
func generate(projectName: String, targets: [String]) -> String {
|
||||
return projectTemplate
|
||||
.replacingOccurrences(of: "{ProjectName}", with: projectName)
|
||||
.replacingOccurrences(of: "{Targets}", with: generate(targets: targets))
|
||||
}
|
||||
|
||||
private func generate(projects: [String]) -> String {
|
||||
return projects.map {
|
||||
workspaceProjectTemplate.replacingOccurrences(of: "{Project}", with: $0)
|
||||
}.joined(separator: ",\n")
|
||||
}
|
||||
|
||||
private func generate(targets: [String]) -> String {
|
||||
return targets.map {
|
||||
targetTemplate.replacingOccurrences(of: "{TargetName}", with: $0)
|
||||
}.joined(separator: ",\n")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
class SourceTemplate {
|
||||
private let template = """
|
||||
import Foundation
|
||||
|
||||
public class {FrameworkName}SomeClass{Number} {
|
||||
public init() {
|
||||
|
||||
}
|
||||
|
||||
public func hello() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
"""
|
||||
|
||||
func generate(frameworkName: String, number: Int) -> String {
|
||||
return template
|
||||
.replacingOccurrences(of: "{FrameworkName}", with: frameworkName)
|
||||
.replacingOccurrences(of: "{Number}", with: "\(number)")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
import Basic
|
||||
import Foundation
|
||||
import SPMUtility
|
||||
|
||||
func main() throws {
|
||||
let parser = ArgumentParser(commandName: "FixtureGenerator",
|
||||
usage: "FixtureGenerator <options>",
|
||||
overview: "Generates large fixtures for the purposes of stress testing Tuist")
|
||||
|
||||
let fileSystem = localFileSystem
|
||||
let generateCommand = GenerateCommand(fileSystem: fileSystem,
|
||||
parser: parser)
|
||||
|
||||
let arguments = ProcessInfo.processInfo.arguments
|
||||
let results = try parser.parse(Array(arguments.dropFirst()))
|
||||
try generateCommand.run(with: results)
|
||||
}
|
||||
|
||||
do {
|
||||
try main()
|
||||
} catch {
|
||||
print("Error: \(error.localizedDescription)")
|
||||
}
|
|
@ -23,3 +23,8 @@
|
|||
twitter: marekfort
|
||||
name: Marek Fořt
|
||||
avatar: https://avatars1.githubusercontent.com/u/9371695?s=460&v=4
|
||||
- handle: vytis
|
||||
github: vytis
|
||||
twitter: vytis0
|
||||
name: Vytis Šibonis
|
||||
avatar: https://avatars1.githubusercontent.com/u/33914?s=460&v=4
|
|
@ -1,10 +1,12 @@
|
|||
const remarkSlug = require('remark-slug')
|
||||
const title = `Tuist - Xcode on steroids`
|
||||
const siteUrl = 'https://tuist.io'
|
||||
|
||||
module.exports = {
|
||||
siteMetadata: {
|
||||
title: `Tuist - Xcode on steroids`,
|
||||
title: title,
|
||||
description: `Tuist is a tool that helps developers manage large Xcode projects by leveraging project generation. Moreover, it provides some tools to automate most common tasks, allowing developers to focus on building apps.`,
|
||||
siteUrl: 'https://tuist.io',
|
||||
siteUrl: siteUrl,
|
||||
githubUrl: 'https://github.com/tuist',
|
||||
releasesUrl: 'https://github.com/tuist/tuist/releases',
|
||||
documentationUrl: 'https://docs.tuist.io/',
|
||||
|
@ -213,6 +215,41 @@ module.exports = {
|
|||
generateMatchPathRewrites: true, // boolean to turn off automatic creation of redirect rules for client only paths
|
||||
},
|
||||
},
|
||||
{
|
||||
resolve: 'gatsby-plugin-next-seo',
|
||||
options: {
|
||||
titleTemplate: '%s | Tuist',
|
||||
openGraph: {
|
||||
type: 'website',
|
||||
locale: 'en_IE',
|
||||
url: siteUrl,
|
||||
site_name: title,
|
||||
keywords: [
|
||||
`tuist`,
|
||||
`engineering`,
|
||||
`xcode`,
|
||||
`swift`,
|
||||
`project generation`,
|
||||
`xcode project generation`,
|
||||
`xcodeproj`,
|
||||
`xcodegen`,
|
||||
'ios',
|
||||
'uikit',
|
||||
'foundation',
|
||||
'tvos',
|
||||
'ios',
|
||||
'watchos',
|
||||
'objective-c',
|
||||
'swift package manager',
|
||||
'swift packages',
|
||||
],
|
||||
},
|
||||
twitter: {
|
||||
site: siteUrl,
|
||||
cardType: 'summary_large_image',
|
||||
},
|
||||
},
|
||||
},
|
||||
'gatsby-plugin-meta-redirect',
|
||||
`gatsby-plugin-robots-txt`,
|
||||
],
|
||||
|
|
|
@ -333,11 +333,11 @@ It represents a glob pattern that refers to source files and the compiler flags
|
|||
},
|
||||
{
|
||||
name: 'Excluding',
|
||||
description: 'Glob pattern for source files that will be excluded.',
|
||||
type: 'Path',
|
||||
description: 'Glob patterns for source files that will be excluded.',
|
||||
type: '[Path]',
|
||||
typeLink: '#path',
|
||||
optional: true,
|
||||
default: 'nil',
|
||||
default: '[]',
|
||||
},
|
||||
{
|
||||
name: 'Compiler flags',
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
layout: post
|
||||
title: Tuist 1.2.0 - Bugfixes, improvements and future direction
|
||||
categories: [tuist, release, swift, 1.2.0, project generation, xcode, swift]
|
||||
excerpt: The newest release brings you many bugfixes and improvements. However with the number of contributors steadily growing the team has also been busy thinking and writing about the direction of Tuist. We have a rough plan for Tuist 2.0 and work has started on compiling a manifesto to explain a bit more about the goals and values of the project.
|
||||
author: vytis
|
||||
---
|
||||
|
||||
We are slowly learning how to do smaller [bi-weekly releases](https://tuist.io/docs/contribution/release/#cadence). This release was planned for last week but it was postponed because there were not enough changes. However lots of new things got merged recently and Tuist 1.2.0 is here for you to enjoy!
|
||||
|
||||
## New contributors
|
||||
|
||||
Firstly, warm welcome to another first-time Tuist contributor [Maciej Piotrowski](https://github.com/paciej00) 👏👏👏. He improved the API introduced in the previous release for excluding files from a target. It makes exclude patterns more flexible which can be very useful when migrating an existing project to Tuist!
|
||||
|
||||
## Future of Tuist
|
||||
|
||||
There are plenty of ideas floating around what other features Tuist should have and [Pedro](https://github.com/pepibumur) laid them out in nicely in [The journey towards Tuist 2.0](https://github.com/tuist/tuist/issues/951). In addition, he also opened a work-in-progress PR for Tuist's [manifesto](https://github.com/tuist/tuist/pull/952). With more and more people joining the project it's very important to lay down the core principles in writing to ensure that everyone is up to speed. For more practical information we also have a new [Best Practices](https://tuist.io/docs/usage/best-practices/) section on the website. It is quite short at the moment, but will contain a growing list of things that can be useful for both new Tuist users and developers trying to improve their setup.
|
||||
|
||||
## Focus on improving performance
|
||||
|
||||
A common complaint, especially for bigger projects, is the time it takes to generate the project. The main focus until this point was adding features, but time has come to start thinking about performance. End of last year [Kas](https://github.com/kwridan) proposed an [idea](https://github.com/tuist/tuist/issues/820) to start performance testing. First part of this initiative already got [merged](https://github.com/tuist/tuist/pull/890). The [`FixtureGenerator`](https://github.com/tuist/tuist/tree/master/fixtures/fixture_generator) tool will allow us to easily generate a project with potentially hundreds of targets and iron out performance issues much more systematically. It is just the beginning and the plan is eventually to integrate performance testing as part of GitHub checks so we can be sure that adding new features would not have an impact on project generation times.
|
||||
|
||||
## Full Changelog
|
||||
|
||||
Of all the things mentioned, there are also plenty of bugfixes and improvements in this release. The full changelog can be found on the [release page](https://github.com/tuist/tuist/releases/tag/1.2.0).
|
|
@ -14,35 +14,36 @@
|
|||
"@mdx-js/mdx": "^1.5.5",
|
||||
"@mdx-js/react": "^1.5.5",
|
||||
"@mdx-js/tag": "^0.20.3",
|
||||
"@theme-ui/color": "^0.2.53",
|
||||
"@theme-ui/presets": "^0.2.44",
|
||||
"@theme-ui/prism": "^0.2.50",
|
||||
"@theme-ui/typography": "^0.2.46",
|
||||
"@theme-ui/color": "^0.3.1",
|
||||
"@theme-ui/presets": "^0.3.0",
|
||||
"@theme-ui/prism": "^0.3.0",
|
||||
"@theme-ui/typography": "^0.3.0",
|
||||
"focus-visible": "^5.0.2",
|
||||
"gatsby": "^2.18.21",
|
||||
"gatsby-image": "^2.2.39",
|
||||
"gatsby-image": "^2.2.40",
|
||||
"gatsby-plugin-favicon": "3.1.6",
|
||||
"gatsby-plugin-feed": "^2.3.26",
|
||||
"gatsby-plugin-manifest": "2.2.37",
|
||||
"gatsby-plugin-feed": "^2.3.27",
|
||||
"gatsby-plugin-manifest": "2.2.41",
|
||||
"gatsby-plugin-mdx": "^1.0.67",
|
||||
"gatsby-plugin-meta-redirect": "^1.1.1",
|
||||
"gatsby-plugin-netlify": "^2.1.31",
|
||||
"gatsby-plugin-offline": "^3.0.32",
|
||||
"gatsby-plugin-react-helmet": "^3.1.21",
|
||||
"gatsby-plugin-next-seo": "^1.4.0",
|
||||
"gatsby-plugin-offline": "^3.0.34",
|
||||
"gatsby-plugin-react-helmet": "^3.1.22",
|
||||
"gatsby-plugin-react-svg": "^3.0.0",
|
||||
"gatsby-plugin-robots-txt": "^1.5.0",
|
||||
"gatsby-plugin-sharp": "2.4.0",
|
||||
"gatsby-plugin-sitemap": "^2.2.26",
|
||||
"gatsby-plugin-theme-ui": "^0.2.53",
|
||||
"gatsby-plugin-sitemap": "^2.2.27",
|
||||
"gatsby-plugin-theme-ui": "^0.3.0",
|
||||
"gatsby-redirect-from": "^0.2.1",
|
||||
"gatsby-remark-check-links": "^2.1.0",
|
||||
"gatsby-remark-images": "^3.1.42",
|
||||
"gatsby-remark-smartypants": "^2.1.20",
|
||||
"gatsby-remark-smartypants": "^2.1.21",
|
||||
"gatsby-remark-social-cards": "https://github.com/pepibumur/gatsby-remark-social-cards.git#0.5.2",
|
||||
"gatsby-source-filesystem": "^2.1.46",
|
||||
"gatsby-transformer-yaml": "^2.2.23",
|
||||
"gatsby-source-filesystem": "^2.1.48",
|
||||
"gatsby-transformer-yaml": "^2.2.24",
|
||||
"moment": "^2.24.0",
|
||||
"polished": "^3.4.2",
|
||||
"polished": "^3.4.4",
|
||||
"prettier": "^1.19.1",
|
||||
"prismjs": "^1.19.0",
|
||||
"prop-types": "^15.7.2",
|
||||
|
@ -51,6 +52,7 @@
|
|||
"react-burger-menu": "^2.6.13",
|
||||
"react-dom": "^16.12.0",
|
||||
"react-helmet": "^5.2.0",
|
||||
"react-helmet-async": "^1.0.4",
|
||||
"react-markdown": "^4.3.1",
|
||||
"react-pose": "^4.0.10",
|
||||
"react-share": "^4.0.1",
|
||||
|
@ -58,7 +60,7 @@
|
|||
"react-use-visibility": "^0.3.0",
|
||||
"remark-slug": "^5.1.2",
|
||||
"semantic-ui-react": "^0.88.1",
|
||||
"slug": "^2.1.0",
|
||||
"slug": "^2.1.1",
|
||||
"theme-ui": "^0.2.52",
|
||||
"url-join": "^4.0.1"
|
||||
},
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/** @jsx jsx */
|
||||
import { jsx } from 'theme-ui'
|
||||
import React from 'react'
|
||||
import { GatsbySeo } from 'gatsby-plugin-next-seo'
|
||||
import { LogoJsonLd } from 'gatsby-plugin-next-seo'
|
||||
import logo from '../../static/tuist.png'
|
||||
import { useStaticQuery, graphql } from 'gatsby'
|
||||
|
||||
export default ({ description, title, ...other }) => {
|
||||
const {
|
||||
site: {
|
||||
siteMetadata: { siteUrl, description: defaultDescription },
|
||||
},
|
||||
} = useStaticQuery(graphql`
|
||||
query {
|
||||
site {
|
||||
siteMetadata {
|
||||
siteUrl
|
||||
description
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
return (
|
||||
<>
|
||||
<GatsbySeo
|
||||
description={description != null ? description : defaultDescription}
|
||||
title={title != null ? title : 'Tuist'}
|
||||
titleTemplate={title != null ? `%s | Tuist` : '%s'}
|
||||
{...other}
|
||||
/>
|
||||
<LogoJsonLd logo={logo} url={siteUrl} />
|
||||
</>
|
||||
)
|
||||
}
|
|
@ -1,11 +1,12 @@
|
|||
/** @jsx jsx */
|
||||
import { jsx } from 'theme-ui'
|
||||
import { withPrefix, Link, useStaticQuery, graphql } from 'gatsby'
|
||||
import { Link, useStaticQuery, graphql } from 'gatsby'
|
||||
import { Styled } from 'theme-ui'
|
||||
import { Location } from '@reach/router'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { faGithub } from '@fortawesome/free-brands-svg-icons'
|
||||
import { faSlack } from '@fortawesome/free-brands-svg-icons'
|
||||
import logo from '../../static/logo.svg'
|
||||
|
||||
export default () => {
|
||||
const hoverStyle = {
|
||||
|
@ -56,7 +57,7 @@ export default () => {
|
|||
}}
|
||||
>
|
||||
<img
|
||||
src={withPrefix('logo.svg')}
|
||||
src={logo}
|
||||
sx={{ height: 30, width: 30 }}
|
||||
alt="Tuist's logotype"
|
||||
/>
|
||||
|
|
|
@ -2,13 +2,11 @@ import React from 'react'
|
|||
import { Styled } from 'theme-ui'
|
||||
import GlobalStyle from './global-style'
|
||||
import Header from '../components/header'
|
||||
import { LogoStructuredData } from '../components/structured-data'
|
||||
|
||||
const Layout = ({ children }) => {
|
||||
return (
|
||||
<>
|
||||
<GlobalStyle />
|
||||
<LogoStructuredData />
|
||||
<Styled.root>
|
||||
<Header />
|
||||
<main>{children}</main>
|
||||
|
|
|
@ -1,82 +0,0 @@
|
|||
import React from 'react'
|
||||
import Helmet from 'react-helmet'
|
||||
import { useStaticQuery, graphql, withPrefix } from 'gatsby'
|
||||
import urljoin from 'url-join'
|
||||
|
||||
function Meta({ description, lang, meta, keywords, title, author, slug }) {
|
||||
const { site } = useStaticQuery(
|
||||
graphql`
|
||||
query {
|
||||
site {
|
||||
siteMetadata {
|
||||
siteUrl
|
||||
title
|
||||
description
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
)
|
||||
|
||||
const metaDescription = description || site.siteMetadata.description
|
||||
const metaTitle = title || site.siteMetadata.title
|
||||
const titleTemplate = title ? `%s | ${site.siteMetadata.title}` : `%s`
|
||||
return (
|
||||
<Helmet
|
||||
htmlAttributes={{
|
||||
lang,
|
||||
}}
|
||||
title={metaTitle}
|
||||
titleTemplate={titleTemplate}
|
||||
>
|
||||
<meta property="og:title" content={title} />
|
||||
<meta property="og:description" content={metaDescription} />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta
|
||||
property="og:image"
|
||||
content={urljoin(
|
||||
site.siteMetadata.siteUrl,
|
||||
withPrefix('squared-logo.png')
|
||||
)}
|
||||
/>
|
||||
|
||||
<meta name="twitter:creator" content={site.siteMetadata.author} />
|
||||
<meta name="twitter:title" content={title} />
|
||||
<meta name="twitter:description" content={metaDescription} />
|
||||
|
||||
<meta name="description" content={metaDescription} />
|
||||
<meta name="keywords" content={keywords.join(`, `)} />
|
||||
|
||||
{slug && (
|
||||
<meta
|
||||
name="twitter:image"
|
||||
content={`${site.siteMetadata.siteUrl}${slug}twitter-card.jpg`}
|
||||
/>
|
||||
)}
|
||||
{slug && <meta name="twitter:card" content="summary_large_image" />}
|
||||
</Helmet>
|
||||
)
|
||||
}
|
||||
|
||||
Meta.defaultProps = {
|
||||
lang: `en`,
|
||||
meta: [],
|
||||
keywords: [
|
||||
`tuist`,
|
||||
`engineering`,
|
||||
`xcode`,
|
||||
`swift`,
|
||||
`project generation`,
|
||||
'ios',
|
||||
'uikit',
|
||||
'foundation',
|
||||
'tvos',
|
||||
'ios',
|
||||
'watchos',
|
||||
'objective-c',
|
||||
'swift package manager',
|
||||
'swift packages',
|
||||
],
|
||||
}
|
||||
|
||||
export default Meta
|
|
@ -1,129 +0,0 @@
|
|||
/** @jsx jsx */
|
||||
import { jsx, Styled } from 'theme-ui'
|
||||
import { withPrefix, useStaticQuery, graphql } from 'gatsby'
|
||||
import Helmet from 'react-helmet'
|
||||
import urljoin from 'url-join'
|
||||
|
||||
const ArticleStructuredData = ({
|
||||
url,
|
||||
title,
|
||||
excerpt,
|
||||
author,
|
||||
siteUrl,
|
||||
date,
|
||||
}) => {
|
||||
const structuredData = `
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "NewsArticle",
|
||||
"mainEntityOfPage": {
|
||||
"@type": "WebPage",
|
||||
"@id": "https://google.com/article"
|
||||
},
|
||||
"headline": "${title}",
|
||||
"datePublished": "${date.toISOString()}",
|
||||
"author": {
|
||||
"@type": "Person",
|
||||
"name": "${author}"
|
||||
},
|
||||
"publisher": {
|
||||
"@type": "Organization",
|
||||
"name": "Tuist",
|
||||
"logo": {
|
||||
"@type": "ImageObject",
|
||||
"url": "${urljoin(siteUrl, withPrefix('tuist.png'))}"
|
||||
}
|
||||
},
|
||||
"description": "${excerpt}"
|
||||
}
|
||||
`
|
||||
return (
|
||||
<Helmet>
|
||||
<script type="application/ld+json">{structuredData}</script>
|
||||
</Helmet>
|
||||
)
|
||||
}
|
||||
|
||||
const LogoStructuredData = () => {
|
||||
const {
|
||||
site: {
|
||||
siteMetadata: { siteUrl },
|
||||
},
|
||||
} = useStaticQuery(graphql`
|
||||
query {
|
||||
site {
|
||||
siteMetadata {
|
||||
siteUrl
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
const structuredData = `
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Organization",
|
||||
"url": "${siteUrl}",
|
||||
"logo": "${urljoin(siteUrl, withPrefix('tuist.png'))}"
|
||||
}
|
||||
`
|
||||
return (
|
||||
<Helmet>
|
||||
<script type="application/ld+json">{structuredData}</script>
|
||||
</Helmet>
|
||||
)
|
||||
}
|
||||
|
||||
const FAQStructuredData = ({ items }) => {
|
||||
const itemListElement = items.map((item, index) => {
|
||||
return {
|
||||
'@type': 'Question',
|
||||
name: item[0],
|
||||
acceptedAnswer: {
|
||||
'@type': 'Answer',
|
||||
text: item[1],
|
||||
},
|
||||
}
|
||||
})
|
||||
const structuredData = `
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "FAQPage",
|
||||
"mainEntity": ${JSON.stringify(itemListElement)}
|
||||
}
|
||||
`
|
||||
return (
|
||||
<Helmet>
|
||||
<script type="application/ld+json">{structuredData}</script>
|
||||
</Helmet>
|
||||
)
|
||||
}
|
||||
|
||||
const BreadcrumbStructuredData = ({ items }) => {
|
||||
const itemListElement = items.map((item, index) => {
|
||||
return {
|
||||
'@type': 'ListItem',
|
||||
position: index,
|
||||
name: item[0],
|
||||
item: item[1],
|
||||
}
|
||||
})
|
||||
const structuredData = `
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "BreadcrumbList",
|
||||
"itemListElement": ${JSON.stringify(itemListElement)}
|
||||
}
|
||||
`
|
||||
return (
|
||||
<Helmet>
|
||||
<script type="application/ld+json">{structuredData}</script>
|
||||
</Helmet>
|
||||
)
|
||||
}
|
||||
|
||||
export {
|
||||
ArticleStructuredData,
|
||||
BreadcrumbStructuredData,
|
||||
LogoStructuredData,
|
||||
FAQStructuredData,
|
||||
}
|
|
@ -2,11 +2,11 @@
|
|||
import { jsx, Styled } from 'theme-ui'
|
||||
import { useStaticQuery, graphql } from 'gatsby'
|
||||
import Layout from '../components/layout'
|
||||
import Meta from '../components/meta'
|
||||
import Main from '../components/main'
|
||||
import { MDXRenderer } from 'gatsby-plugin-mdx'
|
||||
import { FAQStructuredData } from '../components/structured-data'
|
||||
import { FAQJsonLd, GatsbySeo } from 'gatsby-plugin-next-seo'
|
||||
import Footer from '../components/footer'
|
||||
import SEO from '../components/SEO'
|
||||
|
||||
const Question = ({ question, body, index }) => {
|
||||
return (
|
||||
|
@ -38,22 +38,15 @@ export default () => {
|
|||
}
|
||||
`)
|
||||
const structuredQuestions = questions.map(question => {
|
||||
return [question.frontmatter.question, question.excerpt]
|
||||
return { question: question.frontmatter.question, answer: question.excerpt }
|
||||
})
|
||||
return (
|
||||
<Layout>
|
||||
<FAQStructuredData items={structuredQuestions} />
|
||||
<Meta
|
||||
<SEO />
|
||||
<FAQJsonLd questions={structuredQuestions} />
|
||||
<GatsbySeo
|
||||
title="FAQ"
|
||||
description={`This page contains answers for questions that are frequently asked by users. Questions such as "Should I gitignore my project?" or "How does Tuist compare to the Swift Package Manager?"`}
|
||||
keywords={[
|
||||
'tuist',
|
||||
'project generation',
|
||||
'frequently asked questions',
|
||||
'xcode',
|
||||
'swift',
|
||||
'faq',
|
||||
]}
|
||||
/>
|
||||
<Main>
|
||||
<Styled.h1>Frequently asked questions</Styled.h1>
|
||||
|
@ -62,7 +55,7 @@ export default () => {
|
|||
<Question
|
||||
question={question.frontmatter.question}
|
||||
body={question.body}
|
||||
index={index}
|
||||
key={index}
|
||||
/>
|
||||
)
|
||||
})}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
import { jsx, Styled } from 'theme-ui'
|
||||
|
||||
import Layout from '../components/layout'
|
||||
import Meta from '../components/meta'
|
||||
import Footer from '../components/footer'
|
||||
import Main from '../components/main'
|
||||
import { graphql, Link } from 'gatsby'
|
||||
|
@ -14,11 +13,10 @@ import Message from '../../assets/message.svg'
|
|||
import Framework from '../../assets/framework.svg'
|
||||
import Arrow from '../../assets/arrow.svg'
|
||||
import Swift from '../../assets/swift.svg'
|
||||
import Soundcloud from '../../assets/soundcloud.svg'
|
||||
import Mytaxi from '../../assets/mytaxi.svg'
|
||||
import posed from 'react-pose'
|
||||
import Code from '../gatsby-plugin-theme-ui/code'
|
||||
import Quote from '../../assets/quote.svg'
|
||||
import SEO from '../components/SEO'
|
||||
|
||||
const PressableButton = posed.div({
|
||||
hoverable: true,
|
||||
|
@ -391,6 +389,7 @@ const Reflection = ({ name, avatarUrl, testimony, role, company }) => {
|
|||
<div sx={{ mt: 4, mb: 3, display: 'inherit' }}>
|
||||
<img
|
||||
src={avatarUrl}
|
||||
alt={`${name} avatar`}
|
||||
sx={{ bg: 'gray6', width: 60, height: 60, borderRadius: 30, ml: 3 }}
|
||||
/>
|
||||
<div
|
||||
|
@ -419,7 +418,7 @@ const Reflection = ({ name, avatarUrl, testimony, role, company }) => {
|
|||
p: 3,
|
||||
}}
|
||||
>
|
||||
<quote>"{testimony}"</quote>
|
||||
<Quote>"{testimony}"</Quote>
|
||||
</div>
|
||||
<div
|
||||
sx={{
|
||||
|
@ -609,6 +608,7 @@ const Contribute = () => {
|
|||
height: 50,
|
||||
borderRadius: 25,
|
||||
}}
|
||||
alt="Ollie's avatar"
|
||||
src="https://avatars2.githubusercontent.com/u/1382565?s=460&v=4"
|
||||
/>
|
||||
</a>
|
||||
|
@ -619,6 +619,7 @@ const Contribute = () => {
|
|||
>
|
||||
<img
|
||||
sx={{ width: 50, height: 50, borderRadius: 25 }}
|
||||
alt="Kas' avatar"
|
||||
src="https://avatars2.githubusercontent.com/u/11914919?s=460&v=4"
|
||||
/>
|
||||
</a>
|
||||
|
@ -635,6 +636,7 @@ const Contribute = () => {
|
|||
height: 50,
|
||||
borderRadius: 25,
|
||||
}}
|
||||
alt="Marek's profile"
|
||||
src="https://avatars1.githubusercontent.com/u/9371695?s=460&v=4"
|
||||
/>
|
||||
</a>
|
||||
|
@ -681,6 +683,7 @@ const Contribute = () => {
|
|||
height: 50,
|
||||
borderRadius: 25,
|
||||
}}
|
||||
alt="Lakpa's avatar"
|
||||
src="https://avatars1.githubusercontent.com/u/389328?s=400&v=4"
|
||||
/>
|
||||
</a>
|
||||
|
@ -707,6 +710,7 @@ const Contribute = () => {
|
|||
height: 50,
|
||||
borderRadius: 25,
|
||||
}}
|
||||
alt="Marcin's avatar"
|
||||
src="https://avatars1.githubusercontent.com/u/946649?s=460&v=4"
|
||||
/>
|
||||
</a>
|
||||
|
@ -719,7 +723,7 @@ const Contribute = () => {
|
|||
const IndexPage = () => {
|
||||
return (
|
||||
<Layout>
|
||||
<Meta />
|
||||
<SEO />
|
||||
<Steroids />
|
||||
<Workspaces />
|
||||
<Principles />
|
||||
|
|
|
@ -2,14 +2,15 @@
|
|||
import { jsx, Styled } from 'theme-ui'
|
||||
|
||||
import Layout from '../components/layout'
|
||||
import Meta from '../components/meta'
|
||||
import Footer from '../components/footer'
|
||||
import { Link } from 'gatsby'
|
||||
import { graphql } from 'gatsby'
|
||||
import Main from '../components/main'
|
||||
import { findWhere } from 'underscore'
|
||||
import { BreadcrumbStructuredData } from '../components/structured-data'
|
||||
import { BreadcrumbJsonLd, BlogJsonLd } from 'gatsby-plugin-next-seo'
|
||||
import urljoin from 'url-join'
|
||||
import moment from 'moment'
|
||||
import SEO from '../components/SEO'
|
||||
|
||||
const Post = ({ post, index, authors }) => {
|
||||
const authorHandle = post.frontmatter.author
|
||||
|
@ -125,17 +126,39 @@ const BlogList = ({
|
|||
allAuthorsYaml: { nodes: authors },
|
||||
},
|
||||
}) => {
|
||||
const breadcrumb = [['Blog', urljoin(siteUrl, '/blog')]]
|
||||
const breadcrumb = [
|
||||
{ position: 1, name: 'Blog', item: urljoin(siteUrl, '/blog') },
|
||||
]
|
||||
const description =
|
||||
'Read about Tuist updates: new releases, engineering challenges, and road-map updates.'
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<BreadcrumbStructuredData items={breadcrumb} />
|
||||
<Meta title="Blog" description={description} />
|
||||
<BreadcrumbJsonLd itemListElements={breadcrumb} />
|
||||
<SEO title="Blog" description={description} />
|
||||
<BlogJsonLd
|
||||
url={urljoin(siteUrl, '/blog')}
|
||||
headline="Tuist Blog"
|
||||
posts={edges.map(edge => {
|
||||
const authorHandle = edge.node.frontmatter.author
|
||||
const author = findWhere(authors, { handle: authorHandle })
|
||||
|
||||
return {
|
||||
headline: edge.node.frontmatter.title,
|
||||
author: author.name,
|
||||
datePublished: moment(edge.node.fields.date).format(),
|
||||
image: author.avatar,
|
||||
publisherName: author.name,
|
||||
publisherLogo: author.avatar,
|
||||
}
|
||||
})}
|
||||
authorName="Tuist"
|
||||
description={description}
|
||||
/>
|
||||
<Main>
|
||||
<Styled.h1>Blog</Styled.h1>
|
||||
{edges.map(({ node }, index) => {
|
||||
return <Post post={node} index={index} authors={authors} />
|
||||
return <Post post={node} key={index} authors={authors} />
|
||||
})}
|
||||
<PostsFooter {...pageContext} />
|
||||
</Main>
|
||||
|
|
|
@ -3,18 +3,15 @@ import { jsx, Styled } from 'theme-ui'
|
|||
import { MDXRenderer } from 'gatsby-plugin-mdx'
|
||||
|
||||
import Layout from '../components/layout'
|
||||
import Meta from '../components/meta'
|
||||
import Footer from '../components/footer'
|
||||
import { graphql } from 'gatsby'
|
||||
import moment from 'moment'
|
||||
import Main from '../components/main'
|
||||
import EditPage from '../components/edit-page'
|
||||
import Share from '../components/share'
|
||||
import {
|
||||
BreadcrumbStructuredData,
|
||||
ArticleStructuredData,
|
||||
} from '../components/structured-data'
|
||||
import urljoin from 'url-join'
|
||||
import SEO from '../components/SEO'
|
||||
import { NewsArticleJsonLd, BreadcrumbJsonLd } from 'gatsby-plugin-next-seo'
|
||||
|
||||
const Avatar = ({ author: { avatar, twitter } }) => {
|
||||
return (
|
||||
|
@ -52,26 +49,39 @@ const IndexPage = ({
|
|||
).format('MMMM Do YYYY')}`
|
||||
|
||||
const breadcrumb = [
|
||||
['Blog', urljoin(siteUrl, '/blog')],
|
||||
[post.frontmatter.title, urljoin(siteUrl, post.fields.slug)],
|
||||
{ position: 1, name: 'Blog', item: urljoin(siteUrl, '/blog') },
|
||||
{
|
||||
position: 2,
|
||||
name: post.frontmatter.title,
|
||||
item: urljoin(siteUrl, post.fields.slug),
|
||||
},
|
||||
]
|
||||
return (
|
||||
<Layout>
|
||||
<BreadcrumbStructuredData items={breadcrumb} />
|
||||
<ArticleStructuredData
|
||||
title={post.frontmatter.title}
|
||||
excerpt={post.frontmatter.excerpt}
|
||||
author={author.name}
|
||||
<BreadcrumbJsonLd itemListElements={breadcrumb} />
|
||||
<NewsArticleJsonLd
|
||||
url={urljoin(siteUrl, post.fields.slug)}
|
||||
siteUrl={siteUrl}
|
||||
date={moment(post.fields.date)}
|
||||
title={post.frontmatter.title}
|
||||
keywords={post.frontmatter.categories}
|
||||
datePublished={moment(post.fields.date).format()}
|
||||
author={author.name}
|
||||
description={post.frontmatter.excerpt}
|
||||
/>
|
||||
<Meta
|
||||
|
||||
<SEO
|
||||
title={post.frontmatter.title}
|
||||
description={post.frontmatter.excerpt}
|
||||
keywords={post.frontmatter.categories}
|
||||
author={author.twitter}
|
||||
slug={post.fields.slug}
|
||||
openGraph={{
|
||||
title: post.frontmatter.title,
|
||||
description: post.frontmatter.excerpt,
|
||||
url: urljoin(siteUrl, post.fields.slug),
|
||||
type: 'article',
|
||||
article: {
|
||||
publishedTime: moment(post.fields.date).format(),
|
||||
authors: [`https://www.twitter.com/${author.twitter}`],
|
||||
tags: post.frontmatter.categories,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
<Main>
|
||||
<div
|
||||
|
|
|
@ -1,26 +1,54 @@
|
|||
/** @jsx jsx */
|
||||
import { jsx, Styled } from 'theme-ui'
|
||||
import { MDXRenderer } from 'gatsby-plugin-mdx'
|
||||
import { graphql, Link } from 'gatsby'
|
||||
import { graphql, Link, withPrefix } from 'gatsby'
|
||||
import Layout from '../components/layout'
|
||||
import Footer from '../components/footer'
|
||||
import Meta from '../components/meta'
|
||||
import { ArticleJsonLd, BreadcrumbJsonLd } from 'gatsby-plugin-next-seo'
|
||||
import urljoin from 'url-join'
|
||||
import moment from 'moment'
|
||||
import SEO from '../components/SEO'
|
||||
|
||||
const DocumentationPage = ({
|
||||
data: {
|
||||
mdx,
|
||||
allFile: { nodes: files },
|
||||
site: {
|
||||
siteMetadata: { documentationCategories },
|
||||
siteMetadata: { documentationCategories, siteUrl },
|
||||
},
|
||||
},
|
||||
}) => {
|
||||
const post = mdx
|
||||
const page = mdx
|
||||
return (
|
||||
<Layout>
|
||||
<Meta
|
||||
title={post.frontmatter.name}
|
||||
description={post.frontmatter.excerpt}
|
||||
<SEO
|
||||
title={page.frontmatter.name}
|
||||
description={page.frontmatter.excerpt}
|
||||
/>
|
||||
<ArticleJsonLd
|
||||
url={urljoin(siteUrl, page.fields.slug)}
|
||||
headline={page.frontmatter.name}
|
||||
description={page.frontmatter.excerpt}
|
||||
images={[urljoin(siteUrl, withPrefix('squared-logo.png'))]}
|
||||
authorName="Tuist"
|
||||
publisherName="Tuist"
|
||||
publisherLogo={urljoin(siteUrl, withPrefix('squared-logo.png'))}
|
||||
datePublished={moment().format()}
|
||||
dateModified={moment().format()}
|
||||
/>
|
||||
<BreadcrumbJsonLd
|
||||
itemListElements={[
|
||||
{
|
||||
position: 1,
|
||||
name: 'Documentation',
|
||||
item: urljoin(siteUrl, 'docs'),
|
||||
},
|
||||
{
|
||||
position: 2,
|
||||
name: page.frontmatter.name,
|
||||
item: urljoin(siteUrl, page.fields.slug),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<div
|
||||
sx={{ display: 'flex', flexDirection: ['column', 'row'], flex: '1' }}
|
||||
|
@ -77,7 +105,7 @@ const DocumentationPage = ({
|
|||
boxShadow: theme => `-1px -1px 12px -4px ${theme.colors.gray5}`,
|
||||
}}
|
||||
>
|
||||
<MDXRenderer>{post.body}</MDXRenderer>
|
||||
<MDXRenderer>{page.body}</MDXRenderer>
|
||||
</div>
|
||||
</div>
|
||||
<Footer />
|
||||
|
|
|
@ -831,14 +831,7 @@
|
|||
core-js-pure "^3.0.0"
|
||||
regenerator-runtime "^0.13.2"
|
||||
|
||||
"@babel/runtime@^7.1.2", "@babel/runtime@^7.3.1", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.4", "@babel/runtime@^7.7.6":
|
||||
version "7.7.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.7.6.tgz#d18c511121aff1b4f2cd1d452f1bac9601dd830f"
|
||||
integrity sha512-BWAJxpNVa0QlE5gZdWjSxXtemZyZ9RmrmVozxt3NUXeZhVIJ5ANyqmMc0JDrivBZyxUuQvFxlvH4OWWOogGfUw==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.2"
|
||||
|
||||
"@babel/runtime@^7.5.1":
|
||||
"@babel/runtime@^7", "@babel/runtime@^7.1.2", "@babel/runtime@^7.3.1", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.4", "@babel/runtime@^7.7.6":
|
||||
version "7.8.3"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.8.3.tgz#0811944f73a6c926bb2ad35e918dcc1bfab279f1"
|
||||
integrity sha512-fVHx1rzEmwB130VTkLnxR+HmxcTjGzH12LYQcFFoBwakMd3aOMD4OsRN7tGG/UOYE2ektgFrS8uACAoRk1CY0w==
|
||||
|
@ -1765,7 +1758,7 @@
|
|||
prop-types "^15.7.2"
|
||||
react-is "^16.6.3"
|
||||
|
||||
"@styled-system/css@^5.0.16", "@styled-system/css@^5.0.23":
|
||||
"@styled-system/css@^5.0.16":
|
||||
version "5.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@styled-system/css/-/css-5.1.4.tgz#fc51d0789a69b3831e00e6f8daf9f1d345eebdc3"
|
||||
integrity sha512-79IFT37Kxb6dlbx/0hwIGOakNHkK5oU3cMypGziShnEK8WMgK/+vuAi4MHO7uLI+FZ5U8MGYvGY9Gtk0mBzxSg==
|
||||
|
@ -1777,111 +1770,129 @@
|
|||
dependencies:
|
||||
defer-to-connect "^1.0.1"
|
||||
|
||||
"@theme-ui/color@^0.2.53":
|
||||
version "0.2.53"
|
||||
resolved "https://registry.yarnpkg.com/@theme-ui/color/-/color-0.2.53.tgz#d4ac58b99639d1370c7e541bfeebb69f0036ca0c"
|
||||
integrity sha512-Xz9146bG+tYZ9cJslAk1oq7hmlHmpso2bKLpjAW9O9382gWGNNoie44W0xi6XkVvDXtmnNei4nM/H5Wbtu9V0w==
|
||||
"@theme-ui/color@^0.3.1":
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@theme-ui/color/-/color-0.3.1.tgz#fceffc0be305ad6ca6be9755ac9cafc955b1e6f5"
|
||||
integrity sha512-Bgew6etspp087AdrKuMpcWjIQDQ8UTp28wtHCXgi1Ip5ClFn9i91DvaKgqXk9UwQJFL/IwydX8Bks/+u9tf0WA==
|
||||
dependencies:
|
||||
"@styled-system/css" "^5.0.23"
|
||||
"@theme-ui/css" "^0.3.1"
|
||||
polished "^3.4.1"
|
||||
|
||||
"@theme-ui/css@^0.3.1":
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@theme-ui/css/-/css-0.3.1.tgz#b85c7e8fae948dc0de65aa30b853368993e25cb3"
|
||||
integrity sha512-QB2/fZBpo4inaLHL3OrB8NOBgNfwnj8GtHzXWHb9iQSRjmtNX8zPXBe32jLT7qQP0+y8JxPT4YChZIkm5ZyIdg==
|
||||
|
||||
"@theme-ui/preset-base@^0.2.44":
|
||||
version "0.2.44"
|
||||
resolved "https://registry.yarnpkg.com/@theme-ui/preset-base/-/preset-base-0.2.44.tgz#ae8e938288a534f129111a56b1971e1cc12ddc9d"
|
||||
integrity sha512-g2BaHKz5/32wHIFoRifHxYikBJICqYx+weypA/zwz+d7rZTE9q+EgTvlFSdVlf1HtR2a3uLB1lp4se0tlI2zwg==
|
||||
|
||||
"@theme-ui/preset-bootstrap@^0.2.40":
|
||||
version "0.2.40"
|
||||
resolved "https://registry.yarnpkg.com/@theme-ui/preset-bootstrap/-/preset-bootstrap-0.2.40.tgz#6494fff018ce20c6cce4e4c06a7aca3c8df6b635"
|
||||
integrity sha512-eIWrmxDYDhw0A0FfiUScuhIVR7xlq/CS56nzidsdKl5R9kBg5K1pcyHPGQrW6jLDnhFL6bOqZuvzchvHXooSew==
|
||||
"@theme-ui/preset-base@^0.3.0":
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@theme-ui/preset-base/-/preset-base-0.3.0.tgz#853a78195beead04ece4391c5672d690899bec47"
|
||||
integrity sha512-bFCYoxfe/Ugr5k5BEy3Gv5jg8+idZHWDt/NM95jgla4qITlaOAMuEL6afoQ5HXbJjp5TnZFZ73qO6cKI8/BFfQ==
|
||||
|
||||
"@theme-ui/preset-bulma@^0.2.44":
|
||||
version "0.2.44"
|
||||
resolved "https://registry.yarnpkg.com/@theme-ui/preset-bulma/-/preset-bulma-0.2.44.tgz#6ee9f7de30471b7b1d6dde7eb00b7ed4c988b37a"
|
||||
integrity sha512-gJ5daQzQZPQVcr34mWE3R2vf9ASRpb7Xjd//FVwcwKn95ZdaeLTAksW9FMDisWtrmF7O8NiF1JHSHnu6i9M3dQ==
|
||||
"@theme-ui/preset-bootstrap@^0.3.0":
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@theme-ui/preset-bootstrap/-/preset-bootstrap-0.3.0.tgz#0a50dff50eb2b444dce1e0273cf359026ef4e10c"
|
||||
integrity sha512-UoBvNNo4JMsdVPuF3tzEPhZu6T1vuFTEDPUwrannaq2ycFfZZVBfr0YaDNtM+n5lcPp3DBXvZrMjDCURteGjVA==
|
||||
|
||||
"@theme-ui/preset-bulma@^0.3.0":
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@theme-ui/preset-bulma/-/preset-bulma-0.3.0.tgz#e7a13222da030052607d48a61b2948ad4761d9c3"
|
||||
integrity sha512-9p7SWvEzqfOVqwzpXFn6xB9fiPj3aomb6gG79FoaSzXRv+ATRtsQam9o8GWhGljiQbNazbxFd95RUP92sflncw==
|
||||
dependencies:
|
||||
"@theme-ui/preset-base" "^0.3.0"
|
||||
|
||||
"@theme-ui/preset-dark@^0.3.0":
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@theme-ui/preset-dark/-/preset-dark-0.3.0.tgz#bce2a12768b64e730ff7307145809fcabac16da1"
|
||||
integrity sha512-biKyaGTy4awA+JbeUO4o2TzkeB4i1nregukS9BUOrub7I4jrKjPvjIlHxlU2uiQIYbxKq4n/QqBIsCbTDdg74w==
|
||||
|
||||
"@theme-ui/preset-deep@^0.3.0":
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@theme-ui/preset-deep/-/preset-deep-0.3.0.tgz#acdf3028ef8dc5af2d20b5a82f9fed1062cf74d6"
|
||||
integrity sha512-5XZckaa1nhm7afb57bCMGKR/TCaf9cjTwhNkfAaFjKVklVB4CCinS43zQ0sDadwd3oihCJmGbXyvgwBb8mp/iw==
|
||||
|
||||
"@theme-ui/preset-funk@^0.3.0":
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@theme-ui/preset-funk/-/preset-funk-0.3.0.tgz#c1fb55d3d49db5b147cb4b58e504e8db50312d1f"
|
||||
integrity sha512-YT/2OgZwx9/FpkM+ol7ixnmusBcMRRwLxlys76cV4Ky1cbb4aL92uDHOh8QIfXilXnyoi8mLVduCMOJCd+1h2Q==
|
||||
dependencies:
|
||||
"@theme-ui/preset-base" "^0.3.0"
|
||||
|
||||
"@theme-ui/preset-future@^0.3.0":
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@theme-ui/preset-future/-/preset-future-0.3.0.tgz#cd9384749328fb49856ef3452f6da8d9796d51fa"
|
||||
integrity sha512-KicYV6Ck2hE3nT+Snkk4mFhshyfrX/jgSHGrmfOGMhLjkapQYUpuIKRQMPjlm2dDtd5exbaxOOjX4edRIkqQyg==
|
||||
dependencies:
|
||||
"@theme-ui/preset-base" "^0.3.0"
|
||||
|
||||
"@theme-ui/preset-polaris@^0.3.0":
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@theme-ui/preset-polaris/-/preset-polaris-0.3.0.tgz#1e9791122d386a813928b2e6f87d3d41fe690fa1"
|
||||
integrity sha512-Tw1xKIbKt28OkevT/WynXnnjHizCQI8XN6P3e3baj5VCdGSXmRJbtZXA85tgjTf6gSTQZrWnaRg2vm/wXn/Wlw==
|
||||
dependencies:
|
||||
"@theme-ui/preset-base" "^0.2.44"
|
||||
|
||||
"@theme-ui/preset-dark@^0.2.40":
|
||||
version "0.2.40"
|
||||
resolved "https://registry.yarnpkg.com/@theme-ui/preset-dark/-/preset-dark-0.2.40.tgz#1328b942d07a1fcdb44e593627ea560187cb375e"
|
||||
integrity sha512-0Zuhrm7UmMgyxa9BRQcBwm8uA7jV4cBhbCVJfx0AO9E1OjrfjsW0kuU82BiBUY14wlqgQuleX0bcTdszXqSgzg==
|
||||
|
||||
"@theme-ui/preset-deep@^0.2.40":
|
||||
version "0.2.40"
|
||||
resolved "https://registry.yarnpkg.com/@theme-ui/preset-deep/-/preset-deep-0.2.40.tgz#1bf1def6ad8e1f0367fd111bee81e7eaf85ec816"
|
||||
integrity sha512-Cj9yYj6QYhhf4MXPtIFd9lL82WzsP8C6obqBI3Fmh51VoUrW6eYbBkmD5N/qvarkMJla29jF/3FjcS6gwMsOqQ==
|
||||
|
||||
"@theme-ui/preset-funk@^0.2.44":
|
||||
version "0.2.44"
|
||||
resolved "https://registry.yarnpkg.com/@theme-ui/preset-funk/-/preset-funk-0.2.44.tgz#2860063e5c5c92f24ea1cb2ff881cad2050d4934"
|
||||
integrity sha512-GEFmDXu21tGnXjYD+V5I5YPl8liWI5kEIFCuVz8awJoE8BYHPDdGo4Gm2TlZQvetiI9BIY2Lk5u/RYS2Zd7wYw==
|
||||
"@theme-ui/preset-roboto@^0.3.0":
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@theme-ui/preset-roboto/-/preset-roboto-0.3.0.tgz#4b7afa633416caf597f91d3624b3166e2786b1be"
|
||||
integrity sha512-7/Bjo3CeVJ73r1PcrnvGVl7TaI+gnwA5ekwfv0yifE5gJBbzvhBRnNIGcBt4aE3pd5WQ+iSKdfBBfxFjkTXQAQ==
|
||||
dependencies:
|
||||
"@theme-ui/preset-base" "^0.2.44"
|
||||
"@theme-ui/preset-base" "^0.3.0"
|
||||
|
||||
"@theme-ui/preset-future@^0.2.44":
|
||||
version "0.2.44"
|
||||
resolved "https://registry.yarnpkg.com/@theme-ui/preset-future/-/preset-future-0.2.44.tgz#43c38ad701d6efcabc4533edf089da93178e161e"
|
||||
integrity sha512-y6LipmPOYxXb3yOGWACKMTLrP+Dg6gwxWGaH3OdqAUl3LX0If+4BLubvl4VJGxfAXb7YVXxDN3Xu+etX76boWg==
|
||||
"@theme-ui/preset-swiss@^0.3.0":
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@theme-ui/preset-swiss/-/preset-swiss-0.3.0.tgz#ea170bc6e29d92a2e5b6e4cf90a17c68ca6f38f9"
|
||||
integrity sha512-ijH0FPHMR9tT7ZOIV73lY4VHEvah2FftwrYUt7w4UhjId8SnKBp5GitU+IG4E5mRdP8IiPRQCBrfs9IuSFxnWA==
|
||||
|
||||
"@theme-ui/preset-system@^0.3.0":
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@theme-ui/preset-system/-/preset-system-0.3.0.tgz#80d0feb3f8a945fe67fed3dc881e37e0ce70b3f8"
|
||||
integrity sha512-mpQbwuqPZysjdpRxtMxEU7kuafzt0QmYmT8t/1OcQMCIb/qIenu/xZsCXxrJQGZcxgO4Pq5Z9FDzXbQwNQBWcA==
|
||||
|
||||
"@theme-ui/preset-tailwind@^0.3.0":
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@theme-ui/preset-tailwind/-/preset-tailwind-0.3.0.tgz#e916023e5111df129b8e04603250ebe5d95f87e8"
|
||||
integrity sha512-Y9BA9ESkOizaN3TV9H+D1gMYgoBTWxo+YGFFfTxn3RRO8V35UUM5tHbhNUWuuu5L5h/syN9f3WENCZ/cGcuaDA==
|
||||
|
||||
"@theme-ui/preset-tosh@^0.3.0":
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@theme-ui/preset-tosh/-/preset-tosh-0.3.0.tgz#c368edaa88703b8552fa731605bffd668ae5cf3b"
|
||||
integrity sha512-YgrRHVhekvS13VGsKSYPa+ixJXmIQ/8hLIAVq6OmJQMHmPFgu/2pp45Plb1RPNlYsZwtXisO1T6nhet/jqiJvw==
|
||||
|
||||
"@theme-ui/presets@^0.3.0":
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@theme-ui/presets/-/presets-0.3.0.tgz#b2636faaa86c77f6b56c6623c954c1ce665705b0"
|
||||
integrity sha512-mPxsNACJZT+EAZ76vLRFUyVMopkOEgTps3l22PhxLWIT5MtPsGXDoyTmjbOVy1suHv5mYwdQdsJ2isW4nsePrA==
|
||||
dependencies:
|
||||
"@theme-ui/preset-base" "^0.2.44"
|
||||
"@theme-ui/preset-base" "^0.3.0"
|
||||
"@theme-ui/preset-bootstrap" "^0.3.0"
|
||||
"@theme-ui/preset-bulma" "^0.3.0"
|
||||
"@theme-ui/preset-dark" "^0.3.0"
|
||||
"@theme-ui/preset-deep" "^0.3.0"
|
||||
"@theme-ui/preset-funk" "^0.3.0"
|
||||
"@theme-ui/preset-future" "^0.3.0"
|
||||
"@theme-ui/preset-polaris" "^0.3.0"
|
||||
"@theme-ui/preset-roboto" "^0.3.0"
|
||||
"@theme-ui/preset-swiss" "^0.3.0"
|
||||
"@theme-ui/preset-system" "^0.3.0"
|
||||
"@theme-ui/preset-tailwind" "^0.3.0"
|
||||
"@theme-ui/preset-tosh" "^0.3.0"
|
||||
|
||||
"@theme-ui/preset-roboto@^0.2.44":
|
||||
version "0.2.44"
|
||||
resolved "https://registry.yarnpkg.com/@theme-ui/preset-roboto/-/preset-roboto-0.2.44.tgz#465b6bb5e5785070b9347636f8ec4065aefdb243"
|
||||
integrity sha512-ZEUzsfp7Yj7o8CVJucrs/uJnd39e4z98jsn6+qbF3cZBtLoUmpikQaiWsM2OgUsptvGKMusvfcfFASUCfKr35Q==
|
||||
dependencies:
|
||||
"@theme-ui/preset-base" "^0.2.44"
|
||||
|
||||
"@theme-ui/preset-swiss@^0.2.40":
|
||||
version "0.2.40"
|
||||
resolved "https://registry.yarnpkg.com/@theme-ui/preset-swiss/-/preset-swiss-0.2.40.tgz#4030f121ce7fcdd191732520c95c9eea68898d9c"
|
||||
integrity sha512-4LHNNrvBBuNNt367haJCztBHUpcrq5VLfkjpq8cyuG8HbTcVbT/Hcad+t1B/0d0NKdE4q5paPXA+l7fv1A5q0Q==
|
||||
|
||||
"@theme-ui/preset-system@^0.2.40":
|
||||
version "0.2.40"
|
||||
resolved "https://registry.yarnpkg.com/@theme-ui/preset-system/-/preset-system-0.2.40.tgz#a84c1589cd37b33fffd8c7c46dfcbf5a8556a3fc"
|
||||
integrity sha512-AI321YIipLM6++6ligmSaAFiBwaWFJWLyHZk5ma415hn2neYddQ5vXeBI7P4Tfhx208qg2ete5qGWM+Q7KA3Sw==
|
||||
|
||||
"@theme-ui/preset-tailwind@^0.2.42":
|
||||
version "0.2.42"
|
||||
resolved "https://registry.yarnpkg.com/@theme-ui/preset-tailwind/-/preset-tailwind-0.2.42.tgz#00e009827da2ffea628fa5b89002cd8cb6db805f"
|
||||
integrity sha512-giQQ0xoGB2btWvLlg9GQSyRiQ6vGCpVF+uf5OxU5TJt2DGyuYckxvlG3za93o80cxHnVlm5YyO2sLNzXyQSi0w==
|
||||
|
||||
"@theme-ui/preset-tosh@^0.2.40":
|
||||
version "0.2.40"
|
||||
resolved "https://registry.yarnpkg.com/@theme-ui/preset-tosh/-/preset-tosh-0.2.40.tgz#68cf4ed5e4c748e7c1762676ddb6119653679ac1"
|
||||
integrity sha512-LatVzEDlVR1pqyn9u+i4ZcZrdfWx0Hvd7ktNGLrA89RD9IX7hDHdvsr0wI6z6nrPtTNoa41YZe7xU8QzgwnpCg==
|
||||
|
||||
"@theme-ui/presets@^0.2.44":
|
||||
version "0.2.44"
|
||||
resolved "https://registry.yarnpkg.com/@theme-ui/presets/-/presets-0.2.44.tgz#5c420cea0e2841e42543cfb4f2a8b019c91d0064"
|
||||
integrity sha512-jPiz3LMwNkz2FU7eqBhOqi+e1YKdFajHg5+7tmwjXkOhWYSGFGi391IFj+cTN9VEC12Og8JWLg1Aig3QL/fi2Q==
|
||||
dependencies:
|
||||
"@theme-ui/preset-base" "^0.2.44"
|
||||
"@theme-ui/preset-bootstrap" "^0.2.40"
|
||||
"@theme-ui/preset-bulma" "^0.2.44"
|
||||
"@theme-ui/preset-dark" "^0.2.40"
|
||||
"@theme-ui/preset-deep" "^0.2.40"
|
||||
"@theme-ui/preset-funk" "^0.2.44"
|
||||
"@theme-ui/preset-future" "^0.2.44"
|
||||
"@theme-ui/preset-roboto" "^0.2.44"
|
||||
"@theme-ui/preset-swiss" "^0.2.40"
|
||||
"@theme-ui/preset-system" "^0.2.40"
|
||||
"@theme-ui/preset-tailwind" "^0.2.42"
|
||||
"@theme-ui/preset-tosh" "^0.2.40"
|
||||
|
||||
"@theme-ui/prism@^0.2.50":
|
||||
version "0.2.50"
|
||||
resolved "https://registry.yarnpkg.com/@theme-ui/prism/-/prism-0.2.50.tgz#0f1dafb7d71248ba26f90cddc643b414dd9f4378"
|
||||
integrity sha512-FD9UtROhol8limL2XtQPfnTUfUJETUC37wYW6dSIfVCDR4l0CSbqYS+niQAqVGcuD0wtL1pbkvb/qDtUg94Ebw==
|
||||
"@theme-ui/prism@^0.3.0":
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@theme-ui/prism/-/prism-0.3.0.tgz#69c2f8bf5f5c5d02f1bde5879a149f6cadab2b7c"
|
||||
integrity sha512-5M3uH5zShttu5k84OfCIWrFKFTrPdck/m/1iU/9i8CMM899mIu7VsVTgaUTKkOCMoreH2u+d7Y76j4Ur2ZMzEw==
|
||||
dependencies:
|
||||
prism-react-renderer "^1.0.2"
|
||||
|
||||
"@theme-ui/typography@^0.2.46":
|
||||
version "0.2.46"
|
||||
resolved "https://registry.yarnpkg.com/@theme-ui/typography/-/typography-0.2.46.tgz#24e20989450a35eb715967b99cbfd8fa4291ba17"
|
||||
integrity sha512-66VMjZ/7fvhwtJHwYZH4/Vl+wYpLXN2QzNU6wn/7VcBf9xJZPXEumI8wSp9P1R2eEjLAlaz8tpl1VDMGPDxsVA==
|
||||
"@theme-ui/typography@^0.3.0":
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@theme-ui/typography/-/typography-0.3.0.tgz#4e9a33a9c42e7bfac3abed4f1d7f86232a4c4ec4"
|
||||
integrity sha512-71xT7M73FbgqBLVISaSjjL65V8Tn75cnoIH9MAPfmLP7+YhH0BtzBWfGiuB4Rz6pHj111MNnnn1PmStgtmDYQw==
|
||||
dependencies:
|
||||
compass-vertical-rhythm "^1.4.5"
|
||||
modularscale "^2.0.1"
|
||||
|
@ -1998,6 +2009,13 @@
|
|||
"@types/history" "*"
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-helmet@^5":
|
||||
version "5.0.15"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-helmet/-/react-helmet-5.0.15.tgz#af0370617307e9f062c6aee0f1f5588224ce646e"
|
||||
integrity sha512-CCjqvecDJTXRrHG8aTc2YECcQCl26za/q+NaBRvy/wtm0Uh38koM2dpv2bG1xJV4ckz3t1lm2/5KU6nt2s9BWg==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react@*":
|
||||
version "16.9.16"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.16.tgz#4f12515707148b1f53a8eaa4341dae5dfefb066d"
|
||||
|
@ -6435,10 +6453,10 @@ gatsby-cli@^2.8.26:
|
|||
ink "^2.6.0"
|
||||
ink-spinner "^3.0.1"
|
||||
|
||||
gatsby-core-utils@^1.0.26:
|
||||
version "1.0.26"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-core-utils/-/gatsby-core-utils-1.0.26.tgz#e1cbdfad498d58d677d9d74f21a1ede661b49d6f"
|
||||
integrity sha512-NPflmXmyTcg3x2mp6cqp/51QeAHRKepfbf0X4erDsnVlewFJuGTe+25ZJvWkkwU2g1cPAxuwzlPe0jOL92iU4A==
|
||||
gatsby-core-utils@^1.0.26, gatsby-core-utils@^1.0.28:
|
||||
version "1.0.28"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-core-utils/-/gatsby-core-utils-1.0.28.tgz#aa66e49cdcc1892e7817a32fdd806cf5e16ea309"
|
||||
integrity sha512-XWKR9Rk2v6iQkmBsTLCdI3adyC9PCh1s5BQ85nlGitlgcVVQq98jZlQdcy0v9mJOrTuce0uf5RqkeGDWFLekoA==
|
||||
dependencies:
|
||||
ci-info "2.0.0"
|
||||
node-object-hash "^2.0.0"
|
||||
|
@ -6450,10 +6468,10 @@ gatsby-graphiql-explorer@^0.2.32:
|
|||
dependencies:
|
||||
"@babel/runtime" "^7.7.6"
|
||||
|
||||
gatsby-image@^2.2.39:
|
||||
version "2.2.39"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-image/-/gatsby-image-2.2.39.tgz#c2982152923409139b03446c58fbaa99c15e47a2"
|
||||
integrity sha512-ypb5J+ACeHoGhyw//O0ye7z8sm8yW/MVqpuZ+gkCyXWt3zexp4jjHqV3uDOkvI9fPQC/QCZLXepE7Ve77iAeEg==
|
||||
gatsby-image@^2.2.40:
|
||||
version "2.2.40"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-image/-/gatsby-image-2.2.40.tgz#2ccb965ba03ed7456a87f42fe0a04bcaa6367b6d"
|
||||
integrity sha512-K1rYYMu36GSJcodFw0Z+MSkxLsyA5J5jx3HsMFcTTWL9m5yNdjiPxaepx23ijNKQ7sWvGdsOfhCciSnMVz0AFg==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.7.6"
|
||||
object-fit-images "^3.2.4"
|
||||
|
@ -6491,10 +6509,10 @@ gatsby-plugin-favicon@3.1.6:
|
|||
html-react-parser "^0.6.4"
|
||||
lodash "^4.17.11"
|
||||
|
||||
gatsby-plugin-feed@^2.3.26:
|
||||
version "2.3.26"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-feed/-/gatsby-plugin-feed-2.3.26.tgz#00043a581b81b73c595b7620fe0f381d241ca8da"
|
||||
integrity sha512-L2/LyCkZ+cPF2QAISszEwi2D2CuRk6ELp75d8tN7oCRDKkcSCJZND6gzIvBxNzGjEnbxtTk9OhL/1TnmJTALNQ==
|
||||
gatsby-plugin-feed@^2.3.27:
|
||||
version "2.3.27"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-feed/-/gatsby-plugin-feed-2.3.27.tgz#c3dd793bb22d62563687350adfd7cedbd84d826b"
|
||||
integrity sha512-YdYyMi2k1d2vJtHq7GCFilWqHGBP74kMfv4vEjbGKnHwjUN+hu1u0ZbZHCO56OLz/Yyi+rG+pNdTDlbDFWD7lw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.7.6"
|
||||
"@hapi/joi" "^15.1.1"
|
||||
|
@ -6502,13 +6520,13 @@ gatsby-plugin-feed@^2.3.26:
|
|||
lodash.merge "^4.6.2"
|
||||
rss "^1.2.2"
|
||||
|
||||
gatsby-plugin-manifest@2.2.37:
|
||||
version "2.2.37"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-manifest/-/gatsby-plugin-manifest-2.2.37.tgz#ea385bbd453d8455d3c4715c4f3b1e8c1313a97b"
|
||||
integrity sha512-RT7ALsnq/H1gZrmyHJ6jJFn+Z/OzDJgiwVlP5qIUmAzAoqC95bq3XbXB5yHCePAvZjKn0liIRjUyp0OHVKQlNQ==
|
||||
gatsby-plugin-manifest@2.2.41:
|
||||
version "2.2.41"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-manifest/-/gatsby-plugin-manifest-2.2.41.tgz#c6952e466b163145b74aa071822a97a797a68e01"
|
||||
integrity sha512-eKbnpDSLbGUzmnfE65uLit/J8XS4LYslyRHtqMhTja6JcdzjXVWFsO9043tqUXfL8+JBw5PccCxZM8BIN23+Vw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.7.6"
|
||||
gatsby-core-utils "^1.0.26"
|
||||
gatsby-core-utils "^1.0.28"
|
||||
semver "^5.7.1"
|
||||
sharp "^0.23.4"
|
||||
|
||||
|
@ -6571,14 +6589,24 @@ gatsby-plugin-netlify@^2.1.31:
|
|||
lodash "^4.17.15"
|
||||
webpack-assets-manifest "^3.1.1"
|
||||
|
||||
gatsby-plugin-offline@^3.0.32:
|
||||
version "3.0.32"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-offline/-/gatsby-plugin-offline-3.0.32.tgz#9907421e7359f79b22da7f654c4a69749cf136c5"
|
||||
integrity sha512-TPVRhD4LaVcCLBMzdbPUZr4bb+dv1h/HMn7ryFozFafYJ1p7XuKv2VHtqNYpfL1UKiZnWIJmEWXxfcWszLoC4w==
|
||||
gatsby-plugin-next-seo@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-next-seo/-/gatsby-plugin-next-seo-1.4.0.tgz#1014250ab3b5822e0811a27a6fc6650880e6e148"
|
||||
integrity sha512-w8kIpihLbiqPxlGCAdD5/euFswCOssjgwEtjlGV5Gi3qg+TARD9P6U5K0sAAe/yI5fAKb1FvFum44htM3BfXxQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7"
|
||||
"@types/react-helmet" "^5"
|
||||
schema-dts "0.4.5"
|
||||
type-fest "^0.8"
|
||||
|
||||
gatsby-plugin-offline@^3.0.34:
|
||||
version "3.0.34"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-offline/-/gatsby-plugin-offline-3.0.34.tgz#6aae8c4cf48a683e7ee107cded8ddd29cf4036bb"
|
||||
integrity sha512-iyps2wM7ktB9osJ8jCxM5gZn3BK3JzKrIgv6R3mD/Gqc9XcF4Ew367AIjNowPQclGfcBHbykjrwlK5T5vMwNEg==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.7.6"
|
||||
cheerio "^1.0.0-rc.3"
|
||||
gatsby-core-utils "^1.0.26"
|
||||
gatsby-core-utils "^1.0.28"
|
||||
glob "^7.1.6"
|
||||
idb-keyval "^3.2.0"
|
||||
lodash "^4.17.15"
|
||||
|
@ -6597,10 +6625,10 @@ gatsby-plugin-page-creator@^2.1.38:
|
|||
lodash "^4.17.15"
|
||||
micromatch "^3.1.10"
|
||||
|
||||
gatsby-plugin-react-helmet@^3.1.21:
|
||||
version "3.1.21"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-react-helmet/-/gatsby-plugin-react-helmet-3.1.21.tgz#659f31020295f42d017e2eb03175d73516ab824d"
|
||||
integrity sha512-6LZ2LEYTwqD+ZqyCH55mVpk2xEXbQoCTfijP1W4ZCQsKtpWGJP+vyd6b96FWVyEb2k5LsQ1u+jk4R8xXULSX+w==
|
||||
gatsby-plugin-react-helmet@^3.1.22:
|
||||
version "3.1.22"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-react-helmet/-/gatsby-plugin-react-helmet-3.1.22.tgz#f4c148dfe964af1e1364e6bcd9a4cd3226e8cd7a"
|
||||
integrity sha512-eG57C7Rm84dOpaFYxqQsKSzP0ge/6SnAEsPH5JcAcJ7vETtn3rCS6SB8qs+Nk/jhziAjdGjBw3CSJnOkg/QUJA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.7.6"
|
||||
|
||||
|
@ -6644,20 +6672,20 @@ gatsby-plugin-sharp@2.4.0:
|
|||
svgo "1.3.2"
|
||||
uuid "^3.3.3"
|
||||
|
||||
gatsby-plugin-sitemap@^2.2.26:
|
||||
version "2.2.26"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-sitemap/-/gatsby-plugin-sitemap-2.2.26.tgz#d0b9a9064966fd31b9ae46e769b05c904c20fd2f"
|
||||
integrity sha512-0kqMM6zD4IWha7Af6kfzwk78870S8XGpOVNJojgtQ83eUu6mKQXdRuae/i52hjclSDsEprbvUfQT0yMxgOotGw==
|
||||
gatsby-plugin-sitemap@^2.2.27:
|
||||
version "2.2.27"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-sitemap/-/gatsby-plugin-sitemap-2.2.27.tgz#efdf0407ae754f806a172785eaab468e8baf42a9"
|
||||
integrity sha512-Iq/nUwMhdl76CPkkUEcprKnGyc3Viaqiaxgn9L2kfF7LhggKVdSKYpJjBa80B0856cDQRJVkatumD43+kf3NZA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.7.6"
|
||||
minimatch "^3.0.4"
|
||||
pify "^3.0.0"
|
||||
sitemap "^1.13.0"
|
||||
|
||||
gatsby-plugin-theme-ui@^0.2.53:
|
||||
version "0.2.53"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-theme-ui/-/gatsby-plugin-theme-ui-0.2.53.tgz#57a52339e50ede7ef4df0b1b5593d360b56b597d"
|
||||
integrity sha512-AlQC+uC9lvrP3LlGsLe0f0azp7B5c49qWl4b3FDj8xbravBoqFmJT7XrNTpYYbxnCnx/K1v0QtwP8qindw0S2g==
|
||||
gatsby-plugin-theme-ui@^0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-plugin-theme-ui/-/gatsby-plugin-theme-ui-0.3.0.tgz#ab84216536ae45abe09a6edf24156b9dbf50d6a5"
|
||||
integrity sha512-Q2tS8EeYMy7AAtt6hvDtEsd1uwrLMjkDNqabyXhAo38AFoWQ0oKtq9u1YqbiRvp1TK06pAMPQQ3to48LAqc9Cw==
|
||||
|
||||
gatsby-react-router-scroll@^2.1.20:
|
||||
version "2.1.20"
|
||||
|
@ -6697,10 +6725,10 @@ gatsby-remark-images@^3.1.42:
|
|||
unist-util-select "^1.5.0"
|
||||
unist-util-visit-parents "^2.1.2"
|
||||
|
||||
gatsby-remark-smartypants@^2.1.20:
|
||||
version "2.1.20"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-remark-smartypants/-/gatsby-remark-smartypants-2.1.20.tgz#d081d93d50b0f1b48dc2b4d660ef6c2b72c00f97"
|
||||
integrity sha512-kvCW8GuXLoqmWp+JQeMuK5x4u+6ObrOInup+hVsxdv5J4FGYACXQYGGf+QgeC7vsBh15J+ha0ZIAOBwB/tSGSQ==
|
||||
gatsby-remark-smartypants@^2.1.21:
|
||||
version "2.1.21"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-remark-smartypants/-/gatsby-remark-smartypants-2.1.21.tgz#2b6ba95a0da4c1f069e3375bc20da8d216618e7e"
|
||||
integrity sha512-iV+DaYeoo7w+IDv21JD0b3jrbxV7Q/0enJj7zB58q8o/lmbdTeFcuwJ/BJI5RW3TsqSiUeFct8n9FkdoAVhK3g==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.7.6"
|
||||
retext "^5.0.0"
|
||||
|
@ -6715,10 +6743,10 @@ gatsby-remark-smartypants@^2.1.20:
|
|||
jimp "^0.6.0"
|
||||
path "^0.12.7"
|
||||
|
||||
gatsby-source-filesystem@^2.1.46:
|
||||
version "2.1.46"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-source-filesystem/-/gatsby-source-filesystem-2.1.46.tgz#ab90c4520f0664218c7334dbec6cd90acc85cf9d"
|
||||
integrity sha512-5LC90+qMKK+/hJzZxKcazx5JvvOO1wHH+ZE7JDSHSzZ1QB+RKWnkvG4a7n6dyiFybo1HN3ql5YQXQLkBEiIfMg==
|
||||
gatsby-source-filesystem@^2.1.48:
|
||||
version "2.1.48"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-source-filesystem/-/gatsby-source-filesystem-2.1.48.tgz#85bd83b953278a7597be38b2e8cd9c69de32fa64"
|
||||
integrity sha512-m1RIYDoV9rhMe2p0ZJA1ae4IIX+iIJCMpNnQiQVtTf+mfihiWyDAdi4lsWzJUxPt8FQwDgUG7GzY3sAoGctvzQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.7.6"
|
||||
better-queue "^3.8.10"
|
||||
|
@ -6726,8 +6754,8 @@ gatsby-source-filesystem@^2.1.46:
|
|||
chokidar "3.3.0"
|
||||
file-type "^12.4.0"
|
||||
fs-extra "^8.1.0"
|
||||
gatsby-core-utils "^1.0.26"
|
||||
got "^7.1.0"
|
||||
gatsby-core-utils "^1.0.28"
|
||||
got "^8.3.2"
|
||||
md5-file "^3.2.3"
|
||||
mime "^2.4.4"
|
||||
pretty-bytes "^5.3.0"
|
||||
|
@ -6759,10 +6787,10 @@ gatsby-telemetry@^1.1.47:
|
|||
stack-utils "1.0.2"
|
||||
uuid "3.3.3"
|
||||
|
||||
gatsby-transformer-yaml@^2.2.23:
|
||||
version "2.2.23"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-transformer-yaml/-/gatsby-transformer-yaml-2.2.23.tgz#44c478c6bd1c467a27ccd43db6fc97e7087a4840"
|
||||
integrity sha512-fGf+LsS6UqzLl/c64qEzyFZhv6uc+zcWBsVFNwKU3hTYf8dd96roo5JdnfiI+kaXsUZ926UOqZsxoZA6Of/0bQ==
|
||||
gatsby-transformer-yaml@^2.2.24:
|
||||
version "2.2.24"
|
||||
resolved "https://registry.yarnpkg.com/gatsby-transformer-yaml/-/gatsby-transformer-yaml-2.2.24.tgz#93989ac6cf7a1c22c597f7b6559ccfff17ed8e84"
|
||||
integrity sha512-6+uQwzIaMRc6WPIFJIaR1MqAULpev8+eo6pdZFm/6/MAMSb9t6A9dge8+V4ahhGhLJr26HI4d2/JpnzLihKTTg==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.7.6"
|
||||
js-yaml "^3.13.1"
|
||||
|
@ -7182,7 +7210,7 @@ got@8.3.2, got@^8.3.1, got@^8.3.2:
|
|||
url-parse-lax "^3.0.0"
|
||||
url-to-options "^1.0.1"
|
||||
|
||||
got@^7.0.0, got@^7.1.0:
|
||||
got@^7.0.0:
|
||||
version "7.1.0"
|
||||
resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a"
|
||||
integrity sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==
|
||||
|
@ -10965,10 +10993,10 @@ pnp-webpack-plugin@^1.5.0:
|
|||
dependencies:
|
||||
ts-pnp "^1.1.2"
|
||||
|
||||
polished@^3.4.1, polished@^3.4.2:
|
||||
version "3.4.2"
|
||||
resolved "https://registry.yarnpkg.com/polished/-/polished-3.4.2.tgz#b4780dad81d64df55615fbfc77acb52fd17d88cd"
|
||||
integrity sha512-9Rch6iMZckABr6EFCLPZsxodeBpXMo9H4fRlfR/9VjMEyy5xpo1/WgXlJGgSjPyVhEZNycbW7UmYMNyWS5MI0g==
|
||||
polished@^3.4.1, polished@^3.4.4:
|
||||
version "3.4.4"
|
||||
resolved "https://registry.yarnpkg.com/polished/-/polished-3.4.4.tgz#ac8cd6e704887398f3b802718f9d389b9ea4307b"
|
||||
integrity sha512-x9PKeExyI9AhWrJP3Q57I1k7GInujjiVBJMPFmycj9hX1yCOo/X9eu9eZwxgOziiXge3WbFQ5XOmkzunOntBSA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.6.3"
|
||||
|
||||
|
@ -11809,11 +11837,22 @@ react-error-overlay@^3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-3.0.0.tgz#c2bc8f4d91f1375b3dad6d75265d51cd5eeaf655"
|
||||
integrity sha512-XzgvowFrwDo6TWcpJ/WTiarb9UI6lhA4PMzS7n1joK3sHfBBBOQHUc0U4u57D6DWO9vHv6lVSWx2Q/Ymfyv4hw==
|
||||
|
||||
react-fast-compare@^2.0.2:
|
||||
react-fast-compare@^2.0.2, react-fast-compare@^2.0.4:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9"
|
||||
integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==
|
||||
|
||||
react-helmet-async@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/react-helmet-async/-/react-helmet-async-1.0.4.tgz#079ef10b7fefcaee6240fefd150711e62463cc97"
|
||||
integrity sha512-KTGHE9sz8N7+fCkZ2a3vzXH9eIkiTNhL2NhKR7XzzQl3WsGlCHh76arauJUIiGdfhjeMp7DY7PkASAmYFXeJYg==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.3.4"
|
||||
invariant "^2.2.4"
|
||||
prop-types "^15.7.2"
|
||||
react-fast-compare "^2.0.4"
|
||||
shallowequal "^1.1.0"
|
||||
|
||||
react-helmet@^5.2.0:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/react-helmet/-/react-helmet-5.2.1.tgz#16a7192fdd09951f8e0fe22ffccbf9bb3e591ffa"
|
||||
|
@ -12720,6 +12759,11 @@ scheduler@^0.18.0:
|
|||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
|
||||
schema-dts@0.4.5:
|
||||
version "0.4.5"
|
||||
resolved "https://registry.yarnpkg.com/schema-dts/-/schema-dts-0.4.5.tgz#7ba5f705bf21301756d8f32acb17d7f9b7f279d1"
|
||||
integrity sha512-LiWBc0/7dGwd5NqWfLBxOwqhBkH2cCuctMKpIjXLI0qD0gu6XqpKGPDDUhAgZOr2BlvYQHhdrEEM1wmTEWWqMw==
|
||||
|
||||
schema-utils@^0.4.0, schema-utils@^0.4.5:
|
||||
version "0.4.7"
|
||||
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.4.7.tgz#ba74f597d2be2ea880131746ee17d0a093c68187"
|
||||
|
@ -13048,10 +13092,10 @@ slice-ansi@^3.0.0:
|
|||
astral-regex "^2.0.0"
|
||||
is-fullwidth-code-point "^3.0.0"
|
||||
|
||||
slug@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/slug/-/slug-2.1.0.tgz#293f8d53de7e55c15871846fd1bc36114841a8c7"
|
||||
integrity sha512-Q4foEgcE7E8UB/BFg4kEzFUICoppzsbbfRjrdKiOM4Z4EFZF5tdn6amkgeaGur3kI4lMWP2BoMv7XJcKZvLg9Q==
|
||||
slug@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/slug/-/slug-2.1.1.tgz#08df390d4b4d51bafb41ac0067c0c2dd70734ef2"
|
||||
integrity sha512-yNGhDdS0DR0JyxnPC84qIx/Vd01RHVY4guJeBqBNdBoOLNWnzw5zkWJvxVSmsuUb92bikdnQFnw3PfGY8uZ82g==
|
||||
dependencies:
|
||||
unicode ">= 0.3.1"
|
||||
|
||||
|
@ -14214,7 +14258,7 @@ type-fest@^0.3.0:
|
|||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1"
|
||||
integrity sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==
|
||||
|
||||
type-fest@^0.8.1:
|
||||
type-fest@^0.8, type-fest@^0.8.1:
|
||||
version "0.8.1"
|
||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
|
||||
integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
|
||||
|
|
Loading…
Reference in New Issue