use crate::tests::prelude::*;
track_file!("ref/asciidoc-lang/docs/modules/tables/pages/width.adoc");
fn parse_table(source: &str) -> crate::blocks::TableBlock<'_> {
let mut parser = Parser::default();
let mi = crate::blocks::Block::parse(crate::Span::new(source), &mut parser)
.unwrap_if_no_warnings()
.unwrap();
match mi.item {
crate::blocks::Block::Table(table) => table,
other => panic!("expected a table block, got {other:?}"),
}
}
fn column_widths(table: &crate::blocks::TableBlock<'_>) -> Vec<(usize, bool)> {
table
.columns()
.iter()
.map(|c| (c.width(), c.is_autowidth()))
.collect()
}
const BASE_H: &str = "|===\n|Column 1, header row |Column 2, header row |Column 3, header row\n\n|Cell in column 1, row 2\n|Cell in column 2, row 2\n|Cell in column 3, row 2\n\n|Cell in column 1, row 3\n|Cell in column 2, row 3\n|Cell in column 3, row 3\n|===";
non_normative!(
r#"
= Table Width
"#
);
#[test]
fn fixed_width() {
verifies!(
r#"
By default, a table will span the width of the content area.
"#
);
let table = parse_table(BASE_H);
assert_eq!(table.width(), None);
assert!(!table.is_autowidth());
non_normative!(
r#"
== Fixed width
"#
);
verifies!(
r#"
To constrain the width of the table to a fixed value, set the `width` attribute in the table's attribute list.
The width is an integer percentage value ranging from 1 to 100.
The `%` sign is optional.
"#
);
let src = format!("[width=75%]\n{BASE_H}");
assert_eq!(parse_table(&src).width(), Some(75));
let src = format!("[width=75]\n{BASE_H}");
assert_eq!(parse_table(&src).width(), Some(75));
let src = format!("[width=0]\n{BASE_H}");
assert_eq!(parse_table(&src).width(), None);
let src = format!("[width=150]\n{BASE_H}");
assert_eq!(parse_table(&src).width(), None);
let src = format!("[width=wide]\n{BASE_H}");
assert_eq!(parse_table(&src).width(), None);
verifies!(
r#"
.Table with width set to 75%
[source#ex-fixed]
----
[width=75%]
include::example$row.adoc[tag=base-h]
----
.Result of <<ex-fixed>>
[width=75%]
include::example$row.adoc[tag=base-h]
"#
);
let src = format!("[width=75%]\n{BASE_H}");
let table = parse_table(&src);
assert_eq!(table.width(), Some(75));
assert_eq!(
column_widths(&table),
vec![(1, false), (1, false), (1, false)]
);
assert!(table.header_row().is_some());
assert_eq!(table.body_rows().len(), 2);
}
#[test]
fn autowidth() {
non_normative!(
r#"
== Autowidth
"#
);
verifies!(
r#"
Alternately, you can make the width fit the content by setting the `autowidth` option.
The columns inherit this setting, so individual columns will also be sized according to the content.
"#
);
let src = format!("[%autowidth]\n{BASE_H}");
let table = parse_table(&src);
assert!(table.is_autowidth());
assert_eq!(table.width(), None);
assert_eq!(column_widths(&table), vec![(1, true), (1, true), (1, true)]);
verifies!(
r#"
.Table using autowidth
[source#ex-auto]
----
[%autowidth]
include::example$row.adoc[tag=base-h]
----
.Result of <<ex-auto>>
[%autowidth]
include::example$row.adoc[tag=base-h]
"#
);
let src = format!("[%autowidth]\n{BASE_H}");
let table = parse_table(&src);
assert!(table.is_autowidth());
assert_eq!(column_widths(&table), vec![(1, true), (1, true), (1, true)]);
assert!(table.header_row().is_some());
assert_eq!(table.body_rows().len(), 2);
verifies!(
r#"
If you want each column to have an automatic width, but want the table to span the width of the content area, add the `stretch` role to the table.
(Alternatively, you can set the `width` attribute to `100%`.)
"#
);
let src = format!("[%autowidth.stretch]\n{BASE_H}");
let table = parse_table(&src);
assert!(table.is_autowidth());
assert_eq!(column_widths(&table), vec![(1, true), (1, true), (1, true)]);
assert!(table.attrlist().unwrap().roles().contains(&"stretch"));
let src = format!("[width=100%]\n{BASE_H}");
let table = parse_table(&src);
assert_eq!(table.width(), Some(100));
verifies!(
r#"
.Full-width table with autowidth columns
[source#ex-stretch]
----
[%autowidth.stretch]
include::example$row.adoc[tag=base-h]
----
The table from <<ex-stretch>> is rendered below.
The columns are sized to the content, but the table spans the width of the page.
.Result of <<ex-stretch>>
[%autowidth.stretch]
include::example$row.adoc[tag=base-h]
"#
);
let src = format!("[%autowidth.stretch]\n{BASE_H}");
let table = parse_table(&src);
assert!(table.is_autowidth());
assert_eq!(column_widths(&table), vec![(1, true), (1, true), (1, true)]);
assert!(table.attrlist().unwrap().roles().contains(&"stretch"));
non_normative!(
r#"
WARNING: The `autowidth` option is not recognized by the DocBook converter.
"#
);
}
#[test]
fn mix_fixed_and_autowidth_columns() {
non_normative!(
r#"
== Mix fixed and autowidth columns
"#
);
verifies!(
r#"
If you want to apply `autowidth` only to certain columns, use the special value `~` as the width of the column.
In this case, width values are assumed to be a percentage value (i.e., 100-based).
"#
);
verifies!(
r#"
.Table with fixed and autowidth columns
[source#ex-mix]
----
[cols="25h,~,~"]
|===
|small |as big as the column needs to be |the rest
|===
----
.Result of <<ex-mix>>
[cols="25h,~,~"]
|===
|small |as big as the column needs to be |the rest
|===
"#
);
let table = parse_table(
"[cols=\"25h,~,~\"]\n|===\n|small |as big as the column needs to be |the rest\n|===",
);
assert_eq!(
column_widths(&table),
vec![(25, false), (1, true), (1, true)]
);
assert_eq!(table.columns()[0].style(), ColumnStyle::Header);
assert!(!table.is_autowidth());
}