Initial implementation of WrapWithDiv command

This commit is contained in:
David Wengier 2021-12-02 14:37:22 +11:00
Родитель b0b810421f
Коммит b7b7611a2d
28 изменённых файлов: 780 добавлений и 2 удалений

Просмотреть файл

@ -2,7 +2,7 @@
<!-- Opt-in arcade features -->
<PropertyGroup>
<UsingToolVSSDK>true</UsingToolVSSDK>
<MicrosoftVSSDKBuildToolsVersion>17.0.63-dev17-g3f11f5ab</MicrosoftVSSDKBuildToolsVersion>
<MicrosoftVSSDKBuildToolsVersion>17.0.5232</MicrosoftVSSDKBuildToolsVersion>
<MicroBuildPluginsSwixBuildVersion>1.1.33</MicroBuildPluginsSwixBuildVersion>
<!-- Use .NET Framework reference assemblies from a nuget package so machine-global targeting packs do not need to be installed. -->
<UsingToolNetFrameworkReferenceAssemblies>true</UsingToolNetFrameworkReferenceAssemblies>

Просмотреть файл

@ -46,6 +46,8 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Common
public const string RazorServerReadyEndpoint = "razor/serverReady";
public const string RazorWrapWithTagEndpoint = "razor/wrapWithTag";
public static class CodeActions
{
public const string EditBasedCodeActionCommand = "EditBasedCodeActionCommand";

Просмотреть файл

@ -130,6 +130,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer
.WithHandler<RazorComponentRenameEndpoint>()
.WithHandler<RazorDefinitionEndpoint>()
.WithHandler<LinkedEditingRangeEndpoint>()
.WithHandler<WrapWithTagEndpoint>()
.WithServices(services =>
{
services.AddLogging(builder => builder

Просмотреть файл

@ -0,0 +1,14 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Razor.LanguageServer.Common;
using Microsoft.VisualStudio.LanguageServerClient.Razor.WrapWithDiv;
using OmniSharp.Extensions.JsonRpc;
namespace Microsoft.AspNetCore.Razor.LanguageServer.AutoInsert
{
[Parallel, Method(LanguageServerConstants.RazorWrapWithTagEndpoint)]
internal interface IWrapWithTagHandler : IJsonRpcRequestHandler<WrapWithTagParams, WrapWithTagResponse>
{
}
}

Просмотреть файл

@ -0,0 +1,106 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.LanguageServer.Common;
using Microsoft.AspNetCore.Razor.LanguageServer.Common.Extensions;
using Microsoft.AspNetCore.Razor.LanguageServer.Extensions;
using Microsoft.AspNetCore.Razor.LanguageServer.ProjectSystem;
using Microsoft.CodeAnalysis.Razor;
using Microsoft.Extensions.Logging;
using Microsoft.VisualStudio.LanguageServerClient.Razor.WrapWithDiv;
namespace Microsoft.AspNetCore.Razor.LanguageServer.AutoInsert
{
internal class WrapWithTagEndpoint : IWrapWithTagHandler
{
private readonly ClientNotifierServiceBase _languageServer;
private readonly ProjectSnapshotManagerDispatcher _projectSnapshotManagerDispatcher;
private readonly DocumentResolver _documentResolver;
private readonly RazorDocumentMappingService _razorDocumentMappingService;
private readonly ILogger _logger;
public WrapWithTagEndpoint(
ClientNotifierServiceBase languageServer,
ProjectSnapshotManagerDispatcher projectSnapshotManagerDispatcher,
DocumentResolver documentResolver,
RazorDocumentMappingService razorDocumentMappingService,
ILoggerFactory loggerFactory)
{
if (languageServer is null)
{
throw new ArgumentNullException(nameof(languageServer));
}
if (projectSnapshotManagerDispatcher is null)
{
throw new ArgumentNullException(nameof(projectSnapshotManagerDispatcher));
}
if (documentResolver is null)
{
throw new ArgumentNullException(nameof(documentResolver));
}
if (razorDocumentMappingService is null)
{
throw new ArgumentNullException(nameof(razorDocumentMappingService));
}
if (loggerFactory is null)
{
throw new ArgumentNullException(nameof(loggerFactory));
}
_languageServer = languageServer;
_projectSnapshotManagerDispatcher = projectSnapshotManagerDispatcher;
_documentResolver = documentResolver;
_razorDocumentMappingService = razorDocumentMappingService;
_logger = loggerFactory.CreateLogger<WrapWithTagEndpoint>();
}
public async Task<WrapWithTagResponse> Handle(WrapWithTagParams request, CancellationToken cancellationToken)
{
var documentSnapshot = await _projectSnapshotManagerDispatcher.RunOnDispatcherThreadAsync(() =>
{
_documentResolver.TryResolveDocument(request.TextDocument.Uri.GetAbsoluteOrUNCPath(), out var documentSnapshot);
return documentSnapshot;
}, cancellationToken).ConfigureAwait(false);
if (documentSnapshot is null || cancellationToken.IsCancellationRequested)
{
_logger.LogWarning($"Failed to find document {request.TextDocument.Uri}.");
return null;
}
var codeDocument = await documentSnapshot.GetGeneratedOutputAsync();
if (codeDocument.IsUnsupported())
{
_logger.LogWarning($"Failed to retrieve generated output for document {request.TextDocument.Uri}.");
return null;
}
var sourceText = await documentSnapshot.GetTextAsync().ConfigureAwait(false);
if (!request.Range.Start.TryGetAbsoluteIndex(sourceText, _logger, out var hostDocumentIndex))
{
return null;
}
var languageKind = _razorDocumentMappingService.GetLanguageKind(codeDocument, hostDocumentIndex);
if (languageKind is not RazorLanguageKind.Html)
{
_logger.LogInformation($"Unsupported language {languageKind:G}.");
return null;
}
var parameter = request;
var response = await _languageServer.SendRequestAsync(LanguageServerConstants.RazorWrapWithTagEndpoint, parameter);
var htmlResponse = await response.Returning<WrapWithTagResponse>(cancellationToken);
return htmlResponse;
}
}
}

Просмотреть файл

@ -0,0 +1,55 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using MediatR;
using Newtonsoft.Json;
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
namespace Microsoft.VisualStudio.LanguageServerClient.Razor.WrapWithDiv
{
/// <summary>
/// Class representing the parameters sent for a textDocument/_vsweb_wrapWithTag request.
/// </summary>
internal class WrapWithTagParams : ITextDocumentIdentifierParams, IRequest<WrapWithTagResponse>, IBaseRequest
{
/// <summary>
/// Gets or sets the identifier for the text document to be operate on.
/// </summary>
[JsonProperty("_vs_textDocument")]
public TextDocumentIdentifier TextDocument
{
get;
set;
}
/// <summary>
/// Gets or sets the selection range to be wrapped.
/// </summary>
[JsonProperty("_vs_range")]
public Range Range
{
get;
set;
}
/// <summary>
/// Gets or sets the wrapping tag name.
/// </summary>
[JsonProperty("_vs_tagName")]
public string TagName
{
get;
set;
}
/// <summary>
/// Gets or sets the formatting options.
/// </summary>
[JsonProperty("_vs_options")]
public FormattingOptions Options
{
get;
set;
}
}
}

Просмотреть файл

@ -0,0 +1,26 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using Newtonsoft.Json;
using OmniSharp.Extensions.LanguageServer.Protocol.Models;
namespace Microsoft.VisualStudio.LanguageServerClient.Razor.WrapWithDiv
{
/// <summary>
/// Class representing the response of an WrapWithTag response.
/// </summary>
internal class WrapWithTagResponse
{
/// <summary>
/// Gets or sets the range of the wrapping tag.
/// </summary>
[JsonProperty("_vs_tagRange")]
public Range TagRange { get; set; }
/// <summary>
/// Gets or sets the text edits.
/// </summary>
[JsonProperty("_vs_textEdits")]
public TextEdit[] TextEdits { get; set; }
}
}

Просмотреть файл

@ -19,6 +19,7 @@ using Microsoft.VisualStudio.LanguageServer.ContainedLanguage.Extensions;
using Microsoft.VisualStudio.LanguageServer.Protocol;
using Microsoft.VisualStudio.LanguageServerClient.Razor.Extensions;
using Microsoft.VisualStudio.LanguageServerClient.Razor.HtmlCSharp;
using Microsoft.VisualStudio.LanguageServerClient.Razor.WrapWithDiv;
using Microsoft.VisualStudio.Threading;
using Newtonsoft.Json.Linq;
using OmniSharpConfigurationParams = OmniSharp.Extensions.LanguageServer.Protocol.Models.ConfigurationParams;
@ -475,5 +476,52 @@ namespace Microsoft.VisualStudio.LanguageServerClient.Razor
return Task.FromResult(result.ToArray());
}
public override async Task<VSInternalWrapWithTagResponse> RazorWrapWithTagAsync(VSInternalWrapWithTagParams wrapWithParams, CancellationToken cancellationToken)
{
const string HtmlWrapWithTagEndpoint = "textDocument/_vsweb_wrapWithTag";
var response = new VSInternalWrapWithTagResponse(wrapWithParams.Range, Array.Empty<TextEdit>());
var hostDocumentUri = wrapWithParams.TextDocument.Uri;
if (!_documentManager.TryGetDocument(hostDocumentUri, out var documentSnapshot))
{
return response;
}
string languageServerName;
Uri projectedUri;
if (documentSnapshot.TryGetVirtualDocument<HtmlVirtualDocumentSnapshot>(out var htmlDocument))
{
languageServerName = RazorLSPConstants.HtmlLanguageServerName;
projectedUri = htmlDocument.Uri;
}
else
{
Debug.Fail("Unexpected RazorLanguageKind. This can't really happen in a real scenario.");
return response;
}
var request = new VSInternalWrapWithTagParams(
wrapWithParams.Range,
wrapWithParams.TagName,
wrapWithParams.Options,
new TextDocumentIdentifier() { Uri = projectedUri });
var textBuffer = htmlDocument.Snapshot.TextBuffer;
var result = await _requestInvoker.ReinvokeRequestOnServerAsync<VSInternalWrapWithTagParams, VSInternalWrapWithTagResponse>(
textBuffer,
HtmlWrapWithTagEndpoint,
languageServerName,
request,
cancellationToken).ConfigureAwait(false);
if (result?.Response is not null)
{
response = result.Response;
}
return response;
}
}
}

Просмотреть файл

@ -8,6 +8,7 @@ using Microsoft.AspNetCore.Razor.LanguageServer.Common;
using Microsoft.AspNetCore.Razor.LanguageServer.Semantic;
using Microsoft.AspNetCore.Razor.LanguageServer.Semantic.Models;
using Microsoft.VisualStudio.LanguageServer.Protocol;
using Microsoft.VisualStudio.LanguageServerClient.Razor.WrapWithDiv;
using StreamJsonRpc;
namespace Microsoft.VisualStudio.LanguageServerClient.Razor
@ -52,5 +53,9 @@ namespace Microsoft.VisualStudio.LanguageServerClient.Razor
[JsonRpcMethod(LanguageServerConstants.RazorServerReadyEndpoint, UseSingleObjectParameterDeserialization = true)]
public abstract Task RazorServerReadyAsync(CancellationToken cancellationToken);
// Called by the Visual Studio to wrap the current selection with a tag
[JsonRpcMethod(LanguageServerConstants.RazorWrapWithTagEndpoint, UseSingleObjectParameterDeserialization = true)]
public abstract Task<VSInternalWrapWithTagResponse> RazorWrapWithTagAsync(VSInternalWrapWithTagParams wrapWithParams, CancellationToken cancellationToken);
}
}

