Skip to content

Commit

Permalink
Fixes #1265. Support setting column widths (#1270)
Browse files Browse the repository at this point in the history
* Fixes #1265. Support setting column widths

* Fix test for upstream

* Add test for autowidth columns

* Update changelog
  • Loading branch information
robertpanzer committed Mar 31, 2024
1 parent c07b2fd commit b669438
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Improvement::
Bug Fixes::

* -s CLI option should be changed to -e to align with Asciidoctor (#1237) (@mojavelinux)
* Column#setWidth is ignored (#1265) (@Vampire)

=== Compatible changes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,5 @@ enum VerticalAlignment {
*/
void setGrid(String grid);

void assignColumnWidths();
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.asciidoctor.jruby.internal.RubyObjectWrapper;
import org.jruby.RubyArray;
import org.jruby.RubyNil;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;

import java.util.AbstractList;
Expand Down Expand Up @@ -72,6 +73,26 @@ public List<Row> getHeader() {
return rows.getHeader();
}

@Override
public void assignColumnWidths() {
int widthBase = 0;
RubyArray autowidthCols = getRuntime().newArray();
for (Column column : getColumns()) {
int width = column.getWidth();
if (width < 0) {
autowidthCols.add(((ColumnImpl)column).getRubyObject());
} else {
widthBase += width;
}
}
ThreadContext threadContext = getRuntime().getThreadService().getCurrentContext();

getRubyObject().callMethod(threadContext, "assign_column_widths", new IRubyObject[] {
getRuntime().newFixnum(widthBase),
autowidthCols.isEmpty() ? getRuntime().getNil() : autowidthCols
});
}

private class Rows extends RubyObjectWrapper {

public Rows(IRubyObject rubyNode) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import org.asciidoctor.util.TestHttpServer
class GithubContributorsBlockMacro extends BlockMacroProcessor {

private static final String IMAGE = 'image'
private static final String WIDTHS = 'widths'

GithubContributorsBlockMacro(String macroName) {
super(macroName)
Expand All @@ -29,12 +30,22 @@ class GithubContributorsBlockMacro extends BlockMacroProcessor {
table.grid = 'rows'
table.title = "Github contributors of $target"

List<Integer> widths = [1,2,2]
if (attributes.containsKey(WIDTHS)) {
widths = (attributes[WIDTHS] as String).split(',').collect {Integer.parseInt(it) }
}
// Create the columns 'Login' and 'Contributions'
Column avatarColumn = createTableColumn(table, 0)
avatarColumn.width = widths[0]
Column loginColumn = createTableColumn(table, 1)
loginColumn.width = widths[1]
Column contributionsColumn = createTableColumn(table, 2)
contributionsColumn.width = widths[2]
contributionsColumn.horizontalAlignment = Table.HorizontalAlignment.CENTER

table.columns << avatarColumn
table.columns << loginColumn
table.columns << contributionsColumn
table.assignColumnWidths()
// Create the single header row with the column titles
Row headerRow = createTableRow(table)
headerRow.cells << createTableCell(avatarColumn, 'Avatar')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,35 @@ import org.asciidoctor.test.extension.ClasspathHelper
import org.asciidoctor.util.TestHttpServer
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import org.jsoup.select.Elements
import spock.lang.Specification
import spock.lang.TempDir

import static java.nio.charset.StandardCharsets.UTF_8

class WhenABlockMacroProcessorCreatesATable extends Specification {

public static final String FIRST_TD = 'td:first-child'
public static final String SECOND_TD = 'td:nth-child(2)'
public static final String THIRD_TD = 'td:nth-child(3)'
public static final String IMG_ELEMENT = 'img'
public static final String COL = 'col'
public static final String STYLE = 'style'
public static final String WIDTH = 'width'
public static final String WIDTH_2 = '2%'
public static final String WIDTH_3 = '3%'
public static final String WIDTH_20 = '20%'
public static final String WIDTH_40 = '40%'
public static final String CONTRIBUTOR = 'bob'
public static final String BLOCKMACRO_NAME = 'githubcontributors'

public static final String AVATAR_URL_REGEXP = /https:\/\/avatars.githubusercontent.com\/u\/.*/
public static final String CSS_QUERY_TABLE = 'table'
public static final String CLASS_GRID_ROWS = 'grid-rows'
public static final String CLASS_HALIGN_LEFT = 'halign-left'
public static final String CLASS_HALIGN_CENTER = 'halign-center'
public static final String ATTR_SRC = 'src'
public static final int THREE = 3

private Asciidoctor asciidoctor

Expand All @@ -30,6 +46,12 @@ class WhenABlockMacroProcessorCreatesATable extends Specification {
= AsciidoctorJRuby contributors
githubcontributors::asciidoctor/asciidoctorj[]
'''

private static final String DOCUMENT_WITH_NEGATIVE_WIDTHS = '''
= AsciidoctorJRuby contributors
githubcontributors::asciidoctor/asciidoctorj[widths="2,3,-1"]
'''

private ClasspathHelper classpathResources
Expand Down Expand Up @@ -60,18 +82,62 @@ githubcontributors::asciidoctor/asciidoctorj[]
asciidoctor.convert(DOCUMENT, options)

then:
Document htmlDocument = Jsoup.parse(resultFile, 'UTF-8')
Document htmlDocument = Jsoup.parse(resultFile, UTF_8.name())

Elements cols = htmlDocument.select(COL)
cols.size() == THREE
cols.get(0).attr(STYLE).contains(WIDTH_20) || cols.get(0).attr(WIDTH).equals(WIDTH_20)
cols.get(1).attr(STYLE).contains(WIDTH_40) || cols.get(1).attr(WIDTH).equals(WIDTH_40)
cols.get(2).attr(STYLE).contains(WIDTH_40) || cols.get(2).attr(WIDTH).equals(WIDTH_40)

htmlDocument.select(CSS_QUERY_TABLE).hasClass(CLASS_GRID_ROWS)

htmlDocument.select(FIRST_TD).every { tdElement -> tdElement.select(IMG_ELEMENT).size() == 1 }
htmlDocument.select(FIRST_TD).every { tdElement -> tdElement.select(IMG_ELEMENT)[0].attr(ATTR_SRC) =~ AVATAR_URL_REGEXP }

htmlDocument.select(SECOND_TD).size() == htmlDocument.select(SECOND_TD) != 0
htmlDocument.select(SECOND_TD).size() != 0

htmlDocument.select(SECOND_TD).every { tdElement -> tdElement.hasClass(CLASS_HALIGN_LEFT) }
htmlDocument.select(THIRD_TD).every { tdElement -> tdElement.hasClass(CLASS_HALIGN_CENTER) }

htmlDocument.select(SECOND_TD).find { tdElement -> tdElement.text() == CONTRIBUTOR } != null
}

def "the table should be rendered to html with negative widths"() {
given:
asciidoctor.javaExtensionRegistry().blockMacro(BLOCKMACRO_NAME, GithubContributorsBlockMacro)
File resultFile = new File(tempDir, 'resultWithNegativeWidth.html')

when:
def options = Options.builder()
.safe(SafeMode.SAFE)
.inPlace(false)
.baseDir(tempDir)
.toDir(tempDir)
.toFile(resultFile)
.build()
asciidoctor.convert(DOCUMENT_WITH_NEGATIVE_WIDTHS, options)

then:
Document htmlDocument = Jsoup.parse(resultFile, UTF_8.name())

Elements cols = htmlDocument.select(COL)
cols.size() == THREE
cols.get(0).attr(STYLE).contains(WIDTH_2) || cols.get(0).attr(WIDTH).equals(WIDTH_2)
cols.get(1).attr(STYLE).contains(WIDTH_3) || cols.get(1).attr(WIDTH).equals(WIDTH_3)
cols.get(2).attr(STYLE).length() == 0 && cols.get(2).attr(WIDTH).length() == 0

htmlDocument.select('table').hasClass('grid-rows')
htmlDocument.select(CSS_QUERY_TABLE).hasClass(CLASS_GRID_ROWS)

htmlDocument.select(FIRST_TD).every { tdElement -> tdElement.select(IMG_ELEMENT).size() == 1 }
htmlDocument.select(FIRST_TD).every { tdElement -> tdElement.select(IMG_ELEMENT)[0].attr('src') =~ AVATAR_URL_REGEXP }
htmlDocument.select(FIRST_TD).every { tdElement -> tdElement.select(IMG_ELEMENT)[0].attr(ATTR_SRC) =~ AVATAR_URL_REGEXP }

htmlDocument.select(SECOND_TD).size() == htmlDocument.select(SECOND_TD) != 0
htmlDocument.select(SECOND_TD).size() != 0

htmlDocument.select(SECOND_TD).every { tdElement -> tdElement.hasClass('halign-left') }
htmlDocument.select(THIRD_TD).every { tdElement -> tdElement.hasClass('halign-center') }
htmlDocument.select(SECOND_TD).every { tdElement -> tdElement.hasClass(CLASS_HALIGN_LEFT) }
htmlDocument.select(THIRD_TD).every { tdElement -> tdElement.hasClass(CLASS_HALIGN_CENTER) }

htmlDocument.select(SECOND_TD).find { tdElement -> tdElement.text() == CONTRIBUTOR } != null
}
Expand Down
4 changes: 3 additions & 1 deletion config/codenarc/codenarc.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ ruleset {
ruleset('rulesets/braces.xml') {
exclude 'IfStatementBraces'
}
ruleset('rulesets/size.xml')
ruleset('rulesets/size.xml') {
exclude 'AbcMetric'
}
ruleset('rulesets/junit.xml') {
// Does not play well with Spock tests
exclude 'JUnitPublicNonTestMethod'
Expand Down

0 comments on commit b669438

Please sign in to comment.