1
0
Fork 0
mirror of https://github.com/TheTaz25/denis.ergin.git synced 2025-07-06 13:18:49 +00:00

feat(slides): add slides for js introduction

This commit is contained in:
Denis Ergin 2024-12-08 17:58:31 +01:00
parent a78cb83e0c
commit 642d71d5ed
8 changed files with 620 additions and 0 deletions

View file

@ -0,0 +1,38 @@
---
import Title from "./title.astro";
import Meta from './meta.astro';
import ProjectSetup from './project-setup.astro';
import Output from './output.astro';
import Variables from "./variables.astro";
import PrimitiveDatatypes from "./primitive-datatypes.astro";
---
<div class="slides">
<Title />
<Meta />
<ProjectSetup />
<Output />
<Variables />
<PrimitiveDatatypes />
</div>
<style is:global>
.red {
color: red;
}
.blue {
color: blue;
}
.green {
color: green;
}
.orange {
color: orange;
}
.gray {
color: lightgray;
}
.indigo {
color: indigo;
}
</style>

View file

@ -0,0 +1,85 @@
<section>
<section>
<h2>Was ist JavaScript?</h2>
</section>
<section>
<p>JavaScript ist eine Programmiersprache mit der Inhalte auf einer Website manipuliert werden können (Read, Create, Update, Delete).</p>
<p>Ihr Haupteinsatszweck befindet sich in Browsern, aber JavaScript und sein "Ökosystem" sind so groß gewachsen, dass es nahezu überall verwendet werden kann.</p>
</section>
<section>
Zu diesen zusätzlichen Anwndungsfällen zählen:
<ul>
<li>Backend Development</li>
<li>Cross-Platform Desktop Application Development</li>
<li>Cross Platform App Development</li>
<li>Game Development</li>
<li>Command Line Interfaces</li>
</ul>
</section>
<section>
<p>JavaScript ist eine Script-Sprache.</p>
<p>Code wird nicht kompiliert sondern wird mit einem Interpreter "geparsed" und dynamisch ausgeführt.</p>
<p>JavaScript hat - obwohl sein Name - NICHTS mit Java zu tun. </p>
</section>
<section>
<p>JavaScript als Sprache wird von einem Standard beschrieben: ECMAScript.</p>
<p>In Summe sind JavaScript und ECMAScript ein Synonym zueinander und sind entsprechend gleich (falls Ihnen einmal "ECMAScript" vorkommen sollte)</p>
</section>
<section>
<p>Features von JavaScript</p>
<ul>
<li>First-Class Functions</li>
<li>Prototype-Based</li>
<li>Multi-Paradigm</li>
<li>Single-Threaded</li>
<li>Dynamic</li>
</ul>
</section>
<section>
<p>Alles in allem ist JavaScript (JS) eine mächtige Sprache.</p>
<p>Dadurch lassen sich viele Dinge "implementieren", die in anderen Sprachen nur durch Mehraufwand möglich sind.</p>
<p>Problem hierbei ist aber auch, dass unerfahrene Entwickler öfters gravierende Fehler produzieren können, die JS "verschluckt" und dies wiederum zu ungewollten Situation in der Website führt.</p>
</section>
<section>
<p>Die Sprache selber hat nur ein paar Kernfunktionalitäten. Browser und andere Runtimes ermöglichen den Zugriff auf verschiedene API's.</p>
<p>So bieten Browser eine DOM-API an, um auf das Dokument selbst zuzugreifen, während NodeJS (eine Runtime zum ausführen auf dem Computer) API's zum Zugriff auf das Dateisystem bereitstellen.</p>
</section>
<section>
<h3>Feature: First-Class Functions</h3>
<p>Funktionen sind einfach als Variablen definiert. Man kann sie ggf. überschreiben und an andere Funktionen übergeben.</p>
</section>
<section>
<h3>Prototype Based</h3>
<p>In JavaScript ist alles ein Objekt mit dem man Interagieren kann.</p>
<p>Je nachdem des Typen des Objektes (zum Beispiel "String"), enthält dieser Objekt-Typ Grundlegende Funktionalitäten, die als "Prototypen" definiert sind.</p>
<p>Im Grundlegensten Sinne kann man das als Klassenbasiertes Verhalten Kennzeichnen.</p>
</section>
<section>
<h3>Mutli-Paradigm Programming</h3>
<p>JavaScript ist eine sehr Flexible Sprache. Sie lässt verschiedene Programmier-Arten zu die auch alle untereinander verwendet werden können.</p>
<p>Beispiele sind: Objektorientert (mittels Klassen), Funktional (moderne Frameworks sind meist so aufgebaut), etc.</p>
</section>
<section>
<h3>Single Threaded</h3>
<p>Als Programmierer entwickelt man auf einem einzigen Thread. Hat für uns Entwickler den Vorteil das wir nicht auf Concurrency achten müssen.</p>
<p>Nachteil hierbei ist natürlich: Wenn der Thread einen Deadlock o.ä. hat, können wir uns davon nicht mehr erholen.</p>
<p>Aber JS bietet moderne Lösungen um lang anhaltende Operationen "auszulagern". Mehr dazu später.</p>
</section>
<section>
<h3>Dynamic</h3>
<p>In JS müssen Datentypen nicht explizit deklariert werden. Tatsächlich lassen sich keine Datentypen auf Variablen deklarieren.</p>
<p>Moderne SuperSets wie TypeScript bilden eine Schicht auf JavaScript, um ein komplexes Typensystem zu implementieren. Am Ende wird aber jeglicher Code für Browser verständlich gebaut.</p>
</section>
</section>

