Kompilieren und bündeln Sie Ihre MDX -Dateien und ihre Abhängigkeiten. SCHNELL.
Sie haben eine Reihe von MDX und verschiedene TS/JS -Dateien, die sie verwendet, und möchten eine gebündelte Version dieser Dateien zum Bewertung im Browser erhalten.
Dies ist eine asynchronisierte Funktion, die Ihre MDX -Dateien und ihre Abhängigkeiten kompiliert und bündelt. Es verwendet MDX V3 und ESBUILD, daher ist es sehr schnell und unterstützt TypeScript -Dateien (für die Abhängigkeiten Ihrer MDX -Dateien).
Ihre Quelldateien können lokal, in einem Remote -Github -Repo, in einem CMS oder überall dort sein, und es spielt keine Rolle. Alles, was mdx-bundler
kümmert, ist, dass Sie alle erforderlichen Dateien und Quellcode übergeben und sich um alles für Sie kümmern.
Mit MDX können Sie die knappe Markdown -Syntax für Ihren Inhalt mit der Leistung von React -Komponenten kombinieren. Bei inhaltsfestigen Websites kann das Schreiben des Inhalts mit direktem HTML ärgerlich ausführlich sein. Oft lösen die Leute dies mit einem WSYWIG -Redakteur, aber zu oft werden die Absicht des Schriftstellers auf HTML zu kurz kommen. Viele Menschen bevorzugen Markdown, um ihre Inhaltsquelle auszudrücken, und lassen sich in HTML analysieren.
Das Problem bei der Verwendung von Markdown für Ihren Inhalt ist, wenn Sie eine Interaktivität in Ihren Inhalt eingebettet haben, sind Sie ziemlich begrenzt. Sie müssen entweder ein Element einfügen, das JavaScript abzielt (was ärgerlich indirekt ist), oder Sie können einen iframe
oder etwas anderes verwenden.
Wie bereits erwähnt, ermöglicht MDX Sie, eine knifflige Markdown -Syntax für Ihren Inhalt mit der Leistung von React -Komponenten zu kombinieren. Sie können also eine React -Komponente importieren und in den Markdown selbst rendern. Es ist das Beste aus beiden Welten.
next-mdx-remote
?" mdx-bundler
bündelt tatsächlich Abhängigkeiten Ihrer MDX-Dateien. Zum Beispiel funktioniert dies nicht mit next-mdx-remote
, aber es wird mit mdx-bundler
:
--- Titel: Beispiel Nach veröffentlicht: 2021-02-13Description: Dies ist eine Beschreibung ---# Wahooimport Demo von './demo' ' Hier ist eine ** ordentliche Demo: <Cec />
next-mdx-remote
erstreckt sich über diesen Import, weil es kein Bundler ist, sondern nur ein Compiler. mdx-bundler
ist ein MDX-Compiler und Bundler. Das ist der Unterschied.
Diese Tools sollen "zur Build Time" ausgeführt werden, und dann stellen Sie die erstellte Version Ihrer Dateien bereit. Dies bedeutet, dass Sie die gesamte Site wieder aufbauen und neu anwenden müssen, wenn Sie Inhalte in MDX haben und einen Tippfehler ändern möchten. Dies bedeutet auch, dass jede MDX-Seite, die Sie Ihrer Website hinzufügen, Ihre Build-Times erhöht, sodass sie nicht so gut skaliert wird.
mdx-bundler
kann definitiv zur Bauzeit verwendet werden, aber es wird stärker als Laufzeit-Bundler verwendet. Ein allgemeiner Anwendungsfall besteht darin, eine Route für Ihren MDX-Inhalt zu haben. Wenn diese Anfrage eingeht, laden Sie den MDX-Inhalt und geben diese zur Bündelung an mdx-bundler
weiter. Dies bedeutet, dass mdx-bundler
unendlich skalierbar ist. Ihr Build wird nicht länger sein, unabhängig davon, wie viel MDX -Inhalt Sie haben. Außerdem ist mdx-bundler
ziemlich schnell, aber um diese On-Demand-Bündelung noch schneller zu machen, können Sie entsprechende Cache-Header verwenden, um unnötige Neubündelung zu vermeiden.
WEBPACK/RULLUP/ETC erfordern außerdem, dass alle Ihre MDX -Dateien im lokalen Dateisystem arbeiten. Wenn Sie Ihre MDX-Inhalte in einem separaten Repo oder CMS speichern möchten, haben Sie ein bisschen Glück oder müssen einige Gymnastik für Bauzeit durchführen, um die Dateien für den Build zu erstellen.
Mit mdx-bundler
spielt es keine Rolle mdx-bundler
woher Ihr MDX-Inhalt kommt. Sie können Dateien von überall aus bündeln.
Völlig. Es funktioniert mit einem dieser Werkzeuge. Abhängig davon, ob Ihr Meta-Framework das Server-Side-Rendering unterstützt, werden Sie es anders implementieren. Sie könnten sich für einen gebauten Ansatz (für Gatsby/CRA) entscheiden, aber wie bereits erwähnt, kommt die wahre Kraft von mdx-bundler
in Form von On-Demand-Bündelung. Es ist also am besten für SSR -Frameworks wie Remix/Next geeignet.
Warum nicht?
Esbuild bietet einen Dienst an, mit dem es interagiert. Nur eine Instanz dieses Dienstes kann jeweils ausgeführt werden und muss eine identische Version zum NPM -Paket haben. Wenn es eine harte Abhängigkeit wäre, könnten Sie nur die MDX-Bundler-Verwendung von ESBUILD-Version verwenden.
Installation
Verwendung
Optionen
Zurück
Typen
Komponentensubstitution
Frontmatter und const
Zugriff auf benannte Exporte
Bildbündelung
Bündeln einer Datei.
Benutzerdefinierte Komponenten in nachgeschalteten Dateien
Bekannte Probleme
Inspiration
Andere Lösungen
Probleme
? Käfer
Feature -Anfragen
Mitwirkende
LIZENZ
Dieses Modul wird über NPM verteilt, das mit Knoten gebündelt ist und als eine der dependencies
Ihres Projekts installiert werden sollte:
npm install --save mdx-bundler esbuild
Eine der Abhängigkeiten von MDX-Bundler erfordert einen funktionierenden Knoten-GYP-Setup, um korrekt installiert zu werden.
Import {bundlemdx} aus 'Mdx-bundler'const mdxSource = `--- title: Beispiel post veröffentlicht: 2021-02-13Description: Dies ist eine Beschreibung ---# Wahooimport Demo von'. * Demo: <Demo />`.Trim()Const -Ergebnis = Warten Sie Bundlemdx ({{{{{{{{ Quelle: MdxSource, Dateien: {'./demo.tsx': "Import * als Reaktion aus 'React'Function Demo () {return <div> ordentliche Demo! </div>} Standard -DeMo`,, },}) const {Code, FrontMatter} = Ergebnis
Von dort senden Sie den code
an Ihren Kunden und dann:
Import * als Reaktion aus 'React'import {getMdxComponent} aus' Mdx-bundler/client'function post ({Code, FrontMatter}) { // Es ist im Allgemeinen eine gute Idee, diesen Funktionsaufruf zu meiern // Vermeiden Sie es, die Komponente bei jedem Render neu zu erstellen. const component = react.usememo (() => getMdxComponent (Code), [Code]) return (<> <header> <h1> {FrontMatter.title} </h1> <p> {FrontMatter.Description} </p> </header> <main> <komponente/> </Main> </> )}
Letztendlich wird dies (im Grunde) wiedergegeben:
<Header> <h1> Dies ist der Titel </h1> <p> Dies ist eine Beschreibung </p> </heate> <main> <div> <h1> wahoo </h1> <p> Hier ist eine <strong> ordentliche </strong> Demo: </p> <div> ordentliche Demo! </div> </div> </main>
Die string
Ihres MDX.
Kann nicht festgelegt werden, wenn file
festgelegt ist
Der Pfad zur Datei auf Ihrer Festplatte mit dem MDX in. Sie möchten wahrscheinlich auch CWD festlegen.
Kann nicht festgelegt werden, wenn source
festgelegt ist
Die files
ist ein Objekt aller von Ihnen bündelenden Dateien. Der Schlüssel ist der Pfad zur Datei (relativ zur MDX -Quelle) und der Wert ist die Zeichenfolge des Dateiquellencode. Sie können diese aus dem Dateisystem oder aus einer Remote -Datenbank erhalten. Wenn Ihr MDX nicht auf andere Dateien verweist (oder nur Dinge aus node_modules
importiert), können Sie dies vollständig weglassen.
Auf diese Weise können Sie die integrierte MDX-Konfiguration (übergeben an @mdx-js/esbuild
) ändern. Dies kann hilfreich sein, um Ihre eigenen Bemerkungsplugins/Rehypeplugins anzugeben.
Die Funktion wird an den Standard -MDXOPTIONISIONEN und der Frontmatter übergeben.
bundlemdx ({{ Quelle: MdxSource, MDXOPTIONS (Optionen, FrontMatter) {// Dies ist die empfohlene Möglichkeit, benutzerdefinierte Bemerkung/Rehype -Plugins hinzuzufügen: // Die Syntax könnte seltsam aussehen, aber es schützt Sie, falls wir // Plugins in Zukunft addieren. = [... (Optionen.Remarkplugins? []), Myremarkplugin] Optionen },})
Sie können alle ESBuild -Optionen mit der Option esbuildOptions
anpassen. Dies erfordert eine Funktion, die die Standard -ESBuild -Optionen und die Frontmatter übergeben und erwartet, dass ein Optionsobjekt zurückgegeben wird.
bundlemdx ({{ Quelle: MdxSource, EsbuildOptions (Optionen, FrontMatter) {options.minify = falseoptions.target = ['es2020', 'Chrome58', 'Firefox57', 'Safari11', 'Edge16', 'Node12', Returnoptionsoptionen },})
Weitere Informationen zu den verfügbaren Optionen finden Sie in der Dokumentation von ESBuild.
Es wird empfohlen, diese Funktion zu verwenden, um das target
mit Ihrer gewünschten Ausgabe zu konfigurieren. Andernfalls ist ESBuild standardmäßig mit esnext
einher, das heißt, dass keine standardisierten Funktionen kompiliert werden, sodass es möglich ist, dass Benutzer älterer Browser Fehler haben.
Dies sagt esbuild, dass ein bestimmtes Modul extern verfügbar ist. Wenn Ihre MDX -Datei beispielsweise die D3 -Bibliothek verwendet und Sie die D3 -Bibliothek in Ihrer App bereits verwenden, versenden Sie d3
zweimal an den Benutzer (einmal für Ihre App und einmal für diese MDX -Komponente). Dies ist verschwenderisch und Sie würden es besser sagen, dass Sie esbuild nicht bündeln, dass Sie d3
nicht bündeln sollen, und Sie können es selbst an die Komponente weitergeben, wenn Sie getMDXComponent
anrufen.
Globale externe Konfigurationsoptionen: https://www.npmjs.com/package/@fal-works/esbuild-plugin-global-externals
Hier ist ein Beispiel:
// Server- oder Build-Time-Code, der im Knoten ausgeführt wird: Import {bundlemdx} aus 'Mdx-Bundler'Const MdxSource = `# Dies ist das TitleImport-Linkspad aus' linkes Pad '<div> {linkSpad (ordentliche Demo ! ", 12, '!')} </Div>` .trim () const result = warte bundlemdx ({{ Quelle: MdxSource, // Hinweis: Dies ist * nur * erforderlich, wenn Sie DEPs zwischen Ihrem MDX teilen möchten // Dateipaket und die Host -App. Andernfalls werden alle DEPs nur gebündelt. // Es funktioniert also in beide Richtungen, dies ist nur eine Optimierung, um das Senden zu vermeiden // Mehrere Kopien derselben Bibliothek an Ihre Benutzer. Global: {'linkes Pad': 'myleftpad'},})
// Server- und/oder clientseitige Code, der im Browser oder Knoten ausgeführt werden kann Mdxpage ({code}: {code: string}) { const component = react.usememo (() => getMdxcomponent (result.code, {myleftpad: link}), [result.code, linkSpad], ) return (<main> <component /> < /main> )}
Das Einstellen von cwd
( aktuelles Arbeitsverzeichnis ) in ein Verzeichnis ermöglicht es ESBUILD, Importe zu beheben. Dieses Verzeichnis könnte das Verzeichnis sein, das der MDX-Inhalt aus gelesen wurde, oder ein Verzeichnis, in dem Off-Disk-MDX ausgeführt werden sollte.
Inhalt/Seiten/Demo.tsx
Import * als Reaktion aus 'React'Function Demo () { return <div> ordentliche Demo!
src/build.ts
Import {bundlemdx} aus 'Mdx-bundler'const mdxSource = `--- title: Beispiel post veröffentlicht: 2021-02-13Description: Dies ist eine Beschreibung ---# Wahooimport Demo von'. * Demo: <Demo />`.Trim()Const -Ergebnis = Warten Sie Bundlemdx ({{{{{{{{ Quelle: MdxSource, CWD: '/user/You/site/_content/pages',}) const {Code, Frontmatter} = Ergebnis
Auf diese Weise können Sie die Optionen für graue Materie konfigurieren.
Ihre Funktion wird über die aktuelle Grau-Materie-Konfiguration übergeben, damit Sie geändert werden können. Geben Sie Ihr geändertes Konfigurationsobjekt für graue Substanz zurück.
bundlemdx ({{ GraymUtteroptions: options => {options.excerpt = Truereturn Optionen },})
Auf diese Weise können Sie das Ausgabeverzeichnis für das Bundle und die öffentliche URL auf das Verzeichnis einstellen. Wenn eine Option festgelegt ist, muss auch die andere sein.
Das JavaScript -Bundle ist nicht in dieses Verzeichnis geschrieben und wird immer noch als Zeichenfolge von bundleMDX
zurückgegeben.
Diese Funktion wird am besten mit Optimierungen an mdxOptions
und esbuildOptions
verwendet. Im folgenden Beispiel werden .png
-Dateien auf die Festplatte geschrieben und dann von /file/
zugestellt.
Auf diese Weise können Sie Vermögenswerte mit Ihrem MDX speichern und sie dann wie alles andere verarbeiten lassen.
Es wird empfohlen, dass jedes Bündel ein eigenes bundleDirectory
hat, sodass mehrere Bündel das Vermögen nicht gegenseitig überschreiben.
const {code} = erwartet bundLemdx ({{{{{{{{{{{{{ Datei: '/path/to/site/content/file.mdx',, CWD: '/path/to/site/content', BundleTirectory: '/path/to/site/public/file', bündelPath: '/Datei/', MDXOPTIONS: options => {options.remarkplugins = [RemarkMdximages] Rückgaberückgabeoptionen }, EsbuildOptions: options => {options.loader = {... options.loader, '.png': 'Datei',} Rückgabeoptionen },})
bundleMDX
gibt ein Versprechen für ein Objekt mit den folgenden Eigenschaften zurück.
code
- Das Bundle Ihres MDX als string
.
frontmatter
- Das Frontmatter object
von Grau -Matter.
matter
- Das gesamte von Grey -Materie zurückgegebene Objekt
mdx-bundler
liefert komplette Typierungen in seinem eigenen Paket.
bundleMDX
hat einen einzelnen Typparameter, der der Typ Ihrer Frontmatter ist. Es ist standardmäßig zu {[key: string]: any}
und muss ein Objekt sein. Dies wird dann verwendet, um die zurückgegebene frontmatter
und die Frontmatter an esbuildOptions
und mdxOptions
zugeben.
const {Frontmatter} = bundlemdx <{title: string}> ({source}) frontmatter.title // hat type String
MDX Bundler gibt die Fähigkeit von MDX weiter, Komponenten durch die von getMDXComponent
zurückgegebene components
auf der Komponente zu ersetzen.
Hier ist ein Beispiel, das P -Tags aus den Bildern entfernt.
Import * als Reaktion aus 'React'import {getMdxComponent} aus' Mdx-bundler/client'Const Absatz: react.fc = props => { if (typeof props.children! } Rückgabe <p {... props} />} Funktion mdxpage ({code}: {code: string}) { const component = react.usememo (() => getMdxComponent (Code), [Code]) return (<main> <Komponentenkomponenten = {{P: Absatz}} /> < /main> )}
Sie können auf die META oder Consts auf Frontmatter im MDX -Inhalt verweisen.
--- Titel: Beispiel Post --- Export const exampleimage = 'https://example.com/image.jpg'# {Frontmatter.title} <img src = {exampleimage} alt = "Bild Alt Text"/>
Sie können getMDXExport
anstelle von getMDXComponent
verwenden, um die MDX -Datei als Modul anstelle einer Komponente zu behandeln. Es dauert die gleichen Argumente, die getMDXComponent
tut.
--- Titel: Beispiel Post --- Export const toc = [{Tiefe: 1, Wert: 'Der Titel'}]# Der Titel
Import * als Reaktion aus 'React'import {getMdxexport} aus' Mdx-bundler/client'function mdxpage ({code}: {code: string}) { const mdxexport = getMdxexport (Code) console.log (mdxexport.toc) // [{Tiefe: 1, Wert: 'Der Titel'}] const component = react.usememo (() => mdxexport.default, [Code]) return <component />}
Mit dem CWD und dem Bemerkung-Plugin-Bemerkung-MDX-Images können Sie Bilder in Ihrem MDX bündeln!
Es gibt zwei Lader in Esbuild, die hier verwendet werden können. Am einfachsten ist dataurl
, der die Bilder als Inline -Daten -URLs im zurückgegebenen Code ausgibt.
Importieren {Remarkmdximages} aus 'Remark-mdx-iMages'const {Code} = warte bundlemdx ({{{{{{{{{{{{{{{{{{{{{{{{{ Quelle: MdxSource, CWD: '/user/You/Site/_content/Pages', MDXOPTIONEN: options => {options.remarkplugins = [... (Optionen }, EsbuildOptions: options => {options.loader = {... options.loader, '.png': 'DataUrl',} Rückgabeoptionen },})
Der file
benötigt etwas mehr Konfiguration, um zu arbeiten. Mit dem file
werden Ihre Bilder in das Ausgabesverzeichnis kopiert, sodass Esbuild auf Schreibdateien eingestellt werden muss und wissen muss, wo sie sie plus die URL des Ordners in Bildquellen einstellen sollen.
Jeder Anruf nach
bundleMDX
ist von den anderen isoliert. Wenn Sie das Verzeichnis für alles einstellen, wasbundleMDX
ohne Vorwarnung überschreibt. Infolgedessen benötigt jedes Bündel ein eigenes Ausgabemittel.
// für die Datei `_content/pages/über.mdx`const {code} = warte bundlemdx ({{{{{{{{{{{ Quelle: MdxSource, CWD: '/user/You/Site/_content/Pages', MDXOPTIONEN: options => {options.remarkplugins = [... (Optionen }, EsbuildOptions: options => {// Setzen Sie das `Outdir` an einem öffentlichen Ort für dieses bundle.options.outdir = '/users/you/site/public/img/about'options.loader = {... options.loader , // Sagen Sie esbuild, den "Datei" Loader für PNGs zu verwenden. so dass esbuild die Dateien ausgibt },})
Wenn sich Ihre MDX mdx-bundler
Datei auf Ihrer Festplatte befindet, können Sie einige Zeit und Code speichern, indem Sie die Datei für Sie lesen lassen. Anstatt eine source
anzugeben, können Sie file
auf dem Pfad des MDX auf der Festplatte einstellen. Stellen Sie cwd
auf seinen Ordner ein, damit die relativen Importe funktionieren.
Importieren {bundlemdx} aus 'Mdx-bundler'const {code, FrontMatter} = wartet bundlemdx ({{{{{{ Datei: '/users/you/site/content/file.mdx', CWD: '/user/du/seiten/content/',})
Um sicherzustellen, dass benutzerdefinierte Komponenten in nachgeschalteten MDX-Dateien zugänglich sind, können Sie den MDXProvider
von @mdx-js/react
verwenden, um benutzerdefinierte Komponenten an Ihre verschachtelten Importe zu übergeben.
npm install --save @mdx-js/react
const Globals = { '@mdx-js/react': {varname: 'mdxjsreact', namedExports: ['UsemdxComponents'], defaultExport: false, },}; const {code} = bundlemdx ({{{{ Quelle, Global, mdxOptions (Optionen: record <String, Any>) {return {... Optionen, ProviderimportSource: '@Mdx-js/react',}; }});
Von dort senden Sie den code
an Ihren Kunden und dann:
Importieren {MdxProvider, UsemdxComponents} aus '@mdx-js/react'; const mdx_global_config = { Mdxjsreact: {UsemdxComponents, },}; exportieren const mdxcomponent: react.fc <{ Code: String; FrontMatter: Aufzeichnung <String, Any>;}> = ({Code}) => { const component = Usememo (() => getMdxComponent (Code, MDX_Global_Config), [Code], ); return (<mdxProvider -Komponenten = {{text: ({Kinder}) => <p> {Kinder} </p>}}> <component/> </mdxprovider> );};
Wir würden uns freuen , dass dies in Cloudflare -Mitarbeitern funktioniert. Leider haben Cloudflares zwei Einschränkungen, die verhindern, dass mdx-bundler
in dieser Umgebung arbeitet:
Arbeiter können Binärdateien nicht ausführen. bundleMDX
verwendet esbuild
(eine Binärdatei), um Ihren MDX -Code zu bündeln.
Die Arbeitnehmer können eval
oder ähnlich ausführen. getMDXComponent
bewertet den gebündelten Code mithilfe new Function
.
Eine Problemumgehung besteht darin, Ihren mit MDX-Bundler bezogenen Code in eine andere Umgebung zu bringen und diese Umgebung aus dem CloudFlare-Mitarbeiter zu bezeichnen. IMO, dies besiegt den Zweck der Verwendung von Cloudflare -Mitarbeitern. Eine weitere potenzielle Problemumgehung besteht darin, WASM innerhalb des Arbeitnehmers aus zu verwenden. Es gibt esbuild-wasm
, aber es gibt einige Probleme mit diesem Paket, das auf diesem Link erklärt wird. Dann gibt es wasm-jseval
, aber ich konnte das nicht dazu bringen, Code auszuführen, der ohne Fehler von mdx-bundler
ausgegeben wurde.
Wenn jemand in das eingehen möchte, wäre das hervorragend, aber leider ist es unwahrscheinlich, dass ich jemals daran arbeiten werde.
Esbuild verlässt sich darauf, dass __dirname
ermittelt wird, wo ausführbare Dateien ist.
Durch das Hinzufügen des folgenden Codes vor Ihrem bundleMDX
wird ESBuild direkt auf die richtige ausführbare Datei für Ihre Plattform verweist.
Pfad von 'path'if (process.platform ===' win32 ') {if (process.platform importieren process.env.esbuild_bary_path = path.join (process.cwd (), 'node_modules', 'esbuild', 'esbuild.exe', )} anders { process.env.esbuild_bary_path = path.join (process.cwd (), 'node_modules', 'esbuild', 'bin', 'esbuild', )}
Weitere Informationen zu diesem Thema finden Sie in diesem Artikel.
Als ich Kentcdodds.com um Remix umschrieben habe, wollte ich meine Blog -Posts als MDX behalten, aber ich wollte sie nicht zum Bauzeit zusammenstellen oder jedes Mal, wenn ich einen Tippfehler behebte, neu einbinden muss. Also habe ich dies gemacht, was es meinem Server ermöglicht, bei Bedarf zu kompilieren.
Es gibt Next-MDX-Remote, aber es ist eher ein MDX-Kompilierer als ein Bundler (kann Ihr MDX für Abhängigkeiten nicht bündeln). Außerdem konzentriert sich es auf Next.js, während dies meta-ramework agnostisch ist.
Möchten Sie einen Beitrag leisten? Suchen Sie nach dem guten ersten Ausgabeetikett.
Bitte stellen Sie ein Problem für Fehler, fehlende Dokumentation oder unerwartetes Verhalten ein.
Siehe Fehler
Bitte stellen Sie ein Problem ein, um neue Funktionen vorzuschlagen. Stimmen Sie über Feature -Anfragen ab, indem Sie ein? Dies hilft den Betreuern, woran sie arbeiten sollen.
Siehe Feature -Anfragen
Danke geht an diese Leute (Emoji -Schlüssel):
Kent C. Dodds ? | Benwis ? ? | Adam Laycock | Titus ? ? | Christian Murphy ? | Pedro Duarte | Erik Rasmussen |
Omar Syx ? | Gaël Haméon | Gabriel Loiácono | Spencer Miskoviak | Casper | Apostolos Christodoulou | Yordis Prieto |
XOUMI | Yasin | Mohammed 'Mo' Mulazada | Kann Rau | Hosenur Rahaman | Maciek Sitkowski | Priyang |
Mosaad | Stefanprobst | Vlad Moroz |
Dieses Projekt folgt der All-Contributors-Spezifikation. Beiträge jeglicher Art willkommen!
MIT