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

Fixes #916. Add factory methods to create lists #917

Merged
merged 2 commits into from
May 2, 2020
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
9 changes: 7 additions & 2 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ Improvement::
* Upgrade to Asciidoctor EPUB3 1.5.0-alpha.16
* Upgrade to Asciidoctor Diagram 2.0.1

Build::
Bug Fixes::

* Upgrade jruby-gradle-plugin to 2.0.0-alpha.7 and load Gems directly from rubygems.org instead of using torquebox Maven proxy.
* Add missing factory methods to create Lists. (@glisicivan) (#916)
The API `Processor.createList()` is experimental and may change with any release until declared to be stable.

Documentation::

Expand All @@ -33,6 +34,10 @@ Build::

* Upgrade to jruby-gradle-plugin 2.0.0

Known Limitations:

* The createList() and createListItem() API is not able to create DescriptionLists.

== 2.2.0 (2019-12-17)

Improvement::
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,21 @@ public ListItem createListItem(org.asciidoctor.ast.List parent, String text) {
return delegate.createListItem(parent, text);
}

@Override
public org.asciidoctor.ast.List createList(StructuralNode parent, String context) {
return delegate.createList(parent, context);
}

@Override
public org.asciidoctor.ast.List createList(StructuralNode parent, String context, Map<String, Object> attributes, Map<Object, Object> options) {
return delegate.createList(parent, context, attributes, options);
}

@Override
public org.asciidoctor.ast.List createList(StructuralNode parent, String context, Map<Object, Object> options) {
return delegate.createList(parent, context);
}

@Override
public ListItem createListItem(DescriptionList parent, String text) {
return delegate.createListItem(parent, text);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,45 @@
*/
String PARAGRAPH = ":paragraph";

/**
* Predefined constant for making a Processor work on ordered lists.
*
* <pre>
* 1. First item
* 2. Second item
* </pre>
*/
String OLIST = ":olist";

/**
* Predefined constant for making a Processor work on unordered lists.
*
* <pre>
* . First item
* . Second item
* </pre>
*/
String ULIST = ":ulist";

/**
* Predefined constant for making a Processor work on unordered lists.
*
* <pre>
* . First item
* . Second item
* </pre>
*/
String COLIST = ":colist";

/**
* Predefined constant for making a Processor work on unordered lists.
*
* <pre>
* First:: The first item
* Second:: The second item
* </pre>
*/
String DLIST = ":dlist";

String[] value();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,36 @@ public interface Processor {
*/
Document createDocument(Document parentDocument);

/**
* Creates a new List.
* This method is experimental and may change in future minor releases until declared to be stable.
* @param parent The block to which the parsed content should be added as children.
* @param context Either {@code "olist"}, {@code ulist}, {@code colist} or {@code dlist}
* @return A List node that can be added to the AST of a document.
*/
org.asciidoctor.ast.List createList(StructuralNode parent, String context);

/**
* Creates a new List.
* This method is experimental and may change in future minor releases until declared to be stable.
* @param parent The block to which the parsed content should be added as children.
* @param context Either {@code "olist"}, {@code ulist}, {@code colist} or {@code dlist}
* @param attributes Additional attributes to be set on the new list node, e.g. <code>Collections.singletonMap("start", "2")</code>.
* @param options Additional options to be set on the new list node.
* @return A List node that can be added to the AST of a document.
*/
org.asciidoctor.ast.List createList(StructuralNode parent, String context, Map<String, Object> attributes, Map<Object, Object> options);

/**
* Creates a new List.
* This method is experimental and may change in future minor releases until declared to be stable.
* @param parent The block to which the parsed content should be added as children.
* @param context Either {@code "olist"}, {@code ulist}, {@code colist} or {@code dlist}
* @param options Additional options to be set on the new list node.
* @return A List node that can be added to the AST of a document.
*/
org.asciidoctor.ast.List createList(StructuralNode parent, String context, Map<Object, Object> options);

ListItem createListItem(final org.asciidoctor.ast.List parent, final String text);

ListItem createListItem(final org.asciidoctor.ast.DescriptionList parent, final String text);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,21 @@
import org.asciidoctor.ast.ContentNode;
import org.asciidoctor.ast.Document;
import org.asciidoctor.ast.ListItem;
import org.asciidoctor.jruby.ast.impl.NodeConverter;
import org.asciidoctor.ast.PhraseNode;
import org.asciidoctor.ast.Row;
import org.asciidoctor.ast.Section;
import org.asciidoctor.ast.StructuralNode;
import org.asciidoctor.ast.Table;
import org.asciidoctor.extension.Processor;
import org.asciidoctor.extension.Reader;
import org.asciidoctor.jruby.ast.impl.ColumnImpl;
import org.asciidoctor.jruby.ast.impl.ContentNodeImpl;
import org.asciidoctor.jruby.ast.impl.DescriptionListImpl;
import org.asciidoctor.jruby.ast.impl.DocumentImpl;
import org.asciidoctor.jruby.ast.impl.ListImpl;
import org.asciidoctor.jruby.ast.impl.NodeConverter;
import org.asciidoctor.jruby.ast.impl.RowImpl;
import org.asciidoctor.jruby.ast.impl.StructuralNodeImpl;
import org.asciidoctor.extension.Processor;
import org.asciidoctor.extension.Reader;
import org.asciidoctor.jruby.internal.JRubyAsciidoctor;
import org.asciidoctor.jruby.internal.JRubyRuntimeContext;
import org.asciidoctor.jruby.internal.RubyHashUtil;
Expand Down Expand Up @@ -291,6 +291,38 @@ public Document createDocument(Document parentDocument) {
return (Document) NodeConverter.createASTNode(runtime, NodeConverter.NodeType.DOCUMENT_CLASS, runtime.getNil(), options);
}


@Override
public org.asciidoctor.ast.List createList(StructuralNode parent, String context) {
return createList(parent, context, new HashMap<>(), new HashMap<>());

}

@Override
public org.asciidoctor.ast.List createList(StructuralNode parent, String context,
Map<String, Object> attributes,
Map<Object, Object> options) {

options.put(Options.ATTRIBUTES, new HashMap<>(attributes));
return createList(parent, context, options);
}

@Override
public org.asciidoctor.ast.List createList(StructuralNode parent, String context,
Map<Object, Object> options) {

Ruby rubyRuntime = JRubyRuntimeContext.get(parent);

RubyHash convertMapToRubyHashWithSymbols = RubyHashUtil.convertMapToRubyHashWithSymbolsIfNecessary(rubyRuntime,
filterBlockOptions(parent, options, "subs", ContentModel.KEY));

IRubyObject[] parameters = {
((StructuralNodeImpl) parent).getRubyObject(),
RubyUtils.toSymbol(rubyRuntime, context),
convertMapToRubyHashWithSymbols};
return (org.asciidoctor.ast.List) NodeConverter.createASTNode(rubyRuntime, NodeConverter.NodeType.LIST_CLASS, parameters);
}

@Override
public ListItem createListItem(final org.asciidoctor.ast.List parent, final String text) {
Ruby rubyRuntime = JRubyRuntimeContext.get(parent);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package org.asciidoctor.extension


import org.asciidoctor.ast.StructuralNode

@Name('list')
class ListCreatorBlockMacro extends BlockMacroProcessor {

String context

ListCreatorBlockMacro(String context) {
this.context = context
}

@Override
Object process(StructuralNode parent, String target, Map<String, Object> attributes) {

def attrs = new HashMap<String, Object>()
attrs['start'] = '42'
def opts = new HashMap<Object, Object>()

org.asciidoctor.ast.List list = createList(parent, context, attrs, opts)

list.getBlocks().add(createListItem(list, 'First item'))
list.getBlocks().add(createListItem(list, 'Second item'))

list
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package org.asciidoctor.extension

import org.asciidoctor.Asciidoctor
import org.asciidoctor.OptionsBuilder
import org.asciidoctor.SafeMode
import org.jboss.arquillian.spock.ArquillianSputnik
import org.jboss.arquillian.test.api.ArquillianResource
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import org.junit.runner.RunWith
import spock.lang.Specification

@RunWith(ArquillianSputnik)
class WhenABlockMacroProcessorCreatesAList extends Specification {

public static final String LISTMACRO_NAME = 'list'
public static final String UTF_8 = 'UTF-8'
public static final String OL = 'ol'
public static final String UL = 'ul'
public static final String LI = 'li'
public static final String FIRST_ITEM = 'First item'
public static final String SECOND_ITEM = 'Second item'

@ArquillianResource
private Asciidoctor asciidoctor

private static final String DOCUMENT = '''
= Section Creation Test

list::HelloWorld[]
'''

def "the ordered list should appear in the resulting document"() {

given:
asciidoctor.javaExtensionRegistry().blockMacro(LISTMACRO_NAME, new ListCreatorBlockMacro('olist'))

when:
String result = asciidoctor.convert(DOCUMENT, OptionsBuilder.options().safe(SafeMode.SAFE).toFile(false).headerFooter(false))

then:
noExceptionThrown()
Document htmlDocument = Jsoup.parse(result, UTF_8)

htmlDocument.select(OL).size() == 1
def ol = htmlDocument.select(OL).first()
ol.attr('start') == '42'
def items = ol.select(LI)
items.size() == 2
items.get(0).text() == FIRST_ITEM
items.get(1).text() == SECOND_ITEM
}

def "the unordered list should appear in the resulting document"() {

given:
asciidoctor.javaExtensionRegistry().blockMacro(LISTMACRO_NAME, new ListCreatorBlockMacro('ulist'))

when:
String result = asciidoctor.convert(DOCUMENT, OptionsBuilder.options().safe(SafeMode.SAFE).toFile(false).headerFooter(false))

then:
noExceptionThrown()
Document htmlDocument = Jsoup.parse(result, UTF_8)

htmlDocument.select(UL).size() == 1
def ul = htmlDocument.select(UL).first()
def items = ul.select(LI)
items.size() == 2
items.get(0).text() == FIRST_ITEM
items.get(1).text() == SECOND_ITEM
}
}
6 changes: 5 additions & 1 deletion config/codenarc/codenarc.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,9 @@ ruleset {
exclude 'UnnecessaryGetter'
exclude 'UnnecessaryCollectCall'
}
ruleset('rulesets/dry.xml')
ruleset('rulesets/dry.xml') {
'DuplicateNumberLiteral' {
ignoreNumbers = '0,1,2'
}
}
}