View file

@ -0,0 +1,54 @@
<section>
<section>
<h2>Daten ausgeben</h2>
</section>
<section>
<p>Um später unsere Berechnungen zu testen, müssen wir natürlich erstmal wissen, welche Möglichkeiten wir haben um Daten aus JS heraus anzuzeigen.</p>
</section>
<section>
<h3>console.log()</h3>
</section>
<section>
<p>Diese Art der Ausgabe wird der (reguläre) Nutzer nicht sehen. Sie ist in den Entwickler-Tools des Browsers zu sehen.</p>
<p>Neben <code>console.log()</code> gibt es noch weitere Ausgabemöglichkeiten wie <code>.warn()</code>, <code>.info()</code> oder <code>error()</code>.</p>
<p>Diese Art der Ausgabe hilft uns als Entwickler potenzielle Fehler zu identifizieren, während wir unsere Website entwickeln.</p>
</section>
<section>
<p>Schreiben wir nun unser erstes JavaScript!</p>
<pre class="js"><code data-trim data-line-numbers>
console.log("Hier könnte Ihre Werbung stehen!");
</code></pre>
</section>
<section>
<p>In den Entwickler-Tools unter dem Reiter "Console" (Sprachenabhängig), sollte nun der ausgegebene Text zu sehen sein.</p>
</section>
<section>
<h3>document.writeln()</h3>
</section>
<section>
<p>Innerhalb des Web-Browsers haben wir ein Objekt zur Verfügung mit dem wir auf das HTML-Dokument zugreifen können.</p>
<p>Wir werden später mehr darüber erfahren, aber fürs erste nutzen wir die erste von vielen Funktionen: <code>document.writeln()</code>.</p>
<p>Dieses Kommando schreibt den Inhalt den wir der Funktion Übergeben in das Dokument.</p>
</section>
<section>
<p>Lasst uns etwas ins Dokument schreiben!</p>
<pre class="js"><code data-trim data-line-numbers>
document.writeln("Hallo Welt!");
</code></pre>
</section>
<section>
<p>Natürlich kann der Text auch in HTML geschrieben sein:</p>
<pre class="js"><code data-trim data-line-numbers is:raw>
document.writeln("&lt;p&gt;&lt;code&gt;Monospace it is!&lt;/code&gt;&lt;/p&gt;");
</code></pre>
</section>
</section>

View file

