Einen „Quelltext anzeigen“-Button erstellen

Avatar of Chris Coyier
Chris Coyier am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Remy Sharps coole Seite für HTML5-Demos hat auf jeder der einzelnen Demo-Seiten einen „Quelltext anzeigen“-Button. Klicke darauf und du siehst den gesamten Quellcode der Seite, die du gerade betrachtest. Es ist kein Popup und keine neue Registerkarte, sondern zeigt den Quelltext direkt auf der Seite an. Ich fand das cool, also habe ich beschlossen, es auf meine eigene Art nachzubilden.

Der schicke Weg

Demo anzeigen   Dateien herunterladen

Die erste Idee, die mir in den Sinn kam, war die Verwendung der :target-Pseudoklasse von CSS3. Wir haben vor einiger Zeit darüber gesprochen, als wir CSS3-Tabs exportiert haben. Die Idee ist, einen Link zu haben, der zur Hash-ID #source-code verlinkt. Das fügt #source-code am Ende der URL hinzu und ermöglicht es dem :target-Selektor, Styling abzugleichen und anzuwenden. Die Grundlagen

<a href="#source-code">View Source</a>
#source-code { display: none; }
#source-code:target { display: block; }

Jetzt geht es nur noch darum, dieses #source-code-Element mit dem tatsächlichen Quellcode zu füllen. Das ist JavaScript-Territorium, da wir diesen Code dynamisch abrufen wollen, anstatt den Quellcode tatsächlich nur zur Anzeige zu wiederholen. So müssen wir nichts anpassen, wenn wir die Seite ändern; unser Quelltext-Button zeigt den aktualisierten Quelltext, wie er geschrieben ist. Wir können uns auf jQuery verlassen, um dies für uns zu erledigen.

var html = $("html").html();

Das gibt uns den gesamten HTML-Code der Seite, ausgenommen nur den DOCTYPE und die tatsächlichen <html>-Tags. Du könntest auch über document.documentElement.innerHTML darauf zugreifen, aber hey, wenn wir schon jQuery verwenden, dann nehmen wir es auch. Wir erstellen ein brandneues <pre>-Element, füllen es mit einem „falschen“ DOCTYPE und HTML-Tags und fügen dann das gerade von der Seite gesammelte HTML ein.

Ein paar schnelle Überlegungen zu dem gesammelten HTML: 1) Lassen Sie uns die <-Zeichen maskieren, damit sie korrekt auf der Seite angezeigt werden, ohne als tatsächliches HTML gerendert zu werden. 2) Lassen Sie uns alle Links „verlinken“, damit sie klickbar sind (teilweise von hier übernommen).

Dann platzieren wir dieses neu erstellte <pre>-Element in unserem #source-code Div.

