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 · 11 comments
Open

OPML Export #2639

AuroraMartell opened this issue Jan 25, 2025 · 11 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?

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