mirror of
https://github.com/Sevichecc/Urara-Blog.git
synced 2025-05-25 05:39:13 +08:00
1366 lines
72 KiB
Text
1366 lines
72 KiB
Text
import path__default from 'path';
|
|
import fs__default from 'fs';
|
|
import { g as get_runtime_directory } from './utils.js';
|
|
import { p as posixify, c as copy, r as rimraf } from './filesystem.js';
|
|
import { fileURLToPath } from 'url';
|
|
import { w as write_if_changed, t as trim, a as write, v as valid_identifier, r as reserved, b as write_tsconfig } from './write_tsconfig.js';
|
|
import { $ } from './index.js';
|
|
import { loadEnv, normalizePath, loadConfigFromFile } from 'vite';
|
|
|
|
/**
|
|
* @param typeMap [Object] Map of MIME type -> Array[extensions]
|
|
* @param ...
|
|
*/
|
|
function Mime$1() {
|
|
this._types = Object.create(null);
|
|
this._extensions = Object.create(null);
|
|
|
|
for (let i = 0; i < arguments.length; i++) {
|
|
this.define(arguments[i]);
|
|
}
|
|
|
|
this.define = this.define.bind(this);
|
|
this.getType = this.getType.bind(this);
|
|
this.getExtension = this.getExtension.bind(this);
|
|
}
|
|
|
|
/**
|
|
* Define mimetype -> extension mappings. Each key is a mime-type that maps
|
|
* to an array of extensions associated with the type. The first extension is
|
|
* used as the default extension for the type.
|
|
*
|
|
* e.g. mime.define({'audio/ogg', ['oga', 'ogg', 'spx']});
|
|
*
|
|
* If a type declares an extension that has already been defined, an error will
|
|
* be thrown. To suppress this error and force the extension to be associated
|
|
* with the new type, pass `force`=true. Alternatively, you may prefix the
|
|
* extension with "*" to map the type to extension, without mapping the
|
|
* extension to the type.
|
|
*
|
|
* e.g. mime.define({'audio/wav', ['wav']}, {'audio/x-wav', ['*wav']});
|
|
*
|
|
*
|
|
* @param map (Object) type definitions
|
|
* @param force (Boolean) if true, force overriding of existing definitions
|
|
*/
|
|
Mime$1.prototype.define = function(typeMap, force) {
|
|
for (let type in typeMap) {
|
|
let extensions = typeMap[type].map(function(t) {
|
|
return t.toLowerCase();
|
|
});
|
|
type = type.toLowerCase();
|
|
|
|
for (let i = 0; i < extensions.length; i++) {
|
|
const ext = extensions[i];
|
|
|
|
// '*' prefix = not the preferred type for this extension. So fixup the
|
|
// extension, and skip it.
|
|
if (ext[0] === '*') {
|
|
continue;
|
|
}
|
|
|
|
if (!force && (ext in this._types)) {
|
|
throw new Error(
|
|
'Attempt to change mapping for "' + ext +
|
|
'" extension from "' + this._types[ext] + '" to "' + type +
|
|
'". Pass `force=true` to allow this, otherwise remove "' + ext +
|
|
'" from the list of extensions for "' + type + '".'
|
|
);
|
|
}
|
|
|
|
this._types[ext] = type;
|
|
}
|
|
|
|
// Use first extension as default
|
|
if (force || !this._extensions[type]) {
|
|
const ext = extensions[0];
|
|
this._extensions[type] = (ext[0] !== '*') ? ext : ext.substr(1);
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Lookup a mime type based on extension
|
|
*/
|
|
Mime$1.prototype.getType = function(path) {
|
|
path = String(path);
|
|
let last = path.replace(/^.*[/\\]/, '').toLowerCase();
|
|
let ext = last.replace(/^.*\./, '').toLowerCase();
|
|
|
|
let hasPath = last.length < path.length;
|
|
let hasDot = ext.length < last.length - 1;
|
|
|
|
return (hasDot || !hasPath) && this._types[ext] || null;
|
|
};
|
|
|
|
/**
|
|
* Return file extension associated with a mime type
|
|
*/
|
|
Mime$1.prototype.getExtension = function(type) {
|
|
type = /^\s*([^;\s]*)/.test(type) && RegExp.$1;
|
|
return type && this._extensions[type.toLowerCase()] || null;
|
|
};
|
|
|
|
var Mime_1 = Mime$1;
|
|
|
|
var standard = {"application/andrew-inset":["ez"],"application/applixware":["aw"],"application/atom+xml":["atom"],"application/atomcat+xml":["atomcat"],"application/atomdeleted+xml":["atomdeleted"],"application/atomsvc+xml":["atomsvc"],"application/atsc-dwd+xml":["dwd"],"application/atsc-held+xml":["held"],"application/atsc-rsat+xml":["rsat"],"application/bdoc":["bdoc"],"application/calendar+xml":["xcs"],"application/ccxml+xml":["ccxml"],"application/cdfx+xml":["cdfx"],"application/cdmi-capability":["cdmia"],"application/cdmi-container":["cdmic"],"application/cdmi-domain":["cdmid"],"application/cdmi-object":["cdmio"],"application/cdmi-queue":["cdmiq"],"application/cu-seeme":["cu"],"application/dash+xml":["mpd"],"application/davmount+xml":["davmount"],"application/docbook+xml":["dbk"],"application/dssc+der":["dssc"],"application/dssc+xml":["xdssc"],"application/ecmascript":["es","ecma"],"application/emma+xml":["emma"],"application/emotionml+xml":["emotionml"],"application/epub+zip":["epub"],"application/exi":["exi"],"application/express":["exp"],"application/fdt+xml":["fdt"],"application/font-tdpfr":["pfr"],"application/geo+json":["geojson"],"application/gml+xml":["gml"],"application/gpx+xml":["gpx"],"application/gxf":["gxf"],"application/gzip":["gz"],"application/hjson":["hjson"],"application/hyperstudio":["stk"],"application/inkml+xml":["ink","inkml"],"application/ipfix":["ipfix"],"application/its+xml":["its"],"application/java-archive":["jar","war","ear"],"application/java-serialized-object":["ser"],"application/java-vm":["class"],"application/javascript":["js","mjs"],"application/json":["json","map"],"application/json5":["json5"],"application/jsonml+json":["jsonml"],"application/ld+json":["jsonld"],"application/lgr+xml":["lgr"],"application/lost+xml":["lostxml"],"application/mac-binhex40":["hqx"],"application/mac-compactpro":["cpt"],"application/mads+xml":["mads"],"application/manifest+json":["webmanifest"],"application/marc":["mrc"],"application/marcxml+xml":["mrcx"],"application/mathematica":["ma","nb","mb"],"application/mathml+xml":["mathml"],"application/mbox":["mbox"],"application/mediaservercontrol+xml":["mscml"],"application/metalink+xml":["metalink"],"application/metalink4+xml":["meta4"],"application/mets+xml":["mets"],"application/mmt-aei+xml":["maei"],"application/mmt-usd+xml":["musd"],"application/mods+xml":["mods"],"application/mp21":["m21","mp21"],"application/mp4":["mp4s","m4p"],"application/msword":["doc","dot"],"application/mxf":["mxf"],"application/n-quads":["nq"],"application/n-triples":["nt"],"application/node":["cjs"],"application/octet-stream":["bin","dms","lrf","mar","so","dist","distz","pkg","bpk","dump","elc","deploy","exe","dll","deb","dmg","iso","img","msi","msp","msm","buffer"],"application/oda":["oda"],"application/oebps-package+xml":["opf"],"application/ogg":["ogx"],"application/omdoc+xml":["omdoc"],"application/onenote":["onetoc","onetoc2","onetmp","onepkg"],"application/oxps":["oxps"],"application/p2p-overlay+xml":["relo"],"application/patch-ops-error+xml":["xer"],"application/pdf":["pdf"],"application/pgp-encrypted":["pgp"],"application/pgp-signature":["asc","sig"],"application/pics-rules":["prf"],"application/pkcs10":["p10"],"application/pkcs7-mime":["p7m","p7c"],"application/pkcs7-signature":["p7s"],"application/pkcs8":["p8"],"application/pkix-attr-cert":["ac"],"application/pkix-cert":["cer"],"application/pkix-crl":["crl"],"application/pkix-pkipath":["pkipath"],"application/pkixcmp":["pki"],"application/pls+xml":["pls"],"application/postscript":["ai","eps","ps"],"application/provenance+xml":["provx"],"application/pskc+xml":["pskcxml"],"application/raml+yaml":["raml"],"application/rdf+xml":["rdf","owl"],"application/reginfo+xml":["rif"],"application/relax-ng-compact-syntax":["rnc"],"application/resource-lists+xml":["rl"],"application/resource-lists-diff+xml":["rld"],"application/rls-services+xml":["rs"],"application/route-apd+xml":["rapd"],"application/route-s-tsid+xml":["sls"],"application/route-usd+xml":["rusd"],"application/rpki-ghostbusters":["gbr"],"application/rpki-manifest":["mft"],"application/rpki-roa":["roa"],"application/rsd+xml":["rsd"],"application/rss+xml":["rss"],"application/rtf":["rtf"],"application/sbml+xml":["sbml"],"application/scvp-cv-request":["scq"],"application/scvp-cv-response":["scs"],"application/scvp-vp-request":["spq"],"application/scvp-vp-response":["spp"],"application/sdp":["sdp"],"application/senml+xml":["senmlx"],"application/sensml+xml":["sensmlx"],"application/set-payment-initiation":["setpay"],"application/set-registration-initiation":["setreg"],"application/shf+xml":["shf"],"application/sieve":["siv","sieve"],"application/smil+xml":["smi","smil"],"application/sparql-query":["rq"],"application/sparql-results+xml":["srx"],"application/srgs":["gram"],"application/srgs+xml":["grxml"],"application/sru+xml":["sru"],"application/ssdl+xml":["ssdl"],"application/ssml+xml":["ssml"],"application/swid+xml":["swidtag"],"application/tei+xml":["tei","teicorpus"],"application/thraud+xml":["tfi"],"application/timestamped-data":["tsd"],"application/toml":["toml"],"application/trig":["trig"],"application/ttml+xml":["ttml"],"application/ubjson":["ubj"],"application/urc-ressheet+xml":["rsheet"],"application/urc-targetdesc+xml":["td"],"application/voicexml+xml":["vxml"],"application/wasm":["wasm"],"application/widget":["wgt"],"application/winhlp":["hlp"],"application/wsdl+xml":["wsdl"],"application/wspolicy+xml":["wspolicy"],"application/xaml+xml":["xaml"],"application/xcap-att+xml":["xav"],"application/xcap-caps+xml":["xca"],"application/xcap-diff+xml":["xdf"],"application/xcap-el+xml":["xel"],"application/xcap-ns+xml":["xns"],"application/xenc+xml":["xenc"],"application/xhtml+xml":["xhtml","xht"],"application/xliff+xml":["xlf"],"application/xml":["xml","xsl","xsd","rng"],"application/xml-dtd":["dtd"],"application/xop+xml":["xop"],"application/xproc+xml":["xpl"],"application/xslt+xml":["*xsl","xslt"],"application/xspf+xml":["xspf"],"application/xv+xml":["mxml","xhvml","xvml","xvm"],"application/yang":["yang"],"application/yin+xml":["yin"],"application/zip":["zip"],"audio/3gpp":["*3gpp"],"audio/adpcm":["adp"],"audio/amr":["amr"],"audio/basic":["au","snd"],"audio/midi":["mid","midi","kar","rmi"],"audio/mobile-xmf":["mxmf"],"audio/mp3":["*mp3"],"audio/mp4":["m4a","mp4a"],"audio/mpeg":["mpga","mp2","mp2a","mp3","m2a","m3a"],"audio/ogg":["oga","ogg","spx","opus"],"audio/s3m":["s3m"],"audio/silk":["sil"],"audio/wav":["wav"],"audio/wave":["*wav"],"audio/webm":["weba"],"audio/xm":["xm"],"font/collection":["ttc"],"font/otf":["otf"],"font/ttf":["ttf"],"font/woff":["woff"],"font/woff2":["woff2"],"image/aces":["exr"],"image/apng":["apng"],"image/avif":["avif"],"image/bmp":["bmp"],"image/cgm":["cgm"],"image/dicom-rle":["drle"],"image/emf":["emf"],"image/fits":["fits"],"image/g3fax":["g3"],"image/gif":["gif"],"image/heic":["heic"],"image/heic-sequence":["heics"],"image/heif":["heif"],"image/heif-sequence":["heifs"],"image/hej2k":["hej2"],"image/hsj2":["hsj2"],"image/ief":["ief"],"image/jls":["jls"],"image/jp2":["jp2","jpg2"],"image/jpeg":["jpeg","jpg","jpe"],"image/jph":["jph"],"image/jphc":["jhc"],"image/jpm":["jpm"],"image/jpx":["jpx","jpf"],"image/jxr":["jxr"],"image/jxra":["jxra"],"image/jxrs":["jxrs"],"image/jxs":["jxs"],"image/jxsc":["jxsc"],"image/jxsi":["jxsi"],"image/jxss":["jxss"],"image/ktx":["ktx"],"image/ktx2":["ktx2"],"image/png":["png"],"image/sgi":["sgi"],"image/svg+xml":["svg","svgz"],"image/t38":["t38"],"image/tiff":["tif","tiff"],"image/tiff-fx":["tfx"],"image/webp":["webp"],"image/wmf":["wmf"],"message/disposition-notification":["disposition-notification"],"message/global":["u8msg"],"message/global-delivery-status":["u8dsn"],"message/global-disposition-notification":["u8mdn"],"message/global-headers":["u8hdr"],"message/rfc822":["eml","mime"],"model/3mf":["3mf"],"model/gltf+json":["gltf"],"model/gltf-binary":["glb"],"model/iges":["igs","iges"],"model/mesh":["msh","mesh","silo"],"model/mtl":["mtl"],"model/obj":["obj"],"model/step+xml":["stpx"],"model/step+zip":["stpz"],"model/step-xml+zip":["stpxz"],"model/stl":["stl"],"model/vrml":["wrl","vrml"],"model/x3d+binary":["*x3db","x3dbz"],"model/x3d+fastinfoset":["x3db"],"model/x3d+vrml":["*x3dv","x3dvz"],"model/x3d+xml":["x3d","x3dz"],"model/x3d-vrml":["x3dv"],"text/cache-manifest":["appcache","manifest"],"text/calendar":["ics","ifb"],"text/coffeescript":["coffee","litcoffee"],"text/css":["css"],"text/csv":["csv"],"text/html":["html","htm","shtml"],"text/jade":["jade"],"text/jsx":["jsx"],"text/less":["less"],"text/markdown":["markdown","md"],"text/mathml":["mml"],"text/mdx":["mdx"],"text/n3":["n3"],"text/plain":["txt","text","conf","def","list","log","in","ini"],"text/richtext":["rtx"],"text/rtf":["*rtf"],"text/sgml":["sgml","sgm"],"text/shex":["shex"],"text/slim":["slim","slm"],"text/spdx":["spdx"],"text/stylus":["stylus","styl"],"text/tab-separated-values":["tsv"],"text/troff":["t","tr","roff","man","me","ms"],"text/turtle":["ttl"],"text/uri-list":["uri","uris","urls"],"text/vcard":["vcard"],"text/vtt":["vtt"],"text/xml":["*xml"],"text/yaml":["yaml","yml"],"video/3gpp":["3gp","3gpp"],"video/3gpp2":["3g2"],"video/h261":["h261"],"video/h263":["h263"],"video/h264":["h264"],"video/iso.segment":["m4s"],"video/jpeg":["jpgv"],"video/jpm":["*jpm","jpgm"],"video/mj2":["mj2","mjp2"],"video/mp2t":["ts"],"video/mp4":["mp4","mp4v","mpg4"],"video/mpeg":["mpeg","mpg","mpe","m1v","m2v"],"video/ogg":["ogv"],"video/quicktime":["qt","mov"],"video/webm":["webm"]};
|
|
|
|
var other = {"application/prs.cww":["cww"],"application/vnd.1000minds.decision-model+xml":["1km"],"application/vnd.3gpp.pic-bw-large":["plb"],"application/vnd.3gpp.pic-bw-small":["psb"],"application/vnd.3gpp.pic-bw-var":["pvb"],"application/vnd.3gpp2.tcap":["tcap"],"application/vnd.3m.post-it-notes":["pwn"],"application/vnd.accpac.simply.aso":["aso"],"application/vnd.accpac.simply.imp":["imp"],"application/vnd.acucobol":["acu"],"application/vnd.acucorp":["atc","acutc"],"application/vnd.adobe.air-application-installer-package+zip":["air"],"application/vnd.adobe.formscentral.fcdt":["fcdt"],"application/vnd.adobe.fxp":["fxp","fxpl"],"application/vnd.adobe.xdp+xml":["xdp"],"application/vnd.adobe.xfdf":["xfdf"],"application/vnd.ahead.space":["ahead"],"application/vnd.airzip.filesecure.azf":["azf"],"application/vnd.airzip.filesecure.azs":["azs"],"application/vnd.amazon.ebook":["azw"],"application/vnd.americandynamics.acc":["acc"],"application/vnd.amiga.ami":["ami"],"application/vnd.android.package-archive":["apk"],"application/vnd.anser-web-certificate-issue-initiation":["cii"],"application/vnd.anser-web-funds-transfer-initiation":["fti"],"application/vnd.antix.game-component":["atx"],"application/vnd.apple.installer+xml":["mpkg"],"application/vnd.apple.keynote":["key"],"application/vnd.apple.mpegurl":["m3u8"],"application/vnd.apple.numbers":["numbers"],"application/vnd.apple.pages":["pages"],"application/vnd.apple.pkpass":["pkpass"],"application/vnd.aristanetworks.swi":["swi"],"application/vnd.astraea-software.iota":["iota"],"application/vnd.audiograph":["aep"],"application/vnd.balsamiq.bmml+xml":["bmml"],"application/vnd.blueice.multipass":["mpm"],"application/vnd.bmi":["bmi"],"application/vnd.businessobjects":["rep"],"application/vnd.chemdraw+xml":["cdxml"],"application/vnd.chipnuts.karaoke-mmd":["mmd"],"application/vnd.cinderella":["cdy"],"application/vnd.citationstyles.style+xml":["csl"],"application/vnd.claymore":["cla"],"application/vnd.cloanto.rp9":["rp9"],"application/vnd.clonk.c4group":["c4g","c4d","c4f","c4p","c4u"],"application/vnd.cluetrust.cartomobile-config":["c11amc"],"application/vnd.cluetrust.cartomobile-config-pkg":["c11amz"],"application/vnd.commonspace":["csp"],"application/vnd.contact.cmsg":["cdbcmsg"],"application/vnd.cosmocaller":["cmc"],"application/vnd.crick.clicker":["clkx"],"application/vnd.crick.clicker.keyboard":["clkk"],"application/vnd.crick.clicker.palette":["clkp"],"application/vnd.crick.clicker.template":["clkt"],"application/vnd.crick.clicker.wordbank":["clkw"],"application/vnd.criticaltools.wbs+xml":["wbs"],"application/vnd.ctc-posml":["pml"],"application/vnd.cups-ppd":["ppd"],"application/vnd.curl.car":["car"],"application/vnd.curl.pcurl":["pcurl"],"application/vnd.dart":["dart"],"application/vnd.data-vision.rdz":["rdz"],"application/vnd.dbf":["dbf"],"application/vnd.dece.data":["uvf","uvvf","uvd","uvvd"],"application/vnd.dece.ttml+xml":["uvt","uvvt"],"application/vnd.dece.unspecified":["uvx","uvvx"],"application/vnd.dece.zip":["uvz","uvvz"],"application/vnd.denovo.fcselayout-link":["fe_launch"],"application/vnd.dna":["dna"],"application/vnd.dolby.mlp":["mlp"],"application/vnd.dpgraph":["dpg"],"application/vnd.dreamfactory":["dfac"],"application/vnd.ds-keypoint":["kpxx"],"application/vnd.dvb.ait":["ait"],"application/vnd.dvb.service":["svc"],"application/vnd.dynageo":["geo"],"application/vnd.ecowin.chart":["mag"],"application/vnd.enliven":["nml"],"application/vnd.epson.esf":["esf"],"application/vnd.epson.msf":["msf"],"application/vnd.epson.quickanime":["qam"],"application/vnd.epson.salt":["slt"],"application/vnd.epson.ssf":["ssf"],"application/vnd.eszigno3+xml":["es3","et3"],"application/vnd.ezpix-album":["ez2"],"application/vnd.ezpix-package":["ez3"],"application/vnd.fdf":["fdf"],"application/vnd.fdsn.mseed":["mseed"],"application/vnd.fdsn.seed":["seed","dataless"],"application/vnd.flographit":["gph"],"application/vnd.fluxtime.clip":["ftc"],"application/vnd.framemaker":["fm","frame","maker","book"],"application/vnd.frogans.fnc":["fnc"],"application/vnd.frogans.ltf":["ltf"],"application/vnd.fsc.weblaunch":["fsc"],"application/vnd.fujitsu.oasys":["oas"],"application/vnd.fujitsu.oasys2":["oa2"],"application/vnd.fujitsu.oasys3":["oa3"],"application/vnd.fujitsu.oasysgp":["fg5"],"application/vnd.fujitsu.oasysprs":["bh2"],"application/vnd.fujixerox.ddd":["ddd"],"application/vnd.fujixerox.docuworks":["xdw"],"application/vnd.fujixerox.docuworks.binder":["xbd"],"application/vnd.fuzzysheet":["fzs"],"application/vnd.genomatix.tuxedo":["txd"],"application/vnd.geogebra.file":["ggb"],"application/vnd.geogebra.tool":["ggt"],"application/vnd.geometry-explorer":["gex","gre"],"application/vnd.geonext":["gxt"],"application/vnd.geoplan":["g2w"],"application/vnd.geospace":["g3w"],"application/vnd.gmx":["gmx"],"application/vnd.google-apps.document":["gdoc"],"application/vnd.google-apps.presentation":["gslides"],"application/vnd.google-apps.spreadsheet":["gsheet"],"application/vnd.google-earth.kml+xml":["kml"],"application/vnd.google-earth.kmz":["kmz"],"application/vnd.grafeq":["gqf","gqs"],"application/vnd.groove-account":["gac"],"application/vnd.groove-help":["ghf"],"application/vnd.groove-identity-message":["gim"],"application/vnd.groove-injector":["grv"],"application/vnd.groove-tool-message":["gtm"],"application/vnd.groove-tool-template":["tpl"],"application/vnd.groove-vcard":["vcg"],"application/vnd.hal+xml":["hal"],"application/vnd.handheld-entertainment+xml":["zmm"],"application/vnd.hbci":["hbci"],"application/vnd.hhe.lesson-player":["les"],"application/vnd.hp-hpgl":["hpgl"],"application/vnd.hp-hpid":["hpid"],"application/vnd.hp-hps":["hps"],"application/vnd.hp-jlyt":["jlt"],"application/vnd.hp-pcl":["pcl"],"application/vnd.hp-pclxl":["pclxl"],"application/vnd.hydrostatix.sof-data":["sfd-hdstx"],"application/vnd.ibm.minipay":["mpy"],"application/vnd.ibm.modcap":["afp","listafp","list3820"],"application/vnd.ibm.rights-management":["irm"],"application/vnd.ibm.secure-container":["sc"],"application/vnd.iccprofile":["icc","icm"],"application/vnd.igloader":["igl"],"application/vnd.immervision-ivp":["ivp"],"application/vnd.immervision-ivu":["ivu"],"application/vnd.insors.igm":["igm"],"application/vnd.intercon.formnet":["xpw","xpx"],"application/vnd.intergeo":["i2g"],"application/vnd.intu.qbo":["qbo"],"application/vnd.intu.qfx":["qfx"],"application/vnd.ipunplugged.rcprofile":["rcprofile"],"application/vnd.irepository.package+xml":["irp"],"application/vnd.is-xpr":["xpr"],"application/vnd.isac.fcs":["fcs"],"application/vnd.jam":["jam"],"application/vnd.jcp.javame.midlet-rms":["rms"],"application/vnd.jisp":["jisp"],"application/vnd.joost.joda-archive":["joda"],"application/vnd.kahootz":["ktz","ktr"],"application/vnd.kde.karbon":["karbon"],"application/vnd.kde.kchart":["chrt"],"application/vnd.kde.kformula":["kfo"],"application/vnd.kde.kivio":["flw"],"application/vnd.kde.kontour":["kon"],"application/vnd.kde.kpresenter":["kpr","kpt"],"application/vnd.kde.kspread":["ksp"],"application/vnd.kde.kword":["kwd","kwt"],"application/vnd.kenameaapp":["htke"],"application/vnd.kidspiration":["kia"],"application/vnd.kinar":["kne","knp"],"application/vnd.koan":["skp","skd","skt","skm"],"application/vnd.kodak-descriptor":["sse"],"application/vnd.las.las+xml":["lasxml"],"application/vnd.llamagraphics.life-balance.desktop":["lbd"],"application/vnd.llamagraphics.life-balance.exchange+xml":["lbe"],"application/vnd.lotus-1-2-3":["123"],"application/vnd.lotus-approach":["apr"],"application/vnd.lotus-freelance":["pre"],"application/vnd.lotus-notes":["nsf"],"application/vnd.lotus-organizer":["org"],"application/vnd.lotus-screencam":["scm"],"application/vnd.lotus-wordpro":["lwp"],"application/vnd.macports.portpkg":["portpkg"],"application/vnd.mapbox-vector-tile":["mvt"],"application/vnd.mcd":["mcd"],"application/vnd.medcalcdata":["mc1"],"application/vnd.mediastation.cdkey":["cdkey"],"application/vnd.mfer":["mwf"],"application/vnd.mfmp":["mfm"],"application/vnd.micrografx.flo":["flo"],"application/vnd.micrografx.igx":["igx"],"application/vnd.mif":["mif"],"application/vnd.mobius.daf":["daf"],"application/vnd.mobius.dis":["dis"],"application/vnd.mobius.mbk":["mbk"],"application/vnd.mobius.mqy":["mqy"],"application/vnd.mobius.msl":["msl"],"application/vnd.mobius.plc":["plc"],"application/vnd.mobius.txf":["txf"],"application/vnd.mophun.application":["mpn"],"application/vnd.mophun.certificate":["mpc"],"application/vnd.mozilla.xul+xml":["xul"],"application/vnd.ms-artgalry":["cil"],"application/vnd.ms-cab-compressed":["cab"],"application/vnd.ms-excel":["xls","xlm","xla","xlc","xlt","xlw"],"application/vnd.ms-excel.addin.macroenabled.12":["xlam"],"application/vnd.ms-excel.sheet.binary.macroenabled.12":["xlsb"],"application/vnd.ms-excel.sheet.macroenabled.12":["xlsm"],"application/vnd.ms-excel.template.macroenabled.12":["xltm"],"application/vnd.ms-fontobject":["eot"],"application/vnd.ms-htmlhelp":["chm"],"application/vnd.ms-ims":["ims"],"application/vnd.ms-lrm":["lrm"],"application/vnd.ms-officetheme":["thmx"],"application/vnd.ms-outlook":["msg"],"application/vnd.ms-pki.seccat":["cat"],"application/vnd.ms-pki.stl":["*stl"],"application/vnd.ms-powerpoint":["ppt","pps","pot"],"application/vnd.ms-powerpoint.addin.macroenabled.12":["ppam"],"application/vnd.ms-powerpoint.presentation.macroenabled.12":["pptm"],"application/vnd.ms-powerpoint.slide.macroenabled.12":["sldm"],"application/vnd.ms-powerpoint.slideshow.macroenabled.12":["ppsm"],"application/vnd.ms-powerpoint.template.macroenabled.12":["potm"],"application/vnd.ms-project":["mpp","mpt"],"application/vnd.ms-word.document.macroenabled.12":["docm"],"application/vnd.ms-word.template.macroenabled.12":["dotm"],"application/vnd.ms-works":["wps","wks","wcm","wdb"],"application/vnd.ms-wpl":["wpl"],"application/vnd.ms-xpsdocument":["xps"],"application/vnd.mseq":["mseq"],"application/vnd.musician":["mus"],"application/vnd.muvee.style":["msty"],"application/vnd.mynfc":["taglet"],"application/vnd.neurolanguage.nlu":["nlu"],"application/vnd.nitf":["ntf","nitf"],"application/vnd.noblenet-directory":["nnd"],"application/vnd.noblenet-sealer":["nns"],"application/vnd.noblenet-web":["nnw"],"application/vnd.nokia.n-gage.ac+xml":["*ac"],"application/vnd.nokia.n-gage.data":["ngdat"],"application/vnd.nokia.n-gage.symbian.install":["n-gage"],"application/vnd.nokia.radio-preset":["rpst"],"application/vnd.nokia.radio-presets":["rpss"],"application/vnd.novadigm.edm":["edm"],"application/vnd.novadigm.edx":["edx"],"application/vnd.novadigm.ext":["ext"],"application/vnd.oasis.opendocument.chart":["odc"],"application/vnd.oasis.opendocument.chart-template":["otc"],"application/vnd.oasis.opendocument.database":["odb"],"application/vnd.oasis.opendocument.formula":["odf"],"application/vnd.oasis.opendocument.formula-template":["odft"],"application/vnd.oasis.opendocument.graphics":["odg"],"application/vnd.oasis.opendocument.graphics-template":["otg"],"application/vnd.oasis.opendocument.image":["odi"],"application/vnd.oasis.opendocument.image-template":["oti"],"application/vnd.oasis.opendocument.presentation":["odp"],"application/vnd.oasis.opendocument.presentation-template":["otp"],"application/vnd.oasis.opendocument.spreadsheet":["ods"],"application/vnd.oasis.opendocument.spreadsheet-template":["ots"],"application/vnd.oasis.opendocument.text":["odt"],"application/vnd.oasis.opendocument.text-master":["odm"],"application/vnd.oasis.opendocument.text-template":["ott"],"application/vnd.oasis.opendocument.text-web":["oth"],"application/vnd.olpc-sugar":["xo"],"application/vnd.oma.dd2+xml":["dd2"],"application/vnd.openblox.game+xml":["obgx"],"application/vnd.openofficeorg.extension":["oxt"],"application/vnd.openstreetmap.data+xml":["osm"],"application/vnd.openxmlformats-officedocument.presentationml.presentation":["pptx"],"application/vnd.openxmlformats-officedocument.presentationml.slide":["sldx"],"application/vnd.openxmlformats-officedocument.presentationml.slideshow":["ppsx"],"application/vnd.openxmlformats-officedocument.presentationml.template":["potx"],"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":["xlsx"],"application/vnd.openxmlformats-officedocument.spreadsheetml.template":["xltx"],"application/vnd.openxmlformats-officedocument.wordprocessingml.document":["docx"],"application/vnd.openxmlformats-officedocument.wordprocessingml.template":["dotx"],"application/vnd.osgeo.mapguide.package":["mgp"],"application/vnd.osgi.dp":["dp"],"application/vnd.osgi.subsystem":["esa"],"application/vnd.palm":["pdb","pqa","oprc"],"application/vnd.pawaafile":["paw"],"application/vnd.pg.format":["str"],"application/vnd.pg.osasli":["ei6"],"application/vnd.picsel":["efif"],"application/vnd.pmi.widget":["wg"],"application/vnd.pocketlearn":["plf"],"application/vnd.powerbuilder6":["pbd"],"application/vnd.previewsystems.box":["box"],"application/vnd.proteus.magazine":["mgz"],"application/vnd.publishare-delta-tree":["qps"],"application/vnd.pvi.ptid1":["ptid"],"application/vnd.quark.quarkxpress":["qxd","qxt","qwd","qwt","qxl","qxb"],"application/vnd.rar":["rar"],"application/vnd.realvnc.bed":["bed"],"application/vnd.recordare.musicxml":["mxl"],"application/vnd.recordare.musicxml+xml":["musicxml"],"application/vnd.rig.cryptonote":["cryptonote"],"application/vnd.rim.cod":["cod"],"application/vnd.rn-realmedia":["rm"],"application/vnd.rn-realmedia-vbr":["rmvb"],"application/vnd.route66.link66+xml":["link66"],"application/vnd.sailingtracker.track":["st"],"application/vnd.seemail":["see"],"application/vnd.sema":["sema"],"application/vnd.semd":["semd"],"application/vnd.semf":["semf"],"application/vnd.shana.informed.formdata":["ifm"],"application/vnd.shana.informed.formtemplate":["itp"],"application/vnd.shana.informed.interchange":["iif"],"application/vnd.shana.informed.package":["ipk"],"application/vnd.simtech-mindmapper":["twd","twds"],"application/vnd.smaf":["mmf"],"application/vnd.smart.teacher":["teacher"],"application/vnd.software602.filler.form+xml":["fo"],"application/vnd.solent.sdkm+xml":["sdkm","sdkd"],"application/vnd.spotfire.dxp":["dxp"],"application/vnd.spotfire.sfs":["sfs"],"application/vnd.stardivision.calc":["sdc"],"application/vnd.stardivision.draw":["sda"],"application/vnd.stardivision.impress":["sdd"],"application/vnd.stardivision.math":["smf"],"application/vnd.stardivision.writer":["sdw","vor"],"application/vnd.stardivision.writer-global":["sgl"],"application/vnd.stepmania.package":["smzip"],"application/vnd.stepmania.stepchart":["sm"],"application/vnd.sun.wadl+xml":["wadl"],"application/vnd.sun.xml.calc":["sxc"],"application/vnd.sun.xml.calc.template":["stc"],"application/vnd.sun.xml.draw":["sxd"],"application/vnd.sun.xml.draw.template":["std"],"application/vnd.sun.xml.impress":["sxi"],"application/vnd.sun.xml.impress.template":["sti"],"application/vnd.sun.xml.math":["sxm"],"application/vnd.sun.xml.writer":["sxw"],"application/vnd.sun.xml.writer.global":["sxg"],"application/vnd.sun.xml.writer.template":["stw"],"application/vnd.sus-calendar":["sus","susp"],"application/vnd.svd":["svd"],"application/vnd.symbian.install":["sis","sisx"],"application/vnd.syncml+xml":["xsm"],"application/vnd.syncml.dm+wbxml":["bdm"],"application/vnd.syncml.dm+xml":["xdm"],"application/vnd.syncml.dmddf+xml":["ddf"],"application/vnd.tao.intent-module-archive":["tao"],"application/vnd.tcpdump.pcap":["pcap","cap","dmp"],"application/vnd.tmobile-livetv":["tmo"],"application/vnd.trid.tpt":["tpt"],"application/vnd.triscape.mxs":["mxs"],"application/vnd.trueapp":["tra"],"application/vnd.ufdl":["ufd","ufdl"],"application/vnd.uiq.theme":["utz"],"application/vnd.umajin":["umj"],"application/vnd.unity":["unityweb"],"application/vnd.uoml+xml":["uoml"],"application/vnd.vcx":["vcx"],"application/vnd.visio":["vsd","vst","vss","vsw"],"application/vnd.visionary":["vis"],"application/vnd.vsf":["vsf"],"application/vnd.wap.wbxml":["wbxml"],"application/vnd.wap.wmlc":["wmlc"],"application/vnd.wap.wmlscriptc":["wmlsc"],"application/vnd.webturbo":["wtb"],"application/vnd.wolfram.player":["nbp"],"application/vnd.wordperfect":["wpd"],"application/vnd.wqd":["wqd"],"application/vnd.wt.stf":["stf"],"application/vnd.xara":["xar"],"application/vnd.xfdl":["xfdl"],"application/vnd.yamaha.hv-dic":["hvd"],"application/vnd.yamaha.hv-script":["hvs"],"application/vnd.yamaha.hv-voice":["hvp"],"application/vnd.yamaha.openscoreformat":["osf"],"application/vnd.yamaha.openscoreformat.osfpvg+xml":["osfpvg"],"application/vnd.yamaha.smaf-audio":["saf"],"application/vnd.yamaha.smaf-phrase":["spf"],"application/vnd.yellowriver-custom-menu":["cmp"],"application/vnd.zul":["zir","zirz"],"application/vnd.zzazz.deck+xml":["zaz"],"application/x-7z-compressed":["7z"],"application/x-abiword":["abw"],"application/x-ace-compressed":["ace"],"application/x-apple-diskimage":["*dmg"],"application/x-arj":["arj"],"application/x-authorware-bin":["aab","x32","u32","vox"],"application/x-authorware-map":["aam"],"application/x-authorware-seg":["aas"],"application/x-bcpio":["bcpio"],"application/x-bdoc":["*bdoc"],"application/x-bittorrent":["torrent"],"application/x-blorb":["blb","blorb"],"application/x-bzip":["bz"],"application/x-bzip2":["bz2","boz"],"application/x-cbr":["cbr","cba","cbt","cbz","cb7"],"application/x-cdlink":["vcd"],"application/x-cfs-compressed":["cfs"],"application/x-chat":["chat"],"application/x-chess-pgn":["pgn"],"application/x-chrome-extension":["crx"],"application/x-cocoa":["cco"],"application/x-conference":["nsc"],"application/x-cpio":["cpio"],"application/x-csh":["csh"],"application/x-debian-package":["*deb","udeb"],"application/x-dgc-compressed":["dgc"],"application/x-director":["dir","dcr","dxr","cst","cct","cxt","w3d","fgd","swa"],"application/x-doom":["wad"],"application/x-dtbncx+xml":["ncx"],"application/x-dtbook+xml":["dtb"],"application/x-dtbresource+xml":["res"],"application/x-dvi":["dvi"],"application/x-envoy":["evy"],"application/x-eva":["eva"],"application/x-font-bdf":["bdf"],"application/x-font-ghostscript":["gsf"],"application/x-font-linux-psf":["psf"],"application/x-font-pcf":["pcf"],"application/x-font-snf":["snf"],"application/x-font-type1":["pfa","pfb","pfm","afm"],"application/x-freearc":["arc"],"application/x-futuresplash":["spl"],"application/x-gca-compressed":["gca"],"application/x-glulx":["ulx"],"application/x-gnumeric":["gnumeric"],"application/x-gramps-xml":["gramps"],"application/x-gtar":["gtar"],"application/x-hdf":["hdf"],"application/x-httpd-php":["php"],"application/x-install-instructions":["install"],"application/x-iso9660-image":["*iso"],"application/x-iwork-keynote-sffkey":["*key"],"application/x-iwork-numbers-sffnumbers":["*numbers"],"application/x-iwork-pages-sffpages":["*pages"],"application/x-java-archive-diff":["jardiff"],"application/x-java-jnlp-file":["jnlp"],"application/x-keepass2":["kdbx"],"application/x-latex":["latex"],"application/x-lua-bytecode":["luac"],"application/x-lzh-compressed":["lzh","lha"],"application/x-makeself":["run"],"application/x-mie":["mie"],"application/x-mobipocket-ebook":["prc","mobi"],"application/x-ms-application":["application"],"application/x-ms-shortcut":["lnk"],"application/x-ms-wmd":["wmd"],"application/x-ms-wmz":["wmz"],"application/x-ms-xbap":["xbap"],"application/x-msaccess":["mdb"],"application/x-msbinder":["obd"],"application/x-mscardfile":["crd"],"application/x-msclip":["clp"],"application/x-msdos-program":["*exe"],"application/x-msdownload":["*exe","*dll","com","bat","*msi"],"application/x-msmediaview":["mvb","m13","m14"],"application/x-msmetafile":["*wmf","*wmz","*emf","emz"],"application/x-msmoney":["mny"],"application/x-mspublisher":["pub"],"application/x-msschedule":["scd"],"application/x-msterminal":["trm"],"application/x-mswrite":["wri"],"application/x-netcdf":["nc","cdf"],"application/x-ns-proxy-autoconfig":["pac"],"application/x-nzb":["nzb"],"application/x-perl":["pl","pm"],"application/x-pilot":["*prc","*pdb"],"application/x-pkcs12":["p12","pfx"],"application/x-pkcs7-certificates":["p7b","spc"],"application/x-pkcs7-certreqresp":["p7r"],"application/x-rar-compressed":["*rar"],"application/x-redhat-package-manager":["rpm"],"application/x-research-info-systems":["ris"],"application/x-sea":["sea"],"application/x-sh":["sh"],"application/x-shar":["shar"],"application/x-shockwave-flash":["swf"],"application/x-silverlight-app":["xap"],"application/x-sql":["sql"],"application/x-stuffit":["sit"],"application/x-stuffitx":["sitx"],"application/x-subrip":["srt"],"application/x-sv4cpio":["sv4cpio"],"application/x-sv4crc":["sv4crc"],"application/x-t3vm-image":["t3"],"application/x-tads":["gam"],"application/x-tar":["tar"],"application/x-tcl":["tcl","tk"],"application/x-tex":["tex"],"application/x-tex-tfm":["tfm"],"application/x-texinfo":["texinfo","texi"],"application/x-tgif":["*obj"],"application/x-ustar":["ustar"],"application/x-virtualbox-hdd":["hdd"],"application/x-virtualbox-ova":["ova"],"application/x-virtualbox-ovf":["ovf"],"application/x-virtualbox-vbox":["vbox"],"application/x-virtualbox-vbox-extpack":["vbox-extpack"],"application/x-virtualbox-vdi":["vdi"],"application/x-virtualbox-vhd":["vhd"],"application/x-virtualbox-vmdk":["vmdk"],"application/x-wais-source":["src"],"application/x-web-app-manifest+json":["webapp"],"application/x-x509-ca-cert":["der","crt","pem"],"application/x-xfig":["fig"],"application/x-xliff+xml":["*xlf"],"application/x-xpinstall":["xpi"],"application/x-xz":["xz"],"application/x-zmachine":["z1","z2","z3","z4","z5","z6","z7","z8"],"audio/vnd.dece.audio":["uva","uvva"],"audio/vnd.digital-winds":["eol"],"audio/vnd.dra":["dra"],"audio/vnd.dts":["dts"],"audio/vnd.dts.hd":["dtshd"],"audio/vnd.lucent.voice":["lvp"],"audio/vnd.ms-playready.media.pya":["pya"],"audio/vnd.nuera.ecelp4800":["ecelp4800"],"audio/vnd.nuera.ecelp7470":["ecelp7470"],"audio/vnd.nuera.ecelp9600":["ecelp9600"],"audio/vnd.rip":["rip"],"audio/x-aac":["aac"],"audio/x-aiff":["aif","aiff","aifc"],"audio/x-caf":["caf"],"audio/x-flac":["flac"],"audio/x-m4a":["*m4a"],"audio/x-matroska":["mka"],"audio/x-mpegurl":["m3u"],"audio/x-ms-wax":["wax"],"audio/x-ms-wma":["wma"],"audio/x-pn-realaudio":["ram","ra"],"audio/x-pn-realaudio-plugin":["rmp"],"audio/x-realaudio":["*ra"],"audio/x-wav":["*wav"],"chemical/x-cdx":["cdx"],"chemical/x-cif":["cif"],"chemical/x-cmdf":["cmdf"],"chemical/x-cml":["cml"],"chemical/x-csml":["csml"],"chemical/x-xyz":["xyz"],"image/prs.btif":["btif"],"image/prs.pti":["pti"],"image/vnd.adobe.photoshop":["psd"],"image/vnd.airzip.accelerator.azv":["azv"],"image/vnd.dece.graphic":["uvi","uvvi","uvg","uvvg"],"image/vnd.djvu":["djvu","djv"],"image/vnd.dvb.subtitle":["*sub"],"image/vnd.dwg":["dwg"],"image/vnd.dxf":["dxf"],"image/vnd.fastbidsheet":["fbs"],"image/vnd.fpx":["fpx"],"image/vnd.fst":["fst"],"image/vnd.fujixerox.edmics-mmr":["mmr"],"image/vnd.fujixerox.edmics-rlc":["rlc"],"image/vnd.microsoft.icon":["ico"],"image/vnd.ms-dds":["dds"],"image/vnd.ms-modi":["mdi"],"image/vnd.ms-photo":["wdp"],"image/vnd.net-fpx":["npx"],"image/vnd.pco.b16":["b16"],"image/vnd.tencent.tap":["tap"],"image/vnd.valve.source.texture":["vtf"],"image/vnd.wap.wbmp":["wbmp"],"image/vnd.xiff":["xif"],"image/vnd.zbrush.pcx":["pcx"],"image/x-3ds":["3ds"],"image/x-cmu-raster":["ras"],"image/x-cmx":["cmx"],"image/x-freehand":["fh","fhc","fh4","fh5","fh7"],"image/x-icon":["*ico"],"image/x-jng":["jng"],"image/x-mrsid-image":["sid"],"image/x-ms-bmp":["*bmp"],"image/x-pcx":["*pcx"],"image/x-pict":["pic","pct"],"image/x-portable-anymap":["pnm"],"image/x-portable-bitmap":["pbm"],"image/x-portable-graymap":["pgm"],"image/x-portable-pixmap":["ppm"],"image/x-rgb":["rgb"],"image/x-tga":["tga"],"image/x-xbitmap":["xbm"],"image/x-xpixmap":["xpm"],"image/x-xwindowdump":["xwd"],"message/vnd.wfa.wsc":["wsc"],"model/vnd.collada+xml":["dae"],"model/vnd.dwf":["dwf"],"model/vnd.gdl":["gdl"],"model/vnd.gtw":["gtw"],"model/vnd.mts":["mts"],"model/vnd.opengex":["ogex"],"model/vnd.parasolid.transmit.binary":["x_b"],"model/vnd.parasolid.transmit.text":["x_t"],"model/vnd.sap.vds":["vds"],"model/vnd.usdz+zip":["usdz"],"model/vnd.valve.source.compiled-map":["bsp"],"model/vnd.vtu":["vtu"],"text/prs.lines.tag":["dsc"],"text/vnd.curl":["curl"],"text/vnd.curl.dcurl":["dcurl"],"text/vnd.curl.mcurl":["mcurl"],"text/vnd.curl.scurl":["scurl"],"text/vnd.dvb.subtitle":["sub"],"text/vnd.fly":["fly"],"text/vnd.fmi.flexstor":["flx"],"text/vnd.graphviz":["gv"],"text/vnd.in3d.3dml":["3dml"],"text/vnd.in3d.spot":["spot"],"text/vnd.sun.j2me.app-descriptor":["jad"],"text/vnd.wap.wml":["wml"],"text/vnd.wap.wmlscript":["wmls"],"text/x-asm":["s","asm"],"text/x-c":["c","cc","cxx","cpp","h","hh","dic"],"text/x-component":["htc"],"text/x-fortran":["f","for","f77","f90"],"text/x-handlebars-template":["hbs"],"text/x-java-source":["java"],"text/x-lua":["lua"],"text/x-markdown":["mkd"],"text/x-nfo":["nfo"],"text/x-opml":["opml"],"text/x-org":["*org"],"text/x-pascal":["p","pas"],"text/x-processing":["pde"],"text/x-sass":["sass"],"text/x-scss":["scss"],"text/x-setext":["etx"],"text/x-sfv":["sfv"],"text/x-suse-ymp":["ymp"],"text/x-uuencode":["uu"],"text/x-vcalendar":["vcs"],"text/x-vcard":["vcf"],"video/vnd.dece.hd":["uvh","uvvh"],"video/vnd.dece.mobile":["uvm","uvvm"],"video/vnd.dece.pd":["uvp","uvvp"],"video/vnd.dece.sd":["uvs","uvvs"],"video/vnd.dece.video":["uvv","uvvv"],"video/vnd.dvb.file":["dvb"],"video/vnd.fvt":["fvt"],"video/vnd.mpegurl":["mxu","m4u"],"video/vnd.ms-playready.media.pyv":["pyv"],"video/vnd.uvvu.mp4":["uvu","uvvu"],"video/vnd.vivo":["viv"],"video/x-f4v":["f4v"],"video/x-fli":["fli"],"video/x-flv":["flv"],"video/x-m4v":["m4v"],"video/x-matroska":["mkv","mk3d","mks"],"video/x-mng":["mng"],"video/x-ms-asf":["asf","asx"],"video/x-ms-vob":["vob"],"video/x-ms-wm":["wm"],"video/x-ms-wmv":["wmv"],"video/x-ms-wmx":["wmx"],"video/x-ms-wvx":["wvx"],"video/x-msvideo":["avi"],"video/x-sgi-movie":["movie"],"video/x-smv":["smv"],"x-conference/x-cooltalk":["ice"]};
|
|
|
|
let Mime = Mime_1;
|
|
var mime = new Mime(standard, other);
|
|
|
|
const param_pattern = /^(\.\.\.)?(\w+)(?:=(\w+))?$/;
|
|
|
|
/** @param {string} id */
|
|
function parse_route_id(id) {
|
|
/** @type {string[]} */
|
|
const names = [];
|
|
|
|
/** @type {string[]} */
|
|
const types = [];
|
|
|
|
// `/foo` should get an optional trailing slash, `/foo.json` should not
|
|
// const add_trailing_slash = !/\.[a-z]+$/.test(key);
|
|
let add_trailing_slash = true;
|
|
|
|
const pattern =
|
|
id === ''
|
|
? /^\/$/
|
|
: new RegExp(
|
|
`^${decodeURIComponent(id)
|
|
.split(/(?:@[a-zA-Z0-9_-]+)?(?:\/|$)/)
|
|
.map((segment, i, segments) => {
|
|
// special case — /[...rest]/ could contain zero segments
|
|
const match = /^\[\.\.\.(\w+)(?:=(\w+))?\]$/.exec(segment);
|
|
if (match) {
|
|
names.push(match[1]);
|
|
types.push(match[2]);
|
|
return '(?:/(.*))?';
|
|
}
|
|
|
|
const is_last = i === segments.length - 1;
|
|
|
|
return (
|
|
segment &&
|
|
'/' +
|
|
segment
|
|
.split(/\[(.+?)\]/)
|
|
.map((content, i) => {
|
|
if (i % 2) {
|
|
const match = param_pattern.exec(content);
|
|
if (!match) {
|
|
throw new Error(
|
|
`Invalid param: ${content}. Params and matcher names can only have underscores and alphanumeric characters.`
|
|
);
|
|
}
|
|
|
|
const [, rest, name, type] = match;
|
|
names.push(name);
|
|
types.push(type);
|
|
return rest ? '(.*?)' : '([^/]+?)';
|
|
}
|
|
|
|
if (is_last && content.includes('.')) add_trailing_slash = false;
|
|
|
|
return (
|
|
content // allow users to specify characters on the file system in an encoded manner
|
|
.normalize()
|
|
// We use [ and ] to denote parameters, so users must encode these on the file
|
|
// system to match against them. We don't decode all characters since others
|
|
// can already be epressed and so that '%' can be easily used directly in filenames
|
|
.replace(/%5[Bb]/g, '[')
|
|
.replace(/%5[Dd]/g, ']')
|
|
// '#', '/', and '?' can only appear in URL path segments in an encoded manner.
|
|
// They will not be touched by decodeURI so need to be encoded here, so
|
|
// that we can match against them.
|
|
// We skip '/' since you can't create a file with it on any OS
|
|
.replace(/#/g, '%23')
|
|
.replace(/\?/g, '%3F')
|
|
// escape characters that have special meaning in regex
|
|
.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
); // TODO handle encoding
|
|
})
|
|
.join('')
|
|
);
|
|
})
|
|
.join('')}${add_trailing_slash ? '/?' : ''}$`
|
|
);
|
|
|
|
return { pattern, names, types };
|
|
}
|
|
|
|
/**
|
|
* A portion of a file or directory name where the name has been split into
|
|
* static and dynamic parts
|
|
* @typedef {{
|
|
* content: string;
|
|
* dynamic: boolean;
|
|
* rest: boolean;
|
|
* type: string | null;
|
|
* }} Part
|
|
*/
|
|
|
|
/**
|
|
* A route, consisting of an endpoint module and/or an array of components
|
|
* (n layouts and one leaf) for successful navigations and an array of
|
|
* n error components to render if navigation fails
|
|
* @typedef {{
|
|
* id: string;
|
|
* pattern: RegExp;
|
|
* segments: Part[][];
|
|
* page?: {
|
|
* a: Array<string | undefined>;
|
|
* b: Array<string | undefined>;
|
|
* };
|
|
* endpoint?: string;
|
|
* }} Unit
|
|
*/
|
|
|
|
/**
|
|
* @typedef {{
|
|
* error: string | undefined;
|
|
* layouts: Record<string, { file: string, name: string }>
|
|
* }} Node
|
|
*/
|
|
|
|
/**
|
|
* @typedef {Map<string, Node>} Tree
|
|
*/
|
|
|
|
const layout_pattern = /^__layout(?:-([a-zA-Z0-9_-]+))?(?:@([a-zA-Z0-9_-]+))?$/;
|
|
const dunder_pattern = /(^|\/)__(?!tests?__)/; // forbid __-prefixed files/directories except __error, __layout[-...], __test__, __tests__
|
|
|
|
const DEFAULT = 'default';
|
|
|
|
/**
|
|
* @param {{
|
|
* config: import('types').ValidatedConfig;
|
|
* fallback?: string;
|
|
* cwd?: string;
|
|
* }} opts
|
|
* @returns {import('types').ManifestData}
|
|
*/
|
|
function create_manifest_data({
|
|
config,
|
|
fallback = `${get_runtime_directory(config.kit)}/components`,
|
|
cwd = process.cwd()
|
|
}) {
|
|
/** @type {import('types').RouteData[]} */
|
|
const routes = [];
|
|
|
|
/** @type {Map<string, Unit>} */
|
|
const units = new Map();
|
|
|
|
/** @type {Tree} */
|
|
const tree = new Map();
|
|
|
|
const default_layout = {
|
|
file: posixify(path__default.relative(cwd, `${fallback}/layout.svelte`)),
|
|
name: DEFAULT
|
|
};
|
|
|
|
// set default root layout/error
|
|
tree.set('', {
|
|
error: posixify(path__default.relative(cwd, `${fallback}/error.svelte`)),
|
|
layouts: { [DEFAULT]: default_layout }
|
|
});
|
|
|
|
const routes_base = posixify(path__default.relative(cwd, config.kit.files.routes));
|
|
const valid_extensions = [...config.extensions, ...config.kit.moduleExtensions];
|
|
|
|
if (fs__default.existsSync(config.kit.files.routes)) {
|
|
list_files(config.kit.files.routes).forEach((file) => {
|
|
const extension = valid_extensions.find((ext) => file.endsWith(ext));
|
|
if (!extension) return;
|
|
|
|
const id = file
|
|
.slice(0, -extension.length)
|
|
.replace(/(?:^|\/)index((?:@[a-zA-Z0-9_-]+)?(?:\.[a-z]+)?)?$/, '$1');
|
|
const project_relative = `${routes_base}/${file}`;
|
|
|
|
const segments = id.split('/');
|
|
const name = /** @type {string} */ (segments.pop());
|
|
|
|
if (name === '__layout.reset') {
|
|
throw new Error(
|
|
'__layout.reset has been removed in favour of named layouts: https://kit.svelte.dev/docs/layouts#named-layouts'
|
|
);
|
|
}
|
|
|
|
if (name === '__error' || layout_pattern.test(name)) {
|
|
const dir = segments.join('/');
|
|
|
|
if (!tree.has(dir)) {
|
|
tree.set(dir, {
|
|
error: undefined,
|
|
layouts: {}
|
|
});
|
|
}
|
|
|
|
const group = /** @type {Node} */ (tree.get(dir));
|
|
|
|
if (name === '__error') {
|
|
group.error = project_relative;
|
|
} else {
|
|
const match = /** @type {RegExpMatchArray} */ (layout_pattern.exec(name));
|
|
|
|
if (match[1] === DEFAULT) {
|
|
throw new Error(`${project_relative} cannot use reserved "${DEFAULT}" name`);
|
|
}
|
|
|
|
const layout_id = match[1] || DEFAULT;
|
|
|
|
const defined = group.layouts[layout_id];
|
|
if (defined && defined !== default_layout) {
|
|
throw new Error(
|
|
`Duplicate layout ${project_relative} already defined at ${defined.file}`
|
|
);
|
|
}
|
|
|
|
group.layouts[layout_id] = {
|
|
file: project_relative,
|
|
name
|
|
};
|
|
}
|
|
|
|
return;
|
|
} else if (dunder_pattern.test(file)) {
|
|
throw new Error(
|
|
`Files and directories prefixed with __ are reserved (saw ${project_relative})`
|
|
);
|
|
}
|
|
|
|
if (!config.kit.routes(file)) return;
|
|
|
|
if (/\]\[/.test(id)) {
|
|
throw new Error(`Invalid route ${project_relative} — parameters must be separated`);
|
|
}
|
|
|
|
if (count_occurrences('[', id) !== count_occurrences(']', id)) {
|
|
throw new Error(`Invalid route ${project_relative} — brackets are unbalanced`);
|
|
}
|
|
|
|
if (!units.has(id)) {
|
|
units.set(id, {
|
|
id,
|
|
pattern: parse_route_id(id).pattern,
|
|
segments: id
|
|
.split('/')
|
|
.filter(Boolean)
|
|
.map((segment) => {
|
|
/** @type {Part[]} */
|
|
const parts = [];
|
|
segment.split(/\[(.+?)\]/).map((content, i) => {
|
|
const dynamic = !!(i % 2);
|
|
|
|
if (!content) return;
|
|
|
|
parts.push({
|
|
content,
|
|
dynamic,
|
|
rest: dynamic && content.startsWith('...'),
|
|
type: (dynamic && content.split('=')[1]) || null
|
|
});
|
|
});
|
|
return parts;
|
|
}),
|
|
page: undefined,
|
|
endpoint: undefined
|
|
});
|
|
}
|
|
|
|
const unit = /** @type {Unit} */ (units.get(id));
|
|
|
|
if (config.extensions.find((ext) => file.endsWith(ext))) {
|
|
const { layouts, errors } = trace(project_relative, file, tree, config.extensions);
|
|
unit.page = {
|
|
a: layouts.concat(project_relative),
|
|
b: errors
|
|
};
|
|
} else {
|
|
unit.endpoint = project_relative;
|
|
}
|
|
});
|
|
}
|
|
|
|
/** @type {string[]} */
|
|
const components = [];
|
|
|
|
tree.forEach(({ layouts, error }) => {
|
|
// we do [default, error, ...other_layouts] so that components[0] and [1]
|
|
// are the root layout/error. kinda janky, there's probably a nicer way
|
|
if (layouts[DEFAULT]) {
|
|
components.push(layouts[DEFAULT].file);
|
|
}
|
|
|
|
if (error) {
|
|
components.push(error);
|
|
}
|
|
|
|
for (const id in layouts) {
|
|
if (id !== DEFAULT) components.push(layouts[id].file);
|
|
}
|
|
});
|
|
|
|
units.forEach((unit) => {
|
|
if (unit.page) {
|
|
const leaf = /** @type {string} */ (unit.page.a[unit.page.a.length - 1]);
|
|
components.push(leaf);
|
|
}
|
|
});
|
|
|
|
Array.from(units.values())
|
|
.sort(compare)
|
|
.forEach((unit) => {
|
|
// TODO when we introduce layout endpoints and scoped middlewares, we
|
|
// will probably want to have a single unified route type here
|
|
// (created in the list_files(...).forEach(...) callback)
|
|
if (unit.page) {
|
|
routes.push({
|
|
type: 'page',
|
|
id: unit.id,
|
|
pattern: unit.pattern,
|
|
path: unit.id.includes('[') ? '' : `/${unit.id.replace(/@(?:[a-zA-Z0-9_-]+)/g, '')}`,
|
|
shadow: unit.endpoint || null,
|
|
a: unit.page.a,
|
|
b: unit.page.b
|
|
});
|
|
} else if (unit.endpoint) {
|
|
routes.push({
|
|
type: 'endpoint',
|
|
id: unit.id,
|
|
pattern: unit.pattern,
|
|
file: unit.endpoint
|
|
});
|
|
}
|
|
});
|
|
|
|
/** @type {import('types').Asset[]} */
|
|
const assets = fs__default.existsSync(config.kit.files.assets)
|
|
? list_files(config.kit.files.assets).map((file) => ({
|
|
file,
|
|
size: fs__default.statSync(`${config.kit.files.assets}/${file}`).size,
|
|
type: mime.getType(file)
|
|
}))
|
|
: [];
|
|
|
|
const params_base = path__default.relative(cwd, config.kit.files.params);
|
|
|
|
/** @type {Record<string, string>} */
|
|
const matchers = {};
|
|
if (fs__default.existsSync(config.kit.files.params)) {
|
|
for (const file of fs__default.readdirSync(config.kit.files.params)) {
|
|
const ext = path__default.extname(file);
|
|
if (!config.kit.moduleExtensions.includes(ext)) continue;
|
|
const type = file.slice(0, -ext.length);
|
|
|
|
if (/^\w+$/.test(type)) {
|
|
const matcher_file = path__default.join(params_base, file);
|
|
|
|
// Disallow same matcher with different extensions
|
|
if (matchers[type]) {
|
|
throw new Error(`Duplicate matchers: ${matcher_file} and ${matchers[type]}`);
|
|
} else {
|
|
matchers[type] = matcher_file;
|
|
}
|
|
} else {
|
|
throw new Error(
|
|
`Matcher names can only have underscores and alphanumeric characters — "${file}" is invalid`
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
return {
|
|
assets,
|
|
components,
|
|
routes,
|
|
matchers
|
|
};
|
|
}
|
|
|
|
/**
|
|
* @param {string} file
|
|
* @param {string} path
|
|
* @param {Tree} tree
|
|
* @param {string[]} extensions
|
|
*/
|
|
function trace(file, path, tree, extensions) {
|
|
/** @type {Array<string | undefined>} */
|
|
const layouts = [];
|
|
|
|
/** @type {Array<string | undefined>} */
|
|
const errors = [];
|
|
|
|
const parts = path.split('/');
|
|
const filename = /** @type {string} */ (parts.pop());
|
|
const extension = /** @type {string} */ (extensions.find((ext) => path.endsWith(ext)));
|
|
const base = filename.slice(0, -extension.length);
|
|
|
|
let layout_id = base.includes('@') ? base.split('@')[1] : DEFAULT;
|
|
|
|
if (parts.findIndex((part) => part.indexOf('@') > -1) > -1) {
|
|
throw new Error(`Invalid route ${file} - named layouts are not allowed in directories`);
|
|
}
|
|
|
|
// walk up the tree, find which __layout and __error components
|
|
// apply to this page
|
|
while (true) {
|
|
const node = tree.get(parts.join('/'));
|
|
const layout = node?.layouts[layout_id];
|
|
|
|
if (layout?.file && layouts.indexOf(layout.file) > -1) {
|
|
throw new Error(`Recursive layout detected: ${layout.file} -> ${layouts.join(' -> ')}`);
|
|
}
|
|
|
|
// any segment that has neither a __layout nor an __error can be discarded.
|
|
// in other words these...
|
|
// layouts: [a, , b, c]
|
|
// errors: [d, , e, ]
|
|
//
|
|
// ...can be compacted to these:
|
|
// layouts: [a, b, c]
|
|
// errors: [d, e, ]
|
|
if (node?.error || layout?.file) {
|
|
errors.unshift(node?.error);
|
|
layouts.unshift(layout?.file);
|
|
}
|
|
|
|
if (layout?.name.includes('@')) {
|
|
layout_id = layout.name.split('@')[1];
|
|
} else {
|
|
if (layout) layout_id = DEFAULT;
|
|
if (parts.length === 0) break;
|
|
parts.pop();
|
|
}
|
|
}
|
|
|
|
if (layout_id !== DEFAULT) {
|
|
throw new Error(`${file} references missing layout "${layout_id}"`);
|
|
}
|
|
|
|
// trim empty space off the end of the errors array
|
|
let i = errors.length;
|
|
while (i--) if (errors[i]) break;
|
|
errors.length = i + 1;
|
|
|
|
return { layouts, errors };
|
|
}
|
|
|
|
/**
|
|
* @param {Unit} a
|
|
* @param {Unit} b
|
|
*/
|
|
function compare(a, b) {
|
|
const max_segments = Math.max(a.segments.length, b.segments.length);
|
|
for (let i = 0; i < max_segments; i += 1) {
|
|
const sa = a.segments[i];
|
|
const sb = b.segments[i];
|
|
|
|
// /x < /x/y, but /[...x]/y < /[...x]
|
|
if (!sa) return a.id.includes('[...') ? +1 : -1;
|
|
if (!sb) return b.id.includes('[...') ? -1 : +1;
|
|
|
|
const max_parts = Math.max(sa.length, sb.length);
|
|
for (let i = 0; i < max_parts; i += 1) {
|
|
const pa = sa[i];
|
|
const pb = sb[i];
|
|
|
|
// xy < x[y], but [x].json < [x]
|
|
if (pa === undefined) return pb.dynamic ? -1 : +1;
|
|
if (pb === undefined) return pa.dynamic ? +1 : -1;
|
|
|
|
// x < [x]
|
|
if (pa.dynamic !== pb.dynamic) {
|
|
return pa.dynamic ? +1 : -1;
|
|
}
|
|
|
|
if (pa.dynamic) {
|
|
// [x] < [...x]
|
|
if (pa.rest !== pb.rest) {
|
|
return pa.rest ? +1 : -1;
|
|
}
|
|
|
|
// [x=type] < [x]
|
|
if (!!pa.type !== !!pb.type) {
|
|
return pa.type ? -1 : +1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
const a_is_endpoint = !a.page && a.endpoint;
|
|
const b_is_endpoint = !b.page && b.endpoint;
|
|
|
|
if (a_is_endpoint !== b_is_endpoint) {
|
|
return a_is_endpoint ? -1 : +1;
|
|
}
|
|
|
|
return a < b ? -1 : 1;
|
|
}
|
|
|
|
/**
|
|
* @param {string} needle
|
|
* @param {string} haystack
|
|
*/
|
|
function count_occurrences(needle, haystack) {
|
|
let count = 0;
|
|
for (let i = 0; i < haystack.length; i += 1) {
|
|
if (haystack[i] === needle) count += 1;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
/**
|
|
* @param {string} dir
|
|
* @param {string} [path]
|
|
* @param {string[]} [files]
|
|
*/
|
|
function list_files(dir, path = '', files = []) {
|
|
fs__default.readdirSync(dir)
|
|
.sort((a, b) => {
|
|
// sort each directory in (__layout, __error, everything else) order
|
|
// so that we can trace layouts/errors immediately
|
|
|
|
if (a.startsWith('__layout')) {
|
|
if (!b.startsWith('__layout')) return -1;
|
|
} else if (b.startsWith('__layout')) {
|
|
return 1;
|
|
} else if (a.startsWith('__')) {
|
|
if (!b.startsWith('__')) return -1;
|
|
} else if (b.startsWith('__')) {
|
|
return 1;
|
|
}
|
|
|
|
return a < b ? -1 : 1;
|
|
})
|
|
.forEach((file) => {
|
|
const full = `${dir}/${file}`;
|
|
const stats = fs__default.statSync(full);
|
|
const joined = path ? `${path}/${file}` : file;
|
|
|
|
if (stats.isDirectory()) {
|
|
list_files(full, joined, files);
|
|
} else {
|
|
files.push(joined);
|
|
}
|
|
});
|
|
|
|
return files;
|
|
}
|
|
|
|
const filename = fileURLToPath(import.meta.url);
|
|
const dirname = path__default.dirname(filename);
|
|
|
|
/** @param {string} dest */
|
|
function copy_assets(dest) {
|
|
let prefix = '..';
|
|
do {
|
|
// we jump through these hoops so that this function
|
|
// works whether or not it's been bundled
|
|
const resolved = path__default.resolve(dirname, `${prefix}/assets`);
|
|
|
|
if (fs__default.existsSync(resolved)) {
|
|
copy(resolved, dest);
|
|
return;
|
|
}
|
|
|
|
prefix = `../${prefix}`;
|
|
} while (true);
|
|
}
|
|
|
|
const s = JSON.stringify;
|
|
|
|
/**
|
|
* Writes the client manifest to disk. The manifest is used to power the router. It contains the
|
|
* list of routes and corresponding Svelte components (i.e. pages and layouts).
|
|
* @param {import('types').ManifestData} manifest_data
|
|
* @param {string} base
|
|
* @param {string} output
|
|
*/
|
|
function write_manifest(manifest_data, base, output) {
|
|
/** @type {Record<string, number>} */
|
|
const component_indexes = {};
|
|
|
|
/** @param {string} c */
|
|
const get_path = (c) => path__default.relative(base, c);
|
|
|
|
const components = `[
|
|
${manifest_data.components
|
|
.map((component, i) => {
|
|
component_indexes[component] = i;
|
|
|
|
return `() => import(${s(get_path(component))})`;
|
|
})
|
|
.join(',\n\t\t\t\t\t')}
|
|
]`.replace(/^\t/gm, '');
|
|
|
|
/** @param {Array<string | undefined>} parts */
|
|
const get_indices = (parts) =>
|
|
`[${parts.map((part) => (part ? component_indexes[part] : '')).join(', ')}]`;
|
|
|
|
const dictionary = `{
|
|
${manifest_data.routes
|
|
.map((route) => {
|
|
if (route.type === 'page') {
|
|
const tuple = [get_indices(route.a), get_indices(route.b)];
|
|
if (route.shadow) tuple.push('1');
|
|
|
|
return `${s(route.id)}: [${tuple.join(', ')}]`;
|
|
}
|
|
})
|
|
.filter(Boolean)
|
|
.join(',\n\t\t')}
|
|
}`.replace(/^\t/gm, '');
|
|
|
|
write_if_changed(
|
|
`${output}/client-manifest.js`,
|
|
trim(`
|
|
export { matchers } from './client-matchers.js';
|
|
|
|
export const components = ${components};
|
|
|
|
export const dictionary = ${dictionary};
|
|
`)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param {import('types').ManifestData} manifest_data
|
|
* @param {string} output
|
|
*/
|
|
function write_matchers(manifest_data, output) {
|
|
const imports = [];
|
|
const matchers = [];
|
|
|
|
for (const key in manifest_data.matchers) {
|
|
const src = manifest_data.matchers[key];
|
|
|
|
imports.push(`import { match as ${key} } from ${s(path__default.relative(output, src))};`);
|
|
matchers.push(key);
|
|
}
|
|
|
|
const module = imports.length
|
|
? `${imports.join('\n')}\n\nexport const matchers = { ${matchers.join(', ')} };`
|
|
: 'export const matchers = {};';
|
|
|
|
write_if_changed(`${output}/client-matchers.js`, module);
|
|
}
|
|
|
|
/**
|
|
* @param {import('types').ManifestData} manifest_data
|
|
* @param {string} output
|
|
*/
|
|
function write_root(manifest_data, output) {
|
|
// TODO remove default layout altogether
|
|
|
|
const max_depth = Math.max(
|
|
...manifest_data.routes.map((route) =>
|
|
route.type === 'page' ? route.a.filter(Boolean).length : 0
|
|
),
|
|
1
|
|
);
|
|
|
|
const levels = [];
|
|
for (let i = 0; i <= max_depth; i += 1) {
|
|
levels.push(i);
|
|
}
|
|
|
|
let l = max_depth;
|
|
|
|
let pyramid = `<svelte:component this={components[${l}]} {...(props_${l} || {})}/>`;
|
|
|
|
while (l--) {
|
|
pyramid = `
|
|
{#if components[${l + 1}]}
|
|
<svelte:component this={components[${l}]} {...(props_${l} || {})}>
|
|
${pyramid.replace(/\n/g, '\n\t\t\t\t\t')}
|
|
</svelte:component>
|
|
{:else}
|
|
<svelte:component this={components[${l}]} {...(props_${l} || {})} />
|
|
{/if}
|
|
`
|
|
.replace(/^\t\t\t/gm, '')
|
|
.trim();
|
|
}
|
|
|
|
write_if_changed(
|
|
`${output}/root.svelte`,
|
|
trim(`
|
|
<!-- This file is generated by @sveltejs/kit — do not edit it! -->
|
|
<script>
|
|
import { setContext, afterUpdate, onMount } from 'svelte';
|
|
|
|
// stores
|
|
export let stores;
|
|
export let page;
|
|
|
|
export let components;
|
|
${levels.map((l) => `export let props_${l} = null;`).join('\n\t\t\t\t')}
|
|
|
|
setContext('__svelte__', stores);
|
|
|
|
$: stores.page.set(page);
|
|
afterUpdate(stores.page.notify);
|
|
|
|
let mounted = false;
|
|
let navigated = false;
|
|
let title = null;
|
|
|
|
onMount(() => {
|
|
const unsubscribe = stores.page.subscribe(() => {
|
|
if (mounted) {
|
|
navigated = true;
|
|
title = document.title || 'untitled page';
|
|
}
|
|
});
|
|
|
|
mounted = true;
|
|
return unsubscribe;
|
|
});
|
|
</script>
|
|
|
|
${pyramid.replace(/\n/g, '\n\t\t\t')}
|
|
|
|
{#if mounted}
|
|
<div id="svelte-announcer" aria-live="assertive" aria-atomic="true" style="position: absolute; left: 0; top: 0; clip: rect(0 0 0 0); clip-path: inset(50%); overflow: hidden; white-space: nowrap; width: 1px; height: 1px">
|
|
{#if navigated}
|
|
{title}
|
|
{/if}
|
|
</div>
|
|
{/if}
|
|
`)
|
|
);
|
|
}
|
|
|
|
/** @param {string} imports */
|
|
const header = (imports) => `
|
|
// this file is auto-generated
|
|
import type { ${imports} } from '@sveltejs/kit';`;
|
|
|
|
/** @param {string} arg */
|
|
const endpoint = (arg) => `
|
|
export type RequestHandler<Output = ResponseBody> = GenericRequestHandler<${arg}, Output>;`;
|
|
|
|
/** @param {string} arg */
|
|
const page = (arg) => `
|
|
export type Load<
|
|
InputProps extends Record<string, any> = Record<string, any>,
|
|
OutputProps extends Record<string, any> = InputProps
|
|
> = GenericLoad<${arg}, InputProps, OutputProps>;`;
|
|
|
|
/**
|
|
* @param {import('types').ValidatedConfig} config
|
|
* @param {import('types').ManifestData} manifest_data
|
|
*/
|
|
function write_types(config, manifest_data) {
|
|
rimraf(`${config.kit.outDir}/types`);
|
|
|
|
/** @type {Map<string, { params: string[], type: 'page' | 'endpoint' | 'both' }>} */
|
|
const shadow_types = new Map();
|
|
|
|
manifest_data.routes.forEach((route) => {
|
|
const file = route.type === 'endpoint' ? route.file : route.shadow;
|
|
|
|
if (file) {
|
|
const ext = /** @type {string} */ (
|
|
config.kit.moduleExtensions.find((ext) => file.endsWith(ext))
|
|
);
|
|
const key = file.slice(0, -ext.length);
|
|
shadow_types.set(key, {
|
|
params: parse_route_id(key).names,
|
|
type: route.type === 'endpoint' ? 'endpoint' : 'both'
|
|
});
|
|
}
|
|
});
|
|
|
|
manifest_data.components.forEach((component) => {
|
|
if (component.startsWith('.')) return; // exclude fallback components
|
|
|
|
const ext = /** @type {string} */ (config.extensions.find((ext) => component.endsWith(ext)));
|
|
const key = component.slice(0, -ext.length);
|
|
|
|
if (!shadow_types.has(key)) {
|
|
shadow_types.set(key, { params: parse_route_id(key).names, type: 'page' });
|
|
}
|
|
});
|
|
|
|
shadow_types.forEach(({ params, type }, key) => {
|
|
const arg =
|
|
params.length > 0 ? `{ ${params.map((param) => `${param}: string`).join('; ')} }` : '{}';
|
|
|
|
const imports = [];
|
|
const content = [];
|
|
|
|
if (type !== 'page') {
|
|
imports.push('RequestHandler as GenericRequestHandler, ResponseBody');
|
|
content.push(endpoint(arg));
|
|
}
|
|
|
|
if (type !== 'endpoint') {
|
|
imports.push('Load as GenericLoad');
|
|
content.push(page(arg));
|
|
}
|
|
|
|
content.unshift(header(imports.join(', ')));
|
|
|
|
const parts = (key || 'index').split('/');
|
|
parts.push('__types', /** @type {string} */ (parts.pop()));
|
|
|
|
write(`${config.kit.outDir}/types/${parts.join('/')}.d.ts`, content.join('\n').trim());
|
|
});
|
|
}
|
|
|
|
/**
|
|
* @param {import('vite').ResolvedConfig} config
|
|
* @param {import('vite').ConfigEnv} config_env
|
|
* @return {Promise<import('vite').UserConfig>}
|
|
*/
|
|
async function get_vite_config(config, config_env) {
|
|
const loaded = await loadConfigFromFile(
|
|
config_env,
|
|
config.configFile,
|
|
undefined,
|
|
config.logLevel
|
|
);
|
|
|
|
if (!loaded) {
|
|
throw new Error('Could not load Vite config');
|
|
}
|
|
return { ...loaded.config, mode: config_env.mode };
|
|
}
|
|
|
|
/**
|
|
* @param {...import('vite').UserConfig} configs
|
|
* @returns {import('vite').UserConfig}
|
|
*/
|
|
function merge_vite_configs(...configs) {
|
|
return deep_merge(
|
|
...configs.map((config) => ({
|
|
...config,
|
|
resolve: {
|
|
...config.resolve,
|
|
alias: normalize_alias(config.resolve?.alias || {})
|
|
}
|
|
}))
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Takes zero or more objects and returns a new object that has all the values
|
|
* deeply merged together. None of the original objects will be mutated at any
|
|
* level, and the returned object will have no references to the original
|
|
* objects at any depth. If there's a conflict the last one wins, except for
|
|
* arrays which will be combined.
|
|
* @param {...Object} objects
|
|
* @returns {Record<string, any>} the merged object
|
|
*/
|
|
function deep_merge(...objects) {
|
|
const result = {};
|
|
/** @type {string[]} */
|
|
objects.forEach((o) => merge_into(result, o));
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* normalize kit.vite.resolve.alias as an array
|
|
* @param {import('vite').AliasOptions} o
|
|
* @returns {import('vite').Alias[]}
|
|
*/
|
|
function normalize_alias(o) {
|
|
if (Array.isArray(o)) return o;
|
|
return Object.entries(o).map(([find, replacement]) => ({ find, replacement }));
|
|
}
|
|
|
|
/**
|
|
* Merges b into a, recursively, mutating a.
|
|
* @param {Record<string, any>} a
|
|
* @param {Record<string, any>} b
|
|
*/
|
|
function merge_into(a, b) {
|
|
/**
|
|
* Checks for "plain old Javascript object", typically made as an object
|
|
* literal. Excludes Arrays and built-in types like Buffer.
|
|
* @param {any} x
|
|
*/
|
|
const is_plain_object = (x) => typeof x === 'object' && x.constructor === Object;
|
|
|
|
for (const prop in b) {
|
|
if (is_plain_object(b[prop])) {
|
|
if (!is_plain_object(a[prop])) {
|
|
a[prop] = {};
|
|
}
|
|
merge_into(a[prop], b[prop]);
|
|
} else if (Array.isArray(b[prop])) {
|
|
if (!Array.isArray(a[prop])) {
|
|
a[prop] = [];
|
|
}
|
|
a[prop].push(...b[prop]);
|
|
} else {
|
|
a[prop] = b[prop];
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Transforms kit.alias to a valid vite.resolve.alias array.
|
|
* Related to tsconfig path alias creation.
|
|
*
|
|
* @param {import('types').ValidatedKitConfig} config
|
|
* */
|
|
function get_aliases(config) {
|
|
/** @type {import('vite').Alias[]} */
|
|
const alias = [
|
|
{ find: '__GENERATED__', replacement: path__default.posix.join(config.outDir, 'generated') },
|
|
{ find: '$app', replacement: `${get_runtime_directory(config)}/app` },
|
|
// For now, we handle `$lib` specially here rather than make it a default value for
|
|
// `config.kit.alias` since it has special meaning for packaging, etc.
|
|
{ find: '$lib', replacement: config.files.lib }
|
|
];
|
|
|
|
for (let [key, value] of Object.entries(config.alias)) {
|
|
if (value.endsWith('/*')) {
|
|
value = value.slice(0, -2);
|
|
}
|
|
if (key.endsWith('/*')) {
|
|
// Doing just `{ find: key.slice(0, -2) ,..}` would mean `import .. from "key"` would also be matched, which we don't want
|
|
alias.push({
|
|
find: new RegExp(`^${key.slice(0, -2)}\\/(.+)$`),
|
|
replacement: `${path__default.resolve(value)}/$1`
|
|
});
|
|
} else if (key + '/*' in config.alias) {
|
|
// key and key/* both exist -> the replacement for key needs to happen _only_ on import .. from "key"
|
|
alias.push({ find: new RegExp(`^${key}$`), replacement: path__default.resolve(value) });
|
|
} else {
|
|
alias.push({ find: key, replacement: path__default.resolve(value) });
|
|
}
|
|
}
|
|
|
|
alias.push({
|
|
find: '$env',
|
|
replacement: `${get_runtime_directory(config)}/env`
|
|
});
|
|
|
|
return alias;
|
|
}
|
|
|
|
/**
|
|
* Given an entry point like [cwd]/src/hooks, returns a filename like [cwd]/src/hooks.js or [cwd]/src/hooks/index.js
|
|
* @param {string} entry
|
|
* @returns {string|null}
|
|
*/
|
|
function resolve_entry(entry) {
|
|
if (fs__default.existsSync(entry)) {
|
|
const stats = fs__default.statSync(entry);
|
|
if (stats.isDirectory()) {
|
|
return resolve_entry(path__default.join(entry, 'index'));
|
|
}
|
|
|
|
return entry;
|
|
} else {
|
|
const dir = path__default.dirname(entry);
|
|
|
|
if (fs__default.existsSync(dir)) {
|
|
const base = path__default.basename(entry);
|
|
const files = fs__default.readdirSync(dir);
|
|
|
|
const found = files.find((file) => file.replace(/\.[^.]+$/, '') === base);
|
|
|
|
if (found) return path__default.join(dir, found);
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* @param {string} str
|
|
* @param {number} times
|
|
*/
|
|
function repeat(str, times) {
|
|
return new Array(times + 1).join(str);
|
|
}
|
|
|
|
/**
|
|
* Create a formatted error for an illegal import.
|
|
* @param {Array<{name: string, dynamic: boolean}>} stack
|
|
* @param {string} out_dir The directory specified by config.kit.outDir
|
|
*/
|
|
function format_illegal_import_chain(stack, out_dir) {
|
|
const app = path__default.join(out_dir, 'runtime/env');
|
|
|
|
stack = stack.map((file) => {
|
|
if (file.name.startsWith(app)) return { ...file, name: file.name.replace(app, '$env') };
|
|
return { ...file, name: path__default.relative(process.cwd(), file.name) };
|
|
});
|
|
|
|
const pyramid = stack
|
|
.map(
|
|
(file, i) =>
|
|
`${repeat(' ', i * 2)}- ${file.name} ${
|
|
file.dynamic ? '(imported by parent dynamically)' : ''
|
|
}`
|
|
)
|
|
.join('\n');
|
|
|
|
return `Cannot import ${stack.at(-1)?.name} into client-side code:\n${pyramid}`;
|
|
}
|
|
|
|
/**
|
|
* Load environment variables from process.env and .env files
|
|
* @param {string} mode
|
|
* @param {string} prefix
|
|
*/
|
|
function get_env(mode, prefix) {
|
|
const entries = Object.entries(loadEnv(mode, process.cwd(), ''));
|
|
|
|
return {
|
|
public: Object.fromEntries(entries.filter(([k]) => k.startsWith(prefix))),
|
|
private: Object.fromEntries(entries.filter(([k]) => !k.startsWith(prefix)))
|
|
};
|
|
}
|
|
|
|
/**
|
|
* @param {(id: string) => import('rollup').ModuleInfo | null} node_getter
|
|
* @param {import('rollup').ModuleInfo} node
|
|
* @param {Set<string>} illegal_imports Illegal module IDs -- be sure to call vite.normalizePath!
|
|
* @param {string} out_dir The directory specified by config.kit.outDir
|
|
*/
|
|
function prevent_illegal_rollup_imports(node_getter, node, illegal_imports, out_dir) {
|
|
const chain = find_illegal_rollup_imports(node_getter, node, false, illegal_imports);
|
|
if (chain) throw new Error(format_illegal_import_chain(chain, out_dir));
|
|
}
|
|
|
|
/**
|
|
* @param {(id: string) => import('rollup').ModuleInfo | null} node_getter
|
|
* @param {import('rollup').ModuleInfo} node
|
|
* @param {boolean} dynamic
|
|
* @param {Set<string>} illegal_imports Illegal module IDs -- be sure to call vite.normalizePath!
|
|
* @param {Set<string>} seen
|
|
* @returns {Array<import('types').ImportNode> | null}
|
|
*/
|
|
const find_illegal_rollup_imports = (
|
|
node_getter,
|
|
node,
|
|
dynamic,
|
|
illegal_imports,
|
|
seen = new Set()
|
|
) => {
|
|
const name = normalizePath(node.id);
|
|
if (seen.has(name)) return null;
|
|
seen.add(name);
|
|
|
|
if (illegal_imports.has(name)) {
|
|
return [{ name, dynamic }];
|
|
}
|
|
|
|
for (const id of node.importedIds) {
|
|
const child = node_getter(id);
|
|
const chain =
|
|
child && find_illegal_rollup_imports(node_getter, child, false, illegal_imports, seen);
|
|
if (chain) return [{ name, dynamic }, ...chain];
|
|
}
|
|
|
|
for (const id of node.dynamicallyImportedIds) {
|
|
const child = node_getter(id);
|
|
const chain =
|
|
child && find_illegal_rollup_imports(node_getter, child, true, illegal_imports, seen);
|
|
if (chain) return [{ name, dynamic }, ...chain];
|
|
}
|
|
|
|
return null;
|
|
};
|
|
|
|
/**
|
|
* Vite does some weird things with import trees in dev
|
|
* for example, a Tailwind app.css will appear to import
|
|
* every file in the project. This isn't a problem for
|
|
* Rollup during build.
|
|
* @param {Iterable<string>} config_module_types
|
|
*/
|
|
const get_module_types = (config_module_types) => {
|
|
return new Set([
|
|
'.ts',
|
|
'.js',
|
|
'.svelte',
|
|
'.mts',
|
|
'.mjs',
|
|
'.cts',
|
|
'.cjs',
|
|
'.svelte.md',
|
|
'.svx',
|
|
'.md',
|
|
...config_module_types
|
|
]);
|
|
};
|
|
|
|
/**
|
|
* Throw an error if a private module is imported from a client-side node.
|
|
* @param {import('vite').ModuleNode} node
|
|
* @param {Set<string>} illegal_imports Illegal module IDs -- be sure to call vite.normalizePath!
|
|
* @param {Iterable<string>} module_types File extensions to analyze in addition to the defaults: `.ts`, `.js`, etc.
|
|
* @param {string} out_dir The directory specified by config.kit.outDir
|
|
*/
|
|
function prevent_illegal_vite_imports(node, illegal_imports, module_types, out_dir) {
|
|
const chain = find_illegal_vite_imports(node, illegal_imports, get_module_types(module_types));
|
|
if (chain) throw new Error(format_illegal_import_chain(chain, out_dir));
|
|
}
|
|
|
|
/**
|
|
* @param {import('vite').ModuleNode} node
|
|
* @param {Set<string>} illegal_imports Illegal module IDs -- be sure to call vite.normalizePath!
|
|
* @param {Set<string>} module_types File extensions to analyze: `.ts`, `.js`, etc.
|
|
* @param {Set<string>} seen
|
|
* @returns {Array<import('types').ImportNode> | null}
|
|
*/
|
|
function find_illegal_vite_imports(node, illegal_imports, module_types, seen = new Set()) {
|
|
if (!node.id) return null; // TODO when does this happen?
|
|
const name = normalizePath(node.id);
|
|
|
|
if (seen.has(name) || !module_types.has(path__default.extname(name))) return null;
|
|
seen.add(name);
|
|
|
|
if (name && illegal_imports.has(name)) {
|
|
return [{ name, dynamic: false }];
|
|
}
|
|
|
|
for (const child of node.importedModules) {
|
|
const chain = child && find_illegal_vite_imports(child, illegal_imports, module_types, seen);
|
|
if (chain) return [{ name, dynamic: false }, ...chain];
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
const autogen_comment = '// this file is generated — do not edit it\n';
|
|
const types_reference = '/// <reference types="@sveltejs/kit" />\n\n';
|
|
|
|
/**
|
|
* Writes ambient declarations including types reference to @sveltejs/kit,
|
|
* and the existing environment variables in process.env to
|
|
* $env/static/private and $env/static/public
|
|
* @param {import('types').ValidatedKitConfig} config
|
|
* @param {string} mode The Vite mode
|
|
*/
|
|
function write_ambient(config, mode) {
|
|
const env = get_env(mode, config.env.publicPrefix);
|
|
|
|
// TODO when testing src, `$app` points at `src/runtime/app`... will
|
|
// probably need to fiddle with aliases
|
|
write_if_changed(
|
|
path__default.join(config.outDir, 'runtime/env/static/public.js'),
|
|
create_env_module('$env/static/public', env.public)
|
|
);
|
|
|
|
write_if_changed(
|
|
path__default.join(config.outDir, 'runtime/env/static/private.js'),
|
|
create_env_module('$env/static/private', env.private)
|
|
);
|
|
|
|
write_if_changed(
|
|
path__default.join(config.outDir, 'ambient.d.ts'),
|
|
autogen_comment +
|
|
types_reference +
|
|
create_env_types('$env/static/public', env.public) +
|
|
'\n\n' +
|
|
create_env_types('$env/static/private', env.private)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param {string} id
|
|
* @param {Record<string, string>} env
|
|
* @returns {string}
|
|
*/
|
|
function create_env_module(id, env) {
|
|
/** @type {string[]} */
|
|
const declarations = [];
|
|
|
|
for (const key in env) {
|
|
const warning = !valid_identifier.test(key)
|
|
? 'not a valid identifier'
|
|
: reserved.has(key)
|
|
? 'a reserved word'
|
|
: null;
|
|
|
|
if (warning) {
|
|
console.error(
|
|
$
|
|
.bold()
|
|
.yellow(`Omitting environment variable "${key}" from ${id} as it is ${warning}`)
|
|
);
|
|
continue;
|
|
}
|
|
|
|
const comment = `/** @type {import('${id}').${key}} */`;
|
|
const declaration = `export const ${key} = ${JSON.stringify(env[key])};`;
|
|
|
|
declarations.push(`${comment}\n${declaration}`);
|
|
}
|
|
|
|
return autogen_comment + declarations.join('\n\n');
|
|
}
|
|
|
|
/**
|
|
* @param {string} id
|
|
* @param {Record<string, string>} env
|
|
* @returns {string}
|
|
*/
|
|
function create_env_types(id, env) {
|
|
const declarations = Object.keys(env)
|
|
.filter((k) => valid_identifier.test(k))
|
|
.map((k) => `\texport const ${k}: string;`)
|
|
.join('\n');
|
|
|
|
return `declare module '${id}' {\n${declarations}\n}`;
|
|
}
|
|
|
|
/**
|
|
* Initialize SvelteKit's generated files.
|
|
* @param {import('types').ValidatedConfig} config
|
|
* @param {string} mode
|
|
*/
|
|
function init(config, mode) {
|
|
copy_assets(path__default.join(config.kit.outDir, 'runtime'));
|
|
|
|
write_tsconfig(config.kit);
|
|
write_ambient(config.kit, mode);
|
|
}
|
|
|
|
/**
|
|
* Update SvelteKit's generated files.
|
|
* @param {import('types').ValidatedConfig} config
|
|
*/
|
|
function update(config) {
|
|
const manifest_data = create_manifest_data({ config });
|
|
|
|
const output = path__default.join(config.kit.outDir, 'generated');
|
|
const base = path__default.relative('.', output);
|
|
|
|
write_manifest(manifest_data, base, output);
|
|
write_root(manifest_data, output);
|
|
write_matchers(manifest_data, output);
|
|
write_types(config, manifest_data);
|
|
|
|
return { manifest_data };
|
|
}
|
|
|
|
/**
|
|
* Run sync.init and sync.update in series, returning the result from sync.update.
|
|
* @param {import('types').ValidatedConfig} config
|
|
* @param {string} mode The Vite mode
|
|
*/
|
|
function all(config, mode) {
|
|
init(config, mode);
|
|
return update(config);
|
|
}
|
|
|
|
var sync = /*#__PURE__*/Object.freeze({
|
|
__proto__: null,
|
|
init: init,
|
|
update: update,
|
|
all: all
|
|
});
|
|
|
|
export { get_vite_config as a, get_env as b, parse_route_id as c, all as d, prevent_illegal_rollup_imports as e, sync as f, get_aliases as g, init as i, merge_vite_configs as m, prevent_illegal_vite_imports as p, resolve_entry as r, s, update as u };
|