@@ -4,88 +4,115 @@ defmodule Mix.Tasks.Lvn.Swiftui.Gen.Docs do
4
4
use Mix.Task
5
5
require Logger
6
6
7
- # Using a temporary folder outside of the project avoids ElixirLS file watching issues
8
- defp temp_doc_folder , do: Path . join ( System . tmp_dir! ( ) , "temp_swiftui_docs" )
9
- defp generate_swift_lvn_docs_command , do: ~c" xcodebuild docbuild -scheme LiveViewNative -destination generic/platform=iOS -derivedDataPath #{ temp_doc_folder ( ) } -skipMacroValidation -skipPackagePluginValidation"
7
+ defp generate_swift_lvn_docs_command ( doc_path ) , do: ~c" xcrun xcodebuild docbuild -scheme LiveViewNative -destination generic/platform=iOS -derivedDataPath #{ doc_path } -skipMacroValidation -skipPackagePluginValidation"
10
8
@ swiftui_interface_path "Platforms/XROS.platform/Developer/SDKs/XROS.sdk/System/Library/Frameworks/SwiftUI.framework/Modules/SwiftUI.swiftmodule/arm64-apple-xros.swiftinterface"
11
9
defp generate_modifier_documentation_extensions ( xcode_path ) , do: ~c( xcrun swift run ModifierGenerator documentation-extensions --interface "#{ Path . join ( xcode_path , @ swiftui_interface_path ) } " --output Sources/LiveViewNative/LiveViewNative.docc/DocumentationExtensions)
12
10
@ generate_documentation_extensions ~c( xcrun swift package plugin --allow-writing-to-package-directory generate-documentation-extensions)
13
11
defp modifier_list ( xcode_path ) , do: ~s( xcrun swift run ModifierGenerator list --interface "#{ Path . join ( xcode_path , @ swiftui_interface_path ) } " --modifier-search-path Sources/LiveViewNative/Stylesheets/Modifiers)
14
12
@ xcode_select_print_path ~c( xcode-select --print-path)
15
13
@ allow_writing_to_package_dir_command ~c" xcrun swift package plugin --allow-writing-to-package-directory generate-documentation-extensions"
16
14
@ doc_folder "generated_docs"
17
- @ cheatsheet_path "#{ @ doc_folder } /view-index.cheatmd "
15
+ @ cheatsheet_path "#{ @ doc_folder } /view-index.md "
18
16
@ modifier_cheatsheet_path "#{ @ doc_folder } /modifier-index.md"
19
17
20
18
@ shortdoc "Generates ex doc files for all SwiftUI views"
21
- def run ( _ ) do
19
+ def run ( args ) do
20
+ { kwargs , [ ] , [ ] } = OptionParser . parse ( args , strict: [ doc_path: :string , no_generate_docc: :boolean ] )
21
+
22
+ # Using a temporary folder outside of the project avoids ElixirLS file watching issues
23
+ doc_path = Keyword . get ( kwargs , :doc_path , Path . join ( System . tmp_dir! ( ) , "temp_swiftui_docs" ) )
24
+ |> Path . absname ( )
25
+
22
26
Logger . info ( "Locating Xcode installation" )
23
27
xcode_path = :os . cmd ( @ xcode_select_print_path ) |> to_string ( ) |> String . trim ( )
24
28
25
- Logger . info ( "Enabling writing to package..." )
26
- :os . cmd ( @ allow_writing_to_package_dir_command )
29
+ if not Keyword . get ( kwargs , :no_generate_docc , false ) do
30
+ Logger . info ( "Enabling writing to package..." )
31
+ :os . cmd ( @ allow_writing_to_package_dir_command )
32
+
33
+ Logger . info ( "Generating documentation extensions" )
34
+ :os . cmd ( @ generate_documentation_extensions )
27
35
28
- Logger . info ( "Generating documentation extensions" )
29
- :os . cmd ( @ generate_documentation_extensions )
30
- Logger . info ( "Generating modifier documentation extensions" )
31
- :os . cmd ( generate_modifier_documentation_extensions ( xcode_path ) )
36
+ Logger . info ( "Generating modifier documentation extensions" )
37
+ :os . cmd ( generate_modifier_documentation_extensions ( xcode_path ) )
32
38
33
- Logger . info ( "Generating SwiftUI documentation files..." )
34
- :os . cmd ( generate_swift_lvn_docs_command ( ) )
39
+ Logger . info ( "Generating SwiftUI documentation files..." )
40
+ :os . cmd ( generate_swift_lvn_docs_command ( doc_path ) )
41
+ end
35
42
36
43
Logger . info ( "Generating LiveView Native documentation files..." )
37
44
# Ensure generated_docs folder exists
38
45
File . mkdir ( "generated_docs" )
39
46
40
- # clear cheatsheet
41
- File . write! ( @ cheatsheet_path , "# View Index\n " )
42
-
43
47
# generate documentation and cheatsheat
44
- for { category , views } <- categorized_views ( ) do
45
- # build cheatsheet sections
46
- File . write! ( @ cheatsheet_path , "## #{ category } \n {: .col-2}\n " , [ :append ] )
47
-
48
- for view <- views do
49
- with { :ok , data } <-
50
- File . read (
51
- "#{ temp_doc_folder ( ) } /Build/Products/Debug-iphoneos/LiveViewNative.doccarchive/data/documentation/liveviewnative/#{ view } .json"
52
- ) do
53
- docs = Jason . decode! ( data )
54
- path = "#{ @ doc_folder } /#{ category } /#{ view } .md"
55
- File . mkdir_p! ( Path . dirname ( path ) )
56
- File . write! ( path , markdown ( docs , docs ) )
57
-
58
- # build cheatsheet entries
59
- File . write! ( @ cheatsheet_path , cheatsheet ( docs , docs ) <> "\n " , [ :append ] )
60
- end
61
- end
62
- end
48
+ views = Path . wildcard ( "Sources/LiveViewNative/Views/**/*.swift" )
49
+ |> Enum . map ( fn view -> Path . basename ( view , ".swift" ) end )
50
+ |> Enum . sort ( )
51
+ |> Enum . map ( fn view ->
52
+ {
53
+ "`<#{ view } >`" ,
54
+ "#{ doc_path } /Build/Products/Debug-iphoneos/LiveViewNative.doccarchive/data/documentation/liveviewnative/#{ view } .json"
55
+ }
56
+ end )
57
+ write_cheatsheet (
58
+ "View Index" ,
59
+ doc_path ,
60
+ views ,
61
+ @ cheatsheet_path
62
+ )
63
63
64
64
Logger . info ( "Generating LiveView Native modifier documentation files..." )
65
+ modifiers = System . shell ( modifier_list ( xcode_path ) )
66
+ |> elem ( 0 )
67
+ |> String . split ( "\n " )
68
+ |> Enum . map ( fn modifier ->
69
+ {
70
+ modifier ,
71
+ "#{ doc_path } /Build/Products/Debug-iphoneos/LiveViewNative.doccarchive/data/documentation/liveviewnative/_#{ modifier } Modifier.json"
72
+ }
73
+ end )
74
+ write_cheatsheet (
75
+ "Modifier Index" ,
76
+ doc_path ,
77
+ modifiers ,
78
+ @ modifier_cheatsheet_path ,
79
+ true
80
+ )
65
81
66
- modifiers = System . shell ( modifier_list ( xcode_path ) ) |> elem ( 0 ) |> String . split ( "\n " )
82
+ if Keyword . get ( kwargs , :doc_path ) == nil do
83
+ Logger . info ( "Cleaning up temporary files..." )
84
+ File . rm_rf ( doc_path )
85
+ end
86
+ end
67
87
88
+ defp write_cheatsheet ( title , doc_path , paths , output_path , use_tabs \\ false ) do
68
89
# clear cheatsheet
69
- File . write! ( @ modifier_cheatsheet_path , "# Modifier Index\n " )
70
-
71
- all_modifier_references = MapSet . new ( )
72
- for modifier <- modifiers do
73
- with { :ok , data } <-
74
- File . read (
75
- "#{ temp_doc_folder ( ) } /Build/Products/Debug-iphoneos/LiveViewNative.doccarchive/data/documentation/liveviewnative/_#{ modifier } Modifier.json"
76
- ) do
90
+ File . write! ( output_path , "# #{ title } \n " )
91
+
92
+ references = MapSet . new ( )
93
+ for { name , path } <- paths do
94
+ with { :ok , data } <- File . read ( path ) do
77
95
docs = Jason . decode! ( data )
78
- File . write! ( @ modifier_cheatsheet_path , "## #{ modifier } \n " , [ :append ] )
79
- File . write! ( @ modifier_cheatsheet_path , "<!-- tabs-open -->\n " , [ :append ] )
80
- File . write! ( @ modifier_cheatsheet_path , modifier_cheatsheet ( docs , docs ) <> "\n " , [ :append ] )
81
- File . write! ( @ modifier_cheatsheet_path , "<!-- tabs-close -->\n " , [ :append ] )
82
- reduce_references ( docs , all_modifier_references )
96
+ File . write! ( output_path , "## #{ name } \n " , [ :append ] )
97
+ if use_tabs do
98
+ File . write! ( output_path , "<!-- tabs-open -->\n " , [ :append ] )
99
+ end
100
+ ctx = if use_tabs do
101
+ docs
102
+ else
103
+ docs |> Map . put ( "inlineHeadings" , true )
104
+ end
105
+ File . write! ( output_path , modifier_cheatsheet ( docs , ctx ) <> "\n " , [ :append ] )
106
+ if use_tabs do
107
+ File . write! ( output_path , "<!-- tabs-close -->\n " , [ :append ] )
108
+ end
109
+ reduce_references ( docs , references )
83
110
end
84
111
end
85
112
86
- all_modifier_references = modifiers
87
- |> Enum . reduce ( MapSet . new ( ) , fn modifier , acc ->
88
- with { :ok , data } <- File . read ( " #{ temp_doc_folder ( ) } /Build/Products/Debug-iphoneos/LiveViewNative.doccarchive/data/documentation/liveviewnative/_ #{ modifier } Modifier.json" )
113
+ references = paths
114
+ |> Enum . reduce ( MapSet . new ( ) , fn { _ , path } , acc ->
115
+ with { :ok , data } <- File . read ( path )
89
116
do
90
117
docs = Jason . decode! ( data )
91
118
reduce_references ( docs , acc )
@@ -95,9 +122,9 @@ defmodule Mix.Tasks.Lvn.Swiftui.Gen.Docs do
95
122
end )
96
123
97
124
# collect references made in references
98
- all_modifier_references = Enum . reduce ( all_modifier_references , all_modifier_references , fn reference , acc ->
125
+ references = Enum . reduce ( references , references , fn reference , acc ->
99
126
path = String . trim_leading ( reference , "doc://LiveViewNative/documentation/LiveViewNative/" )
100
- with { :ok , data } <- File . read ( "#{ temp_doc_folder ( ) } /Build/Products/Debug-iphoneos/LiveViewNative.doccarchive/data/documentation/liveviewnative/#{ path } .json" )
127
+ with { :ok , data } <- File . read ( "#{ doc_path } /Build/Products/Debug-iphoneos/LiveViewNative.doccarchive/data/documentation/liveviewnative/#{ path } .json" )
101
128
do
102
129
docs = Jason . decode! ( data )
103
130
reduce_references ( docs , acc )
@@ -107,13 +134,10 @@ defmodule Mix.Tasks.Lvn.Swiftui.Gen.Docs do
107
134
end )
108
135
109
136
# write references to end of modifier index
110
- File . write! ( @ modifier_cheatsheet_path , "## Types\n " , [ :append ] )
111
- for reference <- Enum . sort ( all_modifier_references ) do
112
- File . write! ( @ modifier_cheatsheet_path , attribute_details ( String . trim_leading ( reference , "doc://LiveViewNative/documentation/LiveViewNative/" ) ) <> "\n " , [ :append ] )
137
+ File . write! ( output_path , "## Types\n " , [ :append ] )
138
+ for reference <- Enum . sort ( references ) do
139
+ File . write! ( output_path , attribute_details ( String . trim_leading ( reference , "doc://LiveViewNative/documentation/LiveViewNative/" ) , doc_path ) <> "\n " , [ :append ] )
113
140
end
114
-
115
- Logger . info ( "Cleaning up temporary files..." )
116
- File . rm_rf ( temp_doc_folder ( ) )
117
141
end
118
142
119
143
### Cheatsheet
@@ -184,7 +208,7 @@ defmodule Mix.Tasks.Lvn.Swiftui.Gen.Docs do
184
208
<!-- attribute list -->
185
209
# References
186
210
187
- #{ Enum . map ( attributes , & attribute_details ( Path . basename ( url ) , & 1 ) ) }
211
+ #{ Enum . map ( attributes , & attribute_details ( Path . basename ( url ) , & 1 , ctx . doc_path ) ) }
188
212
189
213
<!-- end attribute list -->
190
214
"""
@@ -249,7 +273,7 @@ defmodule Mix.Tasks.Lvn.Swiftui.Gen.Docs do
249
273
% { "references" => references , "includeAllReferences" => true }
250
274
) do
251
275
% { "title" => title } = Map . get ( references , identifier )
252
- hash = "#{ title |> String . replace ( "<" , "" ) |> String . replace ( ">" , "" ) } /1"
276
+ hash = "#{ identifier } /1"
253
277
"[`#{ title } `](##{ hash } )"
254
278
end
255
279
@@ -258,7 +282,7 @@ defmodule Mix.Tasks.Lvn.Swiftui.Gen.Docs do
258
282
% { "references" => references , "identifier" => % { "url" => base_url } }
259
283
) do
260
284
% { "title" => title , "url" => url } = Map . get ( references , identifier )
261
- hash = "#{ title |> String . replace ( "<" , "" ) |> String . replace ( ">" , "" ) } /1"
285
+ hash = "#{ url } /1"
262
286
263
287
resolved_url =
264
288
case url do
@@ -278,23 +302,24 @@ defmodule Mix.Tasks.Lvn.Swiftui.Gen.Docs do
278
302
279
303
def markdown ( _data , _ctx ) , do: ""
280
304
281
- defp attribute_details ( view , identifier ) do
282
- attribute_details ( "#{ view } /#{ Path . basename ( identifier ) } " )
305
+ defp attribute_details ( view , identifier , doc_path ) do
306
+ attribute_details ( "#{ view } /#{ Path . basename ( identifier ) } " , doc_path )
283
307
end
284
308
285
- defp attribute_details ( path ) do
286
- "#{ temp_doc_folder ( ) } /Build/Products/Debug-iphoneos/LiveViewNative.doccarchive/data/documentation/liveviewnative/#{ path } .json"
309
+ defp attribute_details ( path , doc_path ) do
310
+ "#{ doc_path } /Build/Products/Debug-iphoneos/LiveViewNative.doccarchive/data/documentation/liveviewnative/#{ path } .json"
287
311
|> File . read ( )
288
312
|> case do
289
313
{ :ok , data } ->
290
314
docs = Jason . decode! ( data )
291
315
292
316
title = Map . get ( docs , "metadata" , % { } ) |> Map . get ( "title" , "" )
317
+ url = Map . get ( docs , "identifier" , % { } ) |> Map . get ( "url" , "" )
293
318
abstract = Map . get ( docs , "abstract" , [ ] )
294
319
content = Map . get ( docs , "primaryContentSections" , [ ] )
295
320
296
321
docs = Map . put ( docs , "inlineHeadings" , true ) |> Map . put ( "includeAllReferences" , true )
297
- hash = "#{ title } /1"
322
+ hash = "#{ url } /1"
298
323
299
324
"""
300
325
<section id="#{ hash } " class="detail">
@@ -349,13 +374,4 @@ defmodule Mix.Tasks.Lvn.Swiftui.Gen.Docs do
349
374
) , do: items |> Enum . reduce ( acc , fn % { "content" => content } , acc -> reduce_references ( content , acc ) end )
350
375
351
376
defp reduce_references ( _markdown , acc ) , do: acc
352
-
353
- @ spec categorized_views ( ) :: % { String . t ( ) => [ String . t ( ) ] }
354
- defp categorized_views do
355
- Path . wildcard ( "Sources/LiveViewNative/Views/**/*.swift" )
356
- |> Enum . group_by (
357
- & Path . basename ( Path . dirname ( & 1 ) ) ,
358
- & Path . basename ( & 1 , ".swift" )
359
- )
360
- end
361
377
end
0 commit comments