fastlane-plugin-wpmreleasetoolkit 1.0.0 → 1.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/drawText +1 -0
- data/ext/drawText/drawText Tests/DigitParsingTests.swift +21 -0
- data/ext/drawText/drawText Tests/ExtensionsTests.swift +5 -0
- data/ext/drawText/drawText Tests/Info.plist +22 -0
- data/ext/drawText/drawText Tests/StylesheetTests.swift +31 -0
- data/ext/drawText/drawText Tests/Test Cases/default-stylesheet.txt +10 -0
- data/ext/drawText/drawText Tests/Test Cases/external-styles-sample.css +3 -0
- data/ext/drawText/drawText Tests/Test Cases/external-styles-test.txt +13 -0
- data/ext/drawText/drawText Tests/Test Cases/large-text-block.txt +1 -0
- data/ext/drawText/drawText Tests/Test Cases/regular-text-block.txt +2 -0
- data/ext/drawText/drawText Tests/Test Cases/rtl-text-block.txt +2 -0
- data/ext/drawText/drawText Tests/Test Cases/text-size-adjustment-test.txt +10 -0
- data/ext/drawText/drawText Tests/TextImageTests.swift +99 -0
- data/ext/drawText/drawText Tests/drawText_Tests.swift +14 -0
- data/ext/drawText/drawText.xcodeproj/project.pbxproj +508 -0
- data/ext/drawText/drawText.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- data/ext/drawText/drawText.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- data/ext/drawText/drawText.xcodeproj/xcshareddata/xcschemes/drawText Tests.xcscheme +57 -0
- data/ext/drawText/drawText.xcodeproj/xcshareddata/xcschemes/drawText.xcscheme +109 -0
- data/ext/drawText/drawText/Assets/style.css +1 -0
- data/ext/drawText/drawText/CoreTextStack.swift +113 -0
- data/ext/drawText/drawText/Helpers/CommandLineHelpers.swift +36 -0
- data/ext/drawText/drawText/Helpers/Extensions.swift +27 -0
- data/ext/drawText/drawText/Helpers/FileSystemHelper.swift +24 -0
- data/ext/drawText/drawText/Stylesheet.swift +48 -0
- data/ext/drawText/drawText/TextImage.swift +100 -0
- data/ext/drawText/drawText/main.swift +61 -0
- data/ext/drawText/extconf.rb +1 -1
- data/ext/drawText/makefile.example +8 -0
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/an_update_metadata_source_action.rb +3 -3
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_betabuild_prechecks.rb +22 -16
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_build_prechecks.rb +15 -9
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_beta.rb +26 -26
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_final_release.rb +27 -24
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_hotfix.rb +21 -23
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_release.rb +31 -40
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_codefreeze_prechecks.rb +16 -9
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_completecodefreeze_prechecks.rb +10 -4
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_create_xml_release_notes.rb +2 -2
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_current_branch_is_hotfix.rb +10 -2
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_download_file_by_version.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_download_translations_action.rb +2 -2
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_finalize_prechecks.rb +11 -7
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_get_alpha_version.rb +8 -2
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_get_app_version.rb +8 -2
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_get_release_version.rb +8 -2
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_hotifx_prechecks.rb +5 -5
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_merge_translators_strings.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_tag_build.rb +11 -5
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_update_metadata.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_update_release_notes.rb +3 -3
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/check_for_toolkit_updates_action.rb +99 -0
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/check_translation_progress.rb +147 -0
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/circleci_trigger_job_action.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/gp_downloadmetadata_action.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/gp_update_metadata_source.rb +6 -5
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/promo_screenshots_action.rb +2 -2
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/removebranchprotection_action.rb +3 -3
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/setbranchprotection_action.rb +3 -3
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/setfrozentag_action.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_betabuild_prechecks.rb +5 -5
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_build_prechecks.rb +4 -4
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_bump_version_beta.rb +2 -2
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_bump_version_hotfix.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_bump_version_release.rb +5 -5
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_check_beta_deps.rb +2 -2
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_clear_intermediate_tags.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_codefreeze_prechecks.rb +4 -4
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_completecodefreeze_prechecks.rb +5 -5
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_current_branch_is_hotfix.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_final_tag.rb +2 -2
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_finalize_prechecks.rb +5 -5
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_get_app_version.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_get_build_version.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_get_store_app_sizes.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_hotifx_prechecks.rb +5 -5
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_lint_localizations.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_localize_project.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_merge_translators_strings.rb +4 -4
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_tag_build.rb +2 -2
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_update_metadata.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_update_release_notes.rb +3 -3
- data/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_validate_ci_build.rb +2 -2
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/an_metadata_update_helper.rb +3 -3
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_git_helper.rb +14 -5
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_localize_helper.rb +11 -2
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_version_helper.rb +133 -55
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/ci_helper.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/configure_helper.rb +2 -2
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/encryption_helper.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/github_helper.rb +4 -6
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/glotpress_helper.rb +79 -0
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_adc_app_sizes_helper.rb +3 -3
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_l10n_helper.rb +3 -4
- data/lib/fastlane/plugin/wpmreleasetoolkit/helper/metadata_update_helper.rb +1 -1
- data/lib/fastlane/plugin/wpmreleasetoolkit/models/configuration.rb +2 -2
- data/lib/fastlane/plugin/wpmreleasetoolkit/version.rb +1 -1
- metadata +45 -15
@@ -0,0 +1,57 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<Scheme
|
3
|
+
LastUpgradeVersion = "1030"
|
4
|
+
version = "1.3">
|
5
|
+
<BuildAction
|
6
|
+
parallelizeBuildables = "YES"
|
7
|
+
buildImplicitDependencies = "YES">
|
8
|
+
</BuildAction>
|
9
|
+
<TestAction
|
10
|
+
buildConfiguration = "Debug"
|
11
|
+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
12
|
+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
13
|
+
codeCoverageEnabled = "YES"
|
14
|
+
shouldUseLaunchSchemeArgsEnv = "YES">
|
15
|
+
<Testables>
|
16
|
+
<TestableReference
|
17
|
+
skipped = "NO">
|
18
|
+
<BuildableReference
|
19
|
+
BuildableIdentifier = "primary"
|
20
|
+
BlueprintIdentifier = "F907EA6F22F3736E00196382"
|
21
|
+
BuildableName = "drawText Tests.xctest"
|
22
|
+
BlueprintName = "drawText Tests"
|
23
|
+
ReferencedContainer = "container:drawText.xcodeproj">
|
24
|
+
</BuildableReference>
|
25
|
+
</TestableReference>
|
26
|
+
</Testables>
|
27
|
+
<AdditionalOptions>
|
28
|
+
</AdditionalOptions>
|
29
|
+
</TestAction>
|
30
|
+
<LaunchAction
|
31
|
+
buildConfiguration = "Debug"
|
32
|
+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
33
|
+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
34
|
+
launchStyle = "0"
|
35
|
+
useCustomWorkingDirectory = "NO"
|
36
|
+
ignoresPersistentStateOnLaunch = "NO"
|
37
|
+
debugDocumentVersioning = "YES"
|
38
|
+
debugServiceExtension = "internal"
|
39
|
+
allowLocationSimulation = "YES">
|
40
|
+
<AdditionalOptions>
|
41
|
+
</AdditionalOptions>
|
42
|
+
</LaunchAction>
|
43
|
+
<ProfileAction
|
44
|
+
buildConfiguration = "Release"
|
45
|
+
shouldUseLaunchSchemeArgsEnv = "YES"
|
46
|
+
savedToolIdentifier = ""
|
47
|
+
useCustomWorkingDirectory = "NO"
|
48
|
+
debugDocumentVersioning = "YES">
|
49
|
+
</ProfileAction>
|
50
|
+
<AnalyzeAction
|
51
|
+
buildConfiguration = "Debug">
|
52
|
+
</AnalyzeAction>
|
53
|
+
<ArchiveAction
|
54
|
+
buildConfiguration = "Release"
|
55
|
+
revealArchiveInOrganizer = "YES">
|
56
|
+
</ArchiveAction>
|
57
|
+
</Scheme>
|
@@ -0,0 +1,109 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<Scheme
|
3
|
+
LastUpgradeVersion = "1030"
|
4
|
+
version = "1.3">
|
5
|
+
<BuildAction
|
6
|
+
parallelizeBuildables = "YES"
|
7
|
+
buildImplicitDependencies = "YES">
|
8
|
+
<BuildActionEntries>
|
9
|
+
<BuildActionEntry
|
10
|
+
buildForTesting = "YES"
|
11
|
+
buildForRunning = "YES"
|
12
|
+
buildForProfiling = "YES"
|
13
|
+
buildForArchiving = "YES"
|
14
|
+
buildForAnalyzing = "YES">
|
15
|
+
<BuildableReference
|
16
|
+
BuildableIdentifier = "primary"
|
17
|
+
BlueprintIdentifier = "F99B0B9722F24329002851D8"
|
18
|
+
BuildableName = "drawText"
|
19
|
+
BlueprintName = "drawText"
|
20
|
+
ReferencedContainer = "container:drawText.xcodeproj">
|
21
|
+
</BuildableReference>
|
22
|
+
</BuildActionEntry>
|
23
|
+
</BuildActionEntries>
|
24
|
+
</BuildAction>
|
25
|
+
<TestAction
|
26
|
+
buildConfiguration = "Debug"
|
27
|
+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
28
|
+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
29
|
+
codeCoverageEnabled = "YES"
|
30
|
+
shouldUseLaunchSchemeArgsEnv = "YES">
|
31
|
+
<Testables>
|
32
|
+
<TestableReference
|
33
|
+
skipped = "NO">
|
34
|
+
<BuildableReference
|
35
|
+
BuildableIdentifier = "primary"
|
36
|
+
BlueprintIdentifier = "F907EA6F22F3736E00196382"
|
37
|
+
BuildableName = "drawText Tests.xctest"
|
38
|
+
BlueprintName = "drawText Tests"
|
39
|
+
ReferencedContainer = "container:drawText.xcodeproj">
|
40
|
+
</BuildableReference>
|
41
|
+
</TestableReference>
|
42
|
+
</Testables>
|
43
|
+
<MacroExpansion>
|
44
|
+
<BuildableReference
|
45
|
+
BuildableIdentifier = "primary"
|
46
|
+
BlueprintIdentifier = "F99B0B9722F24329002851D8"
|
47
|
+
BuildableName = "drawText"
|
48
|
+
BlueprintName = "drawText"
|
49
|
+
ReferencedContainer = "container:drawText.xcodeproj">
|
50
|
+
</BuildableReference>
|
51
|
+
</MacroExpansion>
|
52
|
+
<AdditionalOptions>
|
53
|
+
</AdditionalOptions>
|
54
|
+
</TestAction>
|
55
|
+
<LaunchAction
|
56
|
+
buildConfiguration = "Debug"
|
57
|
+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
58
|
+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
59
|
+
launchStyle = "0"
|
60
|
+
useCustomWorkingDirectory = "NO"
|
61
|
+
ignoresPersistentStateOnLaunch = "NO"
|
62
|
+
debugDocumentVersioning = "YES"
|
63
|
+
debugServiceExtension = "internal"
|
64
|
+
allowLocationSimulation = "YES">
|
65
|
+
<BuildableProductRunnable
|
66
|
+
runnableDebuggingMode = "0">
|
67
|
+
<BuildableReference
|
68
|
+
BuildableIdentifier = "primary"
|
69
|
+
BlueprintIdentifier = "F99B0B9722F24329002851D8"
|
70
|
+
BuildableName = "drawText"
|
71
|
+
BlueprintName = "drawText"
|
72
|
+
ReferencedContainer = "container:drawText.xcodeproj">
|
73
|
+
</BuildableReference>
|
74
|
+
</BuildableProductRunnable>
|
75
|
+
<EnvironmentVariables>
|
76
|
+
<EnvironmentVariable
|
77
|
+
key = "CG_CONTEXT_SHOW_BACKTRACE"
|
78
|
+
value = ""
|
79
|
+
isEnabled = "YES">
|
80
|
+
</EnvironmentVariable>
|
81
|
+
</EnvironmentVariables>
|
82
|
+
<AdditionalOptions>
|
83
|
+
</AdditionalOptions>
|
84
|
+
</LaunchAction>
|
85
|
+
<ProfileAction
|
86
|
+
buildConfiguration = "Release"
|
87
|
+
shouldUseLaunchSchemeArgsEnv = "YES"
|
88
|
+
savedToolIdentifier = ""
|
89
|
+
useCustomWorkingDirectory = "NO"
|
90
|
+
debugDocumentVersioning = "YES">
|
91
|
+
<BuildableProductRunnable
|
92
|
+
runnableDebuggingMode = "0">
|
93
|
+
<BuildableReference
|
94
|
+
BuildableIdentifier = "primary"
|
95
|
+
BlueprintIdentifier = "F99B0B9722F24329002851D8"
|
96
|
+
BuildableName = "drawText"
|
97
|
+
BlueprintName = "drawText"
|
98
|
+
ReferencedContainer = "container:drawText.xcodeproj">
|
99
|
+
</BuildableReference>
|
100
|
+
</BuildableProductRunnable>
|
101
|
+
</ProfileAction>
|
102
|
+
<AnalyzeAction
|
103
|
+
buildConfiguration = "Debug">
|
104
|
+
</AnalyzeAction>
|
105
|
+
<ArchiveAction
|
106
|
+
buildConfiguration = "Release"
|
107
|
+
revealArchiveInOrganizer = "YES">
|
108
|
+
</ArchiveAction>
|
109
|
+
</Scheme>
|
@@ -0,0 +1 @@
|
|
1
|
+
|
@@ -0,0 +1,113 @@
|
|
1
|
+
import Cocoa
|
2
|
+
import CoreGraphics
|
3
|
+
|
4
|
+
struct CoreTextStack {
|
5
|
+
|
6
|
+
let layoutManager: NSLayoutManager
|
7
|
+
let textContainer: NSTextContainer
|
8
|
+
var textStorage: NSTextStorage
|
9
|
+
|
10
|
+
let frameSize: CGSize
|
11
|
+
var alignment: NSTextAlignment
|
12
|
+
|
13
|
+
enum Errors: Error {
|
14
|
+
case unableToInitializeTextStorage
|
15
|
+
}
|
16
|
+
|
17
|
+
init(html: Data, size: CGSize, alignment: NSTextAlignment = .natural) throws {
|
18
|
+
|
19
|
+
guard let textStorage = NSTextStorage(html: html, documentAttributes: nil) else {
|
20
|
+
throw Errors.unableToInitializeTextStorage
|
21
|
+
}
|
22
|
+
|
23
|
+
///Storage
|
24
|
+
self.textStorage = textStorage
|
25
|
+
self.textContainer = NSTextContainer(size: size)
|
26
|
+
self.layoutManager = NSLayoutManager()
|
27
|
+
self.frameSize = size
|
28
|
+
self.alignment = alignment
|
29
|
+
|
30
|
+
/// Setup
|
31
|
+
layoutManager.addTextContainer(textContainer)
|
32
|
+
textStorage.addLayoutManager(layoutManager)
|
33
|
+
|
34
|
+
/// Configuration
|
35
|
+
textContainer.lineFragmentPadding = 0
|
36
|
+
textContainer.lineBreakMode = .byWordWrapping
|
37
|
+
layoutManager.usesFontLeading = true
|
38
|
+
layoutManager.typesetter.lineFragmentPadding = 0
|
39
|
+
|
40
|
+
applyParagraphStyles()
|
41
|
+
}
|
42
|
+
|
43
|
+
func setFontSize(_ size: CGFloat) {
|
44
|
+
|
45
|
+
/// Process each attribute run separately so that if the first word is bold,
|
46
|
+
/// it doesn't make all of the words bold.
|
47
|
+
textStorage.attributeRuns.forEach {
|
48
|
+
|
49
|
+
let range = NSRange(location: 0, length: $0.length)
|
50
|
+
|
51
|
+
$0.font = NSFont(name: $0.font!.fontName, size: size)
|
52
|
+
$0.edited(.editedAttributes, range: range, changeInLength: 0)
|
53
|
+
$0.fixAttributes(in: range)
|
54
|
+
}
|
55
|
+
|
56
|
+
applyParagraphStyles()
|
57
|
+
}
|
58
|
+
|
59
|
+
mutating func setAlignment(_ alignment: NSTextAlignment) {
|
60
|
+
self.alignment = alignment
|
61
|
+
applyParagraphStyles()
|
62
|
+
}
|
63
|
+
|
64
|
+
func applyParagraphStyles() {
|
65
|
+
|
66
|
+
let paragraphStyle = NSMutableParagraphStyle()
|
67
|
+
paragraphStyle.paragraphSpacingBefore = 0
|
68
|
+
paragraphStyle.paragraphSpacing = 0
|
69
|
+
paragraphStyle.alignment = self.alignment
|
70
|
+
|
71
|
+
textStorage.addAttributes([
|
72
|
+
NSAttributedString.Key.paragraphStyle: paragraphStyle
|
73
|
+
], range: range)
|
74
|
+
textStorage.edited(.editedAttributes, range: range, changeInLength: 0)
|
75
|
+
textStorage.fixAttributes(in: range)
|
76
|
+
}
|
77
|
+
|
78
|
+
func draw(inContext context: NSGraphicsContext) throws -> CGImage {
|
79
|
+
NSGraphicsContext.saveGraphicsState()
|
80
|
+
|
81
|
+
/// Without the transform, text is drawn upside down and backwards because of
|
82
|
+
/// macOS' flipped coordinate system.
|
83
|
+
NSGraphicsContext.current = NSGraphicsContext(cgContext: context.cgContext, flipped: true)
|
84
|
+
let transform = NSAffineTransform()
|
85
|
+
transform.scaleX(by: 1, yBy: -1)
|
86
|
+
transform.translateX(by: 0, yBy: frameSize.height * -1)
|
87
|
+
transform.concat()
|
88
|
+
|
89
|
+
layoutManager.drawGlyphs(forGlyphRange: range, at: .zero)
|
90
|
+
|
91
|
+
guard let image = context.cgContext.makeImage() else {
|
92
|
+
throw TextImageProcessingError(kind: .unableToDrawImage)
|
93
|
+
}
|
94
|
+
NSGraphicsContext.restoreGraphicsState()
|
95
|
+
|
96
|
+
return image
|
97
|
+
}
|
98
|
+
|
99
|
+
/// `fits` is used to determine whether we should shrink the font size in order to fit the text in
|
100
|
+
/// a smaller box. Turns out the best way to do that is to check whether all the characters fit into
|
101
|
+
/// the textContainer, rather than trying to measure the drawing area.
|
102
|
+
var fits: Bool {
|
103
|
+
|
104
|
+
let textStorageLength = textStorage.length
|
105
|
+
let textContainerRange = layoutManager.glyphRange(for: textContainer)
|
106
|
+
|
107
|
+
return textStorageLength == textContainerRange.length
|
108
|
+
}
|
109
|
+
|
110
|
+
var range: NSRange {
|
111
|
+
return layoutManager.glyphRange(for: textContainer)
|
112
|
+
}
|
113
|
+
}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
import Foundation
|
2
|
+
|
3
|
+
func readCommandLineArguments() -> [String : String] {
|
4
|
+
|
5
|
+
return CommandLine.arguments
|
6
|
+
.filter{ $0.contains("=") }
|
7
|
+
.reduce([String : String](), { (dictionary, argument) -> [String : String] in
|
8
|
+
|
9
|
+
var dictionary = dictionary //shadow for mutability
|
10
|
+
|
11
|
+
var parts = argument.split(separator: "=")
|
12
|
+
dictionary[String(parts.remove(at: 0))] = parts.joined(separator: "=")
|
13
|
+
|
14
|
+
return dictionary
|
15
|
+
})
|
16
|
+
}
|
17
|
+
|
18
|
+
func printUsageAndExit() -> Never {
|
19
|
+
print("""
|
20
|
+
Usage: ./draw-text
|
21
|
+
html={file path or quotes-enclosed HTML string [required]}
|
22
|
+
maxWidth={ integer [required] }
|
23
|
+
maxHeight={ integer [required] }
|
24
|
+
fontSize={ CSS-size compatible string [default = 12px }
|
25
|
+
color={ color or hex code [default = white] }
|
26
|
+
align={ CSS text-alignment value [default = center] }
|
27
|
+
stylesheet={ File Path to a custom stylesheet [default = none] }
|
28
|
+
""")
|
29
|
+
exit(1)
|
30
|
+
}
|
31
|
+
|
32
|
+
func printError(_ string: String) {
|
33
|
+
let redColor = "\u{001B}[0;31m"
|
34
|
+
let endColor = "\u{001B}[0;m"
|
35
|
+
fputs("\(redColor)Error: \(string)\(endColor)\n", stderr)
|
36
|
+
}
|
@@ -0,0 +1,27 @@
|
|
1
|
+
import Foundation
|
2
|
+
import Cocoa
|
3
|
+
|
4
|
+
extension String {
|
5
|
+
var digits: Int? {
|
6
|
+
let digits = self
|
7
|
+
.components(separatedBy: CharacterSet.decimalDigits.inverted)
|
8
|
+
.joined()
|
9
|
+
|
10
|
+
return Int(digits)
|
11
|
+
}
|
12
|
+
|
13
|
+
var withNewlinesConvertedToBreakTags: String {
|
14
|
+
return self.replacingOccurrences(of: "\n", with: "<br />")
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
extension NSTextAlignment {
|
19
|
+
static func fromString(_ string: String) -> NSTextAlignment {
|
20
|
+
switch string.lowercased() {
|
21
|
+
case "left": return .left
|
22
|
+
case "center": return .center
|
23
|
+
case "right": return .right
|
24
|
+
default: return .natural
|
25
|
+
}
|
26
|
+
}
|
27
|
+
}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
import Foundation
|
2
|
+
import Cocoa
|
3
|
+
|
4
|
+
struct File {
|
5
|
+
|
6
|
+
static func write(image: CGImage, toFileAtPath path: String) {
|
7
|
+
|
8
|
+
/// Turn it into a `png`
|
9
|
+
let rep = NSBitmapImageRep(cgImage: image)
|
10
|
+
let pngData = rep.representation(using: .png, properties: [:])
|
11
|
+
|
12
|
+
/// Then write it out to the provided path
|
13
|
+
do {
|
14
|
+
let pathString = NSString(string: path).expandingTildeInPath
|
15
|
+
let output = NSURL(fileURLWithPath: pathString)
|
16
|
+
|
17
|
+
try pngData?.write(to: output as URL)
|
18
|
+
}
|
19
|
+
catch let err {
|
20
|
+
printError("Unable to write image to \(path): \(err.localizedDescription)")
|
21
|
+
exit(6)
|
22
|
+
}
|
23
|
+
}
|
24
|
+
}
|
@@ -0,0 +1,48 @@
|
|
1
|
+
import Cocoa
|
2
|
+
|
3
|
+
struct Stylesheet {
|
4
|
+
|
5
|
+
var contents: String = ""
|
6
|
+
var externalStyles = "/* EXTERNAL STYLES */"
|
7
|
+
|
8
|
+
private let color: String
|
9
|
+
|
10
|
+
init(color: String, fontSize: Int) {
|
11
|
+
self.fontSize = fontSize
|
12
|
+
self.color = color
|
13
|
+
|
14
|
+
update()
|
15
|
+
}
|
16
|
+
|
17
|
+
mutating func updateWith(filePath: String) {
|
18
|
+
|
19
|
+
guard
|
20
|
+
FileManager.default.fileExists(atPath: filePath),
|
21
|
+
let fileContents = FileManager.default.contents(atPath: filePath),
|
22
|
+
let externalStyles = String(bytes: fileContents, encoding: .utf8) else {
|
23
|
+
return
|
24
|
+
}
|
25
|
+
|
26
|
+
self.externalStyles = externalStyles
|
27
|
+
update()
|
28
|
+
}
|
29
|
+
|
30
|
+
var fontSize: Int {
|
31
|
+
didSet { update() }
|
32
|
+
}
|
33
|
+
|
34
|
+
fileprivate mutating func update() {
|
35
|
+
self.contents = """
|
36
|
+
<style>
|
37
|
+
* {
|
38
|
+
padding: 0;
|
39
|
+
margin: 0;
|
40
|
+
color: \(color);
|
41
|
+
font-size: \(fontSize)px;
|
42
|
+
}
|
43
|
+
|
44
|
+
\(externalStyles)
|
45
|
+
</style>
|
46
|
+
""".trimmingCharacters(in: .whitespacesAndNewlines)
|
47
|
+
}
|
48
|
+
}
|