@ -0,0 +1,239 @@
<section>
<section>
<h2>Primitive Datentypen</h2>
</section>
<section>
<p>Schauen wir uns mal näher an, was wir da genau in den Variablen bisher gespeichert haben.</p>
<p>Hierfür haben wir ein kleines Keyword in JS, dass uns hilft den Datentypen zu identifizieren.</p>
</section>
<section>
<p>Wir nutzen das keyword <code>typeof</code> um den Datentypen einer Variable auszugeben.</p>
<pre class="js"><code data-trim data-line-numbers>
const message = "Hallo Welt!";
// Gibt "string" aus
document.writeln(typeof message);
</code></pre>
</section>
<section>
<h3>Strings</h3>
</section>
<section>
<p>Nun, wir wussten bereits vorher, dasss wir einen String verwendet haben. Der Text war in doppelten Anführungszeichen.</p>
<p>Strings beinhalten Texte. Die Länge des Textes muss nicht angegeben werden wie in alten Programmiersprachen (z.B. C).</p>
</section>
<section>
<p>Das Konzept des Grundlegenden Datentypes "char" gibt es in JS nicht. Alles ist ein String.</p>
<p>Entsprechend ist es egal, ob man doppelte oder einfache Anführungszeichen verwendet.</p>
</section>
<section>
<pre class="js"><code data-trim data-line-numbers>
let message = 'Geht auch einfach!';
document.writeln(message);
</code></pre>
</section>
<section>
<p>Es gibt eine dritte Art, Strings zu definieren, und zwar in sogenannten "Backticks" (``).</p>
<p>Wenn wir diese Backticks verwenden, erzeugen wir in JavaScript ein sogenanntes "Template Literal", mit dem wir ganz einfach Variablen innerhalb des Strings verwenden können.</p>
<p>Um Variablen im String zu referenzieren, müssen diese nur in geschweiften Klammer mit einem anführenden Dollar-Zeichen geschrieben sein</p>
</section>
<section>
<pre class=""><code data-trim data-line-numbers is:raw>
const world = "Welt";
const message = `Hello, ${world}!`;
// Gibt "Hallo, Welt!" aus
document.writeln(message);
</code></pre>
</section>
<section>
<p>Strings besitzen eine Reihe an eingebauten Funktionen, um diese zu modifizeren, Tests auszuführen oder aufzuteilen.</p>
</section>
<section>
<h4>Zugriff auf einzelne Character</h4>
</section>
<section>
<p>Wir können Strings in JS wie ein Array "behandeln" und mit eckigen Klammern auf einen bestimmten Index innerhalb des Strings zugreifen.</p>
<pre class="js"><code data-trim data-line-numbers is:raw>
let hello = "Hallo";
// Gibt 'a' aus
document.writeln(hello[1]);
</code></pre>
</section>
<section>
<h4>Strings zusammenführen</h4>
</section>
<section>
<p>Mittels <code>concat</code>, können wir einen String, mit einem oder mehreren anderen zusammenführen.</p>
<pre class="js"><code data-trim data-line-numbers>
const hello = "Hallo";
const world = "Welt!";
const message = hello.concat(', ', world);
// Gibt "Hallo, Welt!" aus
document.writeln(message);
</code></pre>
</section>
<section>
<h4>Prüfen ob ein "Wort enthalten ist"</h4>
</section>
<section>
<p>Mit <code>includes</code> können wir abfragen, ob in einem String ein bestimmtes Wort / Wörter enthalten sind.</p>
<pre class="js"><code data-trim data-line-numbers>
const message = "Hallo Welt!";
document.writeln(message.includes("Welt!"));
document.writeln(message.includes("Welt?"));
</code></pre>
</section>
<section>
<h4>Teile eines Strings austauschen</h4>
</section>
<section>
<p>Wollen wir den Inhalt eines Strings mit etwas neuem austauschen, so nutzen wir <code>replace</code> oder <code>replaceAll</code></p>
<p>Die Operation modifiziert den existierenden String nicht. Sie gibt einen neuen String aus der modifiziert wurde</p>
<pre class="js"><code data-trim data-line-numbers>
const message = "Hallo, Welt!";
// Gibt "Hallo, Stundenten!" aus;
document.writeln(message.replace("Welt", "Studenten"));
// Gibt "HaLLo, WeLt!" aus
document.writeln(message.replaceAll('l', 'L'));
</code></pre>
</section>
<section>
<p><code>replace</code> tauscht nur das erste "Vorkommen" in einem String aus.</p>
<p>Während <code>replaceAll</code> alle Vorkommen austauscht. Interessanterweise gibt es replaceAll erst seit kurzer Zeit.</p>
</section>
<section>
<h4>Aufteilen eines Strings anhand eines Patterns</h4>
</section>
<section>
<p>Wir können einen String in ein Array aufsplitten indem wir ein bestimmtes Zeichen, beziehungsweise eine Zeichenfolge als "trenner" bestimmen</p>
<pre class="js"><code data-trim data-line-numbers>
const message = "Hallo, Welt!";
// Gibt "Ha,,o, We,t!" aus
document.writeln(message.split('l'));
</code></pre>
<p>Wichtig hierbei ist zu wissen, das <code>document.writeln</code>, ein Array aus Strings annimmt und die Werte Komma-separiert ausgibt.</p>
<p>Anstatt es ins Dokument zu schreiben, geben Sie <code>message.split('l')</code> nun einmal in der Konsole aus.</p>
</section>
<section>
<h4>Groß/ und Klein-Setzung</h4>
</section>
<section>
<p>Mit den Funktionen <code>toLowerCase</code> und <code>toUpperCase</code> können wir alle Buchstaben in GROßE und kleine Umwandeln.</p>
<pre class="js"><code data-trim data-line-numbers>
const message = "Hallo, Welt!";
console.log(message.toUpperCase());
</code></pre>
<p>Auch hier wird der originale String nicht modifiziert, sondern eine modifizierte Version zurück gegeben.</p>
</section>
<section>
<h3>Zahlen</h3>
</section>
<section>
<p>In JS können natürlich Zahlen in Variablen stecken.</p>
<p>Aufgrund der fehlenden Unterscheidung der Datentypen, beinhaltet der Datentyp "number" sowohl ganze Zahlen aus auch Long Floating Point Zahlen (Double Precision)</p>
</section>
<section>
<p>Rechenoperationen sind genauso möglich wie in allen anderen Sprachen</p>
<pre class="js"><code data-trim data-line-numbers is:raw>
const theAnswer = 40 + (2*2) - (20/10);
document.writeln(`Die Antwort auf alles lautet ${theAnswer}`);
</code></pre>
</section>
<section>
<p>Mittels den Funktionen <code>parseInt</code> und <code>parseFloat</code> kann eine Zahl aus einem String konvertiert werden.</p>
<pre class="js"><code data-trim data-line-numbers is:raw>
const parsedInt = parseInt("314");
document.writeln(`{parsedInt}`);
</code></pre>
<p>Die Funktion scannt eine Zahl so lange, bis sie ein "invalides" Zeichen findet und liefert dann das gefundene Resultat (oder "NaN")</p>
</section>
<section>
<p>Not a Number</p>
<p>Falls JS den String nicht konvertieren kann, ist der Zahlenwert "Not a Number".</p>
<p>Mit der Funktion "isNaN" kann geprüft werden ob eine Konversion erfolgreich war.</p>
</section>
<section>
<p>Wenn wir eine lange Kommazahl verkürzt darstellen wollen, gibt es noch die Funktion <code>toFixed</code></p>
<pre class="js"><code data-trim data-line-numbers is:raw>
const longFloat = 3.14159265358979323;
document.writeln(`Die ersten 5 Nachkommestellen von PI sind: longFloat.toFixed(2)`)
</code></pre>
</section>
<section>
<h3>Boolean</h3>
</section>
<section>
<p>Wie in anderen Sprachen kann ein Bool in JS 2 Werte annehmen: <code>true</code> und <code>false</code></p>
<pre class="js"><code data-trim data-line-numbers>
const wahr = true;
const falsch = false;
</code></pre>
</section>
<section>
<p>Wir werden in den nächsten Folien über Control-Flows reden, bis dahin reicht uns zu wissen das wir einfache wahr/falsch Zustände haben können.</p>
</section>
<section>
<h3>undefined &amp; null</h3>
</section>
<section>
<p>JavaScript kennt 2 Arten um "nichts" darzustellen: <code>undefined</code> und <code>null</code>.</p>
<p>Wenn eine Variable deklariert aber nicht initialisiert wird, ist sie zu Beginn <code>undefined</code>.</p>
<p>Wir können uns also undefined als einen impliziten Zustand vorstellen, wenn etwas (noch) nicht definiert ist.</p>
</section>
<section>
<pre class="js"><code data-trim data-line-numbers is:raw>
let message;
document.writeln(`Ich bin ${undefined}`);
</code></pre>
</section>
<section>
<p><code>null</code> stellt eine intentionelle Zuweisung eines nicht existierenden Wertes dar.</p>
<p>Nichtsdestotrotz ist es möglich, eine Variable mit dem Wert <code>undefined</code> explizit zu initialisieren.</p>
</section>
</section>

