Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OPML Export #2639

Open
AuroraMartell opened this issue Jan 25, 2025 · 31 comments
Open

OPML Export #2639

AuroraMartell opened this issue Jan 25, 2025 · 31 comments

Comments

@AuroraMartell
Copy link

Describe the solution you'd like
Would it be possible to add the option to export nodes to .opml? OPML is used by Scrivener to automatically populate a project when importing a .opml file.

If it helps I can produce a sample OPML file so you can see how they're formatted.

Thank you (:

@gitvectors
Copy link

Scrivener is Windows mainly and I am on Ubuntu.

However here is a thought

https://github.com/edavis/pandoc-opml

  • Export CT to HTML

  • Pandoc HTML to Markdown

  • Markdown to OPML

On reflection my preference would be to have CT export to Scribus. *.sla which is XML format.

@AuroraMartell
Copy link
Author

Scrivener is Windows mainly and I am on Ubuntu.

However here is a thought

https://github.com/edavis/pandoc-opml

* Export CT to HTML

* Pandoc HTML to Markdown

* Markdown to OPML

On reflection my preference would be to have CT export to Scribus. *.sla which is XML format.

I export to TXT and use Panwriter to convert from Markdown to OPML, but native export would save a few clicks.

@gitvectors
Copy link

Remembering that some years ago Scrivener was available as Linux AppImage I downloaded just to refresh my experience of some years earlier. That works.

https://www.reddit.com/r/scrivener/comments/102pvtk/scrivener_on_linux_abandoned/

Scrivener for Linux

https://www.linux-apps.com/p/1673680/

To run a Scrivener AppImage in Linux, download the AppImage file, make it executable using chmod +x scrivener.appimage, and then simply double-click or run it from the command line by typing ./scrivener.appimage. 

Now I see that in addition to OPML, rtf can be imported.

Searching .. this workaround comes up ...

To export a CherryTree document as an RTF file, you cannot directly export to RTF format within the application itself; CherryTree only offers export options like HTML, PDF, and plain text.
Workarounds to export CherryTree as RTF:
Export to HTML and convert using a word processor:
Export your CherryTree document as HTML.
Open the exported HTML file in a word processor like Microsoft Word or LibreOffice Writer.
Save the document in RTF format within the word processor.

What you might do is write a CodeBox Python script in CT to run this workflow if you want to "minimise your clicks". What ate a few extra clicks? You can automate clicks in UI macros.

This thread does trigger thoughts on exporting CT to other apps, other than Scrivener. For example using CT as a prototyping platform then post content to other applications. For say web development. I see CodeBox as the extension of toolbar without need for new features.

Interesting after thoughts are
CherryTree to Zettlr (Markdown)
CherryTree to Pandoc
CherryTree to PHPStorm
and so on ..

@AuroraMartell
Copy link
Author

What you might do is write a CodeBox Python script in CT to run this workflow if you want to "minimise your clicks". What ate a few extra clicks? You can automate clicks in UI macros.

I'm not a coder, though. I'm a writer 😂

@gitvectors
Copy link

Fair enough. It seems that there have been previous requests.

#1859

Although you are not a coder there are companion tools which can "drive" your CT operations as macros. Emulating key presses and the like.

In Windows there is autohotkey but another cross platform tool is Actiona.
I'll experiment (when I find some time) since I have a similar requirement for other export operations to other editors.

@AuroraMartell
Copy link
Author

Although you are not a coder there are companion tools which can "drive" your CT operations as macros. Emulating key presses and the like.

In Windows there is autohotkey but another cross platform tool is Actiona. I'll experiment (when I find some time) since I have a similar requirement for other export operations to other editors.

Do you have any resources for that?

@gitvectors
Copy link

gitvectors commented Jan 26, 2025

I seem to have cracked it with the help of an AI companion (Phind.com). I had recollected some prior experience in using xml.etree.ElementTree - The ElementTree XML API (look it up).

I posed the scenario of a CT document dedicated to document conversion, remembering that *.ctd is in fact XML. The first attempt required a Python script alongside the *.ctd document to be converted but a more general usage is to have a dialogue to choose in a dialogue the CherryTree *.ctd file to be converted.

I created a dedicated CherryTree document for running such conversions ahead.

I created one node for OPML conversion. Other nodes can be setup for different conversions ahead.

In there I created a CodeBox and inserted the following script. Delete the opening/closing characters `` when pasting into CodeBox. The just Execute the CodeBox Python script. The OPML might need more tweaking to be understood by Scrivener but the principle is demonstrated.

`import tkinter as tk
from tkinter import filedialog
import xml.etree.ElementTree as ET
from xml.dom import minidom

def ctd_to_opml(ctd_file):
tree = ET.parse(ctd_file)
root = tree.getroot()

opml = ET.Element("opml")
head = ET.SubElement(opml, "head")
body = ET.SubElement(opml, "body")

def process_node(node):
    opml_node = ET.SubElement(body, "outline")
    for attr in node.attrib:
        opml_node.set(attr, node.attrib[attr])
    opml_node.text = node.text
    for child in node:
        process_node(child)

process_node(root)

pretty_xml = minidom.parseString(ET.tostring(opml))
return pretty_xml.toprettyxml(indent="  ")

def convert_files():
root = tk.Tk()
root.withdraw()

# Ask for input file path
ctd_file = filedialog.askopenfilename(
    title="Select CherryTree .ctd file",
    filetypes=[("CherryTree files", "*.ctd")]
)

if not ctd_file:
    print("No file selected. Exiting.")
    return

# Ask for output file path
opml_file = filedialog.asksaveasfilename(
    defaultextension=".opml",
    filetypes=[("OPML files", "*.opml")]
)

if not opml_file:
    print("No file saved. Exiting.")
    return

try:
    opml_content = ctd_to_opml(ctd_file)
    with open(opml_file, "w") as f:
        f.write(opml_content)
    print(f"Conversion successful. Output saved to {opml_file}")
except Exception as e:
    print(f"An error occurred during conversion: {e}")

if name == "main":
convert_files()`

@AuroraMartell
Copy link
Author

I seem to have cracked it with the help of an AI companion (Phind.com). I had recollected some prior experience in using xml.etree.ElementTree - The ElementTree XML API (look it up).

I posed the scenario of a CT document dedicated to document conversion, remembering that *.ctd is in fact XML. The first attempt required a Python script alongside the *.ctd document to be converted but a more general usage is to have a dialogue to choose in a dialogue the CherryTree *.ctd file to be converted.

I created a dedicated CherryTree document for running such conversions ahead.

I created one node for OPML conversion. Other nodes can be setup for different conversions ahead.

In there I created a CodeBox and inserted the following script. Delete the opening/closing characters `` when pasting into CodeBox. The just Execute the CodeBox Python script. The OPML might need more tweaking to be understood by Scrivener but the principle is demonstrated.

`import tkinter as tk from tkinter import filedialog import xml.etree.ElementTree as ET from xml.dom import minidom

def ctd_to_opml(ctd_file): tree = ET.parse(ctd_file) root = tree.getroot()

opml = ET.Element("opml")
head = ET.SubElement(opml, "head")
body = ET.SubElement(opml, "body")

def process_node(node):
    opml_node = ET.SubElement(body, "outline")
    for attr in node.attrib:
        opml_node.set(attr, node.attrib[attr])
    opml_node.text = node.text
    for child in node:
        process_node(child)

process_node(root)

pretty_xml = minidom.parseString(ET.tostring(opml))
return pretty_xml.toprettyxml(indent="  ")

def convert_files(): root = tk.Tk() root.withdraw()

# Ask for input file path
ctd_file = filedialog.askopenfilename(
    title="Select CherryTree .ctd file",
    filetypes=[("CherryTree files", "*.ctd")]
)

if not ctd_file:
    print("No file selected. Exiting.")
    return

# Ask for output file path
opml_file = filedialog.asksaveasfilename(
    defaultextension=".opml",
    filetypes=[("OPML files", "*.opml")]
)

if not opml_file:
    print("No file saved. Exiting.")
    return

try:
    opml_content = ctd_to_opml(ctd_file)
    with open(opml_file, "w") as f:
        f.write(opml_content)
    print(f"Conversion successful. Output saved to {opml_file}")
except Exception as e:
    print(f"An error occurred during conversion: {e}")

if name == "main": convert_files()`

I'll test this tomorrow (:

But how do I make a codebox?

@gitvectors
Copy link

On second thoughts it might be easier for you to just run the Python script in the same location (directory) as your CT document. Avoids the need for you to get to grips with CodeBoxes you can learn later .. optional.

@AuroraMartell
Copy link
Author

On second thoughts it might be easier for you to just run the Python script in the same location (directory) as your CT document. Avoids the need for you to get to grips with CodeBoxes you can learn later .. optional.

I don't have Python on my system, tho. I only have a 500gb drive so I'm stingy with space.

@AuroraMartell
Copy link
Author

On second thoughts it might be easier for you to just run the Python script in the same location (directory) as your CT document. Avoids the need for you to get to grips with CodeBoxes you can learn later .. optional.

Does python take up too much space?

@gitvectors
Copy link

Looking again I suspect that OPML route/experiments might go down a rabbit hole. Having looked at internal structure of Scrivener (Linux) I think that it might be easier to build a script (such as in Actiona UI emulator) to copy and paste from CT node hierarchy into Scrivener project. Just grabbing rtf content.

Read here ..

https://scrivener.tenderapp.com/help/kb/cloud-syncing/using-scrivener-with-cloud-sync-services

So CherryTree might push content into dropbox and your Scrivener could pull content.

Now that I have Scrivener installed (it has superior formatting options for reports) I will experiment. I would also point to Zettlr Markdown editor.

@gitvectors
Copy link

P.S. read warning here from above link:

Note on External Folder Sync
External folder sync is intended for working on files in other programs and then being able to sync them back to Scrivener. You should never try to use external folder sync to synchronise Scrivener projects between machines - if you do so, you will corrupt your project and see some very odd results.

For more information, visit §14 Cloud Integration and Sharing in the Scrivener manual.

@AuroraMartell
Copy link
Author

P.S. read warning here from above link:

Note on External Folder Sync External folder sync is intended for working on files in other programs and then being able to sync them back to Scrivener. You should never try to use external folder sync to synchronise Scrivener projects between machines - if you do so, you will corrupt your project and see some very odd results.

For more information, visit §14 Cloud Integration and Sharing in the Scrivener manual.

I already knew this, I'm an advanced Scrivener user.

@gitvectors
Copy link

I have given up on trying to second guess your planned workflow as an advanced Scrivener user. I have found other advanced users but not having Python experience is an obstacle. I do conclude that OPML might be a red herring as first stage (although that route is possible, just harder). I can write that in my own dual boot setup (Windows/Ubuntu) I have Scrivener+CherryTree installed both sides (Windows+Ubuntu) and I can CherryTree export nodes into a shared vault (not Dropbox but a shared NTFS partition) so that I can keep both in sync. That is CherryTree exported nodes appear on corkboards (Windows and Ubuntu) for further processing. I can also sync with a cloud based vault for secure sharing.
CherryTree is handy frontend tool for structuring and scaffolding parts of documents but falls short on professional document production. So the pairing of CherryTree with Scrivener is a good move. But also similar pairing can be built between CherryTree and Scribus and indeed other editors. Scribus is next on list. OPML I will look at later.

@AuroraMartell
Copy link
Author

I have given up on trying to second guess your planned workflow as an advanced Scrivener user. I have found other advanced users but not having Python experience is an obstacle. I do conclude that OPML might be a red herring as first stage (although that route is possible, just harder). I can write that in my own dual boot setup (Windows/Ubuntu) I have Scrivener+CherryTree installed both sides (Windows+Ubuntu) and I can CherryTree export nodes into a shared vault (not Dropbox but a shared NTFS partition) so that I can keep both in sync. That is CherryTree exported nodes appear on corkboards (Windows and Ubuntu) for further processing. I can also sync with a cloud based vault for secure sharing. CherryTree is handy frontend tool for structuring and scaffolding parts of documents but falls short on professional document production. So the pairing of CherryTree with Scrivener is a good move. But also similar pairing can be built between CherryTree and Scribus and indeed other editors. Scribus is next on list. OPML I will look at later.

You got me at Scribus. Please share (:

@gitvectors
Copy link

gitvectors commented Jan 29, 2025

Here you go.

Try shaping text flow around images.
Or using Python scripts such as ScribusGenerator.

On a par with Scrivener. Both excellent tools but CherryTree can feed both.

@AuroraMartell
Copy link
Author

Here you go.

Try shaping text flow around images. Or using Python scripts such as ScribusGenerator.

On a par with Scrivener. Both excellent tools but CherryTree can feed both.

But I use text, not images.

@gitvectors
Copy link

But I use text, not images.

@gitvectors
Copy link

"But I use text, not images"
Then your task is made even simpler. Concentrate on "textframes" ignore "imageframes".
And you might consider only a markdown editor such as Zettlr in association with CherryTree and Pandoc. The front end "node export idea" of CherryTree applies for all. Indeed OPML creation also becomes simpler.

Might I suggest that when you next post some new issue .. wherever .. you set out in advance your constraints, and the context of your issue?

Windows, Linux, Mac.
Text only.
No images
No code blocks
No coding experience.

Saves a lot of time both sides.
But consider the pipeline flow for any project.

@AuroraMartell
Copy link
Author

"But I use text, not images" Then your task is made even simpler. Concentrate on "textframes" ignore "imageframes". And you might consider only a markdown editor such as Zettlr in association with CherryTree and Pandoc. The front end "node export idea" of CherryTree applies for all. Indeed OPML creation also becomes simpler.

Might I suggest that when you next post some new issue .. wherever .. you set out in advance your constraints, and the context of your issue?

Windows, Linux, Mac.
Text only.
No images
No code blocks
No coding experience.

Saves a lot of time both sides. But consider the pipeline flow for any project.

Noted.

@gitvectors
Copy link

Final tip then we can move on ..

Stumbled onto this site when searching around Scrivener uses.
My writing is technical rather than novels but you might find some empathy there.

@AuroraMartell
Copy link
Author

Final tip then we can move on ..

Stumbled onto this site when searching around Scrivener uses. My writing is technical rather than novels but you might find some empathy there.

Thank you (:

Probably will continue to use my current workflow until some kind soul replicates OmniOutliner for Windows 11 and Linux.

@gitvectors
Copy link

Re: OmniOutliner quest.
I'm now starting to explore Obsidian, with idea of working with CT as front end curator of ideas.

@AuroraMartell
Copy link
Author

Re: OmniOutliner quest. I'm now starting to explore Obsidian, with idea of working with CT as front end curator of ideas.

I tried that. Too complicated. I use Keynote NF as a companion to CT + Pandoc.

@gitvectors
Copy link

O.K. I read this article and thought I might try it.

@AuroraMartell
Copy link
Author

O.K. I read this article and thought I might try it.

It works for some but not for me.

@gitvectors
Copy link

as a companion to CT + Pandoc

That is fine for CT text only export (as you confirmed you use) but more tweaking is required when images plus text (HTML) pass through Pandoc to achieve same quality as Scrivener/Scribus. Perhaps a Lua script might achieve this formatting.

@AuroraMartell
Copy link
Author

as a companion to CT + Pandoc

That is fine for CT text only export (as you confirmed you use) but more tweaking is required when images plus text (HTML) pass through Pandoc to achieve same quality as Scrivener/Scribus. Perhaps a Lua script might achieve this formatting.

I don't need CT to replicate Scrivener but you got me at Lua script. What could be done using Lua?

@gitvectors
Copy link

Perhaps not a good idea if you are not into coding (I forgot that earlier constraint).

But here are examples:

https://pandoc.org/try/

Set: Markdown to RST .. example.

@AuroraMartell
Copy link
Author

Perhaps not a good idea if you are not into coding (I forgot that earlier constraint).

But here are examples:

https://pandoc.org/try/

Set: Markdown to RST .. example.

I'm fine with pandoc (but I do use PanWriter as a "frontend")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants