1use serde::Serialize;
9
10mod plugin_api;
11mod plugins;
12
13pub use plugin_api::*;
14pub use plugins::{built_in_omena_plugins, execute_built_in_omena_plugin};
15
16pub use omena_bundler::{
17 EmissionOrderingPolicyV0, LinkedEmissionArtifactV0, LinkedEmissionMaterializationErrorV0,
18 LinkedStylesheetV0, TransformBundleAssetUrlRewriteSummaryV0, TransformBundleEdgeKind,
19 TransformBundleLinkErrorV0, TransformBundleLinkOptionsV0, TransformBundleModuleInputV0,
20 TransformBundleSemanticReachabilityInputV0, TransformBundleSourceSummaryV0,
21 TransformBundleTransformedModuleV0, link_omena_transform_bundle_modules,
22 link_omena_transform_bundle_modules_with_options,
23 link_omena_transform_bundle_modules_with_semantic_reachability,
24 link_omena_transform_bundle_modules_with_semantic_reachability_and_metadata,
25 materialize_omena_transform_bundle_linked_stylesheet,
26 rewrite_omena_transform_bundle_asset_urls_in_source,
27 summarize_omena_transform_bundle_from_source,
28};
29pub use omena_transform_cst::{
30 MinifyPassClassificationV0, MinifyPassProfileClassV0,
31 NATIVE_CSS_STATIC_EVAL_DIALECT_RESTRICTION_V0, NATIVE_CSS_STATIC_EVAL_OPT_IN_POLICY_V0,
32 NATIVE_CSS_STATIC_EVAL_SPEC_SNAPSHOT_V0, STRICT_VERIFICATION_BUILD_PROFILE_ID_V0,
33 TRANSFORM_PASS_CATALOG_LEN, TransformBuildProfileV0, TransformPassKind,
34 TransformStrictPolicyDescriptorV0, all_transform_pass_kinds, closed_world_minify_build_profile,
35 default_minify_build_profiles, default_minify_pass_classifications, safe_minify_build_profile,
36 semantic_minify_build_profile, strict_policy_descriptor_for_profile,
37 strict_verification_build_profile, transform_pass_requires_closed_world_bundle,
38 transform_pass_sort_ordinal, with_transform_pass_sort_ordinal_overrides_for_test,
39};
40pub use omena_transform_egg::{
41 EggRewriteSourceWitnessV0, TransformEggPlanV0, execute_egg_rewrite_witnesses_for_css_source,
42 plan_egg_rewrite_passes_for_source,
43};
44pub use omena_transform_passes::{
45 CustomPropertyLeastFixedPointSummaryV0, ExternalCssSemanticChangeClassificationV0,
46 ExternalCssSemanticChangeKindV0, ExternalCssSemanticChangeV0, ExternalCssSemanticDiffV0,
47 ExternalCssSemanticEntryV0, RollbackReceiptV0, RollbackScopeV0,
48 TransformCascadeEnvironmentDeclarationV0, TransformCascadeEnvironmentV0,
49 TransformClassNameRewriteV0, TransformCssModuleComposesResolutionV0,
50 TransformCssModuleValueResolutionV0, TransformDecision, TransformDesignTokenRouteV0,
51 TransformExecutionContextV0, TransformExecutionPolicyV0, TransformExecutionSummaryV0,
52 TransformImportInlineV0, TransformLessInlineLiteralPlaceholderV0,
53 TransformModuleEvaluationNativeEditV0, TransformModuleEvaluationNativeReplacementV0,
54 TransformModuleEvaluationOracleV0, TransformModuleEvaluationV0,
55 TransformModuleQualifiedExecutionErrorV0, TransformModuleQualifiedShakeSummaryV0,
56 TransformPassExecutionOutcomeV0, TransformPassPlanV0, TransformSemanticGuaranteeTierV0,
57 TransformSemanticPreservationDecisionV0, TransformStrictPolicyEventV0,
58 TransformStrictPolicyReasonV0, TransformStrictPolicySummaryV0, TransformVendorPrefixPolicyV0,
59 TransformWinnerEqualityAbsenceReasonV0, TransformWinnerEqualityAbsenceV0,
60 TransformWinnerEqualityAxisV0, classify_transform_reachability_precision,
61 compare_external_css_semantic_changes_v0, compare_transform_css_semantics_v0,
62 execute_transform_passes_on_module_with_dialect_context_and_closed_world_bundle,
63 execute_transform_passes_on_source_with_dialect_and_context,
64 execute_transform_passes_on_source_with_dialect_context_and_closed_world_bundle,
65 execute_transform_passes_on_source_with_dialect_context_and_policy,
66 execute_transform_passes_on_source_with_dialect_context_closed_world_bundle_and_precision,
67 execute_transform_passes_on_source_with_dialect_context_closed_world_bundle_precision_and_policy,
68 expand_css_nested_selector, external_css_semantic_diff_is_total_v0, inline_css_imports,
69 inline_css_imports_for_static_module_evaluation, parse_static_css_cascade_value,
70 plan_transform_passes, reduce_static_numeric_expression,
71 resolve_static_css_modules_local_value_resolutions_from_source,
72 restore_less_inline_literal_placeholders,
73 summarize_static_css_custom_property_fixed_point_from_source,
74};
75#[cfg(feature = "lawvere-trace")]
76pub use omena_transform_passes::{
77 LawvereDifferentialCommutativityWitnessV0, LawvereModelTraceV0, ReorderabilityCertificateV0,
78 TransformPassParallelPlanV0, evaluate_lawvere_reorderability_with_differential_corpus,
79 execute_transform_passes_on_source_with_lawvere_trace_and_dialect,
80 plan_transform_passes_parallel_lawvere_layers,
81};
82pub use omena_transform_print::{
83 PrettyFormatOptionsV0, StyleDialect, TransformPrintArtifactV0, TransformPrintMode,
84 TransformPrintOptionsV0, TransformSourceMapCompositionV0, TransformSourceMapPointV0,
85 TransformSourceMapSegmentV0, TransformSourceMapV3V0,
86 compose_transform_source_map_v3_with_upstream_map, default_print_options,
87 print_transform_cst_source_with_dialect_and_pretty_options,
88 print_transform_execution_artifact_with_dialect_and_source, serialize_transform_source_map_v3,
89 serialize_transform_source_map_v3_with_source_contents, transform_source_map_point,
90};
91pub use omena_transform_target::{
92 TargetFeatureSupportV0, TargetTransformOptionsV0, TransformTargetPlanV0,
93 TransformTargetQueryPlanV0, conservative_target_options, modern_feature_support,
94 plan_target_transforms, plan_target_transforms_from_query,
95};
96
97pub const OMENA_QUERY_TRANSFORM_RUNNER_COLLAPSED_CRATES_V0: [&str; 6] = [
98 "omena-bundler",
99 "omena-transform-cst",
100 "omena-transform-egg",
101 "omena-transform-passes",
102 "omena-transform-print",
103 "omena-transform-target",
104];
105
106pub fn materialize_transform_module_evaluation_native_edits(
107 input_css: &str,
108 native_edits: &[TransformModuleEvaluationNativeEditV0],
109) -> Option<String> {
110 if native_edits.is_empty() {
111 return None;
112 }
113
114 let mut edits = native_edits.to_vec();
115 edits.sort_by_key(|edit| edit.start);
116
117 let mut previous_end = 0usize;
118 for edit in &edits {
119 if edit.start < previous_end
120 || edit.start > edit.end
121 || edit.end > input_css.len()
122 || !input_css.is_char_boundary(edit.start)
123 || !input_css.is_char_boundary(edit.end)
124 {
125 return None;
126 }
127 previous_end = edit.end;
128 }
129
130 let mut output = input_css.to_string();
131 for edit in edits.iter().rev() {
132 output.replace_range(edit.start..edit.end, edit.replacement.as_str());
133 }
134 Some(output)
135}
136
137#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
138#[serde(rename_all = "camelCase")]
139pub struct OmenaQueryTransformRunnerBoundaryV0 {
140 pub schema_version: &'static str,
141 pub product: &'static str,
142 pub boundary_kind: &'static str,
143 pub collapsed_transform_crate_count: usize,
144 pub collapsed_transform_crates: Vec<&'static str>,
145 pub direct_query_dependency_replacement: &'static str,
146 pub ready_surfaces: Vec<&'static str>,
147}
148
149pub fn summarize_omena_query_transform_runner_boundary_v0() -> OmenaQueryTransformRunnerBoundaryV0 {
150 let ready_surfaces = vec![
151 "transformPlannerBoundary",
152 "transformExecutorBoundary",
153 "transformPrinterBoundary",
154 "transformSourceMapV3SerializerBoundary",
155 "transformTargetPlannerBoundary",
156 "transformEggWitnessBoundary",
157 ];
158 #[cfg(feature = "lawvere-trace")]
159 let mut ready_surfaces = ready_surfaces;
160 #[cfg(feature = "lawvere-trace")]
161 ready_surfaces.push("transformLawvereTraceBoundary");
162
163 OmenaQueryTransformRunnerBoundaryV0 {
164 schema_version: "0",
165 product: "omena-query-transform-runner.boundary",
166 boundary_kind: "query-transform-runner-split",
167 collapsed_transform_crate_count: OMENA_QUERY_TRANSFORM_RUNNER_COLLAPSED_CRATES_V0.len(),
168 collapsed_transform_crates: OMENA_QUERY_TRANSFORM_RUNNER_COLLAPSED_CRATES_V0.to_vec(),
169 direct_query_dependency_replacement: "omena-query-transform-runner",
170 ready_surfaces,
171 }
172}
173
174#[cfg(test)]
175mod tests {
176 use super::*;
177
178 #[test]
179 fn transform_runner_boundary_collapses_transform_family_for_query() {
180 let summary = summarize_omena_query_transform_runner_boundary_v0();
181
182 assert_eq!(summary.collapsed_transform_crate_count, 6);
183 assert_eq!(
184 summary.collapsed_transform_crates,
185 OMENA_QUERY_TRANSFORM_RUNNER_COLLAPSED_CRATES_V0
186 );
187 assert!(
188 summary
189 .ready_surfaces
190 .contains(&"transformExecutorBoundary")
191 );
192 assert!(
193 summary
194 .ready_surfaces
195 .contains(&"transformTargetPlannerBoundary")
196 );
197 }
198
199 #[test]
200 fn transform_runner_materializes_sorted_native_edits() {
201 let input_css = ".button { color: red; margin: 1px; }";
202 let color_start = input_css.find("red").unwrap_or(input_css.len());
203 let margin_start = input_css.find("1px").unwrap_or(input_css.len());
204
205 let output = materialize_transform_module_evaluation_native_edits(
206 input_css,
207 &[
208 TransformModuleEvaluationNativeEditV0 {
209 start: margin_start,
210 end: margin_start + "1px".len(),
211 replacement: "2px".to_string(),
212 edit_kind: "value".to_string(),
213 abstract_value: None,
214 abstract_value_kind: None,
215 },
216 TransformModuleEvaluationNativeEditV0 {
217 start: color_start,
218 end: color_start + "red".len(),
219 replacement: "blue".to_string(),
220 edit_kind: "value".to_string(),
221 abstract_value: None,
222 abstract_value_kind: None,
223 },
224 ],
225 );
226
227 assert_eq!(
228 output.as_deref(),
229 Some(".button { color: blue; margin: 2px; }")
230 );
231 }
232
233 #[test]
234 fn transform_runner_rejects_overlapping_native_edits() {
235 let output = materialize_transform_module_evaluation_native_edits(
236 "abcdef",
237 &[
238 TransformModuleEvaluationNativeEditV0 {
239 start: 1,
240 end: 4,
241 replacement: "x".to_string(),
242 edit_kind: "value".to_string(),
243 abstract_value: None,
244 abstract_value_kind: None,
245 },
246 TransformModuleEvaluationNativeEditV0 {
247 start: 3,
248 end: 5,
249 replacement: "y".to_string(),
250 edit_kind: "value".to_string(),
251 abstract_value: None,
252 abstract_value_kind: None,
253 },
254 ],
255 );
256
257 assert_eq!(output, None);
258 }
259}