Просмотреть файл

@ -0,0 +1,67 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System.Runtime.Serialization;
using Microsoft.VisualStudio.LanguageServer.Protocol;
namespace Microsoft.VisualStudio.LanguageServerClient.Razor.WrapWithDiv
{
/// <summary>
/// Class representing the parameters sent for a textDocument/_vsweb_wrapWithTag request.
/// Matches corresponding class in Web Tools' Html language server
/// </summary>
[DataContract]
internal class VSInternalWrapWithTagParams
{
public VSInternalWrapWithTagParams(Range range,
string tagName,
FormattingOptions options,
TextDocumentIdentifier textDocument)
{
Range = range;
Options = options;
TagName = tagName;
TextDocument = textDocument;
}
/// <summary>
/// Gets or sets the identifier for the text document to be operate on.
/// </summary>
[DataMember(Name = "_vs_textDocument")]
public TextDocumentIdentifier TextDocument
{
get;
set;
}
/// <summary>
/// Gets or sets the selection range to be wrapped.
/// </summary>
[DataMember(Name = "_vs_range")]
public Range Range
{
get;
set;
}
/// <summary>
/// Gets or sets the wrapping tag name.
/// </summary>
[DataMember(Name = "_vs_tagName")]
public string TagName
{
get;
set;
}
/// <summary>
/// Gets or sets the formatting options.
/// </summary>
[DataMember(Name = "_vs_options")]
public FormattingOptions Options
{
get;
set;
}
}
}

