Compare commits
2 Commits
229c6478a5
...
7da0368758
Author | SHA1 | Date |
---|---|---|
Shadowfacts | 7da0368758 | |
Shadowfacts | 268566c165 |
|
@ -31,6 +31,19 @@
|
|||
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 */; };
|
||||
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 */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
|
@ -76,6 +89,34 @@
|
|||
remoteGlobalIDString = D62664A724BBF26A00DF9B88;
|
||||
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 */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
|
@ -85,12 +126,24 @@
|
|||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
D62664E424BC081B00DF9B88 /* GeminiRenderer.framework in Embed Frameworks */,
|
||||
D62664BE24BBF26A00DF9B88 /* GeminiFormat.framework in Embed Frameworks */,
|
||||
D626648D24BBF22E00DF9B88 /* GeminiProtocol.framework in Embed Frameworks */,
|
||||
);
|
||||
name = "Embed Frameworks";
|
||||
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 */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
|
@ -123,6 +176,18 @@
|
|||
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>"; };
|
||||
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 */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
@ -130,6 +195,7 @@
|
|||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D62664E324BC081B00DF9B88 /* GeminiRenderer.framework in Frameworks */,
|
||||
D62664BD24BBF26A00DF9B88 /* GeminiFormat.framework in Frameworks */,
|
||||
D626648C24BBF22E00DF9B88 /* GeminiProtocol.framework in Frameworks */,
|
||||
);
|
||||
|
@ -165,6 +231,22 @@
|
|||
);
|
||||
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 */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
|
@ -176,7 +258,10 @@
|
|||
D626648524BBF22E00DF9B88 /* GeminiProtocolTests */,
|
||||
D62664A924BBF26A00DF9B88 /* GeminiFormat */,
|
||||
D62664B624BBF26A00DF9B88 /* GeminiFormatTests */,
|
||||
D62664CF24BC081B00DF9B88 /* GeminiRenderer */,
|
||||
D62664DC24BC081B00DF9B88 /* GeminiRendererTests */,
|
||||
D626645C24BBF1C200DF9B88 /* Products */,
|
||||
D62664EF24BC0D7700DF9B88 /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
|
@ -188,6 +273,8 @@
|
|||
D626647F24BBF22E00DF9B88 /* GeminiProtocolTests.xctest */,
|
||||
D62664A824BBF26A00DF9B88 /* GeminiFormat.framework */,
|
||||
D62664B024BBF26A00DF9B88 /* GeminiFormatTests.xctest */,
|
||||
D62664CE24BC081B00DF9B88 /* GeminiRenderer.framework */,
|
||||
D62664D624BC081B00DF9B88 /* GeminiRendererTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
|
@ -253,12 +340,43 @@
|
|||
D62664B624BBF26A00DF9B88 /* GeminiFormatTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D62664F924BC12BC00DF9B88 /* DocumentTests.swift */,
|
||||
D62664B724BBF26A00DF9B88 /* GeminiParserTests.swift */,
|
||||
D62664B924BBF26A00DF9B88 /* Info.plist */,
|
||||
);
|
||||
path = GeminiFormatTests;
|
||||
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 */
|
||||
|
||||
/* Begin PBXHeadersBuildPhase section */
|
||||
|
@ -278,6 +396,14 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D62664C924BC081B00DF9B88 /* Headers */ = {
|
||||
isa = PBXHeadersBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D62664E024BC081B00DF9B88 /* GeminiRenderer.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXHeadersBuildPhase section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
|
@ -295,6 +421,7 @@
|
|||
dependencies = (
|
||||
D626648B24BBF22E00DF9B88 /* PBXTargetDependency */,
|
||||
D62664BC24BBF26A00DF9B88 /* PBXTargetDependency */,
|
||||
D62664E224BC081B00DF9B88 /* PBXTargetDependency */,
|
||||
);
|
||||
name = Gemini;
|
||||
productName = Gemini;
|
||||
|
@ -375,6 +502,45 @@
|
|||
productReference = D62664B024BBF26A00DF9B88 /* GeminiFormatTests.xctest */;
|
||||
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 */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
|
@ -403,6 +569,14 @@
|
|||
CreatedOnToolsVersion = 12.0;
|
||||
TestTargetID = D626645A24BBF1C200DF9B88;
|
||||
};
|
||||
D62664CD24BC081B00DF9B88 = {
|
||||
CreatedOnToolsVersion = 12.0;
|
||||
LastSwiftMigration = 1200;
|
||||
};
|
||||
D62664D524BC081B00DF9B88 = {
|
||||
CreatedOnToolsVersion = 12.0;
|
||||
TestTargetID = D626645A24BBF1C200DF9B88;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = D626645624BBF1C200DF9B88 /* Build configuration list for PBXProject "Gemini" */;
|
||||
|
@ -423,6 +597,8 @@
|
|||
D626647E24BBF22E00DF9B88 /* GeminiProtocolTests */,
|
||||
D62664A724BBF26A00DF9B88 /* GeminiFormat */,
|
||||
D62664AF24BBF26A00DF9B88 /* GeminiFormatTests */,
|
||||
D62664CD24BC081B00DF9B88 /* GeminiRenderer */,
|
||||
D62664D524BC081B00DF9B88 /* GeminiRendererTests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
@ -466,6 +642,20 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D62664CC24BC081B00DF9B88 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
D62664D424BC081B00DF9B88 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
|
@ -513,10 +703,31 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D62664FA24BC12BC00DF9B88 /* DocumentTests.swift in Sources */,
|
||||
D62664B824BBF26A00DF9B88 /* GeminiParserTests.swift in Sources */,
|
||||
);
|
||||
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 */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
|
@ -550,6 +761,26 @@
|
|||
target = D62664A724BBF26A00DF9B88 /* GeminiFormat */;
|
||||
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 */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
|
@ -927,6 +1158,105 @@
|
|||
};
|
||||
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 */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
|
@ -984,6 +1314,24 @@
|
|||
defaultConfigurationIsVisible = 0;
|
||||
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 */
|
||||
};
|
||||
rootObject = D626645324BBF1C200DF9B88 /* Project object */;
|
||||
|
|
|
@ -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>
|
|
@ -12,12 +12,25 @@
|
|||
<key>GeminiFormat.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>2</integer>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
<key>GeminiProtocol.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<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>
|
||||
|
|
|
@ -7,12 +7,15 @@
|
|||
|
||||
import Cocoa
|
||||
import SwiftUI
|
||||
import GeminiProtocol
|
||||
|
||||
@NSApplicationMain
|
||||
class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
|
||||
var window: NSWindow!
|
||||
|
||||
var connection: GeminiConnection!
|
||||
let url = URL(string: "gemini://localhost:1965/overview.gmi")!
|
||||
|
||||
func applicationDidFinishLaunching(_ aNotification: Notification) {
|
||||
// Create the SwiftUI view that provides the window contents.
|
||||
|
@ -27,13 +30,40 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||
window.center()
|
||||
window.setFrameAutosaveName("Main Window")
|
||||
window.contentView = NSHostingView(rootView: contentView)
|
||||
window.title = "Gemini"
|
||||
window.makeKeyAndOrderFront(nil)
|
||||
|
||||
connection = GeminiConnection(endpoint: .url(url), delegate: self)
|
||||
}
|
||||
|
||||
func applicationWillTerminate(_ aNotification: Notification) {
|
||||
// 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")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,5 +6,7 @@
|
|||
<true/>
|
||||
<key>com.apple.security.files.user-selected.read-only</key>
|
||||
<true/>
|
||||
<key>com.apple.security.network.client</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
@ -8,19 +8,19 @@
|
|||
import Foundation
|
||||
import Network
|
||||
|
||||
protocol GeminiConnectionDelegate: class {
|
||||
public protocol GeminiConnectionDelegate: class {
|
||||
func connectionReady(_ connection: GeminiConnection)
|
||||
func connection(_ connection: GeminiConnection, receivedData data: Data?, header: GeminiResponseHeader)
|
||||
func connectionCompleted(_ connection: GeminiConnection)
|
||||
}
|
||||
|
||||
class GeminiConnection {
|
||||
public class GeminiConnection {
|
||||
|
||||
weak var delegate: GeminiConnectionDelegate?
|
||||
public weak var delegate: GeminiConnectionDelegate?
|
||||
|
||||
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.delegate = delegate
|
||||
|
||||
|
@ -49,7 +49,7 @@ class GeminiConnection {
|
|||
|
||||
var report: NWConnection.PendingDataTransferReport!
|
||||
|
||||
func sendRequest(_ request: GeminiRequest) {
|
||||
public func sendRequest(_ request: GeminiRequest) {
|
||||
guard let connection = connection else { return }
|
||||
|
||||
let message = NWProtocolFramer.Message(geminiRequest: request)
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
struct GeminiRequest {
|
||||
let url: URL
|
||||
public struct GeminiRequest {
|
||||
public let url: URL
|
||||
|
||||
init(url: URL) throws {
|
||||
public init(url: URL) throws {
|
||||
if url.absoluteString.count > 1024 {
|
||||
throw Error.urlTooLong
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ struct GeminiRequest {
|
|||
}
|
||||
}
|
||||
|
||||
extension GeminiRequest {
|
||||
public extension GeminiRequest {
|
||||
enum Error: Swift.Error {
|
||||
case urlTooLong
|
||||
}
|
||||
|
|
|
@ -8,11 +8,14 @@
|
|||
import Foundation
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
struct GeminiResponse {
|
||||
let status: StatusCode
|
||||
let meta: String
|
||||
let body: Data?
|
||||
public struct GeminiResponse {
|
||||
public let status: StatusCode
|
||||
public let meta: String
|
||||
public let body: Data?
|
||||
|
||||
}
|
||||
|
||||
public extension GeminiResponse {
|
||||
// Helpers
|
||||
var rawMimeType: String? {
|
||||
guard status.isSuccess else { return nil }
|
||||
|
@ -53,7 +56,7 @@ struct GeminiResponse {
|
|||
}
|
||||
}
|
||||
|
||||
extension GeminiResponse {
|
||||
public extension GeminiResponse {
|
||||
enum StatusCode: Int {
|
||||
// All statuses and subtypes
|
||||
case input = 10
|
||||
|
@ -89,7 +92,7 @@ extension GeminiResponse {
|
|||
}
|
||||
|
||||
extension GeminiResponse.StatusCode: CustomStringConvertible {
|
||||
var description: String {
|
||||
public var description: String {
|
||||
switch self {
|
||||
case .input:
|
||||
return "input"
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
struct GeminiResponseHeader {
|
||||
let status: GeminiResponse.StatusCode
|
||||
let meta: String
|
||||
public struct GeminiResponseHeader {
|
||||
public let status: GeminiResponse.StatusCode
|
||||
public let meta: String
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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>
|
||||
|
||||
|
|
@ -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>
|
|
@ -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()
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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"))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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>
|
Loading…
Reference in New Issue