Skip to content
This repository has been archived by the owner on Nov 10, 2020. It is now read-only.

Implement relative includes. #37

Merged
merged 16 commits into from
Oct 20, 2015
Merged

Implement relative includes. #37

merged 16 commits into from
Oct 20, 2015

Conversation

egonelbre
Copy link

Now this works as with relative imports.

toc.md
chapter1/toc.md
chapter1/A.md

Where toc.md contains:

# Chapter 1
{{chapter1/toc.md}}

and chapter1/toc.md:

## A
{{A.md}}

When specifying {{/xyz.md}} will refer to the folder where main file is located. {{/../xyz.md}} will resolve to {{/xyz.md}}, because it is disallowed to go outside of the root folder.

Fixes #36

@@ -209,7 +209,8 @@ implements the following extensions:
to use 2 backslashes it the end of the line.\\

* **Includes**, support including files with `{{filename}}` syntax. This is only
done when include is started at the beginning of a line.
done when include is started at the beginning of a line. The filename is
specified with forward slashes `/`.
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would word this as 'The path separator is for the forward slash /. Even on non-Unix environments'.'

@miekg
Copy link
Owner

miekg commented Oct 18, 2015

I like the PR, but would like to see it be minimized or be put into multiple PR that each fix a different thing. The ParseAt name is fine; think the Linux kernel uses the same naming scheme.

@egonelbre
Copy link
Author

Anyways, as you need it split/minimized... how do these PR-s sound?

  1. Add FileSystem and ParseAt, without relative including, but runs mmark in the "root file" working directory. (This needs to be first so it can be used to test the implementation using virtualFileSystem)
  2. Add language and "isblock" detection for inline code-blocks. (This is necessary to make code-blocks inside lists work.)
  3. Do the code-inclusion in the first-pass. (This is necessary for tracking the correct cwd)
  4. Implement relative includes. (Finally the feature)
  5. A few PR-s for code-simplifications using linespan iterator. (Noticed a few places where it would make code more readable.)

@miekg
Copy link
Owner

miekg commented Oct 18, 2015

As to your final comment: I get the gist of your PR (sorry missed that before). Just cleaning up this one seems fine.

@egonelbre
Copy link
Author

I hope I fixed all the issues raised.

type linespan struct{ begin, end int }