Просмотреть файл

@ -0,0 +1,38 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System.Runtime.Serialization;
using Microsoft.VisualStudio.LanguageServer.Protocol;
namespace Microsoft.VisualStudio.LanguageServerClient.Razor.WrapWithDiv
{
/// <summary>
/// Class representing the response of an WrapWithTag response.
/// Matches corresponding class in Web Tools' Html language server
/// </summary>
[DataContract]
internal class VSInternalWrapWithTagResponse
{
public VSInternalWrapWithTagResponse(Range tagRange, TextEdit[] textEdits)
{
TagRange = tagRange;
TextEdits = textEdits;
}
/// <summary>
/// Gets or sets the range of the wrapping tag.
/// </summary>
[DataMember(Name = "_vs_tagRange")]
public Range TagRange { get; }
/// <summary>
/// Gets or sets the text edits.
/// </summary>
[DataMember(Name = "_vs_textEdits")]
public TextEdit[] TextEdits
{
get;
set;
}
}
}

Просмотреть файл

@ -0,0 +1,216 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
#nullable enable
using System;
using System.ComponentModel.Composition;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.LanguageServer.Common;
using Microsoft.VisualStudio.Commanding;
using Microsoft.VisualStudio.Editor.Commanding;
using Microsoft.VisualStudio.LanguageServer.ContainedLanguage;
using Microsoft.VisualStudio.LanguageServer.Protocol;
using Microsoft.VisualStudio.LanguageServerClient.Razor.Extensions;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Text.Editor.Commanding;
using Microsoft.VisualStudio.Threading;
using Microsoft.VisualStudio.Utilities;
namespace Microsoft.VisualStudio.LanguageServerClient.Razor.WrapWithDiv
{
[Export(typeof(ICommandHandler))]
[ContentType(RazorLSPConstants.RazorLSPContentTypeName)]
[Name(nameof(WrapWithDivCommandHandler))]
internal sealed class WrapWithDivCommandHandler : ICommandHandler<WrapWithDivCommandArgs>
{
private readonly LSPRequestInvoker _requestInvoker;
private readonly JoinableTaskFactory _jtf;
private readonly ITextDocumentFactoryService _textDocumentFactoryService;
private readonly FormattingOptionsProvider _formattingOptionsProvider;
public string DisplayName => nameof(WrapWithDivCommandHandler);
[ImportingConstructor]
public WrapWithDivCommandHandler(
LSPRequestInvoker requestInvoker,
JoinableTaskContext joinableTaskContext,
ITextDocumentFactoryService textDocumentFactoryService,
FormattingOptionsProvider formattingOptionsProvider)
{
_requestInvoker = requestInvoker;
_jtf = joinableTaskContext.Factory;
_textDocumentFactoryService = textDocumentFactoryService;
_formattingOptionsProvider = formattingOptionsProvider;
}
public CommandState GetCommandState(WrapWithDivCommandArgs args)
{
if (!args.SubjectBuffer.IsRazorLSPBuffer())
{
return CommandState.Unavailable;
}
return CommandState.Available;
}
public bool ExecuteCommand(WrapWithDivCommandArgs args, CommandExecutionContext executionContext)
{
var buffer = args.SubjectBuffer;
var snapshot = buffer.CurrentSnapshot;
var viewSpanToWrap = args.TextView.Selection.StreamSelectionSpan.SnapshotSpan;
// Handle projection view scenarios (eg: Tools.DiffFiles inline)
var mappedSpansToWrap = args.TextView.BufferGraph.MapDownToBuffer(viewSpanToWrap, SpanTrackingMode.EdgeInclusive, buffer);
if (mappedSpansToWrap.Count != 1)
{
// The selection spanned multiple buffers, not supported
return false;
}
// Note: It's important to not use a jtf.Run here to try to achieve synchronous behavioe. JsonRPC doesn't carry over the
// synchronization context, which means unresponsiveness will occur if if the inproc json handler on the other side attempts to
// do a jtf.SwitchToMainThread.
// Also, intentionally not using IUIThreadOperationExecutor to bring up the wait dialog as there would be interweaved
// creation/disposal of these objects since vs's commanding infrastructure creates/disposes an instance around their
// call into this handler.
_ = _jtf.RunAsync(async () =>
{
var result = await InvokeWrapWithDivAsync(snapshot, mappedSpansToWrap[0], buffer);
if (result is not null && result.TextEdits.Length > 0)
{
ApplyChanges(snapshot, result, args.TextView);
}
});
return true;
}
private async Task<VSInternalWrapWithTagResponse?> InvokeWrapWithDivAsync(ITextSnapshot snapshot, SnapshotSpan spanToWrap, ITextBuffer subjectBuffer)
{
if (!_textDocumentFactoryService.TryGetTextDocument(subjectBuffer, out var document) ||
document?.FilePath is null)
{
return null;
}
var hostUri = new Uri(document.FilePath);
var wrapWithTagParams = new VSInternalWrapWithTagParams(
range: spanToWrap.AsRange(),
tagName: "div",
options: _formattingOptionsProvider.GetOptions(hostUri),
textDocument: new TextDocumentIdentifier() { Uri = hostUri }
);
// Send the WrapWithTag request to the appropriate language server.
var wrapWithTagResponse = await _requestInvoker.ReinvokeRequestOnServerAsync<VSInternalWrapWithTagParams, VSInternalWrapWithTagResponse>(
subjectBuffer,
LanguageServerConstants.RazorWrapWithTagEndpoint,
RazorLSPConstants.RazorLanguageServerName,
wrapWithTagParams,
CancellationToken.None).ConfigureAwait(false);
return wrapWithTagResponse?.Response;
}
private static void ApplyChanges(ITextSnapshot snapshot, VSInternalWrapWithTagResponse wrapWithTagResponse, ITextView? textView = null)
{
// Make sure we're still looking at the same snapshot before we try to change anything
if (snapshot != snapshot.TextBuffer.CurrentSnapshot)
{
return;
}
var buffer = snapshot.TextBuffer;
using var edit = buffer.CreateEdit();
foreach (var curEdit in wrapWithTagResponse.TextEdits)
{
if (ToSnapshotSpan(curEdit.Range, snapshot) is SnapshotSpan currentSpan)
{
edit.Replace(currentSpan.Start, currentSpan.Length, curEdit.NewText);
}
}
var newSnapshot = edit.Apply();
if (textView is not null && ToSnapshotSpan(wrapWithTagResponse.TagRange, snapshot) is SnapshotSpan newSelection)
{
var bufferNewSelection = new SnapshotSpan(newSnapshot, newSelection);
var newSelectionsInView = textView.BufferGraph.MapUpToBuffer(bufferNewSelection, SpanTrackingMode.EdgeInclusive, textView.TextBuffer);
if (newSelectionsInView.Count == 1)
{
textView.Selection.Select(newSelectionsInView[0], true);
textView.Caret.MoveTo(textView.Selection.Start);
}
}
}
private static int? GetPositionFromLineColumn(ITextSnapshot snapshot, int line, int column)
{
if ((line >= 0) && (line < snapshot.LineCount))
{
var textLine = snapshot.GetLineFromLineNumber(line);
// Non-strict equality below, because caret can be position *after*
// the last character of the line. So for line of length 1 both
// column 0 and column 1 are valid caret locations.
if (column <= textLine.Length)
{
return textLine.Start + column;
}
}
return null;
}
private static SnapshotSpan? ToSnapshotSpan(Range range, ITextSnapshot snapshot)
{
if (ToSnapshotPoint(range.Start, snapshot) is SnapshotPoint startPoint &&
ToSnapshotPoint(range.End, snapshot) is SnapshotPoint endPoint)
{
return new SnapshotSpan(startPoint, endPoint);
}
return null;
}
private static SnapshotPoint? ToSnapshotPoint(Position position, ITextSnapshot snapshot)
{
if (GetPositionFromLineColumn(snapshot, position.Line, position.Character) is int positionIndex)
{
return new SnapshotPoint(snapshot, positionIndex);
}
return null;
}
}
#nullable disable
internal class WrapWithDivCommandBindings
{
// These values match those in RazorContextMenu.vsct
internal const string GuidRazorGroupString = "a3a603a2-2b17-4ce2-bd21-cbb8ccc084ec";
internal const uint CmdIDWrapWithDiv = 0x101;
// This exports this command handler to handle the menu item defined in the vsct file
[Export]
[CommandBinding(GuidRazorGroupString, CmdIDWrapWithDiv, typeof(WrapWithDivCommandArgs))]
internal CommandBindingDefinition wrapWithDivCommandBinding;
}
// EditorCommandArgs is abstract, so we need to subclass it, but we have no value to add
internal class WrapWithDivCommandArgs : EditorCommandArgs
{
public WrapWithDivCommandArgs(ITextView textView, ITextBuffer subjectBuffer)
: base(textView, subjectBuffer)
{
}
}
}