$(function() {
	$("<pre />", {
		"html":   '&lt;!DOCTYPE html>\n&lt;html>\n' + 
				$("html")
					.html()
					.replace(/[<>]/g, function(m) { return {'<':'&lt;','>':'&gt;'}[m]})
					.replace(/((ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?)/gi,'<a href="$1">$1</a>') + 
				'\n&lt;/html>'
	}).appendTo("#source-code");
});

Das Schließen des Quellcodes ist köstlich einfach. Da der „Quelltext anzeigen“-Button beim Klicken eine Hash-ID zur Seite hinzufügt, bedeutet das, dass der „Zurück“-Button im Browser funktioniert. Das Drücken entfernt die Hash-ID, sodass #source-code nicht mehr :targetet wird und automatisch durch CSS ausgeblendet wird. Das #source-code Div enthält auch eine einfache „X“-Grafik, die zur Hash-ID „#“ verlinkt, was exakt denselben Effekt hat.

Dies verlinkt einfach auf „#“, was unser Quelltext-Anzeigeelement aus :target nimmt, was es sofort ausblendet.

Formatierung des Codes

Eine der einfachsten Möglichkeiten, die Syntax hervorzuheben, ist das google-code-prettify-Projekt. Dies ist ein JavaScript-basierter Highlighter. Im Wesentlichen verlinken Sie die JavaScript-Datei und die CSS-Datei, die mit dem Download geliefert werden.

<link rel='stylesheet' href='css/prettify.css' />
<script src="prettify/prettify.js"></script>

Stellen Sie sicher, dass Ihre <pre>-Tags die Klasse „prettyprint“ haben. Ich habe dies zur Elementerstellungssyntax hinzugefügt, die wir verwenden, um das <pre> zu erstellen.

"class": "prettyprint"

und rufen Sie die Funktion prettyPrint() auf, wenn die Seite bereit ist. Sie empfehlen, ein onload zur body-Tag hinzuzufügen, aber da wir die jQuery DOM-Ready-Funktion verwenden, können wir sie einfach dort aufrufen.

Ich habe die Farben etwas angepasst, um sie auf dem dunklen Hintergrund gut aussehen zu lassen. Dies ist der obere Teil der prettify.css-Datei.

.str { color: #61ff74; }
.kwd { color: #ea5eff; }
.com { color: white; }
.typ { color: red; }
.lit { color: red; }
.pun { color: white; }
.pln { color: white; }
.tag { color: #ffab58; }
.atn { color: #fabb4e; }
.atv { color: #ffd996; }
.dec { color: red; }

Prettify funktioniert, indem es Teile des Codes in Spans verpackt, die diesen Teil einfärben. Beachten Sie auch die ordnungsgemäß maskierten Zeichen.

Kompatibilität

So ziemlich alles Moderne, solange es CSS3 :target unterstützt. Funktioniert nicht in IE 8 und darunter, aber in IE 9.

Primitive Methode

Firefox und Chrome unterstützen das URL-Protokoll „view-source:“, das ihren nativen Quellcode-Viewer öffnet. Wenn Sie diese Links nur für sich selbst erstellen, könnten Sie Folgendes tun:

<a class="button" onClick='window.location="view-source:" + window.location.href'>View Source</a>

Remys Methode

Es stellt sich heraus, dass meine Methode ziemlich anders ist als die auf den HTML5-Demo-Seiten verwendete. Hier ist mein Versuch, seine Technik zu erklären.

  1. Auf alle Klicks achten
  2. Wenn der Klick auf einen Link mit der Hash-ID #view-source erfolgte...
  3. Fügen Sie der body-Klasse einen Klassennamen .view-source hinzu (diese Klasse enthüllt das ansonsten versteckte <pre>)
  4. Wenn noch keiner vorhanden ist, fügen Sie ein <pre> mit der ID #view-source zur body hinzu.
  5. <pre> wird mit HTML aus document.documentElement.innerHTML gefüllt.
  6. Stellen Sie einen Timer ein, der alle 200 Millisekunden prüft, ob die URL immer noch die Hash-ID #view-source enthält.
  7. Wenn die Hash-ID verschwunden oder geändert wurde, entfernen Sie den Klassennamen von der body (wodurch das <pre> versteckt wird) und brechen Sie den Timer ab.
(function () {

var pre = document.createElement('pre');
pre.id = "view-source"

// private scope to avoid conflicts with demos
addEvent(window, 'click', function (event) {
  if (event.target.hash == '#view-source') {
    // event.preventDefault();
    if (!document.getElementById('view-source')) {
      pre.innerHTML = ('<!DOCTYPE html>\n<html>\n' + document.documentElement.innerHTML + '\n</html>').replace(/[<>]/g, function (m) { return {'<':'&lt;','>':'&gt;'}[m]});
      document.body.appendChild(pre);      
    }
    document.body.className = 'view-source';
    
    var sourceTimer = setInterval(function () {
      if (window.location.hash != '#view-source') {
        clearInterval(sourceTimer);
        document.body.className = '';
      }
    }, 200);
  }
});
  
})();

Und dann das clevere CSS, das den Quellcode normalerweise versteckt und den Bildschirm übernimmt, wenn die body die .view-source-Klasse erhält.

#view-source {
  display: none;
}

body.view-source > * {
  display: none;
}

body.view-source #view-source {
  display: block !important;
}

Große Vorteile

Das Coole an Remys Methode ist, dass sie viel besser mit verschiedenen Browsern kompatibel ist als meine Idee. Sie verwendet reines JavaScript, ist also nicht von Bibliotheken abhängig und verwendet keine „schicken“ Techniken, die in älteren Browsern nicht funktionieren würden. Er hätte zum Beispiel das hashchange-Ereignis verwenden können, um zu verfolgen, wann #view-source verschwindet, aber das wird in einigen älteren Browsern nicht unterstützt, daher war selbst das gut gelöst.

Verwendung

Selbstverständlich können Sie dies nach Belieben verwenden.

Demo anzeigen   Dateien herunterladen

In seiner jetzigen Form setzt dieser Code bestimmte Markup-Elemente auf der Seite voraus, nämlich den Button selbst und das #view-source Div. Dies könnte definitiv in ein Plugin umgewandelt werden, das diese Elemente automatisch hinzufügt, was die Implementierung deutlich erleichtern würde. Das werde ich vielleicht irgendwann tun.

Das bringt mich auch dazu, dass 1) ich wirklich die Syntaxhervorhebung wieder in das Blog-Design hier auf CSS-Tricks einbauen muss und 2) ich dieses View Source-Ding auf allen Demo-Seiten machen sollte. Beides wird mit der Zeit erledigt werden.

Eine weitere coole Sache wäre, dies als Bookmarklet zu ermöglichen. Das wäre besonders cool für Safari, das ein mieses Quelltext-Anzeige-Tool hat (obwohl es eine Erweiterung gibt, die das behebt). Dennoch bietet keiner der Browser die Quelltextanzeige in einem modalen Fenster, was ich manchmal schöner finde als das Öffnen eines neuen Fensters oder Tabs.