From 3f23481bc3f4f018ffb14c6a3e0560d6a59694ef Mon Sep 17 00:00:00 2001 From: Dean Marcussen Date: Tue, 7 Jul 2020 10:47:33 +0100 Subject: [PATCH] Shortcodes refactor (#6561) --- OrchardCore.sln | 4 +- mkdocs.yml | 2 +- src/OrchardCore.Build/Dependencies.props | 1 + .../Drivers/HtmlFieldDisplayDriver.cs | 10 +- .../OrchardCore.ContentFields/Manifest.cs | 2 +- .../OrchardCore.ContentFields.csproj | 2 +- .../Drivers/HtmlBodyPartDisplayDriver.cs | 10 +- .../GraphQL/HtmlBodyQueryObjectType.cs | 6 +- .../Handlers/HtmlBodyPartHandler.cs | 10 +- .../OrchardCore.Html/Manifest.cs | 2 +- .../OrchardCore.Html/OrchardCore.Html.csproj | 2 +- .../Filters/ShortCodeFilter.cs | 8 +- .../OrchardCore.Liquid/Manifest.cs | 2 +- .../OrchardCore.Liquid.csproj | 2 +- .../OrchardCore.Liquid/Startup.cs | 2 +- .../Drivers/MarkdownBodyPartDisplay.cs | 10 +- .../Drivers/MarkdownFieldDriver.cs | 10 +- .../GraphQL/MarkdownBodyQueryObjectType.cs | 7 +- .../GraphQL/MarkdownFieldQueryObjectType.cs | 10 +- .../Handlers/MarkdownBodyPartHandler.cs | 10 +- .../OrchardCore.Markdown/Manifest.cs | 2 +- .../OrchardCore.Markdown.csproj | 2 +- .../Razor/MarkdownHelperExtensions.cs | 6 +- .../OrchardCore.Media/Manifest.cs | 2 +- .../OrchardCore.Media.csproj | 3 +- .../ShortCodes/ImageShortCode.cs | 121 ------------------ .../Shortcodes/ImageShortcodeProvider.cs | 107 ++++++++++++++++ .../OrchardCore.Media/Startup.cs | 7 +- .../Services/ShortCodeService.cs | 25 ---- .../Manifest.cs | 2 +- .../OrchardCore.Shortcodes.csproj} | 3 +- .../Properties/AssemblyInfo.cs | 0 .../Razor/OrchardRazorHelperExtensions.cs | 8 +- .../Services/ShortcodeService.cs | 21 +++ .../Startup.cs | 7 +- ...rdCore.Application.Cms.Core.Targets.csproj | 2 +- .../Services/IShortCodeService.cs | 9 -- ...rchardCore.Shortcodes.Abstractions.csproj} | 6 +- .../Services/IShortcodeService.cs} | 4 +- .../reference/modules/ShortCodes/README.md | 3 - .../reference/modules/Shortcodes/README.md | 7 + .../OrchardCore.Media/ImageShortCodeTests.cs | 49 ------- .../OrchardCore.Media/ImageShortcodeTests.cs | 75 +++++++++++ 43 files changed, 296 insertions(+), 287 deletions(-) delete mode 100644 src/OrchardCore.Modules/OrchardCore.Media/ShortCodes/ImageShortCode.cs create mode 100644 src/OrchardCore.Modules/OrchardCore.Media/Shortcodes/ImageShortcodeProvider.cs delete mode 100644 src/OrchardCore.Modules/OrchardCore.ShortCodes/Services/ShortCodeService.cs rename src/OrchardCore.Modules/{OrchardCore.ShortCodes => OrchardCore.Shortcodes}/Manifest.cs (92%) rename src/OrchardCore.Modules/{OrchardCore.ShortCodes/OrchardCore.ShortCodes.csproj => OrchardCore.Shortcodes/OrchardCore.Shortcodes.csproj} (71%) rename src/OrchardCore.Modules/{OrchardCore.ShortCodes => OrchardCore.Shortcodes}/Properties/AssemblyInfo.cs (100%) rename src/OrchardCore.Modules/{OrchardCore.ShortCodes => OrchardCore.Shortcodes}/Razor/OrchardRazorHelperExtensions.cs (60%) create mode 100644 src/OrchardCore.Modules/OrchardCore.Shortcodes/Services/ShortcodeService.cs rename src/OrchardCore.Modules/{OrchardCore.ShortCodes => OrchardCore.Shortcodes}/Startup.cs (60%) delete mode 100644 src/OrchardCore/OrchardCore.ShortCodes.Abstractions/Services/IShortCodeService.cs rename src/OrchardCore/{OrchardCore.ShortCodes.Abstractions/OrchardCore.ShortCodes.Abstractions.csproj => OrchardCore.Shortcodes.Abstractions/OrchardCore.Shortcodes.Abstractions.csproj} (64%) rename src/OrchardCore/{OrchardCore.ShortCodes.Abstractions/IShortCode.cs => OrchardCore.Shortcodes.Abstractions/Services/IShortcodeService.cs} (55%) delete mode 100644 src/docs/reference/modules/ShortCodes/README.md create mode 100644 src/docs/reference/modules/Shortcodes/README.md delete mode 100644 test/OrchardCore.Tests/Modules/OrchardCore.Media/ImageShortCodeTests.cs create mode 100644 test/OrchardCore.Tests/Modules/OrchardCore.Media/ImageShortcodeTests.cs diff --git a/OrchardCore.sln b/OrchardCore.sln index c30bd4a1893..1d450ca223a 100644 --- a/OrchardCore.sln +++ b/OrchardCore.sln @@ -376,9 +376,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OrchardCore.Docs", "src\doc EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OrchardCore.Markdown.Abstractions", "src\OrchardCore\OrchardCore.Markdown.Abstractions\OrchardCore.Markdown.Abstractions.csproj", "{38EE0258-F010-425B-949F-9ECCE886584B}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OrchardCore.ShortCodes", "src\OrchardCore.Modules\OrchardCore.ShortCodes\OrchardCore.ShortCodes.csproj", "{9EEEB83D-85C5-4025-8367-CD7D1ACBBB1A}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OrchardCore.Shortcodes", "src\OrchardCore.Modules\OrchardCore.Shortcodes\OrchardCore.Shortcodes.csproj", "{9EEEB83D-85C5-4025-8367-CD7D1ACBBB1A}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OrchardCore.ShortCodes.Abstractions", "src\OrchardCore\OrchardCore.ShortCodes.Abstractions\OrchardCore.ShortCodes.Abstractions.csproj", "{901DA1A3-E5C7-4965-80EA-A1780BE1B820}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OrchardCore.Shortcodes.Abstractions", "src\OrchardCore\OrchardCore.Shortcodes.Abstractions\OrchardCore.Shortcodes.Abstractions.csproj", "{901DA1A3-E5C7-4965-80EA-A1780BE1B820}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/mkdocs.yml b/mkdocs.yml index 39e031eca52..0f1ecf16c7a 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -129,7 +129,7 @@ nav: - Media Azure: docs/reference/modules/Media.Azure/README.md - ReCaptcha: docs/reference/modules/ReCaptcha/README.md - Resources: docs/reference/modules/Resources/README.md - - ShortCodes: docs/reference/modules/ShortCodes/README.md + - Shortcodes: docs/reference/modules/Shortcodes/README.md - Sitemaps: docs/reference/modules/Sitemaps/README.md - XML-RPC: docs/reference/modules/XmlRpc/README.md - Menu: docs/reference/modules/Menu/README.md diff --git a/src/OrchardCore.Build/Dependencies.props b/src/OrchardCore.Build/Dependencies.props index e115208e272..a576e485a82 100644 --- a/src/OrchardCore.Build/Dependencies.props +++ b/src/OrchardCore.Build/Dependencies.props @@ -34,6 +34,7 @@ + diff --git a/src/OrchardCore.Modules/OrchardCore.ContentFields/Drivers/HtmlFieldDisplayDriver.cs b/src/OrchardCore.Modules/OrchardCore.ContentFields/Drivers/HtmlFieldDisplayDriver.cs index dac7dd14bdf..4b3064613ba 100644 --- a/src/OrchardCore.Modules/OrchardCore.ContentFields/Drivers/HtmlFieldDisplayDriver.cs +++ b/src/OrchardCore.Modules/OrchardCore.ContentFields/Drivers/HtmlFieldDisplayDriver.cs @@ -9,7 +9,7 @@ using OrchardCore.ContentManagement.Metadata.Models; using OrchardCore.DisplayManagement.ModelBinding; using OrchardCore.DisplayManagement.Views; -using OrchardCore.ShortCodes.Services; +using OrchardCore.Shortcodes.Services; using OrchardCore.Infrastructure.Html; using OrchardCore.Liquid; @@ -20,19 +20,19 @@ public class HtmlFieldDisplayDriver : ContentFieldDisplayDriver private readonly ILiquidTemplateManager _liquidTemplateManager; private readonly HtmlEncoder _htmlEncoder; private readonly IHtmlSanitizerService _htmlSanitizerService; - private readonly IShortCodeService _shortCodeService; + private readonly IShortcodeService _shortcodeService; private readonly IStringLocalizer S; public HtmlFieldDisplayDriver(ILiquidTemplateManager liquidTemplateManager, HtmlEncoder htmlEncoder, IHtmlSanitizerService htmlSanitizerService, - IShortCodeService shortCodeService, + IShortcodeService shortcodeService, IStringLocalizer localizer) { _liquidTemplateManager = liquidTemplateManager; _htmlEncoder = htmlEncoder; _htmlSanitizerService = htmlSanitizerService; - _shortCodeService = shortCodeService; + _shortcodeService = shortcodeService; S = localizer; } @@ -52,7 +52,7 @@ public override IDisplayResult Display(HtmlField field, BuildFieldDisplayContext scope => scope.SetValue("ContentItem", field.ContentItem)); } - model.Html = await _shortCodeService.ProcessAsync(model.Html); + model.Html = await _shortcodeService.ProcessAsync(model.Html); }) .Location("Detail", "Content") diff --git a/src/OrchardCore.Modules/OrchardCore.ContentFields/Manifest.cs b/src/OrchardCore.Modules/OrchardCore.ContentFields/Manifest.cs index a2aeb47c614..567607c6162 100644 --- a/src/OrchardCore.Modules/OrchardCore.ContentFields/Manifest.cs +++ b/src/OrchardCore.Modules/OrchardCore.ContentFields/Manifest.cs @@ -13,7 +13,7 @@ Name = "Content Fields", Category = "Content Management", Description = "Content Fields module adds common content fields to be used with your custom types.", - Dependencies = new[] { "OrchardCore.ContentTypes", "OrchardCore.ShortCodes" } + Dependencies = new[] { "OrchardCore.ContentTypes", "OrchardCore.Shortcodes" } )] [assembly: Feature( diff --git a/src/OrchardCore.Modules/OrchardCore.ContentFields/OrchardCore.ContentFields.csproj b/src/OrchardCore.Modules/OrchardCore.ContentFields/OrchardCore.ContentFields.csproj index 21d4df3d0f6..2e7178d7901 100644 --- a/src/OrchardCore.Modules/OrchardCore.ContentFields/OrchardCore.ContentFields.csproj +++ b/src/OrchardCore.Modules/OrchardCore.ContentFields/OrchardCore.ContentFields.csproj @@ -21,7 +21,7 @@ - + diff --git a/src/OrchardCore.Modules/OrchardCore.Html/Drivers/HtmlBodyPartDisplayDriver.cs b/src/OrchardCore.Modules/OrchardCore.Html/Drivers/HtmlBodyPartDisplayDriver.cs index 4a41e64857a..1896a11794d 100644 --- a/src/OrchardCore.Modules/OrchardCore.Html/Drivers/HtmlBodyPartDisplayDriver.cs +++ b/src/OrchardCore.Modules/OrchardCore.Html/Drivers/HtmlBodyPartDisplayDriver.cs @@ -9,7 +9,7 @@ using OrchardCore.Html.Models; using OrchardCore.Html.Settings; using OrchardCore.Html.ViewModels; -using OrchardCore.ShortCodes.Services; +using OrchardCore.Shortcodes.Services; using OrchardCore.Infrastructure.Html; using OrchardCore.Liquid; @@ -20,19 +20,19 @@ public class HtmlBodyPartDisplayDriver : ContentPartDisplayDriver private readonly ILiquidTemplateManager _liquidTemplateManager; private readonly IHtmlSanitizerService _htmlSanitizerService; private readonly HtmlEncoder _htmlEncoder; - private readonly IShortCodeService _shortCodeService; + private readonly IShortcodeService _shortcodeService; private readonly IStringLocalizer S; public HtmlBodyPartDisplayDriver(ILiquidTemplateManager liquidTemplateManager, IHtmlSanitizerService htmlSanitizerService, HtmlEncoder htmlEncoder, - IShortCodeService shortCodeService, + IShortcodeService shortcodeService, IStringLocalizer localizer) { _liquidTemplateManager = liquidTemplateManager; _htmlSanitizerService = htmlSanitizerService; _htmlEncoder = htmlEncoder; - _shortCodeService = shortCodeService; + _shortcodeService = shortcodeService; S = localizer; } @@ -88,7 +88,7 @@ private async ValueTask BuildViewModelAsync(HtmlBodyPartViewModel model, HtmlBod scope => scope.SetValue("ContentItem", model.ContentItem)); } - model.Html = await _shortCodeService.ProcessAsync(model.Html); + model.Html = await _shortcodeService.ProcessAsync(model.Html); } } } diff --git a/src/OrchardCore.Modules/OrchardCore.Html/GraphQL/HtmlBodyQueryObjectType.cs b/src/OrchardCore.Modules/OrchardCore.Html/GraphQL/HtmlBodyQueryObjectType.cs index 76298cf132f..6fab2ecb1d1 100644 --- a/src/OrchardCore.Modules/OrchardCore.Html/GraphQL/HtmlBodyQueryObjectType.cs +++ b/src/OrchardCore.Modules/OrchardCore.Html/GraphQL/HtmlBodyQueryObjectType.cs @@ -9,7 +9,7 @@ using OrchardCore.Html.Models; using OrchardCore.Html.Settings; using OrchardCore.Html.ViewModels; -using OrchardCore.ShortCodes.Services; +using OrchardCore.Shortcodes.Services; using OrchardCore.Liquid; namespace OrchardCore.Html.GraphQL @@ -30,7 +30,7 @@ public HtmlBodyQueryObjectType(IStringLocalizer S) private static async Task RenderHtml(ResolveFieldContext ctx) { var serviceProvider = ctx.ResolveServiceProvider(); - var shortCodeService = serviceProvider.GetRequiredService(); + var shortcodeService = serviceProvider.GetRequiredService(); var contentDefinitionManager = serviceProvider.GetRequiredService(); var contentTypeDefinition = contentDefinitionManager.GetTypeDefinition(ctx.Source.ContentItem.ContentType); @@ -54,7 +54,7 @@ private static async Task RenderHtml(ResolveFieldContext c scope => scope.SetValue("ContentItem", model.ContentItem)); } - return await shortCodeService.ProcessAsync(html); + return await shortcodeService.ProcessAsync(html); } } } diff --git a/src/OrchardCore.Modules/OrchardCore.Html/Handlers/HtmlBodyPartHandler.cs b/src/OrchardCore.Modules/OrchardCore.Html/Handlers/HtmlBodyPartHandler.cs index d9f349407e5..8ec9443a704 100644 --- a/src/OrchardCore.Modules/OrchardCore.Html/Handlers/HtmlBodyPartHandler.cs +++ b/src/OrchardCore.Modules/OrchardCore.Html/Handlers/HtmlBodyPartHandler.cs @@ -8,7 +8,7 @@ using OrchardCore.Html.Models; using OrchardCore.Html.Settings; using OrchardCore.Html.ViewModels; -using OrchardCore.ShortCodes.Services; +using OrchardCore.Shortcodes.Services; using OrchardCore.Liquid; namespace OrchardCore.Html.Handlers @@ -16,19 +16,19 @@ namespace OrchardCore.Html.Handlers public class HtmlBodyPartHandler : ContentPartHandler { private readonly IContentDefinitionManager _contentDefinitionManager; - private readonly IShortCodeService _shortCodeService; + private readonly IShortcodeService _shortcodeService; private readonly ILiquidTemplateManager _liquidTemplateManager; private readonly HtmlEncoder _htmlEncoder; private HtmlString _bodyAspect; private int _contentItemId; public HtmlBodyPartHandler(IContentDefinitionManager contentDefinitionManager, - IShortCodeService shortCodeService, + IShortcodeService shortcodeService, ILiquidTemplateManager liquidTemplateManager, HtmlEncoder htmlEncoder) { _contentDefinitionManager = contentDefinitionManager; - _shortCodeService = shortCodeService; + _shortcodeService = shortcodeService; _liquidTemplateManager = liquidTemplateManager; _htmlEncoder = htmlEncoder; } @@ -64,7 +64,7 @@ public override Task GetContentItemAspectAsync(ContentItemAspectContext context, scope => scope.SetValue("ContentItem", model.ContentItem)); } - html = await _shortCodeService.ProcessAsync(html); + html = await _shortcodeService.ProcessAsync(html); bodyAspect.Body = _bodyAspect = new HtmlString(html); _contentItemId = part.ContentItem.Id; diff --git a/src/OrchardCore.Modules/OrchardCore.Html/Manifest.cs b/src/OrchardCore.Modules/OrchardCore.Html/Manifest.cs index 0f57dc3958c..e4d6a9e4b8a 100644 --- a/src/OrchardCore.Modules/OrchardCore.Html/Manifest.cs +++ b/src/OrchardCore.Modules/OrchardCore.Html/Manifest.cs @@ -6,6 +6,6 @@ Website = ManifestConstants.OrchardCoreWebsite, Version = ManifestConstants.OrchardCoreVersion, Description = "The Html module enables content items to have Html bodies.", - Dependencies = new[] { "OrchardCore.ContentTypes", "OrchardCore.ShortCodes" }, + Dependencies = new[] { "OrchardCore.ContentTypes", "OrchardCore.Shortcodes" }, Category = "Content Management" )] diff --git a/src/OrchardCore.Modules/OrchardCore.Html/OrchardCore.Html.csproj b/src/OrchardCore.Modules/OrchardCore.Html/OrchardCore.Html.csproj index b555b07808f..60bc83a3dde 100644 --- a/src/OrchardCore.Modules/OrchardCore.Html/OrchardCore.Html.csproj +++ b/src/OrchardCore.Modules/OrchardCore.Html/OrchardCore.Html.csproj @@ -22,7 +22,7 @@ - + diff --git a/src/OrchardCore.Modules/OrchardCore.Liquid/Filters/ShortCodeFilter.cs b/src/OrchardCore.Modules/OrchardCore.Liquid/Filters/ShortCodeFilter.cs index 875b9265015..c2ad4a57ac3 100644 --- a/src/OrchardCore.Modules/OrchardCore.Liquid/Filters/ShortCodeFilter.cs +++ b/src/OrchardCore.Modules/OrchardCore.Liquid/Filters/ShortCodeFilter.cs @@ -3,11 +3,11 @@ using Fluid; using Fluid.Values; using Microsoft.Extensions.DependencyInjection; -using OrchardCore.ShortCodes.Services; +using OrchardCore.Shortcodes.Services; namespace OrchardCore.Liquid.Filters { - public class ShortCodeFilter : ILiquidFilter + public class ShortcodeFilter : ILiquidFilter { public async ValueTask ProcessAsync(FluidValue input, FilterArguments arguments, TemplateContext ctx) { @@ -16,9 +16,9 @@ public async ValueTask ProcessAsync(FluidValue input, FilterArgument throw new ArgumentException("Services missing while invoking 'shortcode'"); } - var shortCodeService = ((IServiceProvider)services).GetRequiredService(); + var shortcodeService = ((IServiceProvider)services).GetRequiredService(); - return new StringValue(await shortCodeService.ProcessAsync(input.ToStringValue())); + return new StringValue(await shortcodeService.ProcessAsync(input.ToStringValue())); } } } diff --git a/src/OrchardCore.Modules/OrchardCore.Liquid/Manifest.cs b/src/OrchardCore.Modules/OrchardCore.Liquid/Manifest.cs index 4782c5463bc..04c981821ba 100644 --- a/src/OrchardCore.Modules/OrchardCore.Liquid/Manifest.cs +++ b/src/OrchardCore.Modules/OrchardCore.Liquid/Manifest.cs @@ -6,6 +6,6 @@ Website = ManifestConstants.OrchardCoreWebsite, Version = ManifestConstants.OrchardCoreVersion, Description = "The liquid module enables content items to have liquid syntax.", - Dependencies = new[] { "OrchardCore.Contents", "OrchardCore.ShortCodes" }, + Dependencies = new[] { "OrchardCore.Contents", "OrchardCore.Shortcodes" }, Category = "Content Management" )] diff --git a/src/OrchardCore.Modules/OrchardCore.Liquid/OrchardCore.Liquid.csproj b/src/OrchardCore.Modules/OrchardCore.Liquid/OrchardCore.Liquid.csproj index 1653874865c..6106035b259 100644 --- a/src/OrchardCore.Modules/OrchardCore.Liquid/OrchardCore.Liquid.csproj +++ b/src/OrchardCore.Modules/OrchardCore.Liquid/OrchardCore.Liquid.csproj @@ -18,7 +18,7 @@ - + diff --git a/src/OrchardCore.Modules/OrchardCore.Liquid/Startup.cs b/src/OrchardCore.Modules/OrchardCore.Liquid/Startup.cs index 0997a96577a..ffea1ed6666 100644 --- a/src/OrchardCore.Modules/OrchardCore.Liquid/Startup.cs +++ b/src/OrchardCore.Modules/OrchardCore.Liquid/Startup.cs @@ -55,7 +55,7 @@ public override void ConfigureServices(IServiceCollection services) services.AddLiquidFilter("liquid"); services.AddLiquidFilter("json"); services.AddLiquidFilter("jsonparse"); - services.AddLiquidFilter("shortcode"); + services.AddLiquidFilter("shortcode"); } } diff --git a/src/OrchardCore.Modules/OrchardCore.Markdown/Drivers/MarkdownBodyPartDisplay.cs b/src/OrchardCore.Modules/OrchardCore.Markdown/Drivers/MarkdownBodyPartDisplay.cs index f115099bcb3..a7c31dee1df 100644 --- a/src/OrchardCore.Modules/OrchardCore.Markdown/Drivers/MarkdownBodyPartDisplay.cs +++ b/src/OrchardCore.Modules/OrchardCore.Markdown/Drivers/MarkdownBodyPartDisplay.cs @@ -6,7 +6,7 @@ using OrchardCore.ContentManagement.Metadata.Models; using OrchardCore.DisplayManagement.ModelBinding; using OrchardCore.DisplayManagement.Views; -using OrchardCore.ShortCodes.Services; +using OrchardCore.Shortcodes.Services; using OrchardCore.Infrastructure.Html; using OrchardCore.Liquid; using OrchardCore.Markdown.Models; @@ -21,21 +21,21 @@ public class MarkdownBodyPartDisplay : ContentPartDisplayDriver localizer) { _liquidTemplateManager = liquidTemplateManager; _htmlEncoder = htmlEncoder; _htmlSanitizerService = htmlSanitizerService; - _shortCodeService = shortCodeService; + _shortcodeService = shortcodeService; _markdownService = markdownService; S = localizer; } @@ -95,7 +95,7 @@ private async ValueTask BuildViewModel(MarkdownBodyPartViewModel model, Markdown scope => scope.SetValue("ContentItem", model.ContentItem)); } - model.Html = await _shortCodeService.ProcessAsync(model.Html ?? ""); + model.Html = await _shortcodeService.ProcessAsync(model.Html ?? ""); if (settings.SanitizeHtml) { diff --git a/src/OrchardCore.Modules/OrchardCore.Markdown/Drivers/MarkdownFieldDriver.cs b/src/OrchardCore.Modules/OrchardCore.Markdown/Drivers/MarkdownFieldDriver.cs index 553c15ece50..0e682112156 100644 --- a/src/OrchardCore.Modules/OrchardCore.Markdown/Drivers/MarkdownFieldDriver.cs +++ b/src/OrchardCore.Modules/OrchardCore.Markdown/Drivers/MarkdownFieldDriver.cs @@ -6,7 +6,7 @@ using OrchardCore.ContentManagement.Metadata.Models; using OrchardCore.DisplayManagement.ModelBinding; using OrchardCore.DisplayManagement.Views; -using OrchardCore.ShortCodes.Services; +using OrchardCore.Shortcodes.Services; using OrchardCore.Infrastructure.Html; using OrchardCore.Liquid; using OrchardCore.Markdown.Fields; @@ -21,21 +21,21 @@ public class MarkdownFieldDisplayDriver : ContentFieldDisplayDriver localizer) { _liquidTemplateManager = liquidTemplateManager; _htmlEncoder = htmlEncoder; _htmlSanitizerService = htmlSanitizerService; - _shortCodeService = shortCodeService; + _shortcodeService = shortcodeService; _markdownService = markdownService; S = localizer; } @@ -62,7 +62,7 @@ public override IDisplayResult Display(MarkdownField field, BuildFieldDisplayCon scope => scope.SetValue("ContentItem", field.ContentItem)); } - model.Html = await _shortCodeService.ProcessAsync(model.Html ?? ""); + model.Html = await _shortcodeService.ProcessAsync(model.Html ?? ""); if (settings.SanitizeHtml) { diff --git a/src/OrchardCore.Modules/OrchardCore.Markdown/GraphQL/MarkdownBodyQueryObjectType.cs b/src/OrchardCore.Modules/OrchardCore.Markdown/GraphQL/MarkdownBodyQueryObjectType.cs index 4904915d93d..bd61a0c5160 100644 --- a/src/OrchardCore.Modules/OrchardCore.Markdown/GraphQL/MarkdownBodyQueryObjectType.cs +++ b/src/OrchardCore.Modules/OrchardCore.Markdown/GraphQL/MarkdownBodyQueryObjectType.cs @@ -6,7 +6,7 @@ using Microsoft.Extensions.Localization; using OrchardCore.Apis.GraphQL; using OrchardCore.ContentManagement.Metadata; -using OrchardCore.ShortCodes.Services; +using OrchardCore.Shortcodes.Services; using OrchardCore.Infrastructure.Html; using OrchardCore.Liquid; using OrchardCore.Markdown.Models; @@ -25,7 +25,6 @@ public MarkdownBodyQueryObjectType(IStringLocalizer Field("markdown", x => x.Markdown, nullable: true) .Description(S["the markdown value"]); - Field() .Name("html") .Description(S["the HTML representation of the markdown content"]) @@ -41,7 +40,7 @@ private static async Task ToHtml(ResolveFieldContext c var serviceProvider = ctx.ResolveServiceProvider(); var markdownService = serviceProvider.GetRequiredService(); - var shortCodeService = serviceProvider.GetRequiredService(); + var shortcodeService = serviceProvider.GetRequiredService(); var contentDefinitionManager = serviceProvider.GetRequiredService(); var contentTypeDefinition = contentDefinitionManager.GetTypeDefinition(ctx.Source.ContentItem.ContentType); @@ -70,7 +69,7 @@ private static async Task ToHtml(ResolveFieldContext c scope => scope.SetValue("ContentItem", model.ContentItem)); } - html = await shortCodeService.ProcessAsync(html); + html = await shortcodeService.ProcessAsync(html); if (settings.SanitizeHtml) { diff --git a/src/OrchardCore.Modules/OrchardCore.Markdown/GraphQL/MarkdownFieldQueryObjectType.cs b/src/OrchardCore.Modules/OrchardCore.Markdown/GraphQL/MarkdownFieldQueryObjectType.cs index 3468ab46798..e6b08a78568 100644 --- a/src/OrchardCore.Modules/OrchardCore.Markdown/GraphQL/MarkdownFieldQueryObjectType.cs +++ b/src/OrchardCore.Modules/OrchardCore.Markdown/GraphQL/MarkdownFieldQueryObjectType.cs @@ -11,7 +11,7 @@ using OrchardCore.Apis.GraphQL; using OrchardCore.ContentManagement; using OrchardCore.ContentManagement.Metadata; -using OrchardCore.ShortCodes.Services; +using OrchardCore.Shortcodes.Services; using OrchardCore.Infrastructure.Html; using OrchardCore.Liquid; using OrchardCore.Markdown.Fields; @@ -27,17 +27,15 @@ public MarkdownFieldQueryObjectType(IStringLocalizer x.Markdown, nullable: true) .Description(S["the markdown value"]); - Field() .Name("html") .Description(S["the HTML representation of the markdown content"]) .ResolveLockedAsync(ToHtml); } - private static async Task ToHtml(ResolveFieldContext ctx) { if (string.IsNullOrEmpty(ctx.Source.Markdown)) @@ -47,7 +45,7 @@ private static async Task ToHtml(ResolveFieldContext ctx) var serviceProvider = ctx.ResolveServiceProvider(); var markdownService = serviceProvider.GetRequiredService(); - var shortCodeService = serviceProvider.GetRequiredService(); + var shortcodeService = serviceProvider.GetRequiredService(); var contentDefinitionManager = serviceProvider.GetRequiredService(); @@ -86,7 +84,7 @@ private static async Task ToHtml(ResolveFieldContext ctx) scope => scope.SetValue("ContentItem", ctx.Source.ContentItem)); } - html = await shortCodeService.ProcessAsync(html); + html = await shortcodeService.ProcessAsync(html); if (settings.SanitizeHtml) { diff --git a/src/OrchardCore.Modules/OrchardCore.Markdown/Handlers/MarkdownBodyPartHandler.cs b/src/OrchardCore.Modules/OrchardCore.Markdown/Handlers/MarkdownBodyPartHandler.cs index 724fc282b8a..fc11d0714a0 100644 --- a/src/OrchardCore.Modules/OrchardCore.Markdown/Handlers/MarkdownBodyPartHandler.cs +++ b/src/OrchardCore.Modules/OrchardCore.Markdown/Handlers/MarkdownBodyPartHandler.cs @@ -6,7 +6,7 @@ using OrchardCore.ContentManagement.Handlers; using OrchardCore.ContentManagement.Metadata; using OrchardCore.ContentManagement.Models; -using OrchardCore.ShortCodes.Services; +using OrchardCore.Shortcodes.Services; using OrchardCore.Infrastructure.Html; using OrchardCore.Liquid; using OrchardCore.Markdown.Models; @@ -19,7 +19,7 @@ namespace OrchardCore.Markdown.Handlers public class MarkdownBodyPartHandler : ContentPartHandler { private readonly IContentDefinitionManager _contentDefinitionManager; - private readonly IShortCodeService _shortCodeService; + private readonly IShortcodeService _shortcodeService; private readonly IMarkdownService _markdownService; private readonly IHtmlSanitizerService _htmlSanitizerService; private readonly ILiquidTemplateManager _liquidTemplateManager; @@ -28,14 +28,14 @@ public class MarkdownBodyPartHandler : ContentPartHandler private int _contentItemId; public MarkdownBodyPartHandler(IContentDefinitionManager contentDefinitionManager, - IShortCodeService shortCodeService, + IShortcodeService shortcodeService, IMarkdownService markdownService, IHtmlSanitizerService htmlSanitizerService, ILiquidTemplateManager liquidTemplateManager, HtmlEncoder htmlEncoder) { _contentDefinitionManager = contentDefinitionManager; - _shortCodeService = shortCodeService; + _shortcodeService = shortcodeService; _markdownService = markdownService; _htmlSanitizerService = htmlSanitizerService; _liquidTemplateManager = liquidTemplateManager; @@ -78,7 +78,7 @@ public override Task GetContentItemAspectAsync(ContentItemAspectContext context, scope => scope.SetValue("ContentItem", model.ContentItem)); } - html = await _shortCodeService.ProcessAsync(html); + html = await _shortcodeService.ProcessAsync(html); if (settings.SanitizeHtml) { diff --git a/src/OrchardCore.Modules/OrchardCore.Markdown/Manifest.cs b/src/OrchardCore.Modules/OrchardCore.Markdown/Manifest.cs index 72f96f81f9d..725941e5b4f 100644 --- a/src/OrchardCore.Modules/OrchardCore.Markdown/Manifest.cs +++ b/src/OrchardCore.Modules/OrchardCore.Markdown/Manifest.cs @@ -6,6 +6,6 @@ Website = ManifestConstants.OrchardCoreWebsite, Version = ManifestConstants.OrchardCoreVersion, Description = "The markdown module enables content items to have markdown editors.", - Dependencies = new[] { "OrchardCore.ContentTypes", "OrchardCore.ShortCodes" }, + Dependencies = new[] { "OrchardCore.ContentTypes", "OrchardCore.Shortcodes" }, Category = "Content Management" )] diff --git a/src/OrchardCore.Modules/OrchardCore.Markdown/OrchardCore.Markdown.csproj b/src/OrchardCore.Modules/OrchardCore.Markdown/OrchardCore.Markdown.csproj index 47fe8a7badd..14175a73ebf 100644 --- a/src/OrchardCore.Modules/OrchardCore.Markdown/OrchardCore.Markdown.csproj +++ b/src/OrchardCore.Modules/OrchardCore.Markdown/OrchardCore.Markdown.csproj @@ -22,7 +22,7 @@ - + diff --git a/src/OrchardCore.Modules/OrchardCore.Markdown/Razor/MarkdownHelperExtensions.cs b/src/OrchardCore.Modules/OrchardCore.Markdown/Razor/MarkdownHelperExtensions.cs index aca0ffc0bbc..d2f78ca6391 100644 --- a/src/OrchardCore.Modules/OrchardCore.Markdown/Razor/MarkdownHelperExtensions.cs +++ b/src/OrchardCore.Modules/OrchardCore.Markdown/Razor/MarkdownHelperExtensions.cs @@ -4,7 +4,7 @@ using Microsoft.AspNetCore.Html; using Microsoft.Extensions.DependencyInjection; using OrchardCore; -using OrchardCore.ShortCodes.Services; +using OrchardCore.Shortcodes.Services; using OrchardCore.Infrastructure.Html; using OrchardCore.Liquid; using OrchardCore.Markdown.Services; @@ -17,7 +17,7 @@ public static class ContentRazorHelperExtensions /// The markdown to convert. public static async Task MarkdownToHtmlAsync(this IOrchardHelper orchardHelper, string markdown, bool sanitize = true) { - var shortCodeService = orchardHelper.HttpContext.RequestServices.GetRequiredService(); + var shortcodeService = orchardHelper.HttpContext.RequestServices.GetRequiredService(); var markdownService = orchardHelper.HttpContext.RequestServices.GetRequiredService(); // The default Markdown option is to entity escape html @@ -33,7 +33,7 @@ public static async Task MarkdownToHtmlAsync(this IOrchardHelper o markdown = await liquidTemplateManager.RenderAsync(markdown, htmlEncoder); } - markdown = await shortCodeService.ProcessAsync(markdown); + markdown = await shortcodeService.ProcessAsync(markdown); if (sanitize) { diff --git a/src/OrchardCore.Modules/OrchardCore.Media/Manifest.cs b/src/OrchardCore.Modules/OrchardCore.Media/Manifest.cs index 4f29ccebb9d..879a1cbd62d 100644 --- a/src/OrchardCore.Modules/OrchardCore.Media/Manifest.cs +++ b/src/OrchardCore.Modules/OrchardCore.Media/Manifest.cs @@ -14,7 +14,7 @@ Dependencies = new[] { "OrchardCore.ContentTypes", - "OrchardCore.ShortCodes" + "OrchardCore.Shortcodes" }, Category = "Content Management" )] diff --git a/src/OrchardCore.Modules/OrchardCore.Media/OrchardCore.Media.csproj b/src/OrchardCore.Modules/OrchardCore.Media/OrchardCore.Media.csproj index 278017232a9..6b1f5a41518 100644 --- a/src/OrchardCore.Modules/OrchardCore.Media/OrchardCore.Media.csproj +++ b/src/OrchardCore.Modules/OrchardCore.Media/OrchardCore.Media.csproj @@ -25,11 +25,12 @@ - + + diff --git a/src/OrchardCore.Modules/OrchardCore.Media/ShortCodes/ImageShortCode.cs b/src/OrchardCore.Modules/OrchardCore.Media/ShortCodes/ImageShortCode.cs deleted file mode 100644 index 207a4c08c6f..00000000000 --- a/src/OrchardCore.Modules/OrchardCore.Media/ShortCodes/ImageShortCode.cs +++ /dev/null @@ -1,121 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using OrchardCore.DisplayManagement; -using OrchardCore.Infrastructure.Html; -using OrchardCore.ShortCodes; - -namespace OrchardCore.Media.ShortCodes -{ - public class ImageShortCode : IShortCode - { - private readonly IHtmlSanitizerService _htmlSanitizerService; - private readonly IMediaFileStore _mediaFileStore; - - public ImageShortCode(IMediaFileStore mediaFileStore, IHtmlSanitizerService htmlSanitizerService) - { - _mediaFileStore = mediaFileStore; - _htmlSanitizerService = htmlSanitizerService; - } - - public ValueTask ProcessAsync(string text) - { - if (string.IsNullOrEmpty(text)) - { - return new ValueTask(string.Empty); - } - - // optimize code path if nothing to do - // if it doesn't have [media] and [/media] - // or doesn't have [image] and [/image] - - var hasMediaCode = text.Contains("[media]", StringComparison.OrdinalIgnoreCase) && - text.Contains("[/media]", StringComparison.OrdinalIgnoreCase); - - var hasImageCode = text.Contains("[image]", StringComparison.OrdinalIgnoreCase) && - text.Contains("[/image]", StringComparison.OrdinalIgnoreCase); - - - if (!hasMediaCode && !hasImageCode) - { - return new ValueTask(text); - } - - using (var sb = StringBuilderPool.GetInstance()) - { - sb.Builder.Append(text); - - var index = -1; - // When acting recursively track the modifications to the string builder start index. - var modifierIndex = 0; - var allIndices = new List(); - - // For backwards compatability check for [media] - // This code can be removed in a future version. - // [media] - if (hasMediaCode) - { - while (-1 != (index = text.IndexOf("[media]", index + 1, StringComparison.Ordinal))) - { - allIndices.Add(index); - } - - foreach (var start in allIndices) - { - var end = text.IndexOf("[/media]", start, StringComparison.Ordinal); - - if (end == -1) - { - continue; - } - - modifierIndex = SubstituteTag(text, sb, start, modifierIndex, end); - } - } - - // [image] - if (hasImageCode) - { - index = -1; - allIndices.Clear(); - while (-1 != (index = text.IndexOf("[image]", index + 1, StringComparison.Ordinal))) - { - allIndices.Add(index); - } - - foreach (var start in allIndices) - { - var end = text.IndexOf("[/image]", start + modifierIndex, StringComparison.Ordinal); - - if (end == -1) - { - continue; - } - - modifierIndex += SubstituteTag(text, sb, start, modifierIndex, end); - } - } - - return new ValueTask(sb.ToString()); - } - } - - private int SubstituteTag(string text, StringBuilderPool sb, int start, int modifierIndex, int end) - { - var url = text.Substring(start + 7, end - start - 7); - - // substitute [thetag] with - sb.Builder.Remove(start + modifierIndex, end - start + 8); - - var publicUrl = _mediaFileStore.MapPathToPublicUrl(url); - - var tag = ""; - tag = _htmlSanitizerService.Sanitize(tag); - - sb.Builder.Insert(start + modifierIndex, tag); - - // Return the value the stringbuilder start index has been modified for recursion. - return publicUrl.Length - url.Length - 3; - } - } -} diff --git a/src/OrchardCore.Modules/OrchardCore.Media/Shortcodes/ImageShortcodeProvider.cs b/src/OrchardCore.Modules/OrchardCore.Media/Shortcodes/ImageShortcodeProvider.cs new file mode 100644 index 00000000000..9eac3fd1bba --- /dev/null +++ b/src/OrchardCore.Modules/OrchardCore.Media/Shortcodes/ImageShortcodeProvider.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.WebUtilities; +using Microsoft.Extensions.Options; +using OrchardCore.Infrastructure.Html; +using OrchardCore.ResourceManagement; +using Shortcodes; + +namespace OrchardCore.Media.Shortcodes +{ + public class ImageShortcodeProvider : IShortcodeProvider + { + private static readonly ValueTask Null = new ValueTask((string)null); + private static readonly ValueTask ImageShortcode = new ValueTask("[image]"); + private static readonly HashSet Shortcodes = new HashSet(StringComparer.OrdinalIgnoreCase) + { + "image", + "media" // [media] is a deprecated shortcode, and can be removed in a future release. + }; + + private readonly IMediaFileStore _mediaFileStore; + private readonly IHtmlSanitizerService _htmlSanitizerService; + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly ResourceManagementOptions _options; + + public ImageShortcodeProvider( + IMediaFileStore mediaFileStore, + IHtmlSanitizerService htmlSanitizerService, + IHttpContextAccessor httpContextAccessor, + IOptions options) + { + _mediaFileStore = mediaFileStore; + _htmlSanitizerService = htmlSanitizerService; + _httpContextAccessor = httpContextAccessor; + _options = options.Value; + } + + public ValueTask EvaluateAsync(string identifier, Arguments arguments, string content) + { + if (!Shortcodes.Contains(identifier)) + { + return Null; + } + + // Handle self closing shortcodes. + if (String.IsNullOrEmpty(content)) + { + content = arguments.NamedOrDefault("src"); + if (String.IsNullOrEmpty(content)) + { + // Do not handle the deprecated media shortcode in this edge case. + return ImageShortcode; + } + } + + if (!content.StartsWith("//", StringComparison.Ordinal) && !content.StartsWith("http", StringComparison.OrdinalIgnoreCase)) + { + // Serve static files from virtual path. + if (content.StartsWith("~/", StringComparison.Ordinal)) + { + content = _httpContextAccessor.HttpContext.Request.PathBase.Add(content.Substring(1)).Value; + if (!String.IsNullOrEmpty(_options.CdnBaseUrl)) + { + content = _options.CdnBaseUrl + content; + } + } + else + { + content = _mediaFileStore.MapPathToPublicUrl(content); + } + } + + if (arguments.Any()) + { + var queryStringParams = new Dictionary(); + + var width = arguments.Named("width"); + var height = arguments.Named("height"); + var mode = arguments.Named("mode"); + + if (width != null) + { + queryStringParams.Add("width", width); + } + + if (height != null) + { + queryStringParams.Add("height", height); + } + + if (mode != null) + { + queryStringParams.Add("rmode", mode); + } + + content = QueryHelpers.AddQueryString(content, queryStringParams); + } + + content = ""; + content = _htmlSanitizerService.Sanitize(content); + + return new ValueTask(content); + } + } +} diff --git a/src/OrchardCore.Modules/OrchardCore.Media/Startup.cs b/src/OrchardCore.Modules/OrchardCore.Media/Startup.cs index 107637c6408..13561d3fbc4 100644 --- a/src/OrchardCore.Modules/OrchardCore.Media/Startup.cs +++ b/src/OrchardCore.Modules/OrchardCore.Media/Startup.cs @@ -22,7 +22,7 @@ using OrchardCore.Environment.Shell; using OrchardCore.FileStorage; using OrchardCore.FileStorage.FileSystem; -using OrchardCore.ShortCodes; +using OrchardCore.Shortcodes; using OrchardCore.Liquid; using OrchardCore.Media.Controllers; using OrchardCore.Media.Core; @@ -34,7 +34,7 @@ using OrchardCore.Media.Handlers; using OrchardCore.Media.Processing; using OrchardCore.Media.Recipes; -using OrchardCore.Media.ShortCodes; +using OrchardCore.Media.Shortcodes; using OrchardCore.Media.Services; using OrchardCore.Media.Settings; using OrchardCore.Media.TagHelpers; @@ -45,6 +45,7 @@ using OrchardCore.Navigation; using OrchardCore.Recipes; using OrchardCore.Security.Permissions; +using Shortcodes; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.Web.Caching; using SixLabors.ImageSharp.Web.Commands; @@ -157,7 +158,7 @@ public override void ConfigureServices(IServiceCollection services) services.AddTagHelpers(); services.AddTagHelpers(); - services.AddScoped(); + services.AddScoped(); } public override void Configure(IApplicationBuilder app, IEndpointRouteBuilder routes, IServiceProvider serviceProvider) diff --git a/src/OrchardCore.Modules/OrchardCore.ShortCodes/Services/ShortCodeService.cs b/src/OrchardCore.Modules/OrchardCore.ShortCodes/Services/ShortCodeService.cs deleted file mode 100644 index d35b5d0abf2..00000000000 --- a/src/OrchardCore.Modules/OrchardCore.ShortCodes/Services/ShortCodeService.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Collections.Generic; -using System.Threading.Tasks; - -namespace OrchardCore.ShortCodes.Services -{ - public class ShortCodeService : IShortCodeService - { - private readonly IEnumerable _shortCodes; - - public ShortCodeService(IEnumerable shortCodes) - { - _shortCodes = shortCodes; - } - - public async ValueTask ProcessAsync(string input) - { - foreach (var shortCode in _shortCodes) - { - input = await shortCode.ProcessAsync(input); - } - - return input; - } - } -} diff --git a/src/OrchardCore.Modules/OrchardCore.ShortCodes/Manifest.cs b/src/OrchardCore.Modules/OrchardCore.Shortcodes/Manifest.cs similarity index 92% rename from src/OrchardCore.Modules/OrchardCore.ShortCodes/Manifest.cs rename to src/OrchardCore.Modules/OrchardCore.Shortcodes/Manifest.cs index faff5d25165..6224cd8d853 100644 --- a/src/OrchardCore.Modules/OrchardCore.ShortCodes/Manifest.cs +++ b/src/OrchardCore.Modules/OrchardCore.Shortcodes/Manifest.cs @@ -1,7 +1,7 @@ using OrchardCore.Modules.Manifest; [assembly: Module( - Name = "ShortCodes", + Name = "Shortcodes", Author = ManifestConstants.OrchardCoreTeam, Website = ManifestConstants.OrchardCoreWebsite, Version = ManifestConstants.OrchardCoreVersion, diff --git a/src/OrchardCore.Modules/OrchardCore.ShortCodes/OrchardCore.ShortCodes.csproj b/src/OrchardCore.Modules/OrchardCore.Shortcodes/OrchardCore.Shortcodes.csproj similarity index 71% rename from src/OrchardCore.Modules/OrchardCore.ShortCodes/OrchardCore.ShortCodes.csproj rename to src/OrchardCore.Modules/OrchardCore.Shortcodes/OrchardCore.Shortcodes.csproj index b464d63cd30..f0cd8dd9833 100644 --- a/src/OrchardCore.Modules/OrchardCore.ShortCodes/OrchardCore.ShortCodes.csproj +++ b/src/OrchardCore.Modules/OrchardCore.Shortcodes/OrchardCore.Shortcodes.csproj @@ -9,8 +9,9 @@ + - + diff --git a/src/OrchardCore.Modules/OrchardCore.ShortCodes/Properties/AssemblyInfo.cs b/src/OrchardCore.Modules/OrchardCore.Shortcodes/Properties/AssemblyInfo.cs similarity index 100% rename from src/OrchardCore.Modules/OrchardCore.ShortCodes/Properties/AssemblyInfo.cs rename to src/OrchardCore.Modules/OrchardCore.Shortcodes/Properties/AssemblyInfo.cs diff --git a/src/OrchardCore.Modules/OrchardCore.ShortCodes/Razor/OrchardRazorHelperExtensions.cs b/src/OrchardCore.Modules/OrchardCore.Shortcodes/Razor/OrchardRazorHelperExtensions.cs similarity index 60% rename from src/OrchardCore.Modules/OrchardCore.ShortCodes/Razor/OrchardRazorHelperExtensions.cs rename to src/OrchardCore.Modules/OrchardCore.Shortcodes/Razor/OrchardRazorHelperExtensions.cs index 7ce03e8d44b..5a3058f8a1b 100644 --- a/src/OrchardCore.Modules/OrchardCore.ShortCodes/Razor/OrchardRazorHelperExtensions.cs +++ b/src/OrchardCore.Modules/OrchardCore.Shortcodes/Razor/OrchardRazorHelperExtensions.cs @@ -2,7 +2,7 @@ using Microsoft.AspNetCore.Html; using Microsoft.Extensions.DependencyInjection; using OrchardCore; -using OrchardCore.ShortCodes.Services; +using OrchardCore.Shortcodes.Services; public static class OrchardRazorHelperExtensions { @@ -10,11 +10,11 @@ public static class OrchardRazorHelperExtensions /// Applies short codes to html. /// /// The html to apply short codes. - public static async Task HtmlToShortCodesAsync(this IOrchardHelper orchardHelper, string html) + public static async Task HtmlToShortcodesAsync(this IOrchardHelper orchardHelper, string html) { - var shortCodeService = orchardHelper.HttpContext.RequestServices.GetRequiredService(); + var shortcodeService = orchardHelper.HttpContext.RequestServices.GetRequiredService(); - html = await shortCodeService.ProcessAsync(html); + html = await shortcodeService.ProcessAsync(html); return new HtmlString(html); } diff --git a/src/OrchardCore.Modules/OrchardCore.Shortcodes/Services/ShortcodeService.cs b/src/OrchardCore.Modules/OrchardCore.Shortcodes/Services/ShortcodeService.cs new file mode 100644 index 00000000000..4afe9990706 --- /dev/null +++ b/src/OrchardCore.Modules/OrchardCore.Shortcodes/Services/ShortcodeService.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Shortcodes; + +namespace OrchardCore.Shortcodes.Services +{ + public class ShortcodeService : IShortcodeService + { + private readonly ShortcodesProcessor _shortcodesProcessor; + + public ShortcodeService(IEnumerable shortcodeProviders) + { + _shortcodesProcessor = new ShortcodesProcessor(shortcodeProviders); + } + + public ValueTask ProcessAsync(string input) + { + return _shortcodesProcessor.EvaluateAsync(input); + } + } +} diff --git a/src/OrchardCore.Modules/OrchardCore.ShortCodes/Startup.cs b/src/OrchardCore.Modules/OrchardCore.Shortcodes/Startup.cs similarity index 60% rename from src/OrchardCore.Modules/OrchardCore.ShortCodes/Startup.cs rename to src/OrchardCore.Modules/OrchardCore.Shortcodes/Startup.cs index ef8b9382c3e..974246100ae 100644 --- a/src/OrchardCore.Modules/OrchardCore.ShortCodes/Startup.cs +++ b/src/OrchardCore.Modules/OrchardCore.Shortcodes/Startup.cs @@ -1,14 +1,15 @@ using Microsoft.Extensions.DependencyInjection; using OrchardCore.Modules; -using OrchardCore.ShortCodes.Services; +using OrchardCore.Shortcodes.Services; +using Shortcodes; -namespace OrchardCore.ShortCodes +namespace OrchardCore.Shortcodes { public class Startup : StartupBase { public override void ConfigureServices(IServiceCollection services) { - services.AddScoped(); + services.AddScoped(); } } } diff --git a/src/OrchardCore/OrchardCore.Application.Cms.Core.Targets/OrchardCore.Application.Cms.Core.Targets.csproj b/src/OrchardCore/OrchardCore.Application.Cms.Core.Targets/OrchardCore.Application.Cms.Core.Targets.csproj index 55cd04dccb4..cedd5527a78 100644 --- a/src/OrchardCore/OrchardCore.Application.Cms.Core.Targets/OrchardCore.Application.Cms.Core.Targets.csproj +++ b/src/OrchardCore/OrchardCore.Application.Cms.Core.Targets/OrchardCore.Application.Cms.Core.Targets.csproj @@ -84,7 +84,7 @@ - + diff --git a/src/OrchardCore/OrchardCore.ShortCodes.Abstractions/Services/IShortCodeService.cs b/src/OrchardCore/OrchardCore.ShortCodes.Abstractions/Services/IShortCodeService.cs deleted file mode 100644 index 925550fe280..00000000000 --- a/src/OrchardCore/OrchardCore.ShortCodes.Abstractions/Services/IShortCodeService.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Threading.Tasks; - -namespace OrchardCore.ShortCodes.Services -{ - public interface IShortCodeService - { - ValueTask ProcessAsync(string input); - } -} diff --git a/src/OrchardCore/OrchardCore.ShortCodes.Abstractions/OrchardCore.ShortCodes.Abstractions.csproj b/src/OrchardCore/OrchardCore.Shortcodes.Abstractions/OrchardCore.Shortcodes.Abstractions.csproj similarity index 64% rename from src/OrchardCore/OrchardCore.ShortCodes.Abstractions/OrchardCore.ShortCodes.Abstractions.csproj rename to src/OrchardCore/OrchardCore.Shortcodes.Abstractions/OrchardCore.Shortcodes.Abstractions.csproj index 8341c76ff77..ca187b6a163 100644 --- a/src/OrchardCore/OrchardCore.ShortCodes.Abstractions/OrchardCore.ShortCodes.Abstractions.csproj +++ b/src/OrchardCore/OrchardCore.Shortcodes.Abstractions/OrchardCore.Shortcodes.Abstractions.csproj @@ -2,11 +2,15 @@ $(AspNetCoreTargetFramework) - OrchardCore.ShortCodes + OrchardCore.Shortcodes + + + + diff --git a/src/OrchardCore/OrchardCore.ShortCodes.Abstractions/IShortCode.cs b/src/OrchardCore/OrchardCore.Shortcodes.Abstractions/Services/IShortcodeService.cs similarity index 55% rename from src/OrchardCore/OrchardCore.ShortCodes.Abstractions/IShortCode.cs rename to src/OrchardCore/OrchardCore.Shortcodes.Abstractions/Services/IShortcodeService.cs index 5bba033ffd1..4f6db33e371 100644 --- a/src/OrchardCore/OrchardCore.ShortCodes.Abstractions/IShortCode.cs +++ b/src/OrchardCore/OrchardCore.Shortcodes.Abstractions/Services/IShortcodeService.cs @@ -1,8 +1,8 @@ using System.Threading.Tasks; -namespace OrchardCore.ShortCodes +namespace OrchardCore.Shortcodes.Services { - public interface IShortCode + public interface IShortcodeService { ValueTask ProcessAsync(string input); } diff --git a/src/docs/reference/modules/ShortCodes/README.md b/src/docs/reference/modules/ShortCodes/README.md deleted file mode 100644 index 3ed21ebab85..00000000000 --- a/src/docs/reference/modules/ShortCodes/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# ShortCodes (`OrchardCore.ShortCodes`) - -Adds short code capabilities. Short codes are small pieces of code wrapped into \[brackets\] that can add some behavior to your content, like embedding media files. \ No newline at end of file diff --git a/src/docs/reference/modules/Shortcodes/README.md b/src/docs/reference/modules/Shortcodes/README.md new file mode 100644 index 00000000000..32035900275 --- /dev/null +++ b/src/docs/reference/modules/Shortcodes/README.md @@ -0,0 +1,7 @@ +# Shortcodes (`OrchardCore.Shortcodes`) + +Adds short code capabilities. Short codes are small pieces of code wrapped into \[brackets\] that can add some behavior to your content, like embedding media files. + +!!! note + Shortcodes is being actively developed during rc2. + The interfaces and implementations are subject to change without notice. \ No newline at end of file diff --git a/test/OrchardCore.Tests/Modules/OrchardCore.Media/ImageShortCodeTests.cs b/test/OrchardCore.Tests/Modules/OrchardCore.Media/ImageShortCodeTests.cs deleted file mode 100644 index eda860a24b1..00000000000 --- a/test/OrchardCore.Tests/Modules/OrchardCore.Media/ImageShortCodeTests.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System.Linq; -using System.Threading.Tasks; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Moq; -using OrchardCore.FileStorage; -using OrchardCore.Infrastructure.Html; -using OrchardCore.Media.Core; -using OrchardCore.Media.Events; -using OrchardCore.Media.ShortCodes; -using Xunit; - -namespace OrchardCore.Tests.Modules.OrchardCore.Media -{ - public class ImageShortCodeTests - { - [Theory] - [InlineData("foo bar baz", "foo bar baz")] - [InlineData("foo [media]bar baz", "foo [media]bar baz")] - [InlineData("foo [media]bar[/media] baz", @"foo baz")] - [InlineData("foo [media]bar[/media] baz foo [media]bar[/media] baz", @"foo baz foo baz")] - [InlineData("foo [media]bàr.jpeg?width=100[/media] baz", @"foo baz")] - [InlineData("foo [media]bàr.jpeg?width=100 onload=\"javascript: alert('XSS')[/media] baz", @"foo baz")] - [InlineData("foo [image]bar baz", "foo [image]bar baz")] - [InlineData("foo [image]bar[/image] baz", @"foo baz")] - [InlineData("foo [image]bar[/image] baz foo [image]bar[/image] baz", @"foo baz foo baz")] - [InlineData("foo [image]bar[/image] baz foo [image]bar[/image] baz foo [image]bar[/image] baz", @"foo baz foo baz foo baz")] - [InlineData("foo [image]bar.png[/image] baz foo-extended [image]bar-extended.png[/image] baz-extended", @"foo baz foo-extended baz-extended")] - [InlineData("foo [media]bar[/media] baz foo [image]bar[/image] baz", @"foo baz foo baz")] - [InlineData("foo [image]bàr.jpeg?width=100[/image] baz", @"foo baz")] - [InlineData("foo [image]bàr.jpeg?width=100 onload=\"javascript: alert('XSS')[/image] baz", @"foo baz")] - - public async Task ShouldProcess(string text, string expected) - { - var mediaShortCode = new ImageShortCode( - new DefaultMediaFileStore(Mock.Of(), - "/media", - string.Empty, - Enumerable.Empty(), - Enumerable.Empty(), - Mock.Of>()), - new HtmlSanitizerService(Options.Create(new HtmlSanitizerOptions())) - ); - - var processed = await mediaShortCode.ProcessAsync(text); - Assert.Equal(expected, processed); - } - } -} diff --git a/test/OrchardCore.Tests/Modules/OrchardCore.Media/ImageShortcodeTests.cs b/test/OrchardCore.Tests/Modules/OrchardCore.Media/ImageShortcodeTests.cs new file mode 100644 index 00000000000..02f66d648a4 --- /dev/null +++ b/test/OrchardCore.Tests/Modules/OrchardCore.Media/ImageShortcodeTests.cs @@ -0,0 +1,75 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Moq; +using OrchardCore.FileStorage; +using OrchardCore.Infrastructure.Html; +using OrchardCore.Media.Core; +using OrchardCore.Media.Events; +using OrchardCore.Media.Shortcodes; +using OrchardCore.ResourceManagement; +using OrchardCore.Shortcodes.Services; +using Shortcodes; +using Xunit; + +namespace OrchardCore.Tests.Modules.OrchardCore.Media +{ + public class ImageShortcodeTests + { + [Theory] + [InlineData("", "foo bar baz", "foo bar baz")] + [InlineData("", "foo [media]bar[/media] baz", @"foo baz")] + [InlineData("", "foo [media]bar[/media] baz foo [media]bar[/media] baz", @"foo baz foo baz")] + [InlineData("", "foo [media]bàr.jpeg?width=100[/media] baz", @"foo baz")] + [InlineData("", "foo [media]bàr.jpeg?width=100 onload=\"javascript: alert('XSS')[/media] baz", @"foo baz")] + [InlineData("", "foo [image]bar baz", "foo [image]bar baz")] + [InlineData("", @"foo [image ""bar""] baz", @"foo baz")] + [InlineData("", @"foo [image src=""bar""] baz", @"foo baz")] + [InlineData("https://cdn.com", @"foo [image src=""bar""] baz", @"foo baz")] + + [InlineData("", "foo [image]~/bar[/image] baz", @"foo baz")] + [InlineData("https://cdn.com", "foo [image]~/bar[/image] baz", @"foo baz")] // new + [InlineData("", "foo [image]http://bar[/image] baz", @"foo baz")] + [InlineData("", "foo [image]//bar[/image] baz", @"foo baz")] + [InlineData("", "foo [image]bar[/image] baz", @"foo baz")] + [InlineData("", @"foo [image width=""100""]bar[/image] baz", @"foo baz")] + [InlineData("", @"foo [image width=""100"" height=""50"" mode=""stretch""]bar[/image] baz", @"foo baz")] + [InlineData("", "foo [image]bar[/image] baz foo [image]bar[/image] baz", @"foo baz foo baz")] + [InlineData("", "foo [image]bar[/image] baz foo [image]bar[/image] baz foo [image]bar[/image] baz", @"foo baz foo baz foo baz")] + [InlineData("", "foo [image]bar.png[/image] baz foo-extended [image]bar-extended.png[/image] baz-extended", @"foo baz foo-extended baz-extended")] + [InlineData("", "foo [media]bar[/media] baz foo [image]bar[/image] baz", @"foo baz foo baz")] + [InlineData("", "foo [image]bàr.jpeg?width=100[/image] baz", @"foo baz")] + [InlineData("", "foo [image]bàr.jpeg?width=100 onload=\"javascript: alert('XSS')[/image] baz", @"foo baz")] + + public async Task ShouldProcess(string cdnBaseUrl, string text, string expected) + { + + var fileStore = new DefaultMediaFileStore( + Mock.Of(), + "/media", + cdnBaseUrl, + Enumerable.Empty(), + Enumerable.Empty(), + Mock.Of>()); + + var sanitizer = new HtmlSanitizerService(Options.Create(new HtmlSanitizerOptions())); + + var defaultHttpContext = new DefaultHttpContext(); + defaultHttpContext.Request.PathBase = new PathString("/tenant"); + var httpContextAccessor = Mock.Of(hca => hca.HttpContext == defaultHttpContext); + + var options = Options.Create(new ResourceManagementOptions{ CdnBaseUrl = cdnBaseUrl }); + + var imageProvider = new ImageShortcodeProvider(fileStore,sanitizer, httpContextAccessor, options); + + var processor = new ShortcodeService(new IShortcodeProvider[] { imageProvider }); + + var processed = await processor.ProcessAsync(text); + Assert.Equal(expected, processed); + + } + } +}