Export topic as markdown

I found this UI: Topic and Category Export/Import but that does not cover what I was thinking about:

  • A means to export an entire public or DM topic as a single markdown document where the export action is UI-accessible to all the participants in said topic.

And maybe (but for me not required) to have this feature available for anyone on public topics.


I interact with many Discourse forums publicly and DM’ingly and have a need to archive discussions there in a personal markdown-based knowledge base. This is not only very time-consuming, but I can’t get the raw markdown of other people’s posts in forums where I’m not mod or admin (logically), so I have to recreate it manually.

7 „Gefällt mir“

You can already access the raw markdown to topics:
Https://meta.discourse.org/raw/152185

2 „Gefällt mir“

Thanks, that would be so cool. But it only returns the first post in the topic and not the entire conversation thread.

Edit: More doable, by iterating over each post in the thread in raw mode, but for a thread with 60 posts still a lot of work. Furthermore it contains only the body of the post and there is no information on who posted, and when.

You can use the print function on a topic and save the output to a pdf. It is not markdown but it is easy!

1 „Gefällt mir“

Thank you, yes, I sometimes use that, but the content becomes ‘locked in’. It does not fit well with my knowledge base (create cross-links, etc.). Markdown is so simple and easy to work with, that I select all my tools around it. It is a great timesaver if you can just move MD snippets around all over the place.

2 „Gefällt mir“

I was just asked that question yesterday. Are you referring to the print function of the browser? Or is there a Discourse feature to print the entire topic thread that I am not seeing?

https://meta.discourse.org/t/print-long-topic-to-pdf-redux-again/44639/37?u=falco

2 „Gefällt mir“

Funny, I too would like something like this! So just another vote of support, I guess…

Hallo,

Ich habe gerade ein Konto hier erstellt, um mich einzubringen und zu sagen, dass ich auch denke, dass diese Art von Funktion sehr wichtig ist!

Der Druck (als PDF) funktioniert derzeit nicht gut mit Threads, die Codeblöcke enthalten, da diese nicht umgebrochen oder erweitert werden, sodass Dinge abgeschnitten werden.

Ich denke, eine zuverlässige und ziemlich einfache Möglichkeit, Inhalte aus Discourse zu extrahieren, beispielsweise zu Archivierungszwecken, ist wirklich wichtig.

Ein weiterer Punkt zur Berücksichtigung: Ich nehme an einem Forum teil, das gerade viele Benutzer von einer geschlossenen Mailingliste zusammengeführt hat – während der Übergangsdiskussionen darüber, ob die Mailingliste aktiv bleiben oder vollständig auf das Forum umsteigen soll, sagte ein blindes Mitglied, dass es aufgrund mangelnder Unterstützung für textbasierte Browser nicht am Forum teilnehmen könne. Ich denke, ein richtiger Rohmodus mit Autorenzuordnung und allen Threads würde zu mehr Inklusion beitragen.

2 „Gefällt mir“

Mal sehen. Ich füge hier einen Codeblock mit einer ganzen Menge Code ein und sehe, wie er gedruckt aussieht:

import java.util.Scanner;

/**
 * Spiel von AceyDucey
 * 
 * Basiert auf dem einfachen Spiel AceyDucey hier
 * https://github.com/coding-horror/basic-computer-games/blob/main/01%20Acey%20Ducey/aceyducey.bas
 * Hinweis: Die Idee war, eine Version des Basic-Spiels aus den 1970er Jahren in Java zu erstellen, ohne neue Funktionen einzuführen - es wurden keine zusätzlichen Texte, Fehlerprüfungen usw. hinzugefügt.
 */
public class AceyDucey {

    // Aktueller Geldbetrag des Spielers
    private int playerAmount;

    // Erste gezogene Dealer-Karte
    private Card firstCard;

    // Zweite gezogene Dealer-Karte
    private Card secondCard;

    // Vom Spieler gezogene Karte
    private Card playersCard;

    // Benutzer zur Anzeige der Spieleinführung/Anweisungen
    private boolean firstTimePlaying = true;

    // Spielstatus zur Bestimmung, ob das Spiel vorbei ist
    private boolean gameOver = false;

    // Wird für Tastatureingaben verwendet
    private final Scanner kbScanner;

    // Konstante für Karten aus einem Deck - 2 niedrigste, 14 (Ass) höchste
    public static final int LOW_CARD_RANGE = 2;
    public static final int HIGH_CARD_RANGE = 14;

    public AceyDucey() {
        // Spieler-Geld initialisieren
        playerAmount = 100;

        // kb-Scanner initialisieren
        kbScanner = new Scanner(System.in);
    }