// next updates begin and end to point to the next line
func (sc *linespan) next(content []byte) bool {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for all changes. I however thing this add something new that should happen in another PR. This (linespan) is only used once (now), and there is is basically to prefix each line with the indent.

@miekg
Copy link
Owner

miekg commented Oct 19, 2015

Nice. One nit about linespan.

@miekg
Copy link
Owner

miekg commented Oct 20, 2015

I'll just merge and clean up myself (if I think it is important enough :) )

Thanks for this PR!

miekg added a commit that referenced this pull request Oct 20, 2015
Implement relative includes.
@miekg miekg merged commit 9df0e1b into miekg:master Oct 20, 2015
@egonelbre
Copy link
Author

I was just about to start working on this. Anyways, thanks.

The reason I introduced linespan was that, I initially implemented code indenting without it, got it wrong, fixed it and I still had a small bug in it. Basically, it was very difficult for me to keep the relevant pieces in my head and to be sure that I got it right. By using linespan it worked correctly the second time.

I'm certain that a more general linescanner that handles both \r and \n would a lot of the line scanning code much easier to comprehend. Adding some additional things such as line.startsWith and line.extractIndent could make it even more useful.

@miekg
Copy link
Owner

miekg commented Oct 20, 2015

Totally agree. There is one snag though: upstream blackfriday. I still need
to incorporate upstream patches.

However I think this change would be such a large clean-up that I can live
with making it more difficult to incorporate upstream fixes.
On 20 Oct 2015 09:14, "Egon Elbre" notifications@github.com wrote:

I was just about to start working on this. Anyways, thanks.

The reason I introduced linespan was that I initially implement the code
indenting without it, got it wrong, fixed it and still had a small bug in
it. Basically, it was very difficult for me to keep the relevant pieces in
my head and be sure that I got it right. By using linespan it worked
correctly the second time.

I'm certain that a more general linescanner that handles both \r and \n
would a lot of the line scanning code much easier to comprehend. Adding
some additional things such as line.startsWith and line.extractIndent
could make it even more useful.


Reply to this email directly or view it on GitHub
#37 (comment).

@miekg
Copy link
Owner

miekg commented Oct 21, 2015

We/I need to double check how images get included with the syntax ![](fig/bumper-inverse.png) and make sure it happens in the same way.

@miekg
Copy link
Owner

miekg commented Oct 21, 2015

So while converting https://github.com/miekg/learninggo to relative includes: I get this:

mmark -page -head inc/head.html -css inc/learninggo.css learninggo.md > learninggo.html
2015/10/21 07:30:17 mmark: failed: `ex/basics/for.md': open ex/basics/ex/basics/for.md: no such file or directory
2015/10/21 07:30:17 mmark: failed: `ex/basics/average-no-func.md': open ex/basics/ex/basics/average-no-func.md: no such file or directory

Which does not seem WAI....

@miekg
Copy link
Owner

miekg commented Oct 21, 2015

Scratch that, everything is relative the the current file.

@miekg
Copy link
Owner

miekg commented Oct 21, 2015

Yep, figure includes don't follow the same rules, see https://github.com/miekg/learninggo/blame/master/ex/functions/stack.md#L9
this gets included relative to the mmark's CWD

@egonelbre
Copy link
Author

Scratch that, everything is relative the the current file.

You can still do includes relative to root directory with {{/ex/basics/for.md}}.

We/I need to double check how images get included with the syntax and make sure it happens in the same way.

I completely forgot about images. I would rewrite them to absolute during the first-pass and during the second pass handle everything else.

@miekg
Copy link
Owner

miekg commented Oct 21, 2015

Ok,

There is also this little thing

diff --git a/markdown.go b/markdown.go
index 946abd2..e73d584 100644
--- a/markdown.go
+++ b/markdown.go
@@ -445,7 +445,7 @@ func firstPass(p *parser, input []byte, depth int) *bytes.Buffer {
                        if end < lastFencedCodeBlockEnd { // Do not expand tabs while inside fenced code blocks.
                                out.Write(input[beg:end])
                        } else if p.flags&EXTENSION_INCLUDE != 0 {
-                               if input[beg] == '{' {
+                               if beg+2 < len(input) && input[beg] == '{' && input[beg+1] == '{' {
                                        if beg == 0 || (beg > 0 && input[beg-1] == '\n') {
                                                if j := p.include(&out, input[beg:end], depth); j > 0 {

Which makes the tests fail.

@miekg
Copy link
Owner

miekg commented Oct 21, 2015

And this is also interesting:

~/html/learninggo master+  
% make
mmark -page -head inc/head.html -css inc/learninggo.css learninggo.md > learninggo.html
2015/10/21 08:00:19 mmark: handling `@a' as normal text
2015/10/21 08:00:19 mmark: handling `@a' as normal text
2015/10/21 08:00:19 mmark: handling `@a' as normal text
2015/10/21 08:00:19 mmark: handling `@ps' as normal text

This means the Perl (/o) code included is not properly detected as code - digging in right now.

Regardless: I think relative includes make a lot of sense.

@miekg
Copy link
Owner

miekg commented Oct 21, 2015

And with my non-pushed {{-fix:

~/html/learninggo master+  
% make learninggo.txt 
mmark -xml2 -page learninggo.md > learninggo.xml && xml2rfc learninggo.xml
...
2015/10/21 08:07:04 mmark: syntax not supported: FootnoteRef
2015/10/21 08:07:04 mmark: handling `@a' as normal text
2015/10/21 08:07:04 mmark: handling `@a' as normal text
2015/10/21 08:07:04 mmark: handling `@a' as normal text
2015/10/21 08:07:04 mmark: handling `@ps' as normal text
2015/10/21 08:07:04 mmark: section jump from H1 to H3, id: "answer-26"
2015/10/21 08:07:04 mmark: syntax not supported: Footnotes
Parsing file learninggo.xml
WARNING: Parsing Error: Opening and ending tag mismatch: middle line 121 and section, line 5296, column 11
ERROR: Unable to parse the XML document: learninggo.xml

Prolly related to parsing that CodeInclude

@miekg
Copy link
Owner

miekg commented Oct 21, 2015

I'm sorry, but I've reverted this PR. These changes make my learning.md not compile at all and the include perl example <{{process.pl}} does not show up correctly.

miekg added a commit that referenced this pull request Oct 21, 2015
This reverts commit 9df0e1b, reversing
changes made to ee781d6.
@miekg
Copy link
Owner

miekg commented Oct 21, 2015

I you were to pick this up again, I think a way forward is doing the relative includes first (without changing any of the other logic) and prepare followup PR to move stuff around. And if not, than I'll give it a whack.

@egonelbre
Copy link
Author

Sad, but I understand. I guess, I can manage with absolute paths or write a minimal markdown parser for my own needs.

I was debugging ~30min to figure out why the perl part isn't working, but didn't reach any good conclusions. The result that comes out of first pass looked correct, although I might have missed something obvious, since there was a lot of it. I was guessing that maybe the code included contained triple accents and terminated the code block early and misaligned rest of it. Although this should've happened with the regular html version as well.

The main problem is that the code including trick can only work, if the fenced blocks have the language header detection. Alternatively if the includes are done with a single pass. Both require changes to the way other code works. I don't think I have a good enough understanding of this code to make a fix that accounts for all corner cases properly (as I initially suspected).

@miekg
Copy link
Owner

miekg commented Oct 23, 2015

Ok, so I gave this a couple of hours and with the current code (based of blackfriday) this is probable insane todo. It works for markdown file includes (that happen in firstPass) but breaks done for code-include which (for know) happen in secondPass - where you loose the info on which file you are working with. This is also problematic for images and stuff because these are inline elements and as such must be dealt with in secondPass.

Of course this can be worked around and everything can be fixed - but this becomes hacky fast and impairs the possibility of incorporating upstream fixes. So I am (also) going to stop implementing this :)

The filename normalizing (i.e. everything uses / - even on windows) is a worthwhile addition though.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
2 participants