extract image information and insert into text

Get help using and writing Nisus Writer Pro macros.
Post Reply
janklug
Posts: 8
Joined: 2014-05-09 11:21:13

extract image information and insert into text

Post by janklug »

Hello,

in my current workflow (writing in Scrivener with MultiMarkdown formatting; exporting as .fodt to keep all the style information intact; importing into Nisus Writer Pro), I encountered a problem with images.

For MMD, the image info is included in the source file like this:

![image caption text][link_to_image_info]

and then later in the file

[link_to_image_info]: /Pictures/image.png width=600px

In Nisus Writer Pro, the images are not included; instead, there's a floating frame with just the caption text.
For now, I'm manually replacing each of these frames with the correct image and caption text, then switch the image placement to "Inline with text", apply a style to the image, apply another style to the caption.

It would be great to have a Macro that would automate this; here's what I imagine (without knowing if it's possible):

I could encode the image information like IMG[image caption text][/Pictures/image.png] or so (so MMD won't mess it up).
The macro could then parse the text for this format, load and place the referenced image as "Inline with text" with the "Image" style applied, and the paste the caption underneath, with the "Caption" style applied...

So I'd be happy to know if this is possible, and would be thankful for any pointers in the good direction! :)

Jan
User avatar
phspaelti
Posts: 1313
Joined: 2007-02-07 00:58:12
Location: Japan

Re: extract image information and insert into text

Post by phspaelti »

Sure this can be done. And since you just want pointers:
  1. Help > Nisus Macro Reference
  2. http://www.nisus.com/forum/viewtopic.ph ... 273#p24273
:)

If you still have trouble after that, it might help if you posted a snippet of the kind of file you are dealing with.
philip
janklug
Posts: 8
Joined: 2014-05-09 11:21:13

Re: extract image information and insert into text

Post by janklug »

Thanks!

I still have to absorb A a bit I guess (and see in the examples how things connect)...
The macro I had already tried (including trying to understand it ;) ).

In the previous way that I referenced images in Scrivener it worked well:

![My boxed image][image]
[image]: /imagetester/images/DD3.png

In this case, the image would be placed in a figure, and your script would list these.

in the inline-referencing way like this: ![My inline image](/imagetester/images/DD3.png) the macro gives an error message (probably because no content floats).
To understand how I can use it for my problem, I'll need a nbit more tinkering.

Now I try to put the image caption / link into scrivener in a way that it will not be transformed by MultiMarkdown, like this:
[My inline image]IMG(/imagetester/images/DD3.png)

I managed to replace all these image links with this macro:

Code: Select all

Select Document Start
While Find Next '\[s*(.+?)\s*\]IMG\(s*(.+?)\s*\)', 'E$'
   Delete
   $path = $2
   $image = Image.newFromFileAtPath $path
   Image.insertInlineImage $image  
End
But if I then try to insert the caption (which should be in $1), the caption replaces the images (as these are the selected)...

Would you have any tip how I can insert the caption after the image, and preferably apply the style 'Image' to the image, and 'Caption' to the caption? Then I would be saved ;)
(text deadline is approaching...)

Thanks,

Jan
User avatar
phspaelti
Posts: 1313
Joined: 2007-02-07 00:58:12
Location: Japan

Re: extract image information and insert into text

Post by phspaelti »

Considering how you started, something like this would be the easiest approach:

Code: Select all

Select Document Start
While Find Next '\[s*(.+?)\s*\]IMG\(s*(.+?)\s*\)', 'E$'
   Delete
   $path = $2
   $image = Image.newFromFileAtPath $path
   Image.insertInlineImage $image
   $selRange = TextSelection.activeRange
   $newSelRange = Range.new $selRange.bound+1, 0
   TextSelection.setActiveRange $newSelRange
   Type Text "$1\n"
End
But in truth I would recommend an approach where you first find the images and then use a "Foreach" loop to process them. Also I would generally put a line like this at the beginning of the code:

Code: Select all

$doc = Document.active
This makes it much easier to use most of Nisus Macro Language powerful commands, since most of them are accessed via the document object.
philip
User avatar
phspaelti
Posts: 1313
Joined: 2007-02-07 00:58:12
Location: Japan

Re: extract image information and insert into text

Post by phspaelti »

Anyhow here is an idea of what such code might look like:

Code: Select all

$doc = Document.active
$imgs = $doc.text.findAll '\[s*(.+?)\s*\]IMG\(s*(.+?)\s*\)', 'Ea'

foreach $img in reversed $imgs
	$img.substring.find '\[s*(?<caption>.+?)\s*\]IMG\(s*(?<path>.+?)\s*\)', 'E$'
	$doc.setSelection $img
	$image = Image.newFromFileAtPath $path
	Image.insertInlineImage $image
	$doc.text.insertAtIndex $img.location+2, "$caption\n"
