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

Define items in a list separately #86

Closed
pdurkim opened this issue Feb 20, 2018 · 11 comments
Closed

Define items in a list separately #86

pdurkim opened this issue Feb 20, 2018 · 11 comments

Comments

@pdurkim
Copy link

pdurkim commented Feb 20, 2018

Is there a way to define list items individually, along with their styles? In other words, each item in a list may have different styles.

@pdurkim pdurkim changed the title List Styles Define items in a list separately Feb 20, 2018
@jdugan
Copy link
Contributor

jdugan commented Feb 20, 2018

Hei, Peter.

If you mean the content of the list items, absolutely you can. List Item models are just subclasses of the paragraph model, so pretty much anything you can style in a normal paragraph can be styled in a list item block.

The only catch here is you have to style the text commands themselves (i.e., you can't style the list item per se). The reason for this is that OOXML doesn't work that way. OOXML does have the concept of list styling, but this refers to indentions, bullet/number type, whether the numbering restarts or continues previous numbering at the same level, etc.

I believe there are examples of what you want in the Caracal sample project. (See link in the README's opening paragraph.) That sample project is designed as a kind of canonical set of examples of what Caracal can do. It's pretty contrived, but it demonstrates a bunch of useful techniques.

@pdurkim
Copy link
Author

pdurkim commented Feb 26, 2018

Hey @jdugan, thanks for following up
This might be a farfetched question, but here it goes...

Given an array of strings to define items in a list, ex:
[{text: "a", depth: 0}, {text: "b", depth: 1}, {text: "c", depth: 2}, {text: "d", depth: 0}]

Can a list be defined so that as I loop through each element, I can define the level of the nest?
Something like...

docx.ol do
  array.each do |item|
    li item[:text], depth: item[:depth]
  end
end

The result in a docx being the following:

1. a
    a. b
        i. c
2. d

@pdurkim
Copy link
Author

pdurkim commented Feb 27, 2018

@jdugan maybe to make the problem easier, can a docx.p be defined as a list?

@jdugan
Copy link
Contributor

jdugan commented Feb 28, 2018

Hei, Peter.

Thanks for your patience. Part of the delay is I live in Oslo, so time zones can wreak havoc on these conversations; part of it is I slipped on the ice yesterday and broke a bone in my ankle. :(

To your question--I think this is too niche a requirement for it to make sense to write into Caracal itself. Instead, what I recommend is preparing your data in a nested structure that matches the list tree you want to build. Then you can just loop your data structure recursively and issue normal Caracal commands to get the output you want.

@pdurkim
Copy link
Author

pdurkim commented Feb 28, 2018

@jdugan oh man, I was afraid you'd say that. Thanks for your help!

@pdurkim
Copy link
Author

pdurkim commented Mar 2, 2018

@jdugan Could you advise on this error I'm running into with implementing a list recursively.

docx.ol do
  nested_ol(items)
end

def nested_ol(list)
  list.each do |item|
    li item[:text]
    ol do
      nested_ol(item[:sublist])
    end
  end
end

Results in the following error:
NoMethodError (undefined method 'nested_ol' for #<Caracal::Core::Models::ListModel:0x007f9c60f833c0>)

My guess is that the context for caracal doesn't persist through the recursion. How do you suggest I define this helper method?

@pdurkim
Copy link
Author

pdurkim commented Mar 5, 2018

@jdugan ^

@jdugan
Copy link
Contributor

jdugan commented Mar 6, 2018

Hei, Peter. Thanks for your patience. Like I wrote earlier, I broke my ankle and it's still a struggle most days just to get through the day. I'm not spending a lot of time in front of my computer right now.

Yes, that's right. Everything inside a Caracal command is a block that has some strict rules about lexical scope. There's a pretty good discussion of the relevant concerns in my answer to this issue.

In your specific case, I believe you're attempting something akin to my print_alsonotcool example. (Side note: You'll also need to pass a reference to the document itself into your recursive function so the new commands are issued against it. Otherwise, ol will also throw a NoMethodError.)

Hang in there and keep trying. What you want to do is definitely possible. If you're still stuck in a few days, I'll try to work up an example when I'm feeling up for it.

@pdurkim
Copy link
Author

pdurkim commented Mar 8, 2018

@jdugan I hope you feel better, man. That sounds rough.

I figured it out though so rest easy! :)

@pdurkim pdurkim closed this as completed Mar 8, 2018
@angelsystem
Copy link

@peyterkim I've the same problem, how did you solved? please!

@jdugan
Copy link
Contributor

jdugan commented Oct 9, 2018

@angelsystem Hi, Angel. I'd encourage you to read through the discussion I linked to in my comment above. Lexical scope is a thorny issue for libraries like Caracal, but I tried to present it more from a Ruby perspective, since the issues aren't really Caracal issues per se but more a function of the design of the ruby components.

Generally speaking, you need to make sure that the variables you want to use are in the lexical scope of the function calls in the Caracal document. Caracal switches context based largely on whether or not you pass the |docx| reference to the block.

Try reading through the issue discussion above. If you still have trouble, you're welcome to open a new issue with a practical version of your problem and I can help you structure the commands there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants