Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support column widths 2.5.x #1271

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ For a detailed view of what has changed, refer to the {url-repo}/commits/main[co

== Unreleased

Bug Fixes::

* Column#setWidth is ignored (#1265) (@Vampire)

== 2.5.12 (2024-03-10)

Improvement::
Expand Down
6 changes: 6 additions & 0 deletions asciidoctorj-api/src/main/java/org/asciidoctor/ast/Table.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,10 @@ enum VerticalAlignment {
*/
void setGrid(String grid);

/**
* Computes the percentual column widths for all columns.
* Before calling this method all columns must have been added to the Table by adding them to
* {@link #getColumns()} and the desired widths must have been set by calling {@link Column#setWidth(int)}.
*/
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
@@ -1,6 +1,7 @@
package org.asciidoctor.extension

import org.asciidoctor.Asciidoctor
import org.asciidoctor.Options
import org.asciidoctor.OptionsBuilder
import org.asciidoctor.SafeMode
import org.asciidoctor.util.ClasspathResources
Expand All @@ -9,36 +10,59 @@ import org.jboss.arquillian.spock.ArquillianSputnik
import org.jboss.arquillian.test.api.ArquillianResource
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import org.jsoup.select.Elements
import org.junit.rules.TemporaryFolder
import org.junit.runner.RunWith
import spock.lang.Specification

import static java.nio.charset.StandardCharsets.UTF_8

@RunWith(ArquillianSputnik)
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

@ArquillianResource
private Asciidoctor asciidoctor

@ArquillianResource
private TemporaryFolder tmp

@ArquillianResource
private ClasspathResources classpathResources

private static final String DOCUMENT = '''
= AsciidoctorJRuby contributors

githubcontributors::asciidoctor/asciidoctorj[]
'''

@ArquillianResource
private ClasspathResources classpathResources
private static final String DOCUMENT_WITH_NEGATIVE_WIDTHS = '''
= AsciidoctorJRuby contributors

githubcontributors::asciidoctor/asciidoctorj[widths="2,3,-1"]
'''


def setup() {
TestHttpServer.start(['http://api.github.com/repos/asciidoctor/asciidoctorj/contributors' : classpathResources.getResource('githubcontributors.json')])
Expand All @@ -60,18 +84,61 @@ githubcontributors::asciidoctor/asciidoctorj[]
asciidoctor.convert(DOCUMENT, OptionsBuilder.options().safe(SafeMode.SAFE).inPlace(false).baseDir(tmp.getRoot()).toDir(tmp.getRoot()).toFile(resultFile))

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 = tmp.newFile('resultWithNegativeWidth.html')

when:
def options = Options.builder()
.safe(SafeMode.SAFE)
.inPlace(false)
.baseDir(tmp.getRoot())
.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
Loading