11using System ;
2- using System . Collections . Generic ;
32using System . IO ;
43using System . Linq ;
54using System . Text ;
6- using System . Text . RegularExpressions ;
7- using System . Threading . Tasks ;
5+ using Blazorise . Docs . Compiler . ExampleSources ;
86
97namespace Blazorise . Docs . Compiler ;
108
119public class CodeSnippets
1210{
13- private const string CopyPasteReadyMarker = "@* copy-paste-ready *@" ;
14- private const string DataGridPackageUsingPattern = "(?m)^@using Blazorise(?:[.]DataGrid|[.]Shared[.](?:Data|Models))?\\ r?\\ n" ;
15- private const string EmployeeDataInjectionPattern = @"(?m)^(?<indent>[ \t]*)\[Inject\][ \t]+EmployeeData EmployeeData \{ get; set; \}" ;
16- private const string RazorDocsDirectivePattern = "@(namespace|layout|page) .+?\\ r?\\ n" ;
17-
18- private static readonly string [ ] DataGridSupportFiles =
19- [
20- "DataGridEmployeeData.csharp" ,
21- "DataGridEmployee.csharp" ,
22- "DataGridSalary.csharp"
23- ] ;
24-
25- private static readonly string [ ] DataGridRequiredUsings =
26- [
27- "@using System" ,
28- "@using System.Collections.Generic" ,
29- "@using System.ComponentModel.DataAnnotations" ,
30- "@using System.Linq" ,
31- "@using System.Threading.Tasks"
32- ] ;
33-
3411 public bool Execute ( )
3512 {
3613 var success = true ;
@@ -94,132 +71,13 @@ private static string EscapeComponentSource( string path )
9471 {
9572 var source = File . ReadAllText ( path , Encoding . UTF8 ) ;
9673 source = PrepareSourceForCopy ( path , source ) ;
97- source = Regex . Replace ( source , RazorDocsDirectivePattern , string . Empty ) ;
74+ source = ExampleSourceComposerHelpers . RemoveDocsDirectives ( source ) ;
9875 return source . Replace ( "\" " , "\" \" " ) . Trim ( ) . ToCrLfLineEndings ( ) ;
9976 }
10077
10178 internal static string PrepareSourceForDisplay ( string path , string source )
102- => PrepareSource ( path , source , false ) ;
79+ => ExampleSourceComposerPipeline . PrepareForDisplay ( path , source ) ;
10380
10481 internal static string PrepareSourceForCopy ( string path , string source )
105- => PrepareSource ( path , source , true ) ;
106-
107- private static string PrepareSource ( string path , string source , bool composeFullExample )
108- {
109- bool isDataGridExample = path . Replace ( '\\ ' , '/' ) . Contains ( "/Extensions/DataGrid/Examples/" , StringComparison . Ordinal ) ;
110-
111- if ( isDataGridExample )
112- {
113- ValidateDataGridSource ( path , source ) ;
114-
115- if ( Path . GetExtension ( path ) . Equals ( ".razor" , StringComparison . OrdinalIgnoreCase ) )
116- {
117- source = Regex . Replace (
118- source ,
119- EmployeeDataInjectionPattern ,
120- "${indent}private readonly EmployeeData EmployeeData = new();" ) ;
121-
122- if ( composeFullExample && ! source . Contains ( CopyPasteReadyMarker , StringComparison . Ordinal ) )
123- {
124- source = InlineDataGridSupportTypes ( path , source ) ;
125- }
126-
127- source = Regex . Replace ( source , DataGridPackageUsingPattern , string . Empty ) ;
128- }
129- else if ( ! composeFullExample )
130- {
131- source = Regex . Replace ( source , "(?m)^using Blazorise[.]Shared[.](?:Data|Models);\\ r?\\ n" , string . Empty ) ;
132- source = Regex . Replace ( source , "(?m)^namespace Blazorise[.]Shared[.](?:Data|Models);\\ r?\\ n" , string . Empty ) ;
133- }
134-
135- source = Regex . Replace ( source , RazorDocsDirectivePattern , string . Empty ) ;
136- }
137-
138- if ( source . Contains ( CopyPasteReadyMarker , StringComparison . Ordinal ) )
139- {
140- ValidateCopyPasteReadySource ( path , source ) ;
141- source = Regex . Replace ( source , $ "{ Regex . Escape ( CopyPasteReadyMarker ) } \\ r?\\ n", string . Empty ) ;
142- }
143-
144- return source ;
145- }
146-
147- private static string InlineDataGridSupportTypes ( string path , string source )
148- {
149- string [ ] missingUsings = DataGridRequiredUsings
150- . Where ( requiredUsing => ! Regex . IsMatch ( source , $ "(?m)^{ Regex . Escape ( requiredUsing ) } \\ r?$" ) )
151- . ToArray ( ) ;
152-
153- if ( missingUsings . Length > 0 )
154- {
155- Match namespaceDirective = Regex . Match ( source , "@namespace[^\\ r\\ n]+\\ r?\\ n" ) ;
156-
157- if ( ! namespaceDirective . Success )
158- throw new InvalidOperationException ( $ "DataGrid example '{ path } ' must declare a namespace before its copy-ready imports can be composed." ) ;
159-
160- string imports = string . Join ( Environment . NewLine , missingUsings ) + Environment . NewLine ;
161- source = source . Insert ( namespaceDirective . Index + namespaceDirective . Length , imports ) ;
162- }
163-
164- string examplesDirectory = Path . GetDirectoryName ( path ) ;
165- string supportTypes = string . Join (
166- Environment . NewLine + Environment . NewLine ,
167- DataGridSupportFiles . Select ( file => ExtractSupportTypes ( Path . Combine ( examplesDirectory , file ) ) ) ) ;
168-
169- int codeBlockEnd = source . LastIndexOf ( '}' ) ;
170-
171- if ( codeBlockEnd < 0 || ! source . Contains ( "@code" , StringComparison . Ordinal ) )
172- throw new InvalidOperationException ( $ "DataGrid example '{ path } ' must end with an @code block so support types can be inlined." ) ;
173-
174- string indentedSupportTypes = string . Join (
175- Environment . NewLine ,
176- supportTypes . Split ( [ "\r \n " , "\n " ] , StringSplitOptions . None ) . Select ( line => $ " { line } " ) ) ;
177-
178- return source . Insert ( codeBlockEnd , $ "{ Environment . NewLine } { Environment . NewLine } { indentedSupportTypes } { Environment . NewLine } " ) ;
179- }
180-
181- private static string ExtractSupportTypes ( string path )
182- {
183- string source = File . ReadAllText ( path , Encoding . UTF8 ) ;
184- source = Regex . Replace ( source , "(?m)^using .+;\\ r?\\ n" , string . Empty ) ;
185- source = Regex . Replace ( source , "(?m)^namespace .+;\\ r?\\ n" , string . Empty ) ;
186- return source . Trim ( ) ;
187- }
188-
189- private static void ValidateCopyPasteReadySource ( string path , string source )
190- {
191- string [ ] docsOnlyDependencies =
192- [
193- "@inject " ,
194- "[Inject]" ,
195- "Blazorise.Shared" ,
196- "EmployeeData"
197- ] ;
198-
199- string docsOnlyDependency = docsOnlyDependencies . FirstOrDefault ( dependency => source . Contains ( dependency , StringComparison . Ordinal ) ) ;
200-
201- if ( docsOnlyDependency is not null )
202- throw new InvalidOperationException ( $ "Copy-paste-ready example '{ path } ' references docs-only dependency '{ docsOnlyDependency } '." ) ;
203-
204- if ( ! source . Contains ( "@code" , StringComparison . Ordinal ) )
205- throw new InvalidOperationException ( $ "Copy-paste-ready example '{ path } ' must include its component state in an @code block." ) ;
206- }
207-
208- private static void ValidateDataGridSource ( string path , string source )
209- {
210- string [ ] docsOnlyDependencies =
211- [
212- "GetManifestResourceStream" ,
213- "IMemoryCache"
214- ] ;
215-
216- string docsOnlyDependency = docsOnlyDependencies . FirstOrDefault ( dependency => source . Contains ( dependency , StringComparison . Ordinal ) ) ;
217-
218- if ( docsOnlyDependency is not null )
219- throw new InvalidOperationException ( $ "DataGrid example source '{ path } ' references docs-only dependency '{ docsOnlyDependency } '." ) ;
220-
221- if ( source . Contains ( "new EmployeeData" , StringComparison . Ordinal ) )
222- throw new InvalidOperationException ( $ "DataGrid example source '{ path } ' must inject the runtime EmployeeData service. The docs compiler makes the displayed source self-contained." ) ;
223-
224- }
82+ => ExampleSourceComposerPipeline . PrepareForCopy ( path , source ) ;
22583}
0 commit comments