diff --git a/cli/file_fetcher.rs b/cli/file_fetcher.rs index e865bf9450..29fe04d8a7 100644 --- a/cli/file_fetcher.rs +++ b/cli/file_fetcher.rs @@ -505,12 +505,16 @@ fn map_content_type(path: &Path, content_type: Option<&str>) -> msg::MediaType { | "text/typescript" | "video/vnd.dlna.mpeg-tts" | "video/mp2t" - | "application/x-typescript" => msg::MediaType::TypeScript, + | "application/x-typescript" => { + map_js_like_extension(path, msg::MediaType::TypeScript) + } "application/javascript" | "text/javascript" | "application/ecmascript" | "text/ecmascript" - | "application/x-javascript" => msg::MediaType::JavaScript, + | "application/x-javascript" => { + map_js_like_extension(path, msg::MediaType::JavaScript) + } "application/json" | "text/json" => msg::MediaType::Json, "text/plain" => map_file_extension(path), _ => { @@ -523,6 +527,21 @@ fn map_content_type(path: &Path, content_type: Option<&str>) -> msg::MediaType { } } +fn map_js_like_extension( + path: &Path, + default: msg::MediaType, +) -> msg::MediaType { + match path.extension() { + None => default, + Some(os_str) => match os_str.to_str() { + None => default, + Some("jsx") => msg::MediaType::JSX, + Some("tsx") => msg::MediaType::TSX, + Some(_) => default, + }, + } +} + fn filter_shebang(bytes: Vec) -> Vec { let string = str::from_utf8(&bytes).unwrap(); if let Some(i) = string.find('\n') { @@ -1410,7 +1429,7 @@ mod tests { } #[test] - fn test_map_content_type() { + fn test_map_content_type_extension_only() { // Extension only assert_eq!( map_content_type(Path::new("foo/bar.ts"), None), @@ -1428,6 +1447,10 @@ mod tests { map_content_type(Path::new("foo/bar.js"), None), msg::MediaType::JavaScript ); + assert_eq!( + map_content_type(Path::new("foo/bar.txt"), None), + msg::MediaType::Unknown + ); assert_eq!( map_content_type(Path::new("foo/bar.jsx"), None), msg::MediaType::JSX @@ -1436,15 +1459,14 @@ mod tests { map_content_type(Path::new("foo/bar.json"), None), msg::MediaType::Json ); - assert_eq!( - map_content_type(Path::new("foo/bar.txt"), None), - msg::MediaType::Unknown - ); assert_eq!( map_content_type(Path::new("foo/bar"), None), msg::MediaType::Unknown ); + } + #[test] + fn test_map_content_type_media_type_with_no_extension() { // Media Type assert_eq!( map_content_type(Path::new("foo/bar"), Some("application/typescript")), @@ -1494,6 +1516,10 @@ mod tests { map_content_type(Path::new("foo/bar"), Some("text/json")), msg::MediaType::Json ); + } + + #[test] + fn test_map_file_extension_media_type_with_extension() { assert_eq!( map_content_type(Path::new("foo/bar.ts"), Some("text/plain")), msg::MediaType::TypeScript @@ -1502,6 +1528,70 @@ mod tests { map_content_type(Path::new("foo/bar.ts"), Some("foo/bar")), msg::MediaType::Unknown ); + assert_eq!( + map_content_type( + Path::new("foo/bar.tsx"), + Some("application/typescript") + ), + msg::MediaType::TSX + ); + assert_eq!( + map_content_type( + Path::new("foo/bar.tsx"), + Some("application/javascript") + ), + msg::MediaType::TSX + ); + assert_eq!( + map_content_type( + Path::new("foo/bar.tsx"), + Some("application/x-typescript") + ), + msg::MediaType::TSX + ); + assert_eq!( + map_content_type( + Path::new("foo/bar.tsx"), + Some("video/vnd.dlna.mpeg-tts") + ), + msg::MediaType::TSX + ); + assert_eq!( + map_content_type(Path::new("foo/bar.tsx"), Some("video/mp2t")), + msg::MediaType::TSX + ); + assert_eq!( + map_content_type( + Path::new("foo/bar.jsx"), + Some("application/javascript") + ), + msg::MediaType::JSX + ); + assert_eq!( + map_content_type( + Path::new("foo/bar.jsx"), + Some("application/x-typescript") + ), + msg::MediaType::JSX + ); + assert_eq!( + map_content_type( + Path::new("foo/bar.jsx"), + Some("application/ecmascript") + ), + msg::MediaType::JSX + ); + assert_eq!( + map_content_type(Path::new("foo/bar.jsx"), Some("text/ecmascript")), + msg::MediaType::JSX + ); + assert_eq!( + map_content_type( + Path::new("foo/bar.jsx"), + Some("application/x-javascript") + ), + msg::MediaType::JSX + ); } #[test] diff --git a/cli/tests/048_media_types_jsx.ts b/cli/tests/048_media_types_jsx.ts new file mode 100644 index 0000000000..c2340de35b --- /dev/null +++ b/cli/tests/048_media_types_jsx.ts @@ -0,0 +1,23 @@ +// When run against the test HTTP server, it will serve different media types +// based on the URL containing `.t#.` strings, which exercises the different +// mapping of media types end to end. +import { loaded as loadedTsx1 } from "http://localhost:4545/cli/tests/subdir/mt_text_typescript_tsx.t1.tsx"; +import { loaded as loadedTsx2 } from "http://localhost:4545/cli/tests/subdir/mt_video_vdn_tsx.t2.tsx"; +import { loaded as loadedTsx3 } from "http://localhost:4545/cli/tests/subdir/mt_video_mp2t_tsx.t3.tsx"; +import { loaded as loadedTsx4 } from "http://localhost:4545/cli/tests/subdir/mt_application_x_typescript_tsx.t4.tsx"; +import { loaded as loadedJsx1 } from "http://localhost:4545/cli/tests/subdir/mt_text_javascript_jsx.j1.jsx"; +import { loaded as loadedJsx2 } from "http://localhost:4545/cli/tests/subdir/mt_application_ecmascript_jsx.j2.jsx"; +import { loaded as loadedJsx3 } from "http://localhost:4545/cli/tests/subdir/mt_text_ecmascript_jsx.j3.jsx"; +import { loaded as loadedJsx4 } from "http://localhost:4545/cli/tests/subdir/mt_application_x_javascript_jsx.j4.jsx"; + +console.log( + "success", + loadedTsx1, + loadedTsx2, + loadedTsx3, + loadedTsx4, + loadedJsx1, + loadedJsx2, + loadedJsx3, + loadedJsx4 +); diff --git a/cli/tests/048_media_types_jsx.ts.out b/cli/tests/048_media_types_jsx.ts.out new file mode 100644 index 0000000000..7b5fdd44fa --- /dev/null +++ b/cli/tests/048_media_types_jsx.ts.out @@ -0,0 +1 @@ +success true true true true true true true true diff --git a/cli/tests/049_info_flag_script_jsx.out b/cli/tests/049_info_flag_script_jsx.out new file mode 100644 index 0000000000..48f5efa9e1 --- /dev/null +++ b/cli/tests/049_info_flag_script_jsx.out @@ -0,0 +1,14 @@ +local: [WILDCARD]048_media_types_jsx.ts +type: TypeScript +compiled: [WILDCARD]048_media_types_jsx.ts.js +map: [WILDCARD]048_media_types_jsx.ts.js.map +deps: +http://127.0.0.1:4545/cli/tests/048_media_types_jsx.ts + ├── http://localhost:4545/cli/tests/subdir/mt_text_typescript_tsx.t1.tsx + ├── http://localhost:4545/cli/tests/subdir/mt_video_vdn_tsx.t2.tsx + ├── http://localhost:4545/cli/tests/subdir/mt_video_mp2t_tsx.t3.tsx + ├── http://localhost:4545/cli/tests/subdir/mt_application_x_typescript_tsx.t4.tsx + ├── http://localhost:4545/cli/tests/subdir/mt_text_javascript_jsx.j1.jsx + ├── http://localhost:4545/cli/tests/subdir/mt_application_ecmascript_jsx.j2.jsx + ├── http://localhost:4545/cli/tests/subdir/mt_text_ecmascript_jsx.j3.jsx + └── http://localhost:4545/cli/tests/subdir/mt_application_x_javascript_jsx.j4.jsx diff --git a/cli/tests/integration_tests.rs b/cli/tests/integration_tests.rs index 4271036d1f..fcf641dc02 100644 --- a/cli/tests/integration_tests.rs +++ b/cli/tests/integration_tests.rs @@ -326,6 +326,18 @@ itest!(_047_jsx { output: "047_jsx_test.jsx.out", }); +itest!(_048_media_types_jsx { + args: "run --reload 048_media_types_jsx.ts", + output: "048_media_types_jsx.ts.out", + http_server: true, +}); + +itest!(_049_info_flag_script_jsx { + args: "info http://127.0.0.1:4545/cli/tests/048_media_types_jsx.ts", + output: "049_info_flag_script_jsx.out", + http_server: true, +}); + itest!(async_error { exit_code: 1, args: "run --reload async_error.ts", diff --git a/cli/tests/subdir/mt_application_ecmascript_jsx.j2.jsx b/cli/tests/subdir/mt_application_ecmascript_jsx.j2.jsx new file mode 100644 index 0000000000..2c7a154916 --- /dev/null +++ b/cli/tests/subdir/mt_application_ecmascript_jsx.j2.jsx @@ -0,0 +1,5 @@ +const React = { + createElement() {} +} +const temp =
; +export const loaded = true; diff --git a/cli/tests/subdir/mt_application_x_javascript_jsx.j4.jsx b/cli/tests/subdir/mt_application_x_javascript_jsx.j4.jsx new file mode 100644 index 0000000000..2c7a154916 --- /dev/null +++ b/cli/tests/subdir/mt_application_x_javascript_jsx.j4.jsx @@ -0,0 +1,5 @@ +const React = { + createElement() {} +} +const temp =
; +export const loaded = true; diff --git a/cli/tests/subdir/mt_application_x_typescript_tsx.t4.tsx b/cli/tests/subdir/mt_application_x_typescript_tsx.t4.tsx new file mode 100644 index 0000000000..2c7a154916 --- /dev/null +++ b/cli/tests/subdir/mt_application_x_typescript_tsx.t4.tsx @@ -0,0 +1,5 @@ +const React = { + createElement() {} +} +const temp =
; +export const loaded = true; diff --git a/cli/tests/subdir/mt_javascript_jsx.jsx b/cli/tests/subdir/mt_javascript_jsx.jsx new file mode 100644 index 0000000000..2c7a154916 --- /dev/null +++ b/cli/tests/subdir/mt_javascript_jsx.jsx @@ -0,0 +1,5 @@ +const React = { + createElement() {} +} +const temp =
; +export const loaded = true; diff --git a/cli/tests/subdir/mt_text_ecmascript_jsx.j3.jsx b/cli/tests/subdir/mt_text_ecmascript_jsx.j3.jsx new file mode 100644 index 0000000000..2c7a154916 --- /dev/null +++ b/cli/tests/subdir/mt_text_ecmascript_jsx.j3.jsx @@ -0,0 +1,5 @@ +const React = { + createElement() {} +} +const temp =
; +export const loaded = true; diff --git a/cli/tests/subdir/mt_text_javascript_jsx.j1.jsx b/cli/tests/subdir/mt_text_javascript_jsx.j1.jsx new file mode 100644 index 0000000000..2c7a154916 --- /dev/null +++ b/cli/tests/subdir/mt_text_javascript_jsx.j1.jsx @@ -0,0 +1,5 @@ +const React = { + createElement() {} +} +const temp =
; +export const loaded = true; diff --git a/cli/tests/subdir/mt_text_typescript_tsx.t1.tsx b/cli/tests/subdir/mt_text_typescript_tsx.t1.tsx new file mode 100644 index 0000000000..2c7a154916 --- /dev/null +++ b/cli/tests/subdir/mt_text_typescript_tsx.t1.tsx @@ -0,0 +1,5 @@ +const React = { + createElement() {} +} +const temp =
; +export const loaded = true; diff --git a/cli/tests/subdir/mt_video_mp2t_tsx.t3.tsx b/cli/tests/subdir/mt_video_mp2t_tsx.t3.tsx new file mode 100644 index 0000000000..2c7a154916 --- /dev/null +++ b/cli/tests/subdir/mt_video_mp2t_tsx.t3.tsx @@ -0,0 +1,5 @@ +const React = { + createElement() {} +} +const temp =
; +export const loaded = true; diff --git a/cli/tests/subdir/mt_video_vdn_tsx.t2.tsx b/cli/tests/subdir/mt_video_vdn_tsx.t2.tsx new file mode 100644 index 0000000000..2c7a154916 --- /dev/null +++ b/cli/tests/subdir/mt_video_vdn_tsx.t2.tsx @@ -0,0 +1,5 @@ +const React = { + createElement() {} +} +const temp =
; +export const loaded = true; diff --git a/tools/http_server.py b/tools/http_server.py index 1951c9e531..0a8212b82e 100755 --- a/tools/http_server.py +++ b/tools/http_server.py @@ -111,6 +111,8 @@ def server(): Handler.extensions_map.update({ ".ts": "application/typescript", ".js": "application/javascript", + ".tsx": "application/typescript", + ".jsx": "application/javascript", ".json": "application/json", }) SocketServer.TCPServer.allow_reuse_address = True