diff --git a/Cargo.lock b/Cargo.lock index ce631a9fc247f..40f5ac28e3038 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10756,6 +10756,7 @@ name = "turbopack-mdx" version = "0.1.0" dependencies = [ "anyhow", + "markdown", "mdxjs", "serde", "turbo-tasks", diff --git a/Cargo.toml b/Cargo.toml index aa56bd46165e5..740cae8e439bb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -110,6 +110,7 @@ async-recursion = "1.0.2" # Keep consistent with preset_env_base through swc_core browserslist-rs = { version = "0.16.0" } miette = { version = "5.10.0", features = ["fancy"] } +markdown = "1.0.0-alpha.18" mdxjs = "0.2.5" modularize_imports = { version = "0.68.7" } styled_components = { version = "0.96.6" } diff --git a/crates/turbopack-core/src/issue/mod.rs b/crates/turbopack-core/src/issue/mod.rs index 30e6123eac468..78ac64b7dea67 100644 --- a/crates/turbopack-core/src/issue/mod.rs +++ b/crates/turbopack-core/src/issue/mod.rs @@ -431,6 +431,7 @@ pub struct IssueSource { range: Option>, } +/// The end position is the first character after the range #[turbo_tasks::value] #[derive(Clone, Debug)] enum SourceRange { diff --git a/crates/turbopack-mdx/Cargo.toml b/crates/turbopack-mdx/Cargo.toml index a3a0ad300823d..0805d28277171 100644 --- a/crates/turbopack-mdx/Cargo.toml +++ b/crates/turbopack-mdx/Cargo.toml @@ -16,6 +16,7 @@ workspace = true anyhow = { workspace = true } serde = { workspace = true } +markdown = { workspace = true } mdxjs = { workspace = true } turbo-tasks = { workspace = true } diff --git a/crates/turbopack-mdx/src/lib.rs b/crates/turbopack-mdx/src/lib.rs index a60d691efe8ba..041a47e1e04ca 100644 --- a/crates/turbopack-mdx/src/lib.rs +++ b/crates/turbopack-mdx/src/lib.rs @@ -1,15 +1,19 @@ #![feature(min_specialization)] #![feature(arbitrary_self_types)] -use anyhow::{anyhow, Result}; +use anyhow::Result; use mdxjs::{compile, MdxParseOptions, Options}; use turbo_tasks::{RcStr, ValueDefault, Vc}; -use turbo_tasks_fs::{rope::Rope, File, FileContent}; +use turbo_tasks_fs::{rope::Rope, File, FileContent, FileSystemPath}; use turbopack_core::{ asset::{Asset, AssetContent}, ident::AssetIdent, - issue::IssueDescriptionExt, + issue::{ + Issue, IssueDescriptionExt, IssueExt, IssueSource, IssueStage, OptionIssueSource, + OptionStyledString, StyledString, + }, source::Source, + source_pos::SourcePos, source_transform::SourceTransform, }; @@ -175,14 +179,56 @@ impl MdxTransformedAsset { ..Default::default() }; - // TODO: upstream mdx currently bubbles error as string - let mdx_jsx_component = - compile(&file.content().to_str()?, &options).map_err(|e| anyhow!("{}", e))?; + let result = compile(&file.content().to_str()?, &options); - Ok(MdxTransformResult { - content: AssetContent::file(File::from(Rope::from(mdx_jsx_component)).into()), + match result { + Ok(mdx_jsx_component) => Ok(MdxTransformResult { + content: AssetContent::file(File::from(Rope::from(mdx_jsx_component)).into()), + } + .cell()), + Err(err) => { + let loc = Vc::cell(err.place.map(|p| { + let (start, end) = match *p { + // markdown's positions are 1-indexed, SourcePos is 0-indexed. + // Both end positions point to the first character after the range + markdown::message::Place::Position(p) => ( + SourcePos { + line: p.start.line - 1, + column: p.start.column - 1, + }, + SourcePos { + line: p.end.line - 1, + column: p.end.column - 1, + }, + ), + markdown::message::Place::Point(p) => { + let p = SourcePos { + line: p.line - 1, + column: p.column - 1, + }; + (p, p) + } + }; + + IssueSource::from_line_col(this.source, start, end) + })); + + MdxIssue { + path: this.source.ident().path(), + loc, + reason: err.reason, + mdx_rule_id: *err.rule_id, + mdx_source: *err.source, + } + .cell() + .emit(); + + Ok(MdxTransformResult { + content: AssetContent::File(FileContent::NotFound.cell()).cell(), + } + .cell()) + } } - .cell()) } } @@ -191,6 +237,47 @@ struct MdxTransformResult { content: Vc, } +#[turbo_tasks::value] +struct MdxIssue { + /// Place of message. + path: Vc, + loc: Vc, + /// Reason for message (should use markdown). + reason: String, + /// Category of message. + mdx_rule_id: String, + /// Namespace of message. + mdx_source: String, +} + +#[turbo_tasks::value_impl] +impl Issue for MdxIssue { + #[turbo_tasks::function] + fn file_path(&self) -> Vc { + self.path + } + + #[turbo_tasks::function] + fn source(&self) -> Vc { + self.loc + } + + #[turbo_tasks::function] + fn stage(self: Vc) -> Vc { + IssueStage::Parse.cell() + } + + #[turbo_tasks::function] + fn title(self: Vc) -> Vc { + StyledString::Text("MDX Parse Error".into()).cell() + } + + #[turbo_tasks::function] + fn description(&self) -> Vc { + Vc::cell(Some(StyledString::Text(self.reason.clone().into()).cell())) + } +} + pub fn register() { turbo_tasks::register(); turbo_tasks_fs::register();