Просмотреть файл

@ -22,7 +22,7 @@
<ExcludeFromSourceBuild>true</ExcludeFromSourceBuild>
<IsPackable>false</IsPackable>
<GenerateResourceUsePreserializedResources>true</GenerateResourceUsePreserializedResources>
<GenerateResourceUsePreserializedResources Condition="'$(MSBuildRuntimeType)' == 'Core'">true</GenerateResourceUsePreserializedResources>
<SetupProductArch>neutral</SetupProductArch>
<ServiceHubCoreSubPath>ServiceHubCore</ServiceHubCoreSubPath>
@ -42,6 +42,12 @@
</Content>
</ItemGroup>
<ItemGroup>
<VSCTCompile Include="RazorContextMenu.vsct">
<ResourceName>Menus.ctmenu</ResourceName>
</VSCTCompile>
</ItemGroup>
<!-- Misc other content -->
<ItemGroup>
<Content Include="NOTICE.txt">

Просмотреть файл

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8" ?>
<CommandTable xmlns="http://schemas.microsoft.com/VisualStudio/2005-10-18/CommandTable">
<Extern href="stdidcmd.h"/>
<Extern href="vsshlids.h"/>
<Commands package="RazorPackage">
<Buttons>
<Button guid="guidRazorGroup" id="cmdidRazorWrapWithDiv" priority="0x0100" type="Button">
<Parent guid="guidSHLMainMenu" id="IDG_VS_CODEWIN_SNIPPETS" />
<!-- This tells VS we want to control visibility at runtime -->
<CommandFlag>DynamicVisibility</CommandFlag>
<!-- This prevents the menu item showing up where QueryStatus doesn't tell it to -->
<CommandFlag>DefaultInvisible</CommandFlag>
<!-- This prevents the menu item showing up in the main menu -->
<CommandFlag>CommandWellOnly</CommandFlag>
<Strings>
<ButtonText>Wrap With &lt;div&gt;</ButtonText>
</Strings>
</Button>
</Buttons>
</Commands>
<KeyBindings>
<KeyBinding guid="guidRazorGroup" id="cmdidRazorWrapWithDiv" mod1="ALT SHIFT" key1="W" editor="guidVSStd97" />
</KeyBindings>
<Symbols>
<GuidSymbol name="RazorPackage" value="{13b72f58-279e-49e0-a56d-296be02f0805}" />
<GuidSymbol name="guidRazorGroup" value ="{a3a603a2-2b17-4ce2-bd21-cbb8ccc084ec}">
<IDSymbol name="cmdidRazorWrapWithDiv" value="0x0101"/>
</GuidSymbol>
</Symbols>
</CommandTable>