View file

@ -0,0 +1,100 @@
<section>
<section>
<h2>Projekt-Setup</h2>
</section>
<section>
<p>Wir können noch bei einfachen Anwendungen weiterhin unser "altbewährtes" Setup weiter verwenden.</p>
<p>Trotzdem möchte ich an diesem Punkt "erweiterte" Setups abdecken die uns später eindeutig mehr helfen werden.</p>
</section>
<section>
<h3>Quick &amp; Easy</h3>
</section>
<section>
<p>Wenn wir das alte Setup noch weiter verwenden wollen, müssen wir nur eine JavaScript-Datei anlegen (Dateiendung .js).</p>
<p>Im HTML kann das Script dann mittels dem Script-Tag eingebunden werden:</p>
</section>
<section>
<pre class="html"><code data-trim data-line-numbers is:raw>
// Das Script-Tag kann nicht mit einem &lt;script/>
// abgekürzt werden.
// Es braucht zwingend ein Start und End-Tag
<script src="/mein-script.js"></script>
</code></pre>
</section>
<section>
<p>Man könnte nun auch JS innerhalb des script-tags schreiben, bei wachsenden Projekten leidet hier aber die Übersichtlichkeit</p>
<p>Nun können wir in der Datei "mein-script.js" Anfangen JS zu schreiben.</p>
</section>
<section>
<h3>Erweiteres Setup</h3>
</section>
<section>
<p>Für diesen Teil muss NodeJS als Programm auf dem Laptop installiert sein.</p>
<p>Mit NodeJS mitenthalten ist der Package-Manager "npm" (node package manager). Mit diesem werden wir das Build-Tool "Vite" verwenden.</p>
<p>Vite bietet uns ein Boilerplate-Projekt an von dem wir schnell starten können</p>
</section>
<section>
<pre class="sh"><code data-trim data-line-numbers>
npm create vite@latest js-intro -- --template vanilla
cd js-intro
npm install
npm run dev
</code></pre>
</section>
<section>
<code><span class="red">npm</span> <span class="blue">create</span> <span class="green">vite@latest</span> <span class="orange">js-intro</span> <span class="gray">--</span> <span class="indigo">--template vanilla</span></code>
<p>Wir nutzen <span class="red">npm</span> um damit ein Projekt mit <span class="green">vite (in der aktuellesten Version)</span> zu <span class="blue">erstellen</span>.</p>
<p>Das Projekt soll in den Ordner "<span class="orange">js-intro</span>" platziert werden.</p>
<p>Das <span class="gray">Doppel-Minus</span> dient als Trenner um Parameter an das Kommando "vite@latest" zu senden.</p>
<p>Hier teilen wir Vite mit, dass es das <span class="indigo">Vanilla-Template</span> verwenden soll.</p>
</section>
<section>
<p>In der JS Welt gibt es mittlerweile sehr viele Möglichkeiten sein Frontend zu bauen. Diese Frameworks und Bibliotheken nehmen einem in großen Projekten sehr viel Arbeit ab und helfen dem Entwickler sich auf die eigentliche Implementierung der Website zu konzentrieren.</p>
<p>Projekte die diese Möglichkeiten nicht nutzen werden in der Entwickler-Community als Vanilla-Projekte bezeichnet.</p>
</section>
<section>
<p>Innerhalb des neu erstellen Projektes kann man die Datei "counter.js" löschen, und den Inhalt innerhalb von "main.js" entfernen.</p>
<p>Die CSS-Datei können wir optional so behalten oder auch leeren (wenn wir wirklich von 0 an Anfangen wollen).</p>
</section>
<section>
<p>Wenn wir Vite verwenden haben wir ein tolles Feature, dass uns bei der Entwicklung "etwas" unter die Hände greift: Hot-Module-Replacement (oder auch kurz HMR).</p>
<p>Sobald wir eine Datei ändern und speichern, werden die Änderungen auf der Website sofort ersichtlich.</p>
</section>
<section>
<p>Mit diesem Setup werden wir für längere Zeit weiter arbeiten.</p>
</section>
<section>
<pre><code data-trim data-line-numbers>
dhbw/
├── 00-introduction/
│ └── index.html
└── index.html
node_modules/
└── ...
public/
└── ...
src/
└── ...
.gitignore
index.html
package-lock.json
package.json
</code></pre>
</section>
<!-- Erste Aufgabe: Projekt Strukturieren -->
</section>

