on master help sign in
Formatting: improve code line wrapping across codebase
commitcc6e75c1506d4910fd3b9b8e44fbe12036e68be5 authoriko <mail@iko.soy> dateSun 26 Apr 2026, 18:16 (5 months ago) parentbf43689
8 files changed+54−56
crates/htmlang-core/src/codegen.rs+11−23 crates/htmlang-core/src/parser.rs+11−9 src/bin/htmlang_lsp/analysis.rs+9−13 src/bin/htmlang_lsp/completion.rs+10−2 src/bin/htmlang_lsp/hover.rs+9−3 src/bin/htmlang_lsp/main.rs+1−2 src/main.rs+2−2 tests/snapshots.rs+1−2
crates/htmlang-core/src/codegen.rs+11−23
@@ -3724,12 +3724,12 @@ fn attrs_to_css(
37243724 "type" | "placeholder" | "name" | "value" | "disabled" | "required" | "checked"
37253725 | "for" | "action" | "method" | "autocomplete" | "min" | "max" | "step" | "pattern"
37263726 | "maxlength" | "rows" | "cols" | "multiple" | "alt" | "role" | "tabindex"
3727− | "title" | "controls" | "autoplay" | "loop" | "muted" | "playsinline" | "poster" | "preload"
3728− | "loading" | "decoding" | "ordered" | "src" | "open" | "novalidate" | "low"
3729− | "high" | "optimum" | "colspan" | "rowspan" | "scope" | "inline" | "responsive"
3730− | "datetime" | "media" | "sizes" | "srcset" | "cite" | "list" | "sandbox" | "allow"
3731− | "allowfullscreen" | "referrerpolicy" | "formaction" | "formmethod" | "formtarget"
3732− | "target" | "autofocus" => {}
3727+ | "title" | "controls" | "autoplay" | "loop" | "muted" | "playsinline" | "poster"
3728+ | "preload" | "loading" | "decoding" | "ordered" | "src" | "open" | "novalidate"
3729+ | "low" | "high" | "optimum" | "colspan" | "rowspan" | "scope" | "inline"
3730+ | "responsive" | "datetime" | "media" | "sizes" | "srcset" | "cite" | "list"
3731+ | "sandbox" | "allow" | "allowfullscreen" | "referrerpolicy" | "formaction"
3732+ | "formmethod" | "formtarget" | "target" | "autofocus" => {}
37333733
37343734 _ => {}
37353735 }
@@ -3795,17 +3795,11 @@ fn substitute_css_vars(css: &str, vars: &[(String, String)]) -> String {
37953795
37963796 let is_boundary_before = |b: Option<u8>| match b {
37973797 None => true,
3798− Some(c) => matches!(
3799− c,
3800− b':' | b' ' | b',' | b'(' | b';' | b'{' | b'\n' | b'\t'
3801− ),
3798+ Some(c) => matches!(c, b':' | b' ' | b',' | b'(' | b';' | b'{' | b'\n' | b'\t'),
38023799 };
38033800 let is_boundary_after = |b: Option<u8>| match b {
38043801 None => true,
3805− Some(c) => matches!(
3806− c,
3807− b';' | b'}' | b',' | b' ' | b')' | b'\n' | b'\t'
3808− ),
3802+ Some(c) => matches!(c, b';' | b'}' | b',' | b' ' | b')' | b'\n' | b'\t'),
38093803 };
38103804
38113805 let bytes = css.as_bytes();
@@ -3920,16 +3914,10 @@ fn auto_extract_repeats(
39203914 // two-digit indices, which only affects very large extraction counts.
39213915 let existing: std::collections::HashSet<&str> =
39223916 existing_vars.iter().map(|(n, _)| n.as_str()).collect();
3923− let mut candidates: Vec<(String, usize)> = counts
3924− .into_iter()
3925− .filter(|(_, n)| *n >= 2)
3926− .collect();
3917+ let mut candidates: Vec<(String, usize)> =
3918+ counts.into_iter().filter(|(_, n)| *n >= 2).collect();
39273919 // Stable, deterministic ordering — longest values first, tiebreak by text.
3928− candidates.sort_by(|a, b| {
3929− b.0.len()
3930− .cmp(&a.0.len())
3931− .then_with(|| a.0.cmp(&b.0))
3932− });
3920+ candidates.sort_by(|a, b| b.0.len().cmp(&a.0.len()).then_with(|| a.0.cmp(&b.0)));
39333921
39343922 let mut extracted: Vec<(String, String)> = Vec::new();
39353923 let mut next_idx: usize = 0;
crates/htmlang-core/src/parser.rs+11−9
@@ -420,8 +420,8 @@ impl Parser {
420420 let rest = rest.trim();
421421
422422 // Check if next lines are indented (function/component definition)
423− let has_body = self.pos < self.lines.len()
424− && self.lines[self.pos].indent > current_indent;
423+ let has_body =
424+ self.pos < self.lines.len() && self.lines[self.pos].indent > current_indent;
425425
426426 if has_body {
427427 // Function definition: @let name $param1 $param2=default
@@ -447,9 +447,7 @@ impl Parser {
447447
448448 // Collect body lines (all lines indented deeper than @let)
449449 let mut body_lines = Vec::new();
450− while self.pos < self.lines.len()
451− && self.lines[self.pos].indent > current_indent
452− {
450+ while self.pos < self.lines.len() && self.lines[self.pos].indent > current_indent {
453451 body_lines.push(self.lines[self.pos].clone());
454452 self.pos += 1;
455453 }
@@ -481,9 +479,7 @@ impl Parser {
481479 if value.starts_with('[') {
482480 let (attrs, _) = parse_attr_brackets(value, line_num, ctx)?;
483481 ctx.defines.insert(name.to_string(), attrs);
484− ctx.define_lines
485− .entry(name.to_string())
486− .or_insert(line_num);
482+ ctx.define_lines.entry(name.to_string()).or_insert(line_num);
487483 return Ok(None);
488484 }
489485
@@ -5189,7 +5185,13 @@ fn validate_tree(
51895185 // Media-specific attributes only on @video/@audio
51905186 if matches!(
51915187 base,
5192− "controls" | "autoplay" | "loop" | "muted" | "playsinline" | "poster" | "preload"
5188+ "controls"
5189+ | "autoplay"
5190+ | "loop"
5191+ | "muted"
5192+ | "playsinline"
5193+ | "poster"
5194+ | "preload"
51935195 ) && !matches!(elem.kind, ElementKind::Video | ElementKind::Audio)
51945196 {
51955197 diagnostics.push(Diagnostic {
src/bin/htmlang_lsp/analysis.rs+9−13
@@ -28,9 +28,7 @@ pub(crate) fn document_symbols(text: &str) -> Vec<SymbolInformation> {
2828 .map(|l| l.starts_with(" ") || l.starts_with('\t'))
2929 .unwrap_or(false);
3030
31− if has_body
32− && (value_part.is_empty() || value_part.starts_with('$'))
33− {
31+ if has_body && (value_part.is_empty() || value_part.starts_with('$')) {
3432 // Component/function definition
3533 let params = parts[1..].join(" ");
3634 let detail = if params.is_empty() {
@@ -1031,22 +1029,20 @@ pub(crate) fn semantic_tokens(text: &str) -> Vec<SemanticToken> {
10311029 }
10321030 let word = &line[start..i];
10331031 let token_type = match word {
1034− "@page" | "@let" | "@if" | "@else" | "@each"
1035− | "@include" | "@import" | "@meta" | "@head" | "@style" | "@keyframes"
1036− | "@match" | "@case" | "@default" | "@slot" | "@children" | "@warn"
1037− | "@debug" | "@lang" | "@favicon" | "@fragment" | "@unless" | "@og"
1038− | "@breakpoint" | "@canonical" | "@base" | "@font-face" | "@json-ld"
1039− | "@assert" | "@theme" | "@deprecated" | "@extends" | "@use"
1040− | "@data" | "@env" | "@fetch" | "@svg" | "@css-property" => 0, // keyword
1032+ "@page" | "@let" | "@if" | "@else" | "@each" | "@include" | "@import"
1033+ | "@meta" | "@head" | "@style" | "@keyframes" | "@match" | "@case"
1034+ | "@default" | "@slot" | "@children" | "@warn" | "@debug" | "@lang"
1035+ | "@favicon" | "@fragment" | "@unless" | "@og" | "@breakpoint"
1036+ | "@canonical" | "@base" | "@font-face" | "@json-ld" | "@assert" | "@theme"
1037+ | "@deprecated" | "@extends" | "@use" | "@data" | "@env" | "@fetch"
1038+ | "@svg" | "@css-property" => 0, // keyword
10411039 _ => {
10421040 // Check if it's a user function call (starts with @ but not a builtin element)
10431041 if is_builtin_element(word) { 0 } else { 2 } // function
10441042 }
10451043 };
10461044 // Mark unused definitions with deprecated modifier (dimmed)
1047− let modifier = if trimmed.starts_with("@let ")
1048− && word != "@let"
1049− {
1045+ let modifier = if trimmed.starts_with("@let ") && word != "@let" {
10501046 let name_part = &word[1..]; // strip @
10511047 if unused_vars.contains(&format!("@{}", name_part)) {
10521048 1
src/bin/htmlang_lsp/completion.rs+10−2
@@ -272,7 +272,11 @@ fn directive_completions(range: Range) -> Vec<CompletionItem> {
272272 ("@meta", "Add a <meta> tag to <head>", "@meta "),
273273 ("@head", "Add raw content to <head>", "@head"),
274274 ("@style", "Add raw CSS to stylesheet", "@style"),
275− ("@slot", "Named slot in component for caller content", "@slot "),
275+ (
276+ "@slot",
277+ "Named slot in component for caller content",
278+ "@slot ",
279+ ),
276280 ("@match", "Pattern matching on a value", "@match "),
277281 ("@case", "Match case (inside @match)", "@case "),
278282 ("@default", "Default case (inside @match)", "@default"),
@@ -308,7 +312,11 @@ fn directive_completions(range: Range) -> Vec<CompletionItem> {
308312 "Define design tokens (colors, spacing, fonts)",
309313 "@theme",
310314 ),
311− ("@deprecated", "Mark next @let component as deprecated", "@deprecated "),
315+ (
316+ "@deprecated",
317+ "Mark next @let component as deprecated",
318+ "@deprecated ",
319+ ),
312320 (
313321 "@extends",
314322 "Inherit a layout template and fill @slot blocks",
src/bin/htmlang_lsp/hover.rs+9−3
@@ -225,9 +225,15 @@ fn hover_builtin(word: &str) -> Option<String> {
225225 "@paragraph" | "@p" => {
226226 "**@paragraph** \u{2014} Text block\n\nRenders as `<p>`.\n\nSupports inline elements: `{@text [bold] word}`"
227227 }
228− "@h1" => "**@h1** \u{2014} Heading level 1\n\nRenders as `<h1>`.\n\nUsage: `@h1 Page Title`",
229− "@h2" => "**@h2** \u{2014} Heading level 2\n\nRenders as `<h2>`.\n\nUsage: `@h2 Section Title`",
230− "@h3" => "**@h3** \u{2014} Heading level 3\n\nRenders as `<h3>`.\n\nUsage: `@h3 Subsection`",
228+ "@h1" => {
229+ "**@h1** \u{2014} Heading level 1\n\nRenders as `<h1>`.\n\nUsage: `@h1 Page Title`"
230+ }
231+ "@h2" => {
232+ "**@h2** \u{2014} Heading level 2\n\nRenders as `<h2>`.\n\nUsage: `@h2 Section Title`"
233+ }
234+ "@h3" => {
235+ "**@h3** \u{2014} Heading level 3\n\nRenders as `<h3>`.\n\nUsage: `@h3 Subsection`"
236+ }
231237 "@h4" => "**@h4** \u{2014} Heading level 4\n\nRenders as `<h4>`.",
232238 "@h5" => "**@h5** \u{2014} Heading level 5\n\nRenders as `<h5>`.",
233239 "@h6" => "**@h6** \u{2014} Heading level 6\n\nRenders as `<h6>`.",
src/bin/htmlang_lsp/main.rs+1−2
@@ -682,8 +682,7 @@ impl LanguageServer for Backend {
682682 .unwrap_or(false);
683683 let value_after_name = rest[name.len()..].trim_start();
684684 if has_body
685− && (value_after_name.is_empty()
686− || value_after_name.starts_with('$'))
685+ && (value_after_name.is_empty() || value_after_name.starts_with('$'))
687686 {
688687 defs.push(Def {
689688 line: i as u32,
src/main.rs+2−2
@@ -2238,8 +2238,8 @@ fn main() {
22382238 .map(|l| l.starts_with(" ") || l.starts_with('\t'))
22392239 .unwrap_or(false);
22402240 // Also include if it has $params (even without checking body)
2241− let has_params = parts.len() > 1
2242− && parts[1..].iter().any(|p| p.starts_with('$'));
2241+ let has_params =
2242+ parts.len() > 1 && parts[1..].iter().any(|p| p.starts_with('$'));
22432243 if is_fn || has_params {
22442244 let params: Vec<&str> = parts[1..]
22452245 .iter()
tests/snapshots.rs+1−2
@@ -5180,8 +5180,7 @@ fn markdown_file_missing_reports_error() {
51805180 let _ = std::fs::remove_dir_all(&dir);
51815181
51825182 let has_err = result.diagnostics.iter().any(|d| {
5183− d.severity == htmlang::parser::Severity::Error
5184− && d.message.contains("cannot read markdown")
5183+ d.severity == htmlang::parser::Severity::Error && d.message.contains("cannot read markdown")
51855184 });
51865185 assert!(
51875186 has_err,