Просмотреть файл

@ -26,6 +26,7 @@ namespace Microsoft.VisualStudio.RazorExtension
[ProvideBrokeredServiceHubService("Microsoft.VisualStudio.Razor.TagHelperProvider64S", Audience = ServiceAudience.Local)]
[ProvideBrokeredServiceHubService("Microsoft.VisualStudio.Razor.TagHelperProviderCore64", ServiceLocation = ProvideBrokeredServiceHubServiceAttribute.DefaultServiceLocation + @"\ServiceHubCore", Audience = ServiceAudience.Local)]
[ProvideBrokeredServiceHubService("Microsoft.VisualStudio.Razor.TagHelperProviderCore64S", ServiceLocation = ProvideBrokeredServiceHubServiceAttribute.DefaultServiceLocation + @"\ServiceHubCore", Audience = ServiceAudience.Local)]
[ProvideMenuResource("Menus.ctmenu", 1)]
[Guid(PackageGuidString)]
public sealed class RazorPackage : AsyncPackage
{

Просмотреть файл

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
<file datatype="xml" source-language="en" target-language="cs" original="../RazorContextMenu.vsct">
<body>
<trans-unit id="cmdidRazorWrapWithDiv|ButtonText">
<source>Wrap With &lt;div&gt;</source>
<target state="new">Wrap With &lt;div&gt;</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
<file datatype="xml" source-language="en" target-language="de" original="../RazorContextMenu.vsct">
<body>
<trans-unit id="cmdidRazorWrapWithDiv|ButtonText">
<source>Wrap With &lt;div&gt;</source>
<target state="new">Wrap With &lt;div&gt;</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
<file datatype="xml" source-language="en" target-language="es" original="../RazorContextMenu.vsct">
<body>
<trans-unit id="cmdidRazorWrapWithDiv|ButtonText">
<source>Wrap With &lt;div&gt;</source>
<target state="new">Wrap With &lt;div&gt;</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
<file datatype="xml" source-language="en" target-language="fr" original="../RazorContextMenu.vsct">
<body>
<trans-unit id="cmdidRazorWrapWithDiv|ButtonText">
<source>Wrap With &lt;div&gt;</source>
<target state="new">Wrap With &lt;div&gt;</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
<file datatype="xml" source-language="en" target-language="it" original="../RazorContextMenu.vsct">
<body>
<trans-unit id="cmdidRazorWrapWithDiv|ButtonText">
<source>Wrap With &lt;div&gt;</source>
<target state="new">Wrap With &lt;div&gt;</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
<file datatype="xml" source-language="en" target-language="ja" original="../RazorContextMenu.vsct">
<body>
<trans-unit id="cmdidRazorWrapWithDiv|ButtonText">
<source>Wrap With &lt;div&gt;</source>
<target state="new">Wrap With &lt;div&gt;</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
<file datatype="xml" source-language="en" target-language="ko" original="../RazorContextMenu.vsct">
<body>
<trans-unit id="cmdidRazorWrapWithDiv|ButtonText">
<source>Wrap With &lt;div&gt;</source>
<target state="new">Wrap With &lt;div&gt;</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
<file datatype="xml" source-language="en" target-language="pl" original="../RazorContextMenu.vsct">
<body>
<trans-unit id="cmdidRazorWrapWithDiv|ButtonText">
<source>Wrap With &lt;div&gt;</source>
<target state="new">Wrap With &lt;div&gt;</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
<file datatype="xml" source-language="en" target-language="pt-BR" original="../RazorContextMenu.vsct">
<body>
<trans-unit id="cmdidRazorWrapWithDiv|ButtonText">
<source>Wrap With &lt;div&gt;</source>
<target state="new">Wrap With &lt;div&gt;</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
<file datatype="xml" source-language="en" target-language="ru" original="../RazorContextMenu.vsct">
<body>
<trans-unit id="cmdidRazorWrapWithDiv|ButtonText">
<source>Wrap With &lt;div&gt;</source>
<target state="new">Wrap With &lt;div&gt;</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
<file datatype="xml" source-language="en" target-language="tr" original="../RazorContextMenu.vsct">
<body>
<trans-unit id="cmdidRazorWrapWithDiv|ButtonText">
<source>Wrap With &lt;div&gt;</source>
<target state="new">Wrap With &lt;div&gt;</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
<file datatype="xml" source-language="en" target-language="zh-Hans" original="../RazorContextMenu.vsct">
<body>
<trans-unit id="cmdidRazorWrapWithDiv|ButtonText">
<source>Wrap With &lt;div&gt;</source>
<target state="new">Wrap With &lt;div&gt;</target>
<note />
</trans-unit>
</body>
</file>
</xliff>

Просмотреть файл

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 xliff-core-1.2-transitional.xsd">
<file datatype="xml" source-language="en" target-language="zh-Hant" original="../RazorContextMenu.vsct">
<body>
<trans-unit id="cmdidRazorWrapWithDiv|ButtonText">
<source>Wrap With &lt;div&gt;</source>
<target state="new">Wrap With &lt;div&gt;</target>
<note />
</trans-unit>
</body>
</file>
</xliff>