end
philip
janklug
Posts: 8
Joined: 2014-05-09 11:21:13

Re: extract image information and insert into text

Post by janklug »

ha, thanks a lot!
I'm almost there...
I extended this a bit to include the styles:

Code: Select all

$doc = Document.active
Select Document Start
$imageStyle = $doc.styleWithName 'Image'
$captionStyle = $doc.styleWithName 'Caption'
While Find Next '\[s*(.+?)\s*\]IMG\(s*(.+?)\s*\)', 'E$'
   Delete
   $path = $2
   $image = Image.newFromFileAtPath $path
   Image.insertInlineImage $image
   $imageStyle.apply
   $selRange = TextSelection.activeRange
   $newSelRange = Range.new $selRange.bound+1, 0
   TextSelection.setActiveRange $newSelRange
   $captionStyle.apply
   Type Text "$1\n"
   Type Newline
End
It applies the 'image' style well, and also the 'caption' style is applied.
Unfortunately - and that is the last remaining problem - also to the style *following* the caption.
Mostly those are headings, which then become unheaded...
User avatar
phspaelti
Posts: 1313
Joined: 2007-02-07 00:58:12
Location: Japan

Re: extract image information and insert into text

Post by phspaelti »

janklug wrote:ha, thanks a lot!
I'm almost there...
I extended this a bit to include the styles:

Code: Select all

$doc = Document.active
Select Document Start
$imageStyle = $doc.styleWithName 'Image'
…
$imageStyle.apply
…
I see, you learnt that from my other example :wink:
While I like that way of applying styles myself, you don't need to do things that complicated. You can just write:

Code: Select all

Paragraph Style:Image
without the need for first getting the style object. This is the same as invoking the menu command.

But now to your actual problem.
janklug wrote:It applies the 'image' style well, and also the 'caption' style is applied.
Unfortunately - and that is the last remaining problem - also to the style *following* the caption.
Mostly those are headings, which then become unheaded...
Your macro edits the file much as the user would. It finds the next image specification, deletes, pastes in the image, applies the style.

Code: Select all

$doc = Document.active
Select Document Start
$imageStyle = $doc.styleWithName 'Image'
$captionStyle = $doc.styleWithName 'Caption'
While Find Next '\[s*(.+?)\s*\]IMG\(s*(.+?)\s*\)', 'E$'
   Delete
   $path = $2
   $image = Image.newFromFileAtPath $path
   Image.insertInlineImage $image
   $imageStyle.apply
   …
At this point the macro places the selection after the paragraph with the image. As you said this is most likely some heading.

Code: Select all

   $selRange = TextSelection.activeRange
   $newSelRange = Range.new $selRange.bound+1, 0
   TextSelection.setActiveRange $newSelRange
So this is where the problem occurs. If you apply the style now, you will change the selected paragraph.

Code: Select all

   $captionStyle.apply
   Type Text "$1\n"
   Type Newline
The simplest way to fix this, is to use "Insert" instead of "Type".

Code: Select all

   Insert Text "$1\n\n"
   $captionStyle.apply
Note that of course now you will have to apply the style afterwards. Also note that since you apparently want an extra new line, I just added it to the "Insert" command.

And in fact you really have to think about how you manipulate the text, when you do things this way. Because the Nisus macro language isn't really set-up to allow you to move around the file the way a user would. And this is probably a good thing, because you don't really want to write macros that edit via the visual interface (What we used to call the "light show" in the Nisus Classic days). The better approach is to work globally using objects.
  1. Grab the document object
  2. Grab the document text object
  3. Find all the edit locations
  4. Change the edit locations (globally or via a loop)
  5. Save the edit locations (in an array)
  6. Select the edit locations in one go
  7. Apply the formatting in one go
Macros written like that will have much better performance, they will be fast even on very large documents. They'll also be easier to comprehend and maintain.
philip
janklug
Posts: 8
Joined: 2014-05-09 11:21:13

Re: extract image information and insert into text

Post by janklug »

Dear Philip,

thank you so much for your enlightening help!
here's the final script that works very well:

Code: Select all

$doc = Document.active
Select Document Start
While Find Next '\[s*(.+?)\s*\]IMG\(s*(.+?)\s*\)', 'E$'
   Delete
   $path = $2
   $image = Image.newFromFileAtPath $path
   Image.insertInlineImage $image
   Paragraph Style:Image 
   $selRange = TextSelection.activeRange
   $newSelRange = Range.new $selRange.bound+1, 0
   TextSelection.setActiveRange $newSelRange
   Insert Text “$1\n\n”
   Paragraph Style:Caption
End
Jan
Post Reply