pillar icon indicating copy to clipboard operation
pillar copied to clipboard

Bad path resolution when building an individual files

Open Ducasse opened this issue 3 years ago • 6 comments

We face a regression (No this is a regression just a missing feature).

Tested and reproduced in Pillar-dev8, v825, v826, v827 on Pharo 9 and Pharo 10 when compiling an individual files, the containing chapter is not part of the path.

how to reproduce

git clone https://github.com/pillar-markup/pillar.git
$ cd pillar
$ git checkout v8.2.6
$ chmod a+x ./scripts/build.sh
$ ./scripts/build.sh

Ducasse avatar Oct 02 '22 08:10 Ducasse

../build/pillar archetype microdown-book
../build/pillar build pdf 

produces correctly a pdf with corresponding figures. Each chapter contains a figures folder with some figures and such figures are correctly referenced hence found.

Here is the contents of Chapters/Chapter1/chapter1.md

## Compilation

![Pillar logo](figures/pillar.png width=30&anchor=fig)


### Welcome to Pillar's little user-guide !!

To write a book, you can create chapters and include them into `book.pillar`
or directly edit the file.
If you don't know ''Pillar'', check its documentation at [http://github.com/pillar-markup/pillar]()

Now

../build/pillar build pdf Chapters/Chapter1/chapter1.md

is failing

➜  tests git:(dev-8) ✗ ../build/pillar build pdf Chapters/Chapter1/chapter1.md
Instance of Character did not understand #readStream
Character(Object)>>doesNotUnderstand: #readStream
[ :stream |
		self encode: string readStream to: stream ] in ZnPercentEncoder>>encode: in Block: [ :stream | ...
String class(SequenceableCollection class)>>new:streamContents:
String class(SequenceableCollection class)>>streamContents:
ZnPercentEncoder>>encode:
ZnResourceMetaUtils class>>encodePercent:safeSet:encoder:
ZnUrl>>encodePath:on:
[ :each |
		stream nextPut: $/.
		each == #/
			ifFalse: [
				self encodePath: each on: stream ] ] in ZnUrl>>printPathOn: in Block: [ :each | ...
OrderedCollection>>do:
ZnUrl>>printPathOn:
ZnUrl>>printPathQueryFragmentOn:
ZnUrl>>printOn:
[:s | self printOn: s] in ZnUrl(Object)>>printStringLimitedTo: in Block: [:s | self printOn: s]
String class(SequenceableCollection class)>>streamContents:limitedTo:
ZnUrl(Object)>>printStringLimitedTo:using:
ZnUrl(Object)>>printStringLimitedTo:
ZnUrl(Object)>>printString
MicZincPathResolver>>resolveReferenceIn:
MicZincPathResolver>>visitLink:
MicLinkBlock>>accept:
[ :each | each accept: self ] in MicZincPathResolver(MicrodownVisitor)>>visitChildrenOf: in Block: [ :each | each accept: self ]
Array(SequenceableCollection)>>collect:
MicZincPathResolver(MicrodownVisitor)>>visitChildrenOf:
MicZincPathResolver(MicrodownVisitor)>>visitParagraph:
MicParagraphBlock>>accept:
[ :each | each accept: self ] in MicZincPathResolver(MicrodownVisitor)>>visitChildrenOf: in Block: [ :each | each accept: self ]
OrderedCollection>>collect:
MicZincPathResolver(MicrodownVisitor)>>visitChildrenOf:
MicZincPathResolver(MicrodownVisitor)>>visitRoot:
MicRootBlock>>accept:
Syntax Error on line 3: 'Variable or expression expected'
=========================================================
1: Optionally parsers its delegate, or answers nil.
2:
3: Examples:
  _^_
4: $a asPParser optional parse: 'b'

in the latex the path is


\begin{figure}[htpb]
\begin{center}
\includegraphics[width=0.3\textwidth]{/private/tmp/pillardev8InP10/pillar/tests/figures/pillar.png}
\caption{Pillar logo}
\end{center}
\end{figure}

/private/tmp/pillardev8InP10/pillar/tests/figures/pillar.png while it should be /private/tmp/pillardev8InP10/pillar/tests/Chapters/Chapter1/figures/pillar.png

Ducasse avatar Oct 02 '22 08:10 Ducasse

Now writing a test showing the problem!

Ducasse avatar Oct 02 '22 10:10 Ducasse

In transformDocumentFor:

transformDocumentFor: aPRPDFDocument 
	"This is a hook to be able to have framework specific transformation hooks.
	see PRAbstractOutputDocument>>#buildOn:"
	self halt.
	^ aPRPDFDocument transformDocument: (self resolveFrom: aPRPDFDocument project baseDirectory asMicResourceReference )

I have a file MicMicrodownInputDocument = '/private/tmp/pillardev8InP10/pillar/tests/Chapters/Chapter1/chapter1.md'

and we asked to resolve it via the baseDirectory `'/private/tmp/pillardev8InP10/pillar/tests'

^ aPRPDFDocument transformDocument: (self resolveFrom: aPRPDFDocument project baseDirectory asMicResourceReference )

and this part is lost: Chapters/Chapter1/

Ducasse avatar Oct 02 '22 11:10 Ducasse

When I do aPRPDFDocument project baseDirectory asMicResourceReference I get a MicFileResourceReference with a uri /private/tmp/pillardev8InP10/pillar/tests

resolveReferenceIn: aNode
	"currently links, figures and input nodes need to be resolved"
	| resolvedUri resolvedReference |
	self halt.
	aNode reference isRelative ifFalse: [ ^ self ].
	resolvedUri := absoluteReference uri withRelativeReference: aNode reference relativePath.
	resolvedReference := MicResourceReference fromUri: resolvedUri printString.
	resolvedReference isFileReference ifTrue: [ resolvedReference filesystem: absoluteReference filesystem ].
	aNode reference: resolvedReference

The bug is showing up In method resolveReferenceIn:

absoluteReference uri withRelativeReference: aNode reference relativePath.

/private/tmp/pillardev8InP10/pillar/tests withRelatedReference: figures/png produces as expected /private/tmp/pillardev8InP10/pillar/tests/figures/png

because in

resolveDocument: document withBase: base
	"resolve all relative urls in document with respect to the absolute uri 
	base can be a aString | aZnUrl | absoluteResourceReference"
	base resolveDocument: document.
	^ document 

there is no reference to Chapters/Chapter1 so it cannot guess.

Now the PRPDFDocument knows that the file is .... Chapters/Chapter1/chapter1.md so instead of the base directory we should resolved from that file parent?

transformDocumentFor: aPRPDFDocument 
	"This is a hook to be able to have framework specific transformation hooks.
	see PRAbstractOutputDocument>>#buildOn:"
	self halt.
	^ aPRPDFDocument transformDocument: (self resolveFrom: aPRPDFDocument file file asMicResourceReference )

No idea if it works for the index.md

Ducasse avatar Oct 02 '22 12:10 Ducasse

I think that it was not a regression and that probably I produced chapter via the inputFile in the main.md. I would prefer to have a missing feature over a bug regression.

Ducasse avatar Oct 02 '22 12:10 Ducasse

Fix is here

MicRootBlock >> transformDocumentFor: aPRPDFDocument 
	"This is a hook to be able to have framework specific transformation hooks.
	see PRAbstractOutputDocument>>#buildOn:"

	^ aPRPDFDocument transformDocument: (self resolveFrom: aPRPDFDocument file file asMicResourceReference)

Ducasse avatar Oct 02 '22 12:10 Ducasse