    // Erneut spielen-Methode - öffentliche Methode, die von der aufrufenden Klasse aufgerufen wird
    // Wenn der Spieler JA eingibt, kann das Spiel erneut gespielt werden (true zurückgegeben)
    // andernfalls nicht (false)
    public boolean playAgain() {
        System.out.println();
        System.out.println("ES TUT MIR LEID, FREUND, ABER DU HAST DEIN GELD VERSP कर. ");
        System.out.println();
        System.out.println();
        System.out.print("VERSUCH ES NOCHMAL (JA ODER NEIN) ");
        String playAgain = kbScanner.next().toUpperCase();
        System.out.println();
        System.out.println();
        if (playAgain.equals("JA")) {
            return true;
        } else {
            System.out.println("OK, ICH HOFFE, DU HATTEST SPASS!");
            return false;
        }
    }

    // Spielschleifen-Methode

    public void play() {

        // Hände weiterspielen, bis der Spieler kein Geld mehr hat
        do {
            if (firstTimePlaying) {
                intro();
                firstTimePlaying = false;
            }
            displayBalance();
            drawCards();
            displayCards();
            int betAmount = getBet();
            playersCard = randomCard();
            displayPlayerCard();
            if (playerWon()) {
                System.out.println("DU GEWINNST!!");
                playerAmount += betAmount;
            } else {
                System.out.println("ES TUT MIR LEID, DU VERLIERST");
                playerAmount -= betAmount;
                // Hat der Spieler kein Geld mehr?
                if (playerAmount <= 0) {
                    gameOver = true;
                }
            }

        } while (!gameOver); // Weiterspielen, bis der Spieler kein Geld mehr hat
    }

    // Methode zur Bestimmung, ob der Spieler gewonnen hat (true zurückgegeben) oder verloren hat (false zurückgegeben)
    // Um zu gewinnen, muss eine Spielerkarte im Bereich der ersten und zweiten gezogenen Dealer-Karten liegen,
    // einschließlich der ersten und zweiten Karten.
    private boolean playerWon() {
        // Gewinner
        return (playersCard.getValue() >= firstCard.getValue())
                && playersCard.getValue() <= secondCard.getValue();

    }

    private void displayPlayerCard() {
        System.out.println(playersCard.getName());
    }

    // Holt die Wette des Spielers und gibt den Betrag zurück
    // 0 gilt als gültige Wette, aber mehr als der Spieler zur Verfügung hat, ist nicht gültig
    // Die Methode wird so lange wiederholt, bis eine gültige Wette eingegeben wird.
    private int getBet() {
        boolean validBet = false;
        int amount;
        do {
            System.out.print("WAS IST DEINE WETTE ");
            amount = kbScanner.nextInt();
            if (amount == 0) {
                System.out.println("FEIGLING!!");
                validBet = true;
            } else if (amount > playerAmount) {
                System.out.println("ES TUT MIR LEID, MEIN FREUND, ABER DU WETTST ZU VIEL.");
                System.out.println("DU HAST NUR " + playerAmount + " DOLLAR ZUM WETTEN.");
            } else {
                validBet = true;
            }
        } while (!validBet);

        return amount;
    }

    private void displayBalance() {
        System.out.println("DU HAST JETZT " + playerAmount + " DOLLAR.");
    }

    private void displayCards() {
        System.out.println("HIER SIND DEINE NÄCHSTEN ZWEI KARTEN: ");
        System.out.println(firstCard.getName());
        System.out.println(secondCard.getName());
    }

    // Zieht zwei Dealer-Karten und speichert sie für die spätere Verwendung.
    // Stelle sicher, dass die erste Karte einen kleineren Wert hat als die zweite.
    private void drawCards() {

        do {
            firstCard = randomCard();
            secondCard = randomCard();
        } while (firstCard.getValue() >= secondCard.getValue());
    }

    // Erstellt eine zufällige Karte
    private Card randomCard() {
        return new Card((int) (Math.random()
                * (HIGH_CARD_RANGE - LOW_CARD_RANGE + 1) + LOW_CARD_RANGE));
    }

    public void intro() {
        System.out.println("ACEY DUCEY KARTENSPIEL");
        System.out.println("CREATIVE COMPUTING  MORRISTOWN, NEW JERSEY");
        System.out.println();
        System.out.println();
        System.out.println("ACEY-DUCEY WIRD FOLGENDERMASSEN GESPIELT");
        System.out.println("DER DEALER (COMPUTER) GIBT ZWEI KARTEN AUF DECK");
        System.out.println("DU HAST DIE OPTION ZU WETTEN ODER NICHT ZU WETTEN, JE NACHDEM");
        System.out.println("OB DU DENKST, DASS DIE KARTE EINEN");
        System.out.println("WERT ZWISCHEN DEN ERSTEN BEIDEN HAT.");
        System.out.println("WENN DU NICHT WETTEN MÖCHTEST, GIB EIN: 0");
    }
}

Beachten Sie, dass wir eine ziemlich vollständige Barrierefreiheitsunterstützung haben. Ich wäre daran interessiert zu erfahren, was für Ihren blinden Benutzer @thresholdpeople speziell nicht funktioniert.

