Compare commits

..

2 Commits

Author SHA1 Message Date
Shadowfacts 7da0368758
Network debugging 2020-07-13 18:22:36 -04:00
Shadowfacts 268566c165
Add GeminiRendererFramework 2020-07-13 18:22:12 -04:00
18 changed files with 833 additions and 25 deletions

View File

@ -31,6 +31,19 @@
D62664BE24BBF26A00DF9B88 /* GeminiFormat.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D62664A824BBF26A00DF9B88 /* GeminiFormat.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; D62664BE24BBF26A00DF9B88 /* GeminiFormat.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D62664A824BBF26A00DF9B88 /* GeminiFormat.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
D62664C624BBF27300DF9B88 /* GeminiParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62664C524BBF27300DF9B88 /* GeminiParser.swift */; }; D62664C624BBF27300DF9B88 /* GeminiParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62664C524BBF27300DF9B88 /* GeminiParser.swift */; };
D62664C824BBF2C600DF9B88 /* Document.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62664C724BBF2C600DF9B88 /* Document.swift */; }; D62664C824BBF2C600DF9B88 /* Document.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62664C724BBF2C600DF9B88 /* Document.swift */; };
D62664D724BC081B00DF9B88 /* GeminiRenderer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D62664CE24BC081B00DF9B88 /* GeminiRenderer.framework */; };
D62664DE24BC081B00DF9B88 /* GeminiRendererTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62664DD24BC081B00DF9B88 /* GeminiRendererTests.swift */; };
D62664E024BC081B00DF9B88 /* GeminiRenderer.h in Headers */ = {isa = PBXBuildFile; fileRef = D62664D024BC081B00DF9B88 /* GeminiRenderer.h */; settings = {ATTRIBUTES = (Public, ); }; };
D62664E324BC081B00DF9B88 /* GeminiRenderer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D62664CE24BC081B00DF9B88 /* GeminiRenderer.framework */; };
D62664E424BC081B00DF9B88 /* GeminiRenderer.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D62664CE24BC081B00DF9B88 /* GeminiRenderer.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
D62664EC24BC0B4D00DF9B88 /* DocumentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62664EB24BC0B4D00DF9B88 /* DocumentView.swift */; };
D62664EE24BC0BCE00DF9B88 /* MaybeLazyVStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62664ED24BC0BCE00DF9B88 /* MaybeLazyVStack.swift */; };
D62664F024BC0D7700DF9B88 /* GeminiFormat.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D62664A824BBF26A00DF9B88 /* GeminiFormat.framework */; };
D62664F124BC0D7700DF9B88 /* GeminiFormat.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D62664A824BBF26A00DF9B88 /* GeminiFormat.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
D62664FA24BC12BC00DF9B88 /* DocumentTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D62664F924BC12BC00DF9B88 /* DocumentTests.swift */; };
D664673624BD07F700B0B741 /* RenderingBlock.swift in Sources */ = {isa = PBXBuildFile; fileRef = D664673524BD07F700B0B741 /* RenderingBlock.swift */; };
D664673824BD086F00B0B741 /* RenderingBlockView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D664673724BD086F00B0B741 /* RenderingBlockView.swift */; };
D664673A24BD0B8E00B0B741 /* Fonts.swift in Sources */ = {isa = PBXBuildFile; fileRef = D664673924BD0B8E00B0B741 /* Fonts.swift */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */ /* Begin PBXContainerItemProxy section */
@ -76,6 +89,34 @@
remoteGlobalIDString = D62664A724BBF26A00DF9B88; remoteGlobalIDString = D62664A724BBF26A00DF9B88;
remoteInfo = GeminiFormat; remoteInfo = GeminiFormat;
}; };
D62664D824BC081B00DF9B88 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = D626645324BBF1C200DF9B88 /* Project object */;
proxyType = 1;
remoteGlobalIDString = D62664CD24BC081B00DF9B88;
remoteInfo = GeminiRenderer;
};
D62664DA24BC081B00DF9B88 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = D626645324BBF1C200DF9B88 /* Project object */;
proxyType = 1;
remoteGlobalIDString = D626645A24BBF1C200DF9B88;
remoteInfo = Gemini;
};
D62664E124BC081B00DF9B88 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = D626645324BBF1C200DF9B88 /* Project object */;
proxyType = 1;
remoteGlobalIDString = D62664CD24BC081B00DF9B88;
remoteInfo = GeminiRenderer;
};
D62664F224BC0D7700DF9B88 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = D626645324BBF1C200DF9B88 /* Project object */;
proxyType = 1;
remoteGlobalIDString = D62664A724BBF26A00DF9B88;
remoteInfo = GeminiFormat;
};
/* End PBXContainerItemProxy section */ /* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */ /* Begin PBXCopyFilesBuildPhase section */
@ -85,12 +126,24 @@
dstPath = ""; dstPath = "";
dstSubfolderSpec = 10; dstSubfolderSpec = 10;
files = ( files = (
D62664E424BC081B00DF9B88 /* GeminiRenderer.framework in Embed Frameworks */,
D62664BE24BBF26A00DF9B88 /* GeminiFormat.framework in Embed Frameworks */, D62664BE24BBF26A00DF9B88 /* GeminiFormat.framework in Embed Frameworks */,
D626648D24BBF22E00DF9B88 /* GeminiProtocol.framework in Embed Frameworks */, D626648D24BBF22E00DF9B88 /* GeminiProtocol.framework in Embed Frameworks */,
); );
name = "Embed Frameworks"; name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
D62664F424BC0D7700DF9B88 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
D62664F124BC0D7700DF9B88 /* GeminiFormat.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */ /* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
@ -123,6 +176,18 @@
D62664B924BBF26A00DF9B88 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; D62664B924BBF26A00DF9B88 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
D62664C524BBF27300DF9B88 /* GeminiParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeminiParser.swift; sourceTree = "<group>"; }; D62664C524BBF27300DF9B88 /* GeminiParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeminiParser.swift; sourceTree = "<group>"; };
D62664C724BBF2C600DF9B88 /* Document.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Document.swift; sourceTree = "<group>"; }; D62664C724BBF2C600DF9B88 /* Document.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Document.swift; sourceTree = "<group>"; };
D62664CE24BC081B00DF9B88 /* GeminiRenderer.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = GeminiRenderer.framework; sourceTree = BUILT_PRODUCTS_DIR; };
D62664D024BC081B00DF9B88 /* GeminiRenderer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeminiRenderer.h; sourceTree = "<group>"; };
D62664D124BC081B00DF9B88 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
D62664D624BC081B00DF9B88 /* GeminiRendererTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GeminiRendererTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
D62664DD24BC081B00DF9B88 /* GeminiRendererTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeminiRendererTests.swift; sourceTree = "<group>"; };
D62664DF24BC081B00DF9B88 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
D62664EB24BC0B4D00DF9B88 /* DocumentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentView.swift; sourceTree = "<group>"; };
D62664ED24BC0BCE00DF9B88 /* MaybeLazyVStack.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MaybeLazyVStack.swift; sourceTree = "<group>"; };
D62664F924BC12BC00DF9B88 /* DocumentTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentTests.swift; sourceTree = "<group>"; };
D664673524BD07F700B0B741 /* RenderingBlock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RenderingBlock.swift; sourceTree = "<group>"; };
D664673724BD086F00B0B741 /* RenderingBlockView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RenderingBlockView.swift; sourceTree = "<group>"; };
D664673924BD0B8E00B0B741 /* Fonts.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Fonts.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@ -130,6 +195,7 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
D62664E324BC081B00DF9B88 /* GeminiRenderer.framework in Frameworks */,
D62664BD24BBF26A00DF9B88 /* GeminiFormat.framework in Frameworks */, D62664BD24BBF26A00DF9B88 /* GeminiFormat.framework in Frameworks */,
D626648C24BBF22E00DF9B88 /* GeminiProtocol.framework in Frameworks */, D626648C24BBF22E00DF9B88 /* GeminiProtocol.framework in Frameworks */,
); );
@ -165,6 +231,22 @@
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
D62664CB24BC081B00DF9B88 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
D62664F024BC0D7700DF9B88 /* GeminiFormat.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
D62664D324BC081B00DF9B88 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
D62664D724BC081B00DF9B88 /* GeminiRenderer.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */ /* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */ /* Begin PBXGroup section */
@ -176,7 +258,10 @@
D626648524BBF22E00DF9B88 /* GeminiProtocolTests */, D626648524BBF22E00DF9B88 /* GeminiProtocolTests */,
D62664A924BBF26A00DF9B88 /* GeminiFormat */, D62664A924BBF26A00DF9B88 /* GeminiFormat */,
D62664B624BBF26A00DF9B88 /* GeminiFormatTests */, D62664B624BBF26A00DF9B88 /* GeminiFormatTests */,
D62664CF24BC081B00DF9B88 /* GeminiRenderer */,
D62664DC24BC081B00DF9B88 /* GeminiRendererTests */,
D626645C24BBF1C200DF9B88 /* Products */, D626645C24BBF1C200DF9B88 /* Products */,
D62664EF24BC0D7700DF9B88 /* Frameworks */,
); );
sourceTree = "<group>"; sourceTree = "<group>";
}; };
@ -188,6 +273,8 @@
D626647F24BBF22E00DF9B88 /* GeminiProtocolTests.xctest */, D626647F24BBF22E00DF9B88 /* GeminiProtocolTests.xctest */,
D62664A824BBF26A00DF9B88 /* GeminiFormat.framework */, D62664A824BBF26A00DF9B88 /* GeminiFormat.framework */,
D62664B024BBF26A00DF9B88 /* GeminiFormatTests.xctest */, D62664B024BBF26A00DF9B88 /* GeminiFormatTests.xctest */,
D62664CE24BC081B00DF9B88 /* GeminiRenderer.framework */,
D62664D624BC081B00DF9B88 /* GeminiRendererTests.xctest */,
); );
name = Products; name = Products;
sourceTree = "<group>"; sourceTree = "<group>";
@ -253,12 +340,43 @@
D62664B624BBF26A00DF9B88 /* GeminiFormatTests */ = { D62664B624BBF26A00DF9B88 /* GeminiFormatTests */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
D62664F924BC12BC00DF9B88 /* DocumentTests.swift */,
D62664B724BBF26A00DF9B88 /* GeminiParserTests.swift */, D62664B724BBF26A00DF9B88 /* GeminiParserTests.swift */,
D62664B924BBF26A00DF9B88 /* Info.plist */, D62664B924BBF26A00DF9B88 /* Info.plist */,
); );
path = GeminiFormatTests; path = GeminiFormatTests;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
D62664CF24BC081B00DF9B88 /* GeminiRenderer */ = {
isa = PBXGroup;
children = (
D62664D024BC081B00DF9B88 /* GeminiRenderer.h */,
D62664D124BC081B00DF9B88 /* Info.plist */,
D664673524BD07F700B0B741 /* RenderingBlock.swift */,
D664673924BD0B8E00B0B741 /* Fonts.swift */,
D62664ED24BC0BCE00DF9B88 /* MaybeLazyVStack.swift */,
D62664EB24BC0B4D00DF9B88 /* DocumentView.swift */,
D664673724BD086F00B0B741 /* RenderingBlockView.swift */,
);
path = GeminiRenderer;
sourceTree = "<group>";
};
D62664DC24BC081B00DF9B88 /* GeminiRendererTests */ = {
isa = PBXGroup;
children = (
D62664DD24BC081B00DF9B88 /* GeminiRendererTests.swift */,
D62664DF24BC081B00DF9B88 /* Info.plist */,
);
path = GeminiRendererTests;
sourceTree = "<group>";
};
D62664EF24BC0D7700DF9B88 /* Frameworks */ = {
isa = PBXGroup;
children = (
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */ /* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */ /* Begin PBXHeadersBuildPhase section */
@ -278,6 +396,14 @@
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
D62664C924BC081B00DF9B88 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
D62664E024BC081B00DF9B88 /* GeminiRenderer.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */ /* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */ /* Begin PBXNativeTarget section */
@ -295,6 +421,7 @@
dependencies = ( dependencies = (
D626648B24BBF22E00DF9B88 /* PBXTargetDependency */, D626648B24BBF22E00DF9B88 /* PBXTargetDependency */,
D62664BC24BBF26A00DF9B88 /* PBXTargetDependency */, D62664BC24BBF26A00DF9B88 /* PBXTargetDependency */,
D62664E224BC081B00DF9B88 /* PBXTargetDependency */,
); );
name = Gemini; name = Gemini;
productName = Gemini; productName = Gemini;
@ -375,6 +502,45 @@
productReference = D62664B024BBF26A00DF9B88 /* GeminiFormatTests.xctest */; productReference = D62664B024BBF26A00DF9B88 /* GeminiFormatTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test"; productType = "com.apple.product-type.bundle.unit-test";
}; };
D62664CD24BC081B00DF9B88 /* GeminiRenderer */ = {
isa = PBXNativeTarget;
buildConfigurationList = D62664E524BC081B00DF9B88 /* Build configuration list for PBXNativeTarget "GeminiRenderer" */;
buildPhases = (
D62664C924BC081B00DF9B88 /* Headers */,
D62664CA24BC081B00DF9B88 /* Sources */,
D62664CB24BC081B00DF9B88 /* Frameworks */,
D62664CC24BC081B00DF9B88 /* Resources */,
D62664F424BC0D7700DF9B88 /* Embed Frameworks */,
);
buildRules = (
);
dependencies = (
D62664F324BC0D7700DF9B88 /* PBXTargetDependency */,
);
name = GeminiRenderer;
productName = GeminiRenderer;
productReference = D62664CE24BC081B00DF9B88 /* GeminiRenderer.framework */;
productType = "com.apple.product-type.framework";
};
D62664D524BC081B00DF9B88 /* GeminiRendererTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = D62664E824BC081B00DF9B88 /* Build configuration list for PBXNativeTarget "GeminiRendererTests" */;
buildPhases = (
D62664D224BC081B00DF9B88 /* Sources */,
D62664D324BC081B00DF9B88 /* Frameworks */,
D62664D424BC081B00DF9B88 /* Resources */,
);
buildRules = (
);
dependencies = (
D62664D924BC081B00DF9B88 /* PBXTargetDependency */,
D62664DB24BC081B00DF9B88 /* PBXTargetDependency */,
);
name = GeminiRendererTests;
productName = GeminiRendererTests;
productReference = D62664D624BC081B00DF9B88 /* GeminiRendererTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */ /* End PBXNativeTarget section */
/* Begin PBXProject section */ /* Begin PBXProject section */
@ -403,6 +569,14 @@
CreatedOnToolsVersion = 12.0; CreatedOnToolsVersion = 12.0;
TestTargetID = D626645A24BBF1C200DF9B88; TestTargetID = D626645A24BBF1C200DF9B88;
}; };
D62664CD24BC081B00DF9B88 = {
CreatedOnToolsVersion = 12.0;
LastSwiftMigration = 1200;
};
D62664D524BC081B00DF9B88 = {
CreatedOnToolsVersion = 12.0;
TestTargetID = D626645A24BBF1C200DF9B88;
};
}; };
}; };
buildConfigurationList = D626645624BBF1C200DF9B88 /* Build configuration list for PBXProject "Gemini" */; buildConfigurationList = D626645624BBF1C200DF9B88 /* Build configuration list for PBXProject "Gemini" */;
@ -423,6 +597,8 @@
D626647E24BBF22E00DF9B88 /* GeminiProtocolTests */, D626647E24BBF22E00DF9B88 /* GeminiProtocolTests */,
D62664A724BBF26A00DF9B88 /* GeminiFormat */, D62664A724BBF26A00DF9B88 /* GeminiFormat */,
D62664AF24BBF26A00DF9B88 /* GeminiFormatTests */, D62664AF24BBF26A00DF9B88 /* GeminiFormatTests */,
D62664CD24BC081B00DF9B88 /* GeminiRenderer */,
D62664D524BC081B00DF9B88 /* GeminiRendererTests */,
); );
}; };
/* End PBXProject section */ /* End PBXProject section */
@ -466,6 +642,20 @@
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
D62664CC24BC081B00DF9B88 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
D62664D424BC081B00DF9B88 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */ /* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */
@ -513,10 +703,31 @@
isa = PBXSourcesBuildPhase; isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
D62664FA24BC12BC00DF9B88 /* DocumentTests.swift in Sources */,
D62664B824BBF26A00DF9B88 /* GeminiParserTests.swift in Sources */, D62664B824BBF26A00DF9B88 /* GeminiParserTests.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
D62664CA24BC081B00DF9B88 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
D664673624BD07F700B0B741 /* RenderingBlock.swift in Sources */,
D664673A24BD0B8E00B0B741 /* Fonts.swift in Sources */,
D62664EE24BC0BCE00DF9B88 /* MaybeLazyVStack.swift in Sources */,
D62664EC24BC0B4D00DF9B88 /* DocumentView.swift in Sources */,
D664673824BD086F00B0B741 /* RenderingBlockView.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
D62664D224BC081B00DF9B88 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
D62664DE24BC081B00DF9B88 /* GeminiRendererTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */ /* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */ /* Begin PBXTargetDependency section */
@ -550,6 +761,26 @@
target = D62664A724BBF26A00DF9B88 /* GeminiFormat */; target = D62664A724BBF26A00DF9B88 /* GeminiFormat */;
targetProxy = D62664BB24BBF26A00DF9B88 /* PBXContainerItemProxy */; targetProxy = D62664BB24BBF26A00DF9B88 /* PBXContainerItemProxy */;
}; };
D62664D924BC081B00DF9B88 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = D62664CD24BC081B00DF9B88 /* GeminiRenderer */;
targetProxy = D62664D824BC081B00DF9B88 /* PBXContainerItemProxy */;
};
D62664DB24BC081B00DF9B88 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = D626645A24BBF1C200DF9B88 /* Gemini */;
targetProxy = D62664DA24BC081B00DF9B88 /* PBXContainerItemProxy */;
};
D62664E224BC081B00DF9B88 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = D62664CD24BC081B00DF9B88 /* GeminiRenderer */;
targetProxy = D62664E124BC081B00DF9B88 /* PBXContainerItemProxy */;
};
D62664F324BC0D7700DF9B88 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = D62664A724BBF26A00DF9B88 /* GeminiFormat */;
targetProxy = D62664F224BC0D7700DF9B88 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */ /* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */ /* Begin PBXVariantGroup section */
@ -927,6 +1158,105 @@
}; };
name = Release; name = Release;
}; };
D62664E624BC081B00DF9B88 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = HGYVAQA9FW;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = GeminiRenderer/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
PRODUCT_BUNDLE_IDENTIFIER = net.shadowfacts.GeminiRenderer;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
D62664E724BC081B00DF9B88 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = HGYVAQA9FW;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
INFOPLIST_FILE = GeminiRenderer/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
PRODUCT_BUNDLE_IDENTIFIER = net.shadowfacts.GeminiRenderer;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
D62664E924BC081B00DF9B88 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = HGYVAQA9FW;
INFOPLIST_FILE = GeminiRendererTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/../Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = net.shadowfacts.GeminiRendererTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Gemini.app/Contents/MacOS/Gemini";
};
name = Debug;
};
D62664EA24BC081B00DF9B88 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = HGYVAQA9FW;
INFOPLIST_FILE = GeminiRendererTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/../Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = net.shadowfacts.GeminiRendererTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Gemini.app/Contents/MacOS/Gemini";
};
name = Release;
};
/* End XCBuildConfiguration section */ /* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */ /* Begin XCConfigurationList section */
@ -984,6 +1314,24 @@
defaultConfigurationIsVisible = 0; defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release; defaultConfigurationName = Release;
}; };
D62664E524BC081B00DF9B88 /* Build configuration list for PBXNativeTarget "GeminiRenderer" */ = {
isa = XCConfigurationList;
buildConfigurations = (
D62664E624BC081B00DF9B88 /* Debug */,
D62664E724BC081B00DF9B88 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
D62664E824BC081B00DF9B88 /* Build configuration list for PBXNativeTarget "GeminiRendererTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
D62664E924BC081B00DF9B88 /* Debug */,
D62664EA24BC081B00DF9B88 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */ /* End XCConfigurationList section */
}; };
rootObject = D626645324BBF1C200DF9B88 /* Project object */; rootObject = D626645324BBF1C200DF9B88 /* Project object */;

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1200"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D62664A724BBF26A00DF9B88"
BuildableName = "GeminiFormat.framework"
BlueprintName = "GeminiFormat"
ReferencedContainer = "container:Gemini.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "D62664A724BBF26A00DF9B88"
BuildableName = "GeminiFormat.framework"
BlueprintName = "GeminiFormat"
ReferencedContainer = "container:Gemini.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -12,12 +12,25 @@
<key>GeminiFormat.xcscheme_^#shared#^_</key> <key>GeminiFormat.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>2</integer> <integer>1</integer>
</dict> </dict>
<key>GeminiProtocol.xcscheme_^#shared#^_</key> <key>GeminiProtocol.xcscheme_^#shared#^_</key>
<dict> <dict>
<key>orderHint</key> <key>orderHint</key>
<integer>1</integer> <integer>2</integer>
</dict>
<key>GeminiRenderer.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>3</integer>
</dict>
</dict>
<key>SuppressBuildableAutocreation</key>
<dict>
<key>D62664A724BBF26A00DF9B88</key>
<dict>
<key>primary</key>
<true/>
</dict> </dict>
</dict> </dict>
</dict> </dict>

