Include partial content from another scribble document

I was wondering whether it's possible to include content from another scribble document directly. I know that it's possible to reference other parts via the tagging functionality, but would something similar be possible that instead grabs the content and inserts it?

Not sure if it is possible since that would also duplicate the tag id (though I guess that could also be renamed).

1 Like

Let’s assume you’re aware of include-section and you’re asking about dynamically loading content from abother scrbl module.

A scribble document exports doc and this can be used to dynamically like this:

foo.rkt:


#lang scribble/manual

@title{Foo}

Content

foo-bar.rkt:


#lang scribble/manual

@(require "foo.scrbl")

@title{Foo Bar}

This is foo-bared content.

@(dynamic-require "foo.scrbl" 'doc)

In this case you essentially get include-section but I have used this to type-set books with distinct parts, and my guess is you’re looking for this.

2 Likes

Let’s assume you’re aware of include-section and you’re asking about dynamically loading content from abother scrbl module.

A scribble document exports doc and this can be used to dynamically like this:

foo.rkt:


#lang scribble/manual

@title{Foo}

Content

foo-bar.rkt:


#lang scribble/manual

@(require "foo.scrbl")

@title{Foo Bar}

This is foo-bared content.

@(dynamic-require "foo.scrbl" 'doc)

In this case you essentially get include-section but I have used this to type-set books with distinct parts, and my guess is you’re looking for this.

Is it possible to get the inclusion without making a new section?

-- hendrik

Thanks for the pointers. This helps already, although I now realize that I didn't phrase my question precise enough.

With dynamic-require I can assign the doc to a variable and then reference the part (or other content) as I want to, so that's good. I now have two follow-up questions:

  1. When I render both documents, I now have a warning about multiple keys (WARNING: collected information for key multiple times). Is there an easy way of renaming the tags that I include?
  2. Is there a more convenient way of referencing other content? Ideally I could use something like the tagging function from scribble, but instead of linking to the content, it would just include it.

Currently, my files are as follows.
use.scrbl:

#lang scribble/base

@(require scribble/core)

@(define x (dynamic-require "doc.scrbl" 'doc))

@(car (part-blocks x))
@(car (part-parts x))

and doc.scrbl:

#lang scribble/base

text

@section{s1}
content

When I now call scribble {doc,use}.scrbl I get the following output/warning:

WARNING: collected information for key multiple times: '(index-entry (part "s1")); values: (list '("s1") (list (element #f '("s1"))) (part-index-desc)) (list '("s1") (list (element #f '("s1"))) (part-index-desc))
WARNING: collected information for key multiple times: '(part "s1"); values: '#(("s1") (part "s1") (1) #<path:doc.html> #f) '#(("s1") (part "s1") (1) #<path:use.html> #f)
 [Output to doc.html]
 [Output to use.html]

I am not sure if the warning is important, but I suppose if I now wanted to link to the section, then scribble would rightfully trip up as it does not know which one to refer to. So I suppose renaming would be a good idea.

To expand on this point a bit more, in the document above, I can now reference the section s1 via @secref["s1"] and get a link to the part/section. What would be nice is another function that essentially works like secref but instead includes the content (possibly renaming the tag to a unique string) in the document where the function is called.

How did you get the warnings? When I run scribble, I don't get them:

[matthias@Texas S (master)]$ scribble --dest Tmp/ use.scrbl 
 [Output to Tmp/use.html]
[matthias@Texas S (master)]$ open Tmp/use.html 
[matthias@Texas S (master)]$ scribble --dest Tmp doc.scrbl
 [Output to Tmp/doc.html]
[matthias@Texas S (master)]$ 

As for the second question, I am not exactly sure what you want.
Based on my understanding of your goal, I would define a function
make-section that consumes a section tag and delivers the entire content
in place:

#lang scribble/base

@(require scribble/core)

@(define (make-section tag)
  @list{
     @section[#:tag tag]{A new section}
     with some content})

@make-section{s1}

@make-section{s2}

(I have written about two dozen course web pages of around 100-150
PDF pages and two books using this technique. It works well.)

How did you get the warnings?

I ran scribble {doc,use}.scrbl, when both files are rendered in the same call, then both tags are available to scribble and the warning is issued. However, I may want to be able to refer to other tags from doc.scrbl hence it would be nice to render them together, such that those can be seen and hyperlinked during the rendering passes.

I agree that defining a function would be one way to solve the problem. But conceptually it feels nicer to be able to refer to content from another file and not go through the “hassle” of defining a function and then calling this function. It seems like it's more flexible to grab the entire doc from a file and then dig out the parts that you want to insert in use.scrbl, hence my question.

I think you may be looking for "tag prefixes". When you get doc, it's a part, and a part has tag-prefix field. You can update that field to give each document a distinct tag. Then ,you can use the #:tag-prefixes argument of secref, for example, to refer to the right part.

1 Like

— I am not sure why you’d render the two files at the same time if one includes the other. I can see why this yields a warning about a duplicate tag.

— I would write the function to (1) insert a line with a tag definition into the separate file and (2) dynamic-require the resulting file. This isn’t elegant but I have done this for quite some time. (If you want to run the separate file independently the manipulation is a bit more complicated.)

I was wondering whether it's possible to include content from another scribble document directly.

Is the intention to "quote" the other document or to reuse the contents
in two different documents?

1 Like

Oh cool, that seems to do the trick, it's actually quite nice since the tags don't need to be renamed.

If someone else stumbles across this, here's my solution for posteriority, the file doc.scrbl remains unchaged from before and use.scrbl can now do:

#lang scribble/base

@(require scribble/core)

@(define x (dynamic-require "doc.scrbl" 'doc))

@(car (part-blocks x))

@secref["s1"] will link to doc.scrbl,
@secref["s1" #:tag-prefixes (list "bla")] 
will link to the included content (below)

@(struct-copy part (car (part-parts x)) [tag-prefix "bla"])

Thanks for pointing this out!

This way the linking between the two documents doc.scrbl and use.scrbl “just works,” so I think it makes sense to render them together for resolving those links.

The former, I wanted to be able to quote parts of another document.

For that, I'd ideally be able to attach a tag to a block, like a paragraph; I am now wondering if that is possible.

I'm still wondering whether it's possible to include content by referencing it, so in essence I'd like to write something like @include-tag["s1"] and get the content inserted at that place; similar to include-section.

1 Like