Auch der obige Codeblock sieht für mich in der gedruckten Version in Ordnung aus. Ich habe gerade in Chrome auf “Drucken” und dann auf “Als PDF speichern” geklickt, um eine PDF-Version dieses Themas zu erstellen:

Thema als Markdown exportieren - Feature - Discourse Meta.pdf (249,9 KB)

Ich sehe kein Problem. Bitte weisen Sie auf bestimmte Bereiche in der PDF-Datei hin, die nicht korrekt sind, wenn Sie ein Problem sehen. Danke!

Vielen Dank, dass Sie sich darum kümmern.

Ich benutze Vivaldi, aber ich habe auch Chrome benutzt, verschiedene Computer, nicht alle mit synchronisierten Browsereinstellungen, aber wenn ich Ihren Codeblock drucke, wird er abgeschnitten bei:

     // Players drawn card
     private Card playersCard;

was auch alles ist, was ich sehen kann, bis ich Ihren Beitrag inline ansehe (ich muss innerhalb des Code-Frames nach unten scrollen, um mehr zu sehen). Ich würde meine Version posten, aber ich habe nicht genug Beiträge, um Dateien hochzuladen, aber Sie verstehen, was ich meine.

Ihre gedruckte Version sieht sicherlich besser aus, ich bin mir nicht sicher, warum sie überhaupt anders ist, aber sie ist auch nicht perfekt. Codezeilen werden nicht umgebrochen und sind somit abgeschnitten, und alle Seiten haben ein schwebendes blaues Rechteck unten links, das auch Text verdeckt. In diesem Zustand ist es leider auch nicht wirklich nutzbar.

Jemand im SuperCollider-Forum hat die Lösung angeboten, den folgenden CSS-Block entweder in den Browser-Inspektor einzufügen oder bei Verwendung eines Browser-Plugins (derzeit habe ich die Chrome-Erweiterung Stylish, und sie fügt ihn automatisch hinzu, wenn ich auf diesem Forum bin):

pre code {
    white-space: 	pre-wrap;
    max-height: 	none;
    background: 	#fafafa;
}

Die Verwendung dieses Codes lässt das Drucken bei mir einwandfrei funktionieren. Und mit der Browser-Erweiterung muss ich nicht jedes Mal, wenn ich etwas speichern möchte, hineingehen und es mühsam hinzufügen, was die eigentliche Lösung ist… sonst ist es zu viel Arbeit.

Dennoch wünschte ich, es gäbe eine einfachere Möglichkeit, Threads zu archivieren, oder besser gesagt, ich wünschte, es gäbe eine Möglichkeit, diese zusätzlichen Schritte nicht zu benötigen.

Besonders da die meiste Funktionalität bereits vorhanden ist: entweder einen Beitrag roh anzeigen oder drucken können. Aber ja, es ist nicht möglich, den gesamten Thread roh anzuzeigen, nur einen einzelnen Beitrag, und das Drucken funktioniert nicht gut.

Davon abgesehen sind Lesezeichen eine großartige Forum-Funktion und ich benutze sie ständig, aber sie behält trotzdem alles innerhalb von Discourse.

1 „Gefällt mir“

Wir könnten eine Route hinzufügen, die das gesamte Thema als Rohdaten im @falco-Format zurückgibt? Das könnte nützlich sein, obwohl wir bei Megathemen vorsichtig sein müssen.

Wir haben dies sicherlich bereits für einzelne Beiträge, z. B.

https://meta.discourse.org/raw/152185/12

3 „Gefällt mir“

Das ist sicherlich machbar, wenn auch ein eher nischenhafter Anwendungsfall.

Das Format wäre in etwa so:

username | timestamp | post_number

post body

---

username | timestamp | post_number

post body

---

username | timestamp | post_number

post body

?

2 „Gefällt mir“

Ja, ich unterstütze es aber. Wenn wir eine /raw/-Route für Beiträge haben, warum nicht auch eine für ein Thema?

2 „Gefällt mir“

Derzeit gibt die Route https://meta.discourse.org/raw/152185 nur den OP zurück. Ist es in Ordnung, das Verhalten dieser Route zu ändern? Benutzer müssen https://meta.discourse.org/raw/152185/1 explizit aufrufen, um nur den OP zu erhalten.

2 „Gefällt mir“

Was immer Sie für am besten halten, ist für mich in Ordnung.

2 „Gefällt mir“

Das ist jetzt live: https://meta.discourse.org/raw/152185

Lass mich wissen, ob das das ist, was du dir vorgestellt hast @here

8 „Gefällt mir“

Liebe es! Sieht gut aus! :heart_eyes:

3 „Gefällt mir“

Das ist wirklich großartig. Danke :pray:

3 „Gefällt mir“

Vielen Dank! und mehr Charaktere!

2 „Gefällt mir“