View File

@ -7,12 +7,15 @@
import Cocoa import Cocoa
import SwiftUI import SwiftUI
import GeminiProtocol
@NSApplicationMain @NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate { class AppDelegate: NSObject, NSApplicationDelegate {
var window: NSWindow! var window: NSWindow!
var connection: GeminiConnection!
let url = URL(string: "gemini://localhost:1965/overview.gmi")!
func applicationDidFinishLaunching(_ aNotification: Notification) { func applicationDidFinishLaunching(_ aNotification: Notification) {
// Create the SwiftUI view that provides the window contents. // Create the SwiftUI view that provides the window contents.
@ -27,13 +30,40 @@ class AppDelegate: NSObject, NSApplicationDelegate {
window.center() window.center()
window.setFrameAutosaveName("Main Window") window.setFrameAutosaveName("Main Window")
window.contentView = NSHostingView(rootView: contentView) window.contentView = NSHostingView(rootView: contentView)
window.title = "Gemini"
window.makeKeyAndOrderFront(nil) window.makeKeyAndOrderFront(nil)
connection = GeminiConnection(endpoint: .url(url), delegate: self)
} }
func applicationWillTerminate(_ aNotification: Notification) { func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application // Insert code here to tear down your application
} }
var alreadyReceived = false
} }
extension AppDelegate: GeminiConnectionDelegate {
func connectionReady(_ connection: GeminiConnection) {
print("!! Ready")
let req = try! GeminiRequest(url: url)
connection.sendRequest(req)
}
func connection(_ connection: GeminiConnection, receivedData data: Data?, header: GeminiResponseHeader) {
if !alreadyReceived {
alreadyReceived = true
print("!! Status: \(header.status)")
print("!! Meta: '\(header.meta)'")
}
if let data = data {
print(String(data: data, encoding: .utf8)!)
}
}
func connectionCompleted(_ connection: GeminiConnection) {
print("!! completed")
}
}

