diff --git a/Directory.Packages.props b/Directory.Packages.props index 5f81ce8..f72c405 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -7,7 +7,8 @@ - + + diff --git a/NuGet.config b/NuGet.config index 83ba759..f96ed09 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,8 +1,8 @@ - + + - diff --git a/OrchardCoreContrib.PoExtractor.sln b/OrchardCoreContrib.PoExtractor.sln index cc86e32..d149bdf 100644 --- a/OrchardCoreContrib.PoExtractor.sln +++ b/OrchardCoreContrib.PoExtractor.sln @@ -35,6 +35,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution ProjectSection(SolutionItems) = preProject Directory.Build.props = Directory.Build.props Directory.Packages.props = Directory.Packages.props + README.md = README.md + NuGet.config = NuGet.config EndProjectSection EndProject Global diff --git a/README.md b/README.md index b2247f1..13109c8 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,24 @@ Specifies the code language to extracts translatable strings from. Default: `C#` Specifies the template engine to extract the translatable strings from. Default: `Razor` & `Liquid` templates. +- **`-p|--plugin {path or URL to CSX file}`** + +Specifies a path to a C# script file that can define further project processors. (You can find an example script [here](test/OrchardCoreContrib.PoExtractor.Tests/PluginTestFiles/BasicJsonLocalizationProcessor.csx).) This can be used to process localization from code languages or template engines not supported by the above options. You can have multiple of these switches in one call to load several plugins simultaneously. If the argument starts with `https://` then it's treated as a web URL and the script at that address is downloaded into memory and executed instead of a local file. + +When executing the plugins, all _OrchardCoreContrib.PoExtractor_ assemblies are automatically loaded, and two globals are defined: + +- `List ProjectProcessors`: Add an instance of your custom `IProjectProcessor` implementation type to this list. +- `List ProjectFiles`: In the unlikely case that you have to add a new project file type (such as _.fsproj_) add the project file paths to this list. + +> [!TIP] +> You can't import NuGet packages in your script file, but you can import local DLL files using the `#r "path/to/package.dll"` directive. The path can be relative to the script file's location so you can import packages from the build directory of the project you are extracting from. This can be especially useful if you launch the tool as using MSBuild as a post-build action. (For remote scripts loaded with a URL, the path can be relative to the current working directory.) For example: +> +> ```csharp +> #r "src/Modules/OrchardCore.Commerce/bin/Debug/net8.0/OrchardCore.Commerce.dll" +> using OrchardCore.Commerce.Constants; +> Console.WriteLine("Imported resource name: {0}", ResourceNames.ShoppingCart); +> ``` + ## Uninstallation ```powershell diff --git a/src/OrchardCoreContrib.PoExtractor/OrchardCoreContrib.PoExtractor.csproj b/src/OrchardCoreContrib.PoExtractor/OrchardCoreContrib.PoExtractor.csproj index 0d5607a..b3265df 100644 --- a/src/OrchardCoreContrib.PoExtractor/OrchardCoreContrib.PoExtractor.csproj +++ b/src/OrchardCoreContrib.PoExtractor/OrchardCoreContrib.PoExtractor.csproj @@ -34,4 +34,7 @@ + + + diff --git a/src/OrchardCoreContrib.PoExtractor/PluginHelper.cs b/src/OrchardCoreContrib.PoExtractor/PluginHelper.cs new file mode 100644 index 0000000..8ea3a1f --- /dev/null +++ b/src/OrchardCoreContrib.PoExtractor/PluginHelper.cs @@ -0,0 +1,38 @@ +using Microsoft.CodeAnalysis.CSharp.Scripting; +using Microsoft.CodeAnalysis.Scripting; + +namespace OrchardCoreContrib.PoExtractor; + +public static class PluginHelper +{ + public static async Task ProcessPluginsAsync( + IEnumerable plugins, + List projectProcessors, + List projectFiles) + { + var sharedOptions = ScriptOptions.Default.AddReferences(typeof(Program).Assembly); + + foreach (var plugin in plugins) + { + string code; + ScriptOptions options; + + if (plugin.StartsWith("https://", StringComparison.OrdinalIgnoreCase)) + { + code = await new HttpClient().GetStringAsync(plugin); + options = sharedOptions.WithFilePath(Path.Join( + Environment.CurrentDirectory, + Path.GetFileName(new Uri(plugin).AbsolutePath))); + } + else + { + code = await File.ReadAllTextAsync(plugin); + options = sharedOptions.WithFilePath(Path.GetFullPath(plugin)); + } + + await CSharpScript.EvaluateAsync(code, options, new PluginContext(projectProcessors, projectFiles)); + } + } + + public record PluginContext(List ProjectProcessors, List ProjectFiles); +} diff --git a/src/OrchardCoreContrib.PoExtractor/Program.cs b/src/OrchardCoreContrib.PoExtractor/Program.cs index 6f128e3..9d3e21a 100644 --- a/src/OrchardCoreContrib.PoExtractor/Program.cs +++ b/src/OrchardCoreContrib.PoExtractor/Program.cs @@ -1,4 +1,6 @@ -using McMaster.Extensions.CommandLineUtils; +using System.ComponentModel.DataAnnotations; +using McMaster.Extensions.CommandLineUtils; +using OrchardCore.Modules; using OrchardCoreContrib.PoExtractor.DotNet; using OrchardCoreContrib.PoExtractor.DotNet.CS; using OrchardCoreContrib.PoExtractor.DotNet.VB; @@ -22,19 +24,29 @@ public static void Main(string[] args) .IsRequired(); // Options - var language = app.Option("-l|--language ", "Specifies the code language to extracts translatable strings from.", CommandOptionType.SingleValue, options => + var language = app.Option("-l|--language ", "Specifies the code language to extracts translatable strings from.", CommandOptionType.SingleValue, option => { - options.Accepts(cfg => cfg.Values("C#", "VB")); - options.DefaultValue = "C#"; + option.Accepts(cfg => cfg.Values("C#", "VB")); + option.DefaultValue = "C#"; }); - var template = app.Option("-t|--template