1
+ // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
2
+ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3
+
4
+ using System ;
5
+ using System . Collections . Generic ;
6
+ using System . Linq ;
7
+ using Microsoft . AspNet . Mvc . Rendering ;
8
+ using Microsoft . AspNet . Razor . Runtime . TagHelpers ;
9
+
10
+ namespace Microsoft . AspNet . Mvc . TagHelpers
11
+ {
12
+ /// <summary>
13
+ /// Utility related extensions for <see cref="TagHelperOutput"/>.
14
+ /// </summary>
15
+ public static class TagHelperOutputExtensions
16
+ {
17
+ /// <summary>
18
+ /// Copies a user-provided attribute from <paramref name="context"/>'s
19
+ /// <see cref="TagHelperContext.AllAttributes"/> to <paramref name="tagHelperOutput"/>'s
20
+ /// <see cref="TagHelperOutput.Attributes"/>.
21
+ /// </summary>
22
+ /// <param name="tagHelperOutput">The <see cref="TagHelperOutput"/> this method extends.</param>
23
+ /// <param name="attributeName">The name of the bound attribute.</param>
24
+ /// <param name="context">The <see cref="TagHelperContext"/>.</param>
25
+ /// <remarks>Only copies the attribute if <paramref name="tagHelperOutput"/>'s
26
+ /// <see cref="TagHelperOutput.Attributes"/> does not contain an attribute with the given
27
+ /// <paramref name="attributeName"/></remarks>
28
+ public static void CopyHtmlAttribute ( this TagHelperOutput tagHelperOutput ,
29
+ string attributeName ,
30
+ TagHelperContext context )
31
+ {
32
+ // We look for the original attribute so we can restore the exact attribute name the user typed.
33
+ var entry = context . AllAttributes . First ( attribute =>
34
+ attribute . Key . Equals ( attributeName , StringComparison . OrdinalIgnoreCase ) ) ;
35
+
36
+ if ( ! tagHelperOutput . Attributes . ContainsKey ( entry . Key ) )
37
+ {
38
+ tagHelperOutput . Attributes . Add ( entry . Key , entry . Value . ToString ( ) ) ;
39
+ }
40
+ }
41
+
42
+ /// <summary>
43
+ /// Returns all attributes from <paramref name="tagHelperOutput"/>'s
44
+ /// <see cref="TagHelperOutput.Attributes"/> that have the given <paramref name="prefix"/>.
45
+ /// </summary>
46
+ /// <param name="tagHelperOutput">The <see cref="TagHelperOutput"/> this method extends.</param>
47
+ /// <param name="prefix">A prefix to look for.</param>
48
+ /// <returns><see cref="KeyValuePair{string, string}"/>s with <see cref="KeyValuePair{string, string}.Key"/>
49
+ /// starting with the given <paramref name="prefix"/>.</returns>
50
+ public static IEnumerable < KeyValuePair < string , string > > FindPrefixedAttributes (
51
+ this TagHelperOutput tagHelperOutput , string prefix )
52
+ {
53
+ // TODO: We will not need this method once https://github.com/aspnet/Razor/issues/89 is completed.
54
+
55
+ // We're only interested in HTML attributes that have the desired prefix.
56
+ var prefixedAttributes = tagHelperOutput . Attributes
57
+ . Where ( attribute => attribute . Key . StartsWith ( prefix , StringComparison . OrdinalIgnoreCase ) )
58
+ . ToArray ( ) ;
59
+
60
+ return prefixedAttributes ;
61
+ }
62
+
63
+ /// <summary>
64
+ /// Merges the given <paramref name="tagBuilder"/> into the <paramref name="tagHelperOutput"/>.
65
+ /// </summary>
66
+ /// <param name="tagHelperOutput">The <see cref="TagHelperOutput"/> this method extends.</param>
67
+ /// <param name="tagBuilder">The <see cref="TagBuilder"/> to merge.</param>
68
+ /// <remarks><paramref name="tagHelperOutput"/>'s <see cref="TagHelperOutput.Content"/> has the given
69
+ /// <paramref name="tagBuilder"/>s <see cref="TagBuilder.InnerHtml"/> appended to it. This is to ensure
70
+ /// multiple <see cref="ITagHelper"/>s running on the same HTML tag don't overwrite each other; therefore,
71
+ /// this method may not be appropriate for all <see cref="ITagHelper"/> scenarios.</remarks>
72
+ public static void Merge ( this TagHelperOutput tagHelperOutput , TagBuilder tagBuilder )
73
+ {
74
+ tagHelperOutput . TagName = tagBuilder . TagName ;
75
+ tagHelperOutput . Content += tagBuilder . InnerHtml ;
76
+
77
+ MergeAttributes ( tagHelperOutput , tagBuilder ) ;
78
+ }
79
+
80
+ /// <summary>
81
+ /// Merges the given <see cref="tagBuilder"/>'s <see cref="TagBuilder.Attributes"/> into the
82
+ /// <paramref name="tagHelperOutput"/>.
83
+ /// </summary>
84
+ /// <param name="tagHelperOutput">The <see cref="TagHelperOutput"/> this method extends.</param>
85
+ /// <param name="tagBuilder">The <see cref="TagBuilder"/> to merge attributes from.</param>
86
+ /// <remarks>Existing <see cref="TagHelperOutput.Attributes"/> on the given <paramref name="tagHelperOutput"/>
87
+ /// are not overriden; "class" attributes are merged with spaces.</remarks>
88
+ public static void MergeAttributes ( this TagHelperOutput tagHelperOutput , TagBuilder tagBuilder )
89
+ {
90
+ foreach ( var attribute in tagBuilder . Attributes )
91
+ {
92
+ if ( ! tagHelperOutput . Attributes . ContainsKey ( attribute . Key ) )
93
+ {
94
+ tagHelperOutput . Attributes . Add ( attribute . Key , attribute . Value ) ;
95
+ }
96
+ else if ( attribute . Key . Equals ( "class" , StringComparison . Ordinal ) )
97
+ {
98
+ tagHelperOutput . Attributes [ "class" ] += " " + attribute . Value ;
99
+ }
100
+ }
101
+ }
102
+
103
+ /// <summary>
104
+ /// Removes the given <paramref name="attributes"/> from <paramref name="tagHelperOutput"/>'s
105
+ /// <see cref="TagHelperOutput.Attributes"/>.
106
+ /// </summary>
107
+ /// <param name="tagHelperOutput">The <see cref="TagHelperOutput"/> this method extends.</param>
108
+ /// <param name="attributes">Attributes to remove.</param>
109
+ public static void RemoveRange (
110
+ this TagHelperOutput tagHelperOutput , IEnumerable < KeyValuePair < string , string > > attributes )
111
+ {
112
+ foreach ( var attribute in attributes )
113
+ {
114
+ tagHelperOutput . Attributes . Remove ( attribute ) ;
115
+ }
116
+ }
117
+ }
118
+ }
0 commit comments