@@ -8,18 +8,32 @@ import {
88// Simplify a mime type as much as we can, without throwing any errors
99export const getBaseContentType = ( mimeType : string | undefined ) => {
1010 const typeWithoutParams = ( mimeType || '' ) . split ( ';' ) [ 0 ] ;
11- const [ type , combinedSubTypes ] = typeWithoutParams . split ( / \/ ( .+ ) / ) ;
1211
12+ let [ type , combinedSubTypes ] = typeWithoutParams . split ( / \/ ( .+ ) / ) ;
1313 if ( ! combinedSubTypes ) return type ;
1414
15- // A list of types from most specific to most generic: [svg, xml] for image/svg+xml
16- const subTypes = combinedSubTypes . split ( '+' ) ;
15+ if ( DEFAULT_SUBTYPE [ combinedSubTypes ] ) {
16+ combinedSubTypes = `${ combinedSubTypes } +${ DEFAULT_SUBTYPE [ combinedSubTypes ] } ` ;
17+ }
18+
19+ // If this is a known type with an exact match, return that directly:
20+ if ( mimeTypeToContentTypeMap [ type + '/' + combinedSubTypes ] ) {
21+ return type + '/' + combinedSubTypes ;
22+ }
1723
24+ // Otherwise, wr collect a list of types from most specific to most generic: [svg, xml] for image/svg+xml
25+ // and then look through in order to see if there are any matches here:
26+ const subTypes = combinedSubTypes . split ( '+' ) ;
1827 const possibleTypes = subTypes . map ( st => type + '/' + st ) ;
19- return _ . find ( possibleTypes , t => ! ! mimeTypeToContentTypeMap [ t ] ) ||
28+
29+ return _ . find ( possibleTypes , t => ! ! mimeTypeToContentTypeMap [ t ] ) || // Subtype match
2030 _ . last ( possibleTypes ) ! ; // If we recognize none - return the most generic
2131}
2232
33+ const DEFAULT_SUBTYPE : { [ type : string ] : string } = {
34+ 'grpc' : 'proto' // Protobuf is the default gRPC content type (but not the only one!)
35+ } ;
36+
2337export type ViewableContentType =
2438 | 'raw'
2539 | 'text'
@@ -34,7 +48,7 @@ export type ViewableContentType =
3448 | 'yaml'
3549 | 'image'
3650 | 'protobuf'
37- | 'grpc' ;
51+ | 'grpc-proto ' ;
3852
3953export const EditableContentTypes = [
4054 'text' ,
@@ -97,7 +111,7 @@ const mimeTypeToContentTypeMap: { [mimeType: string]: ViewableContentType } = {
97111 'application/proto' : 'protobuf' , // N.b. this covers all application/XXX+proto values
98112 'application/x-protobuffer' : 'protobuf' , // Commonly seen in Google apps
99113
100- 'application/grpc' : 'grpc' , // Used in GRPC requests (protobuf with special headers)
114+ 'application/grpc+proto ' : 'grpc-proto ' , // Used in GRPC requests (protobuf but with special headers)
101115
102116 'application/octet-stream' : 'raw'
103117} as const ;
@@ -124,7 +138,7 @@ export function getContentEditorName(contentType: ViewableContentType): string {
124138 : contentType === 'json' ? 'JSON'
125139 : contentType === 'css' ? 'CSS'
126140 : contentType === 'url-encoded' ? 'URL-Encoded'
127- : contentType === 'grpc' ? 'gRPC'
141+ : contentType === 'grpc-proto ' ? 'gRPC'
128142 : _ . capitalize ( contentType ) ;
129143}
130144
@@ -166,14 +180,15 @@ export function getCompatibleTypes(
166180 types . add ( 'xml' ) ;
167181 }
168182
169- if ( ! types . has ( 'grpc' ) && rawContentType && rawContentType === 'application/grpc' ) {
170- types . add ( 'grpc' )
183+ if ( ! types . has ( 'grpc-proto' ) && rawContentType === 'application/grpc' ) {
184+ types . add ( 'grpc-proto ' )
171185 }
186+
172187 if (
173188 body &&
174189 isProbablyProtobuf ( body ) &&
175190 ! types . has ( 'protobuf' ) &&
176- ! types . has ( 'grpc' ) &&
191+ ! types . has ( 'grpc-proto ' ) &&
177192 // If it's probably unmarked protobuf, and it's a manageable size, try
178193 // parsing it just to check:
179194 ( body . length < 100_000 && isValidProtobuf ( body ) )
0 commit comments