View File

@ -6,5 +6,7 @@
<true/> <true/>
<key>com.apple.security.files.user-selected.read-only</key> <key>com.apple.security.files.user-selected.read-only</key>
<true/> <true/>
<key>com.apple.security.network.client</key>
<true/>
</dict> </dict>
</plist> </plist>

View File

@ -8,19 +8,19 @@
import Foundation import Foundation
import Network import Network
protocol GeminiConnectionDelegate: class { public protocol GeminiConnectionDelegate: class {
func connectionReady(_ connection: GeminiConnection) func connectionReady(_ connection: GeminiConnection)
func connection(_ connection: GeminiConnection, receivedData data: Data?, header: GeminiResponseHeader) func connection(_ connection: GeminiConnection, receivedData data: Data?, header: GeminiResponseHeader)
func connectionCompleted(_ connection: GeminiConnection) func connectionCompleted(_ connection: GeminiConnection)
} }
class GeminiConnection { public class GeminiConnection {
weak var delegate: GeminiConnectionDelegate? public weak var delegate: GeminiConnectionDelegate?
private var connection: NWConnection? private var connection: NWConnection?
init(endpoint: NWEndpoint, delegate: GeminiConnectionDelegate? = nil) { public init(endpoint: NWEndpoint, delegate: GeminiConnectionDelegate? = nil) {
self.connection = NWConnection(to: endpoint, using: .gemini) self.connection = NWConnection(to: endpoint, using: .gemini)
self.delegate = delegate self.delegate = delegate
@ -49,7 +49,7 @@ class GeminiConnection {
var report: NWConnection.PendingDataTransferReport! var report: NWConnection.PendingDataTransferReport!
func sendRequest(_ request: GeminiRequest) { public func sendRequest(_ request: GeminiRequest) {
guard let connection = connection else { return } guard let connection = connection else { return }
let message = NWProtocolFramer.Message(geminiRequest: request) let message = NWProtocolFramer.Message(geminiRequest: request)

View File

@ -7,10 +7,10 @@
import Foundation import Foundation
struct GeminiRequest { public struct GeminiRequest {
let url: URL public let url: URL
init(url: URL) throws { public init(url: URL) throws {
if url.absoluteString.count > 1024 { if url.absoluteString.count > 1024 {
throw Error.urlTooLong throw Error.urlTooLong
} }
@ -24,7 +24,7 @@ struct GeminiRequest {
} }
} }
extension GeminiRequest { public extension GeminiRequest {
enum Error: Swift.Error { enum Error: Swift.Error {
case urlTooLong case urlTooLong
} }

View File

@ -8,11 +8,14 @@
import Foundation import Foundation
import UniformTypeIdentifiers import UniformTypeIdentifiers
struct GeminiResponse { public struct GeminiResponse {
let status: StatusCode public let status: StatusCode
let meta: String public let meta: String
let body: Data? public let body: Data?
}
public extension GeminiResponse {
// Helpers // Helpers
var rawMimeType: String? { var rawMimeType: String? {
guard status.isSuccess else { return nil } guard status.isSuccess else { return nil }
@ -53,7 +56,7 @@ struct GeminiResponse {
} }
} }
extension GeminiResponse { public extension GeminiResponse {
enum StatusCode: Int { enum StatusCode: Int {
// All statuses and subtypes // All statuses and subtypes
case input = 10 case input = 10
@ -89,7 +92,7 @@ extension GeminiResponse {
} }
extension GeminiResponse.StatusCode: CustomStringConvertible { extension GeminiResponse.StatusCode: CustomStringConvertible {
var description: String { public var description: String {
switch self { switch self {
case .input: case .input:
return "input" return "input"

View File

@ -7,7 +7,7 @@
import Foundation import Foundation
struct GeminiResponseHeader { public struct GeminiResponseHeader {
let status: GeminiResponse.StatusCode public let status: GeminiResponse.StatusCode
let meta: String public let meta: String
} }

View File

@ -0,0 +1,47 @@
//
// DocumentView.swift
// GeminiRenderer
//
// Created by Shadowfacts on 7/12/20.
//
import SwiftUI
import GeminiFormat
public struct DocumentView: View {
private let document: Document
private let blocks: [RenderingBlock]
public init(document: Document) {
self.document = document
self.blocks = document.renderingBlocks
}
public var body: some View {
ScrollView(.vertical) {
MaybeLazyVStack(alignment: .leading) {
ForEach(blocks.indices) { (index) in
RenderingBlockView(block: blocks[index])
}
}.padding()
}
}
}
struct DocumentView_Previews: PreviewProvider {
static var doc: Document {
Document(url: URL(string: "gemini://example.com")!, lines: [
.heading("Hello World", level: .h1),
.text("Some text"),
.preformattedToggle(alt: "blah"),
.preformattedText("test"),
.preformattedToggle(alt: nil),
.quote("whatever"),
.unorderedListItem("something")
])
}
static var previews: some View {
DocumentView(document: doc)
}
}

View File

@ -0,0 +1,41 @@
//
// Fonts.swift
// GeminiRenderer
//
// Created by Shadowfacts on 7/13/20.
//
import SwiftUI
import GeminiFormat
extension Document.HeadingLevel {
var font: Font {
let style: Font.TextStyle
switch self {
case .h1:
style = .title
case .h2:
if #available(macOS 10.16, iOS 14.0, *) {
style = .title2
} else {
style = .headline
}
case .h3:
if #available(macOS 10.16, iOS 14.0, *) {
style = .title3
} else {
style = .subheadline
}
}
return .system(style, design: .serif)
}
}
extension Font {
static var documentBody: Font {
.system(.body, design: .serif)
}
static var documentBodyPreformatted: Font {
.system(.body, design: .monospaced)
}
}

View File

@ -0,0 +1,18 @@
//
// GeminiRenderer.h
// GeminiRenderer
//
// Created by Shadowfacts on 7/12/20.
//
#import <Foundation/Foundation.h>
//! Project version number for GeminiRenderer.
FOUNDATION_EXPORT double GeminiRendererVersionNumber;
//! Project version string for GeminiRenderer.
FOUNDATION_EXPORT const unsigned char GeminiRendererVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <GeminiRenderer/PublicHeader.h>

22
GeminiRenderer/Info.plist Normal file
View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
</dict>
</plist>

View File

@ -0,0 +1,40 @@
//
// MaybeLazyVStack.swift
// GeminiRenderer
//
// Created by Shadowfacts on 7/12/20.
//
import SwiftUI
struct MaybeLazyVStack<Content: View>: View {
private let alignment: HorizontalAlignment
private let spacing: CGFloat?
private let content: Content
init(alignment: HorizontalAlignment = .center, spacing: CGFloat? = nil, @ViewBuilder content: () -> Content) {
self.alignment = alignment
self.spacing = spacing
self.content = content()
}
@ViewBuilder
var body: some View {
if #available(macOS 16.0, iOS 14.0, *) {
LazyVStack(alignment: alignment, spacing: spacing) {
content
}
} else {
VStack(alignment: alignment, spacing: spacing) {
content
}
}
}
}
struct MaybeLazyVStack_Previews: PreviewProvider {
static var previews: some View {
// MaybeLazyVStack()
EmptyView()
}
}

View File

@ -0,0 +1,56 @@
//
// RenderingBlock.swift
// GeminiRenderer
//
// Created by Shadowfacts on 7/12/20.
//
import Foundation
import GeminiFormat
enum RenderingBlock: Equatable {
case text(String)
case link(URL, text: String?)
case preformatted(String, alt: String?)
case heading(String, level: Document.HeadingLevel)
case unorderedListItem(String)
case quote(String)
}
extension Document {
var renderingBlocks: [RenderingBlock] {
var blocks = [RenderingBlock]()
var currentPreformatted: (text: String, alt: String?)?
for line in self.lines {
switch line {
case let .preformattedToggle(alt: alt):
if let (text, alt) = currentPreformatted {
// drop last trailing newline
let realText = String(text.dropLast(1))
blocks.append(.preformatted(realText, alt: alt))
currentPreformatted = nil
} else {
currentPreformatted = ("", alt: alt)
}
case let .preformattedText(text):
currentPreformatted!.text += text
currentPreformatted!.text += "\n"
case let .text(text):
blocks.append(.text(text))
case let .link(url, text: text):
blocks.append(.link(url, text: text))
case let .heading(text, level: level):
blocks.append(.heading(text, level: level))
case let .unorderedListItem(text):
blocks.append(.unorderedListItem(text))
case let .quote(text):
blocks.append(.quote(text))
}
}
return blocks
}
}

View File

@ -0,0 +1,66 @@
//
// RenderingBlockView.swift
// GeminiRenderer
//
// Created by Shadowfacts on 7/13/20.
//
import SwiftUI
import GeminiFormat
struct RenderingBlockView: View {
let block: RenderingBlock
@ViewBuilder
var body: some View {
switch block {
case let .text(text):
Text(verbatim: text)
.font(.documentBody)
.frame(maxWidth: .infinity, alignment: .leading)
case let .link(url, text: linkText):
let text = linkText ?? url.absoluteString
Text(verbatim: text)
.font(.documentBody)
.foregroundColor(.blue)
.underline()
.frame(maxWidth: .infinity, alignment: .leading)
case let .preformatted(text, alt: _):
ScrollView(.horizontal) {
Text(verbatim: text)
.font(.documentBodyPreformatted)
.frame(maxWidth: .infinity, alignment: .leading)
}
case let .heading(text, level: level):
Text(verbatim: text)
.font(level.font)
.frame(maxWidth: .infinity, alignment: .leading)
case let .unorderedListItem(text):
// todo: should this be .firstTextBaseline?
HStack(alignment: .top, spacing: 4) {
Text(verbatim: "\u{2022}")
Text(verbatim: text)
.font(.documentBody)
Spacer()
}.frame(maxWidth: .infinity, alignment: .leading)
case let .quote(text):
HStack(spacing: 4) {
Color.gray
.frame(width: 4)
Text(verbatim: text)
.font(Font.documentBody.italic())
.foregroundColor(.gray)
Spacer()
}.frame(maxWidth: .infinity, alignment: .leading)
}
}
}
struct RenderingBlockView_Previews: PreviewProvider {
static var previews: some View {
Group {
RenderingBlockView(block: .text("Some Text"))
RenderingBlockView(block: .quote("A Quote"))
}
}
}

View File

@ -0,0 +1,33 @@
//
// GeminiRendererTests.swift
// GeminiRendererTests
//
// Created by Shadowfacts on 7/12/20.
//
import XCTest
@testable import GeminiRenderer
class GeminiRendererTests: XCTestCase {
override func setUpWithError() throws {
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDownWithError() throws {
// Put teardown code here. This method is called after the invocation of each test method in the class.
}
func testExample() throws {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
}
func testPerformanceExample() throws {
// This is an example of a performance test case.
self.measure {
// Put the code you want to measure the time of here.
}
}
}

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>