Combine a series of different pages into a dv.pages object

I have a series of pages in different parts of my vault that I would like to combine into a single dv.pages object.

For example:

/Misc/A/a.md
/Projects/B/b.md
/Summaries/C/c.md

How can this be done?

I see that dv.page can be used to turn a path into a page, so

dv.page(“/Misc/A/a.md”)
dv.page(“/Projects/B/b.md”)
dv.page(“/Summaries/C/c.md”)

Would generate a series of individual page objects but I can’t see how to turn them into a single dv.pages object.

Any suggestions?

Thanks in advance

I think you can put them in an array, and use dv.array(), and it would behave similarly.

But might I ask why you want them to do this? What are you going to use the result for afterwards?

Thanks. I read that in the documentation and tried it, with some Javascript like:

const pags = [“/Misc/A/a.md”], [“/Projects/B/b.md”], [“/Summaries/C/c.md”];

and then

const pages = dv.array(pags)

but when I try and use it in some Javascript, an error is generated:

Evaluation Error: SyntaxError: Invalid or unexpected token

Why do I want it? Because I have a header section (Key Points, where I write a summary of the content) in some pages that I want to pull out into another page, kind of an overall summary page. I currently do this with the following code (based upon something a kind soul left somewhere else in this forum):

const header = ‘## Key Points’
const pages = dv.pages("${dv.current().file.folder}").sort()

const regex = new RegExp(\n${header}\r?\n(.*?)(\n#+ |\n---|$), ‘s’)

for (const page of pages) {
const file = app.vault.getAbstractFileByPath(page.file.path)
const contents = await app.vault.read(file)
const summary = contents.match(regex)
if (summary) {
dv.header(2, file.basename)
dv.paragraph(summary[1].trim())
}
}

Works perfectly! The problem is that I want to be more selective and not just process all the pages in one folder, I want to build a list of files and then process them, extracting the Key Points section.

Building on the code you presented here, I would rather switch it around a little, and let the start of your script look like:

[“/Summaries/C/c.md”];
const header = '## Key Points'
const regex = new RegExp(\n${header}\r?\n(.*?)(\n#+ |\n---|$), 's')
const pageNames = [
  "/Misc/A/a.md", 
  "/Projects/B/b.md", 
  "/Summaries/C/c.md"
];

for (const pageName of pageNames) {
  const page = dv.page(pageName)
  const file = app.vault.getAbstractFileByPath(page.file.path)
  ... same as before ...
}

I’ve not tested this, but it should work. And it could possibly work with just doing this at the start of the for loop:

for (const pageName of pageNames) {
  const file = app.vault.getAbstractFileByPath(pageName)
  ...
}

And then you wouldn’t actually need to do the dv.page() read first at all.

Bonus tip: How to present code properly in a forum post

If you want to showcase either markdown, or code blocks, or dataview queries properly in a forum post, be sure to add one line before and one life after what you want to present with four backticks, ````. This will ensure that any other backticks (like for code blocks or queries) is properly shown.

1 Like

Wow, many, many thanks for your help. I have added a version of this code to a real example, to test it out:

```dataviewjs
const header = '## Notes' 
const regex = new RegExp(\n${header}\r?\n(.*?)(\n#+ |\n---|$), 's') 
const pageNames = [
	"/Daily Notes/05/W19/2023-05-12.md",
	"/Daily Notes/05/W19/2023-05-13.md",
	"/Daily Notes/05/W19/2023-05-14.md" ]; 

for (const pageName of pageNames) { 
	const page = dv.page(pageName) 
	const file = app.vault.getAbstractFileByPath(page.file.path) 
	
	const contents = await app.vault.read(file)
	const summary = contents.match(regex)
	if (summary) {
	    Output the header and summary
	    dv.header(2, file.basename)
	    dv.paragraph(summary[1].trim())
	}
}
```

Which generates the following error:

Evaluation Error: SyntaxError: Invalid or unexpected token
    at DataviewInlineApi.eval (plugin:dataview:18370:21)
    at evalInContext (plugin:dataview:18371:7)
    at asyncEvalInContext (plugin:dataview:18378:16)
    at DataviewJSRenderer.render (plugin:dataview:18402:19)
    at DataviewJSRenderer.onload (plugin:dataview:17986:14)
    at e.load (app://obsidian.md/app.js:1:631178)
    at DataviewApi.executeJs (plugin:dataview:18921:18)
    at DataviewPlugin.dataviewjs (plugin:dataview:19423:18)
    at eval (plugin:dataview:19344:124)
    at app://obsidian.md/app.js:1:1186678

What I am doing wrong?

BTW, while were on the subject, I don’t understand the relation between the line numbers in the error message and my lines of code. Which line tells me where the error is being generated?

I’ve not found a reliable relationship between the line numbers in the error messages, and the actual line of the errors. So sometimes I just know which area I was working within, and see the error easily, and sometimes I need to add other code (or even introduce a known error to locate it.

In this case, I think it was introduced when I copied your code from plain text, so I lost the backticks in the regex line. Try with the following:

const regex = new RegExp(`\n${header}\r?\n(.*?)(\n#+ |\n---|$)`, 's')

I’m not able to test it out today, as I’m rather busy, but if this fix fails, let us know, and we’ll figure it out.

1 Like

Add // before “Output the …” near the end

1 Like

Thanks holroy, yes indeed, that fixed it, it works!!

Sorry but I managed to delete my previous message…

Kind regards!

One last question holroy, if that is OK.

You can get a list of all the pages from a folder with:

const pages = dv.pages("${dv.current().file.folder}").sort()

Is there anyway to remove one page from that list, if, for example, it has a capital W in the title?

Thanks

OK, i’ve figured it out, just in case it is of interest to anyone…

```dataviewjs
const FolderPath = '"Where the folder is"'
dv.list(dv.pages(FolderPath)
.where(page => !page.file.name.includes("W")))
```

Thanks anyway!