View file

@ -0,0 +1,3 @@
<section>
<h1>Einführung in JavaScript</h1>
</section>

View file

@ -0,0 +1,93 @@
<section>
<section>
<h2>Variablen</h2>
</section>
<section>
<p>Schauen wir uns nun an, wie wir in JS Variablen anlegen können.</p>
<p>Grundlegend gibt es 2 "Arten" von Variablen: Konstanten und änderbare Variablen</p>
</section>
<section>
<p>In JS müssen wir nicht angeben, was für ein Typ eine Variable hat. Anhand des aktuellen Wertes weiß JS womit wir arbeiten und kennt somit auch die Möglichkeiten, was wir mit der Variable "anstellen" können.</p>
</section>
<section>
<h3>const</h3>
</section>
<section>
<p>Mit <code>const</code> lassen sich Konstante Variablen definieren.</p>
<p>Die Variable nach dem Anlegen nicht mehr ändern, so wie man es auch aus anderen Programmiersprachen kennt.</p>
</section>
<section>
<pre class="js"><code data-trim data-line-numbers>
const message = "Ziemlich konstant hier";
document.writeln(message);
message = "Oder vielleicht doch nicht?";
document.writeln(message);
</code></pre>
</section>
<section>
<p>Wir sollten nun mehrere Sachen beobachten können:</p>
<p>Es sollte eine Nachricht in der Konsolenausgabe der Entwickler-Tools erscheinen. In dieser steht wir können nichts mehr zur Variable "message" zuweisen.</p>
<p>Aber es gibt noch eine wichtige Sache: Wir haben die Nachricht "Ziemlich konstant hier" einmal im Dokument stehen. Die 2. Ausgabe erscheint hier nicht mehr.</p>
</section>
<section>
<p>JavaScript beendet die Abarbeitung von Code, sobald ein Fehler auftritt.</p>
<p>Dies bedeutet nicht, dass man gar kein JS mehr ausführen kann. Nur die Ausführung im aktuellen Call-Stack wurde beendet.</p>
</section>
<section>
<p>Hier haben Skript-Sprachen einen gravierenden Unterschied gegenüber kompilierten Sprachen:</p>
<p>Eine Skript-Sprache führt den Code, der "eingescannt" wurde, (in der Regel) sofort aus. Dem Gegenüber stehen kompilierte Sprachen, die einen Haupteinstiegspunkt haben (Java: <code>public static void main(...)</code>)</p>
</section>
<section>
<p>In dem Moment, in dem der gesamte Code aus der JS-Datei vom Browser eingescannt wurde, hat der Browser auch angefangen den Code auszuführen.</p>
</section>
<section>
<p>Der Code in Zeile 5 wird niemals ausgeführt</p>
<pre class="js"><code data-trim data-line-numbers="1|2|4">
const message = "Ziemlich konstant hier";
document.writeln(message);
message = "Oder vielleicht doch nicht?";
document.writeln(message);
</code></pre>
</section>
<section>
<h3>let</h3>
</section>
<section>
<p>Das Gegenteil zum Konstanten bildet hier <code>let</code> ab.</p>
<p>Eine Variable mit <code>let</code> initialisiert kann jederzeit neu beschrieben werden (zum Verlust der alten Daten natürlich).</p>
</section>
<section>
<pre class="js"><code data-trim data-line-numbers>
let message = "Das ist nur der Anfang!";
document.writeln(message);
message = "Aber wann kommt das Ende?";
document.writeln(message);
</code></pre>
</section>
<section>
<h3>let's älterer Bruder "var"</h3>
</section>
<section>
<p>Bevor es <code>let</code> gab, existierte <code>var</code>.</p>
<p>Beide haben "leicht" andere Verhaltensweisen, die wir sehen werden, sobald wir uns das Thema "Scoping" näher betrachten.</p>
<p>Insgesamt ist aber meine Empfehlung, <code>let</code> zu verwenden. Das Verhalten ist kontrollierter gegenüber <code>var</code></p>
</section>
</section>

View file

@ -0,0 +1,8 @@
---
import Reveal from "../../../layouts/Reveal.astro"
import Slides from '../../../components/slides/javascript/00-intro/index.astro';
---
<Reveal title="JavaScript - Introduction">
<Slides />
</Reveal>