diff --git a/.gitignore b/.gitignore index 9aeaa78e..719d95cd 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ node_modules .gitattributes .well-known package-lock.json +/views/archive/gfiles/rarch/roms \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index 3964ec10..9d8192c6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -26,9 +26,11 @@ path = views/archive/g/adarkroom url = https://github.com/doublespeakgames/adarkroom -[submodule "views/archive/bunker"] - path = views/archive/bunker - url = https://github.com/stewpidtnlvr/The-Bunker-Offline -[submodule "src/Corrosion"] - path = src/Corrosion - url = https://github.com/titaniumnetwork-dev/Corrosion/ + +[submodule "views/archive/g/trimps"] + path = views/archive/g/trimps + url = https://github.com/Trimps/Trimps.github.io + +[submodule "views/archive/g/zork1"] + path = views/archive/g/zork1 + url = https://github.com/jessicalevine/Adventure.js \ No newline at end of file diff --git a/.gitpod.yml b/.gitpod.yml deleted file mode 100644 index 18319db9..00000000 --- a/.gitpod.yml +++ /dev/null @@ -1,2 +0,0 @@ -tasks: - - init: npm install \ No newline at end of file diff --git a/app.json b/app.json index 6c9eabbf..03207ff0 100644 --- a/app.json +++ b/app.json @@ -1,7 +1,7 @@ { "name": "Holy Unblocker", - "description": "A website that can be used to bypass web filters; both extension and firewall. Corrosion Proxy hosted locally. (Can be used as a template.)", + "description": "A website that can be used to bypass web filters; both extension and firewall. Alloy Proxy hosted locally. (Can be used as a template.)", "repository": "https://github.com/QuiteAFancyEmerald/HolyUnblockerPublic/", "logo": "https://github.com/QuiteAFancyEmerald/HolyUnblockerPublic/blob/master/views/assets/img/i.png?raw=true", - "keywords": ["node", "proxy", "unblocker", "webproxy", "games", "holyunblocker", "corrosion"] + "keywords": ["node", "proxy", "unblocker", "webproxy", "games", "holyunblocker", "alloy"] } diff --git a/app.js b/backend.js similarity index 59% rename from app.js rename to backend.js index f7fe9832..dc8e783a 100644 --- a/app.js +++ b/backend.js @@ -1,18 +1,18 @@ /* ----------------------------------------------- - * Authors: QuiteAFancyEmerald, BinBashBanana (OlyB), YÖCTDÖNALD'S - * Additional help from Divide and SexyDuceDuce - * MIT license: http://opensource.org/licenses/MIT + * Authors: QuiteAFancyEmerald, BinBashBanana (OlyB), YÖCTDÖNALD'S and the lime + * Additional help from Divide and SexyDuceDuce >:D test aaaa * ----------------------------------------------- */ -const - corrosion = require('./src/Corrosion'), - path = require('path'), - config = require('./config.json'), - fs = require('fs'), - http = require('http'), - express = require('express'), - app = express(), - port = process.env.PORT || config.port, - server = http.createServer(app); +const fs = require('fs'); +const path = require('path'); +const http = require('http'); +const https = require('https'); +const express = require('express'); +const corrosion = require('corrosion'); +const config = require('./config.json'); +const insert = require('./randomization.json'); +const app = express(); +const port = process.env.PORT || config.port; +const server = config.ssl ? https.createServer({ key: fs.readFileSync('./ssl/ssl.key'), cert: fs.readFileSync('./ssl/ssl.cert') }, app) : http.createServer(app); btoa = (str) => { return new Buffer.from(str).toString('base64'); @@ -23,8 +23,8 @@ atob = (str) => { } const text404 = fs.readFileSync(path.normalize(__dirname + '/views/404.html'), 'utf8'), - siteIndex = 'index.html', pages = { + 'index': 'index.html', /* Main */ 'in': 'info.html', 'faq': 'faq.html', @@ -53,79 +53,71 @@ const text404 = fs.readFileSync(path.normalize(__dirname + '/views/404.html'), ' /* Ruffle and Webretro */ 'fg': 'archive/gfiles/flash/index.html', 'eg': 'archive/gfiles/rarch/index.html' - }, - fileMod = [ - "/views/assets/css/styles.min.css", - ], - cookingInserts = [ - "Random sentence one filled with certain keywords.", - "Random sentence two filled with certain keywords." - ], - splashtext = [ - 'This is simply a public demo for Holy Unblocker. Certain functions may not work properly. Join the TN Discord for official site links' - ], - vegetables = ['Cooking1', 'Cooking2'], - charRandom = ['­', '​']; + }; + +const cookingInserts = insert.content; +const vegetables = insert.keywords; +const charRandom = insert.chars; function randomListItem(lis) { return lis[Math.floor(Math.random() * lis.length)]; } -// The inline function returns are necessary to prevent all replaced things from being the same +function redditFix(str) { + return str.replace(/Ch­a­tbo­x/g, 'Re­dd­it'); +} function insertCharset(str) { return str.replace(/­|​|/g, function() { return randomListItem(charRandom); }); } -function insertSplash(str) { - return str.replace(/️/g, function() { return splashtext; }); -} - function insertCooking(str) { return str.replace(//g, function() { return '' + randomListItem(cookingInserts) + ''; }); } function cacheBusting(str) { - return str.replace(/styles.min.css/g, 'styles-368357.min.css'); + return str.replace(/styles.min.css/g, 'styles-1636936688.min.css'); +} + +function cacheBusting2(str) { + return str.replace(/common.js/g, 'common-1628457888.js'); +} + +function cacheBusting3(str) { + return str.replace(/surf.js/g, 'surf-1628130462.js'); } function insertAll(str) { - return insertCharset(insertCooking(insertSplash(cacheBusting(str)))); + return insertCharset(insertCooking(redditFix(cacheBusting(cacheBusting2(cacheBusting3(str)))))); } -/* Cache Busting -const stats = fs.statSync(path.normalize(__dirname + fileMod), 'utf8'), - seconds = (new Date().getTime() - stats.mtime); - -fs.renameSync(path.normalize(__dirname + fileMod), 'links-' + seconds + '.js'); - -function cacheBusting(str) { - return str.replace(/links.js/g, "links" + '-' + seconds + '.js'); -} -*/ - function tryReadFile(file) { return fs.existsSync(file) ? fs.readFileSync(file, 'utf8') : text404; } -// Local Corrosion Proxy +const fetch = (...args) => + import ('node-fetch').then(({ default: fetch }) => fetch(...args)); + +let blacklist; + +fetch("https://blocklistproject.github.io/Lists/alt-version/everything-nl.txt").then(response => response.text()).then(data => { + blacklist = data.split("\n") && config.blacklist; +}); const proxy = new corrosion({ - prefix: '/search/', - title: 'Untitled Document', - ws: true, - codec: 'xor', + title: config.title, + prefix: config.prefix || '/search/', + codec: config.codec || 'xor', + ws: config.ws, requestMiddleware: [ - corrosion.middleware.blacklist([ - 'accounts.google.com', - ], 'Page is blocked'), + corrosion.middleware.blacklist(blacklist, 'Service not allowed due to bot protection! Make sure you are not trying to verify on a proxy.'), ], }); proxy.bundleScripts(); /* Querystring Navigation */ -app.get('/', async(req, res) => res.send(insertAll(tryReadFile(path.normalize(__dirname + '/views/' + (['/', '/?'].includes(req.url) ? siteIndex : pages[Object.keys(req.query)[0]])))))); +app.get('/', async(req, res) => res.send(insertAll(tryReadFile(path.normalize(__dirname + '/views/' + (['/', '/?'].includes(req.url) ? pages.index : pages[Object.keys(req.query)[0]])))))); /* Static Files Served */ app.use(express.static(path.normalize(__dirname + '/views'))); diff --git a/blacklist.txt b/blacklist.txt deleted file mode 100644 index 46364b89..00000000 --- a/blacklist.txt +++ /dev/null @@ -1 +0,0 @@ -accounts.google.com diff --git a/config.json b/config.json index 494f9c59..6d1d668a 100644 --- a/config.json +++ b/config.json @@ -1,3 +1,12 @@ { - "port": "8080" + "title": "Untitled Document", + "port": "8080", + "ssl": false, + "ws": true, + "prefix": "/search/", + "codec": "xor", + "blacklist": [ + "accounts.google.com", + "dcounter.space" + ] } \ No newline at end of file diff --git a/ecosystem.config.js b/ecosystem.config.js new file mode 100644 index 00000000..f494b6d9 --- /dev/null +++ b/ecosystem.config.js @@ -0,0 +1,21 @@ +module.exports = { + apps: [{ + name: 'HolyUB', + script: './backend.js', + env: { + PORT: 8080, + NODE_ENV: "development", + }, + env_production: { + PORT: 8080, + NODE_ENV: "production", + }, + instances: "1", + exec_mode: "cluster", + autorestart: true, + exp_backoff_restart_delay: 100, + cron_restart: "*/10 * * * *", + kill_timeout: 3000, + watch: false + }] +}; \ No newline at end of file diff --git a/package.json b/package.json index a95105c3..64868905 100644 --- a/package.json +++ b/package.json @@ -3,9 +3,9 @@ "version": "4.8.0", "repository": "https://github.com/QuiteAFancyEmerald/Holy-Unblocker", "description": "Holy Unblocker is a secure web proxy service with support for many sites.", - "main": "app.js", + "main": "backend.js", "scripts": { - "start": "node app.js" + "start": "node backend.js" }, "keywords": [ "proxy", @@ -18,6 +18,7 @@ "corrosion": "^1.0.0", "express": "^4.17.1", "mime-types": "^2.1.27", - "ws": "^7.5.3" + "ws": "^7.5.3", + "node-fetch": "^3.1.0" } -} +} \ No newline at end of file diff --git a/randomization.json b/randomization.json new file mode 100644 index 00000000..7c104e45 --- /dev/null +++ b/randomization.json @@ -0,0 +1,16 @@ +{ + "chars": [ + "­", "​" + ], + "keywords": [ + "RandomTerm1", "RandomTerm2", "RandomTerm3", "RandomTerm4", "RandomTerm5", "RandomTerm6" + ], + "content": [ + "RandomTermRandomTermRandomTermRandomTermRandomTermRandomTermRandomTermRandomTermRandomTermRandomTermRandomTermRandomTerm", + "RandomTerm2RandomTerm2RandomTerm2RandomTerm2RandomTerm2RandomTerm2RandomTerm2RandomTerm2RandomTerm2RandomTerm2RandomTerm2RandomTerm2RandomTerm2RandomTerm2RandomTerm2", + "RandomTerm3RandomTerm3RandomTerm3RandomTerm3RandomTerm3RandomTerm3RandomTerm3RandomTerm3RandomTerm3RandomTerm3RandomTerm3RandomTerm3RandomTerm3", + "RandomTerm4RandomTerm4RandomTerm4RandomTerm4RandomTerm4RandomTerm4RandomTerm4RandomTerm4RandomTerm4RandomTerm4RandomTerm4RandomTerm4RandomTerm4RandomTerm4", + "RandomTerm5RandomTerm5RandomTerm5RandomTerm5RandomTerm5RandomTerm5RandomTerm5RandomTerm5RandomTerm5RandomTerm5RandomTerm5RandomTerm5RandomTerm5RandomTerm5RandomTerm5", + "RandomTerm6RandomTerm6RandomTerm6RandomTerm6RandomTerm6RandomTerm6RandomTerm6RandomTerm6RandomTerm6RandomTerm6RandomTerm6RandomTerm6RandomTerm6RandomTerm6RandomTerm6RandomTerm6" + ] +} \ No newline at end of file diff --git a/src/Corrosion/README.md b/src/Corrosion/README.md deleted file mode 100644 index 4df0221c..00000000 --- a/src/Corrosion/README.md +++ /dev/null @@ -1,223 +0,0 @@ -# Corrosion -Titanium Networks main web proxy. -Successor to [Alloy](https://github.com/titaniumnetwork-dev/alloy) -# Installation: -``` -npm i corrosion -``` - -# Example: -```javascript -const Corrosion = require('corrosion'); -const proxy = new Corrosion(); -const http = require('http') -http.createServer((req, res) => - proxy.request(req, res) // Request Proxy -).on('upgrade', (req, socket, head) => - proxy.upgrade(req, socket, head) // WebSocket Proxy -).listen(80); -``` -Much more in depth one is in the [demo folder](demo/). - -# API: - - -## Index -- `config` - - `prefix` String - URL Prefix - - `title` (Boolean / String) - Title used for HTML documents - - `ws` Boolean - WebSocket rewriting - - `cookie` Boolean - Request Cookies - - `codec` String - URL encoding (base64, plain, xor). - - `requestMiddleware` Array - Array of [middleware](#middleware) functions for proxy request (Server). - - `responseMiddleware` Array - Array of [middleware](#middleware) functions for proxy response (Server). - - `standardMiddleware` Boolean - Use the prebuilt [middleware](#middleware) used by default (Server). - -#### request - - `request` Request - - `response` Response - -#### upgrade - - `request` Request - - `socket` Socket - - `head` Head - -#### bundleScripts -Bundles scripts for client injection. Important when updating proxy. - -## Properties - - [url](#url) - - [html](#html) - - [js](#js) - - [css](#css) - - [cookies](#cookies) - - [config](#index) - - [codec](#codec) - - [prefix](#url) - - - -## url - -#### wrap - - `val` String - - `config` Configuration - - `base` WHATWG URL - - `origin` Location origin - Adds a location origin before the proxy url - - `flags` Array - ['xhr'] => /service/xhr_/https%3A%2F%2Fexample.org/ - -#### unwrap - - `val` String - - `config` Configuration - - `origin` Location origin - Required if a location origin starts before the proxy url - - `flags` Boolean - Returns with both the URL and flags found { value: 'https://example.org', flags: ['xhr'], }) - - `leftovers` Boolean - Use any leftovers if any after the encoded proxy url - - -## Properties - - `regex` Regex used to determine to rewrite the URL or not. - - - `prefix` URL Prefix - - - `codec` (base64, plain, xor) - - -## js - -#### process - - `source` JS script - - `url` URL for heading - -#### iterate - - `ast` JS AST - - `Callback` Handler initated on AST node - -#### createHead - - `url` URL for heading - -#### createCallExperssion - - `callee` Acorn.js Node - - `args` Array - -#### createArrayExpression - - `elements` Array - -#### createIdentifier - - `name` Identifier name - - `preventRewrite` Prevent further rewrites - -#### createLiteral - - `value` Literal value - -## css - -#### process - - `source` CSS - - `config` Configuration - - `base` WHATWG URL - - `origin` Location origin - - `context` CSS-Tree context - -## html - -#### process - - `source` HTML Source - - `config` Configuration - - `document` Determines of its a document or fragment for parsing - - `base` WHATWG URL - - `origin` Location origin - -#### source - - `processed` Rewritten HTML - - `config` Configuration - - `document` Determines of its a document or fragment for parsing - -### Properties -- `map` Map for attribute rewriting - - -## cookies - -#### encode - - `input` New (Cookie / Cookies) - - `config` Configuration - - `url` WHATWG URL - - `domain` Cookie Domain - - `secure` Cookie Secure - -#### decode - - `store` Encoded Cookies - - `config` Configuration - - `url` WHATWG URL - -## codec - -#### encode -#### decode - - `str` String - -## middleware - -Middleware are functions that will be executed either before request or after response. These can alter the way a request is made or response is sent. - -```javascript -function(ctx) {r - ctx.body; // (Request / Response) Body (Will return null if none) - ctx.headers; // (Request / Response) Headers - ctx.url; // WHATWG URL - ctx.flags; // URL Flags - ctx.origin; // Request origin - ctx.method; // Request method - ctx.rewrite; // Corrosion object - ctx.statusCode; // Response status (Only available on response) - ctx.agent; // HTTP agent - ctx.address; // Address used to make remote request - ctx.clientSocket; // Node.js Server Socket (Only available on upgrade) - ctx.clientRequest; // Node.js Server Request - ctx.clientResponse; // Node.js Server Response - ctx.remoteResponse; // Node.js Remote Response (Only available on response) -}; -``` - -### Default middleware - -- Request - - requestHeaders - -- Response - - responseHeaders - - decompress - - rewriteBody - -### Available Middleware - -#### address (Request) - - `arr` Array of IP addresses to use in request - -```javascript -const Corrosion = require('corrosion'); -const proxy = new Corrosion({ - requestMiddleware: [ - Corrosion.middleware.address([ - 0.0.0.0, - 0.0.0.0 - ]), - ], -}); -``` - -### blacklist - - `arr` Array of hostnames to block clients from seeing - - `page` Block page - -```javascript -const Corrosion = require('corrosion'); -const proxy = new Corrosion({ - requestMiddleware: [ - Corrosion.middleware.blacklist([ - 'example.org', - 'example.com', - ], 'Page is blocked'), - ], -}); -``` diff --git a/src/Corrosion/demo/index.html b/src/Corrosion/demo/index.html deleted file mode 100644 index ad595e6e..00000000 --- a/src/Corrosion/demo/index.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - -
- - -
- - \ No newline at end of file diff --git a/src/Corrosion/demo/index.js b/src/Corrosion/demo/index.js deleted file mode 100644 index d3a8b82b..00000000 --- a/src/Corrosion/demo/index.js +++ /dev/null @@ -1,19 +0,0 @@ -const https = require('https'); -const fs = require('fs'); -const path = require('path'); -const ssl = { - key: fs.readFileSync(path.join(__dirname, '/ssl.key')), - cert: fs.readFileSync(path.join(__dirname, '/ssl.cert')), -}; -const server = https.createServer(ssl); -const Corrosion = require('../'); -const proxy = new Corrosion({ - codec: 'xor', -}); - -proxy.bundleScripts(); - -server.on('request', (request, response) => { - if (request.url.startsWith(proxy.prefix)) return proxy.request(request, response); - response.end(fs.readFileSync(__dirname + '/index.html', 'utf-8')); -}).on('upgrade', (clientRequest, clientSocket, clientHead) => proxy.upgrade(clientRequest, clientSocket, clientHead)).listen(443); \ No newline at end of file diff --git a/src/Corrosion/lib/server/bundle.js b/src/Corrosion/lib/server/bundle.js deleted file mode 100644 index fa3700b2..00000000 --- a/src/Corrosion/lib/server/bundle.js +++ /dev/null @@ -1,30109 +0,0 @@ -/******/ (() => { // webpackBootstrap -/******/ var __webpack_modules__ = ([ -/* 0 */, -/* 1 */ -/***/ ((module) => { - -function createDocumentRewriter(ctx) { - return function rewriteDocument() { - if (ctx.serviceWorker) return; - const { - HTMLMediaElement, - HTMLScriptElement, - HTMLAudioElement, - HTMLVideoElement, - HTMLInputElement, - HTMLEmbedElement, - HTMLTrackElement, - HTMLAnchorElement, - HTMLIFrameElement, - HTMLAreaElement, - HTMLLinkElement, - HTMLBaseElement, - HTMLFormElement, - HTMLImageElement, - HTMLSourceElement, - } = ctx.window; - const cookie = Object.getOwnPropertyDescriptor(ctx.window.Document.prototype, 'cookie'); - const domain = Object.getOwnPropertyDescriptor(ctx.window.Document.prototype, 'domain'); - const title = Object.getOwnPropertyDescriptor(ctx.window.Document.prototype, 'title'); - const baseURI = Object.getOwnPropertyDescriptor(ctx.window.Node.prototype, 'baseURI'); - const cookieEnabled = Object.getOwnPropertyDescriptor(ctx.window.Navigator.prototype, 'cookieEnabled'); - let spoofTitle = ''; - let spoofDomain = ctx.location.hostname; - - if (ctx.window.Document.prototype.write) { - ctx.window.Document.prototype.write = new Proxy(ctx.window.Document.prototype.write, { - apply: (target, that , args) => { - if (args.length) args = [ ctx.html.process(args.join(''), ctx.meta) ]; - return Reflect.apply(target, that, args); - }, - }); - }; - if (ctx.window.Document.prototype.hasOwnProperty('cookie')) { - Object.defineProperty(ctx.window.Document.prototype, 'cookie', { - get: new Proxy(cookie.get, { - apply: (target, that, args) => { - const cookies = Reflect.apply(target, that, args); - return ctx.config.cookie ? ctx.cookies.decode(cookies, ctx.meta) : ''; - }, - }), - set: new Proxy(cookie.set, { - apply: (target, that, [ val ]) => { - return Reflect.apply(target, that, [ ctx.config.cookie ? ctx.cookies.encode(val, ctx.meta) : '' ]); - }, - }), - }); - }; - if (ctx.window.Document.prototype.writeln) { - ctx.window.Document.prototype.writeln = new Proxy(ctx.window.Document.prototype.writeln, { - apply: (target, that , args) => { - if (args.length) args = [ ctx.html.process(args.join(''), ctx.meta) ]; - return Reflect.apply(target, that, args); - }, - }); - }; - if (ctx.window.Element.prototype.setAttribute) { - ctx.window.Element.prototype.setAttribute = new Proxy(ctx.window.Element.prototype.setAttribute, { - apply: (target, that, args) => { - if (args[0] && args[1]) { - const handler = ctx.html.attributeRoute({ - name: args[0], - value: args[1], - node: that, - }); - switch(handler) { - case 'url': - Reflect.apply(target, that, [`corrosion-${args[0]}`, args[1]]); - //if (that.tagName == 'SCRIPT' && args[0] == 'src') flags.push('js'); - args[1] = ctx.url.wrap(args[1], ctx.meta); - break; - case 'srcset': - Reflect.apply(target, that, [`corrosion-${args[0]}`, args[1]]); - args[1] = ctx.html.srcset(args[1], ctx.meta); - break; - case 'css': - Reflect.apply(target, that, [`corrosion-${args[0]}`, args[1]]); - args[1] = ctx.css.process(args[1], { ...ctx.meta, context: 'declarationList' }); - break; - case 'html': - Reflect.apply(target, that, [`corrosion-${args[0]}`, args[1]]); - args[1] = ctx.html.process(args[1], ctx.meta); - break; - case 'delete': - return Reflect.apply(target, that, [`corrosion-${args[0]}`, args[1]]); - }; - }; - return Reflect.apply(target, that, args); - }, - }); - }; - if (ctx.window.Element.prototype.getAttribute) { - ctx.window.Element.prototype.getAttribute = new Proxy(ctx.window.Element.prototype.getAttribute, { - apply: (target, that, args) => { - if (args[0] && that.hasAttribute(`corrosion-${args[0]}`)) args[0] = `corrosion-${args[0]}`; - return Reflect.apply(target, that, args); - }, - }); - }; - ctx.window.CSSStyleDeclaration.prototype.setProperty = new Proxy(ctx.window.CSSStyleDeclaration.prototype.setProperty, { - apply: (target, that, args) => { - if (args[1]) args[1] = ctx.css.process(args[1], { context: 'value', ...ctx.meta, }); - return Reflect.apply(target, that, args); - }, - }); - if (ctx.window.Audio) { - ctx.window.Audio = new Proxy(ctx.window.Audio, { - construct: (target, args) => { - if (args[0]) args[0] = ctx.url.wrap(args[0], ctx.meta); - return Reflect.construct(target, args); - }, - }); - }; - [ - 'innerHTML', - 'outerHTML', - ].forEach(html => { - const descriptor = Object.getOwnPropertyDescriptor(ctx.window.Element.prototype, html); - Object.defineProperty(ctx.window.Element.prototype, html, { - get: new Proxy(descriptor.get, { - apply: (target, that, args) => { - const body = Reflect.apply(target, that, args); - if (!body || html == 'innerHTML' && that.tagName == 'SCRIPT') return body; - return ctx.html.source(body, ctx.meta); - }, - }), - set: new Proxy(descriptor.set, { - apply(target, that, [ val ]) { - return Reflect.apply(target, that, [ val ? ctx.html.process(val.toString(), ctx.meta) : val, ]); - }, - }), - }); - }); - [ - ['background', 'background'], - ['backgroundImage', 'background-image'], - ['listStyleImage', 'list-style-image'], - ].forEach(([key, cssProperty]) => { - Object.defineProperty(ctx.window.CSS2Properties ? ctx.window.CSS2Properties.prototype : ctx.window.CSSStyleDeclaration.prototype, key, { - get() { - return this.getPropertyValue(cssProperty); - }, - set(val) { - return this.setProperty(cssProperty, val); - }, - }); - }); - Object.defineProperty(ctx.window.Document.prototype, 'domain', { - get: new Proxy(domain.get, { - apply: () => spoofDomain, - }), - set: new Proxy(domain.set, { - apply: (target, that, [ val ]) => { - if (!val.toString().endsWith(ctx.location.hostname.split('.').slice(-2).join('.'))) return Reflect.apply(target, that, ['']); - return spoofDomain = val; - }, - }), - }); - if (ctx.config.title) Object.defineProperty(ctx.window.Document.prototype, 'title', { - get: new Proxy(title.get, { - apply: () => spoofTitle, - }), - set: new Proxy(title.set, { - apply: (target, that, [ val ]) => spoofTitle = val, - }), - }); - Object.defineProperty(ctx.window.Navigator.prototype, 'cookieEnabled', { - get: new Proxy(cookieEnabled.get, { - apply: () => ctx.config.cookie, - }), - }); - Object.defineProperty(ctx.window.Node.prototype, 'baseURI', { - get: new Proxy(baseURI.get, { - apply: (target, that, args) => { - const val = Reflect.apply(target, that, args); - return val.startsWith(ctx.meta.origin) ? ctx.url.unwrap(val, ctx.meta) : val; - }, - }), - }); - [ - { - elements: [ HTMLScriptElement, HTMLMediaElement, HTMLImageElement, HTMLAudioElement, HTMLVideoElement, HTMLInputElement, HTMLEmbedElement, HTMLIFrameElement, HTMLTrackElement, HTMLSourceElement], - properties: ['src'], - handler: 'url', - }, - { - elements: [ HTMLFormElement ], - properties: ['action'], - handler: 'url', - }, - { - elements: [ HTMLAnchorElement, HTMLAreaElement, HTMLLinkElement, HTMLBaseElement ], - properties: ['href'], - handler: 'url', - }, - { - elements: [ HTMLImageElement, HTMLSourceElement ], - properties: ['srcset'], - handler: 'srcset', - }, - { - elements: [ HTMLScriptElement ], - properties: ['integrity'], - handler: 'delete', - }, - { - elements: [ HTMLIFrameElement ], - properties: ['contentWindow'], - handler: 'window', - }, - ].forEach(entry => { - entry.elements.forEach(element => { - if (!element) return; - entry.properties.forEach(property => { - if (!element.prototype.hasOwnProperty(property)) return; - const descriptor = Object.getOwnPropertyDescriptor(element.prototype, property); - Object.defineProperty(element.prototype, property, { - get: descriptor.get ? new Proxy(descriptor.get, { - apply: (target, that, args) => { - let val = Reflect.apply(target, that, args); - let flags = []; - switch(entry.handler) { - case 'url': - //if (that.tagName == 'SCRIPT' && property == 'src') flags.push('js'); - val = ctx.url.unwrap(val, ctx.meta); - break; - case 'srcset': - val = ctx.html.unsrcset(val, ctx.meta); - break; - case 'delete': - val = that.getAttribute(`corrosion-${property}`); - break; - case 'window': - try { - if (!val.$corrosion) { - val.$corrosion = new ctx.constructor({ ...ctx.config, window: val, }); - val.$corrosion.init(); - val.$corrosion.meta = ctx.meta; - }; - } catch(e) {}; - }; - return val; - }, - }) : undefined, - set: descriptor.set ? new Proxy(descriptor.set, { - apply(target, that, [ val ]) { - let newVal = val; - switch(entry.handler) { - case 'url': - newVal = ctx.url.wrap(newVal, ctx.meta); - break; - case 'srcset': - newVal = ctx.html.srcset(newVal, ctx.meta); - break; - case 'delete': - that.setAttribute(property, newVal); - return newVal; - }; - return Reflect.apply(target, that, [ newVal ]); - }, - }) : undefined, - }); - }); - }); - }); - }; -}; -module.exports = createDocumentRewriter; - -/***/ }), -/* 2 */ -/***/ ((module) => { - -function createHistoryRewriter(ctx) { - return function rewriteHistory() { - if (ctx.serviceWorker) return; - if (ctx.window.History.prototype.pushState) { - ctx.window.History.prototype.pushState = new Proxy(ctx.window.History.prototype.pushState, { - apply: (target, that, args) => { - if (args[2]) args[2] = ctx.url.wrap(args[2], ctx.meta); - const ret = Reflect.apply(target, that, args); - ctx.updateLocation(); - return ret; - }, - }); - }; - if (ctx.window.History.prototype.replaceState) { - ctx.window.History.prototype.replaceState = new Proxy(ctx.window.History.prototype.replaceState, { - apply: (target, that, args) => { - if (args[2]) args[2] = ctx.url.wrap(args[2], ctx.meta); - const ret = Reflect.apply(target, that, args); - ctx.updateLocation(); - return ret; - }, - }); - }; - }; -}; -module.exports = createHistoryRewriter; - -/***/ }), -/* 3 */ -/***/ ((module) => { - -function createHttpRewriter(ctx = {}) { - return function rewriteHttp() { - if (ctx.window.Request) { - const requestURL = Object.getOwnPropertyDescriptor(ctx.window.Request.prototype, 'url'); - ctx.window.Request = new Proxy(ctx.window.Request, { - construct(target, args) { - if (args[0]) args[0] = ctx.url.wrap(args[0], { ...ctx.meta, flags: ['xhr'], }) - return Reflect.construct(target, args); - }, - }); - Object.defineProperty(ctx.window.Request.prototype, 'url', { - get: new Proxy(requestURL.get, { - apply: (target, that, args) => { - var url = Reflect.apply(target, that, args); - return url ? ctx.url.unwrap(url, ctx.meta) : url; - }, - }), - }); - }; - if (ctx.window.Response) { - const responseURL = Object.getOwnPropertyDescriptor(ctx.window.Response.prototype, 'url'); - Object.defineProperty(ctx.window.Response.prototype, 'url', { - get: new Proxy(responseURL.get, { - apply: (target, that, args) => { - var url = Reflect.apply(target, that, args); - return url ? ctx.url.unwrap(url, ctx.meta) : url; - }, - }), - }); - }; - if (ctx.window.open) { - ctx.window.open = new Proxy(ctx.window.open, { - apply: (target, that, args) => { - if (args[0]) args[0] = ctx.url.wrap(args[0], ctx.meta); - return Reflect.apply(target, that, args) - }, - }); - }; - if (ctx.window.fetch) { - ctx.window.fetch = new Proxy(ctx.window.fetch, { - apply: (target, that, args) => { - if (args[0] instanceof ctx.window.Request) return Reflect.apply(target, that, args); - if (args[0]) args[0] = ctx.url.wrap(args[0], { ...ctx.meta, flags: ['xhr'], }); - return Reflect.apply(target, that, args); - }, - }); - }; - if (ctx.window.Navigator && ctx.window.Navigator.prototype.sendBeacon) { - ctx.window.Navigator.prototype.sendBeacon = new Proxy(ctx.window.Navigator.prototype.sendBeacon, { - apply: (target, that, args) => { - if (args[0]) ctx.url.wrap(args[0], { ...ctx.meta, flags: ['xhr'], }); - return Reflect.apply(target, that, args); - }, - }); - }; - if (ctx.window.XMLHttpRequest) { - const responseURL = Object.getOwnPropertyDescriptor(ctx.window.XMLHttpRequest.prototype, 'responseURL'); - ctx.window.XMLHttpRequest.prototype.open = new Proxy(ctx.window.XMLHttpRequest.prototype.open, { - apply: (target, that, args) => { - if (args[1]) args[1] = ctx.url.wrap(args[1], { ...ctx.meta, flags: ['xhr'], }); - return Reflect.apply(target, that, args); - }, - }); - Object.defineProperty(ctx.window.XMLHttpRequest.prototype, 'responseURL', { - get: new Proxy(responseURL.get, { - apply: (target, that, args) => { - const url = Reflect.apply(target, that, args); - return url ? ctx.url.unwrap(url, ctx.meta) : url; - }, - }), - }); - }; - if (ctx.window.postMessage) { - ctx.window.postMessage = new Proxy(ctx.window.postMessage, { - apply: (target, that, args) => { - if (!ctx.serviceWorker && args[1]) args[1] = ctx.meta.origin; - return Reflect.apply(target, that, args); - }, - }); - }; - if (ctx.window.WebSocket && ctx.config.ws) { - ctx.window.WebSocket = new Proxy(ctx.window.WebSocket, { - construct: (target, args) => { - if (args[0]) args[0] = ctx.url.wrap(args[0].toString().replace('ws', 'http'), ctx.meta).replace('http', 'ws') + '?origin=' + ctx.location.origin; - return Reflect.construct(target, args); - }, - }); - }; - }; -}; - -module.exports = createHttpRewriter; - -/***/ }), -/* 4 */ -/***/ ((module) => { - -class Location { - get [Symbol.toPrimitive]() { - return () => this.href; - }; -}; - -function createLocation(ctx, url) { - const _location = new Location(); - const _url = new URL(url); - [ - 'hash', - 'host', - 'hostname', - 'href', - 'pathname', - 'port', - 'protocol', - 'search', - 'origin', - ].forEach(property => { - Object.defineProperty(_location, property, { - get() { - return _url[property]; - }, - set(val) { - if (ctx.serviceWorker || property == 'origin') return; - if (property == 'href') { - return ctx.window.location.href = ctx.url.wrap(new URL(val, _url).href); - }; - _url[property] = val; - return ctx.window.location.href = ctx.url.wrap(_url); - }, - }); - }); - if (!ctx.serviceWorker) [ - 'assign', - 'replace', - 'reload', - ].forEach(method => { - _location[method] = new Proxy(ctx.window.location[method], { - apply(target, that, args) { - if (args[0]) args[0] = ctx.url.wrap(args[0], ctx.meta); - return Reflect.apply(target.bind(ctx.window.location), that, args); - }, - }); - }); - _location.toString = new Proxy(_url.toString, { - apply(target, that, args) { - return Reflect.apply(target.bind(_url), that, args); - }, - }); - return _location; -}; - -createLocation.Location = Location; -module.exports = createLocation; - -/***/ }), -/* 5 */ -/***/ ((module) => { - -function createWorkerRewriter(ctx = {}) { - return function rewriteWorker() { - if (ctx.window.Worker) { - ctx.window.Worker = new Proxy(ctx.window.Worker, { - construct: (target, args) => { - if (args[0]) { - if (args[0].trim().startsWith(`blob:${ctx.window.location.origin}`)) { - const xhr = new ctx.originalXhr(); - xhr.open('GET', args[0], false); - xhr.send(); - const script = ctx.js.process(xhr.responseText, ctx.location.origin + args[0].trim().slice(`blob:${ctx.window.location.origin}`.length)); - const blob = new Blob([ script ], { type: 'application/javascript' }); - args[0] = URL.createObjectURL(blob); - } else { - args[0] = ctx.url.wrap(args[0], ctx.meta); - }; - }; - return Reflect.construct(target, args); - }, - }); - }; - if (ctx.serviceWorker && ctx.window.importScripts) { - ctx.window.importScripts = new Proxy(ctx.window.importScripts, { - apply: (target, that, args) => { - if (args[0]) args[0] = ctx.url.wrap(args[0], ctx.meta); - return Reflect.apply(target, that, args); - }, - }); - }; - }; -}; - -module.exports = createWorkerRewriter; - -/***/ }), -/* 6 */ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -const URLWrapper = __webpack_require__(7); -const CookieRewriter = __webpack_require__(9); -const CSSRewriter = __webpack_require__(11); -const HTMLRewriter = __webpack_require__(134); -const JSRewriter = __webpack_require__(159); -const defaultConfig = { - prefix: '/service/', - codec: 'plain', - ws: true, - cookie: true, - title: 'Service', -}; - -class Rewrite { - constructor(config = defaultConfig) { - this.config = Object.assign(defaultConfig, config); - this.prefix = this.config.prefix; - this.url = new URLWrapper(this.config || {}); - this.codec = this.url.codec; - this.cookies = new CookieRewriter(this); - this.css = new CSSRewriter(this); - this.js = new JSRewriter(this); - this.html = new HTMLRewriter(this); - }; -}; - -module.exports = Rewrite; - -/***/ }), -/* 7 */ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -const codec = __webpack_require__(8); -const defaultConfig = { - prefix: '/service/', - codec: 'plain' -}; - -class URLWrapper { - constructor(config = defaultConfig) { - this.prefix = config.prefix || defaultConfig.prefix; - this.codec = codec[config.codec || 'plain'] || codec['plain']; - this.regex = /^(#|about:|data:|blob:|mailto:|javascript:)/; - }; - wrap(val, config = {}) { - if (!val || this.regex.test(val)) return val; - let flags = ''; - (config.flags || []).forEach(flag => flags += `${flag}_/`); - if (config.base) try { - if (!['http:', 'https:', 'ws:', 'wss:'].includes(new URL(val, config.base).protocol)) return val; - } catch(e) { - return val; - }; - return (config.origin || '') + this.prefix + flags + this.codec.encode(config.base ? new URL(val, config.base) : val) + '/'; - }; - unwrap(val, config = {}) { - if (!val || this.regex.test(val)) return val; - let processed = val.slice((config.origin || '').length + this.prefix.length); - const flags = ('/' + processed).match(/(?<=\/)(.*?)(?=_\/)/g) || []; - flags.forEach(flag => processed = processed.slice(`${flag}_/`.length)); - let [ url, leftovers ] = processed.split(/\/(.+)?/); - return config.flags ? { value: this.codec.decode((url || '')) + (config.leftovers && leftovers ? leftovers : ''), flags } : this.codec.decode((url || '')) + (config.leftovers && leftovers ? leftovers : ''); - }; -}; - -module.exports = URLWrapper; - -/***/ }), -/* 8 */ -/***/ ((__unused_webpack_module, exports) => { - -exports.xor = { - encode(str){ - if (!str) return str; - return encodeURIComponent(str.toString().split('').map((char, ind) => ind % 2 ? String.fromCharCode(char.charCodeAt() ^ 2) : char).join('')); - }, - decode(str){ - if (!str) return str; - return decodeURIComponent(str).split('').map((char, ind) => ind % 2 ? String.fromCharCode(char.charCodeAt() ^ 2) : char).join(''); - }, -}; -exports.plain = { - encode(str) { - if (!str) return str; - return encodeURIComponent(str); - }, - decode(str) { - if (!str) return str; - return decodeURIComponent(str); - }, -}; -exports.base64 = { - encode(str){ - if (!str) return str; - str = str.toString(); - const b64chs = Array.from('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='); - let u32; - let c0; - let c1; - let c2; - let asc = ''; - let pad = str.length % 3; - - for (let i = 0; i < str.length;) { - if((c0 = str.charCodeAt(i++)) > 255 || (c1 = str.charCodeAt(i++)) > 255 || (c2 = str.charCodeAt(i++)) > 255)throw new TypeError('invalid character found'); - u32 = (c0 << 16) | (c1 << 8) | c2; - asc += b64chs[u32 >> 18 & 63] - + b64chs[u32 >> 12 & 63] - + b64chs[u32 >> 6 & 63] - + b64chs[u32 & 63]; - } - - return encodeURIComponent(pad ? asc.slice(0, pad - 3) + '==='.substr(pad) : asc); - }, - decode(str){ - if (!str) return str; - str = decodeURIComponent(str.toString()); - const b64tab = {"0":52,"1":53,"2":54,"3":55,"4":56,"5":57,"6":58,"7":59,"8":60,"9":61,"A":0,"B":1,"C":2,"D":3,"E":4,"F":5,"G":6,"H":7,"I":8,"J":9,"K":10,"L":11,"M":12,"N":13,"O":14,"P":15,"Q":16,"R":17,"S":18,"T":19,"U":20,"V":21,"W":22,"X":23,"Y":24,"Z":25,"a":26,"b":27,"c":28,"d":29,"e":30,"f":31,"g":32,"h":33,"i":34,"j":35,"k":36,"l":37,"m":38,"n":39,"o":40,"p":41,"q":42,"r":43,"s":44,"t":45,"u":46,"v":47,"w":48,"x":49,"y":50,"z":51,"+":62,"/":63,"=":64}; - str = str.replace(/\s+/g, ''); - str += '=='.slice(2 - (str.length & 3)); - let u24; - let bin = ''; - let r1; - let r2; - - for (let i = 0; i < str.length;) { - u24 = b64tab[str.charAt(i++)] << 18 - | b64tab[str.charAt(i++)] << 12 - | (r1 = b64tab[str.charAt(i++)]) << 6 - | (r2 = b64tab[str.charAt(i++)]); - bin += r1 === 64 ? String.fromCharCode(u24 >> 16 & 255) - : r2 === 64 ? String.fromCharCode(u24 >> 16 & 255, u24 >> 8 & 255) - : String.fromCharCode(u24 >> 16 & 255, u24 >> 8 & 255, u24 & 255); - }; - return bin; - }, -}; - -/***/ }), -/* 9 */ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -const { SetCookie, CookieStore } = __webpack_require__(10); - -class CookieRewriter { - constructor(ctx) { - this.ctx = ctx; - }; - decode(store, config = {}) { - const url = new URL(config.url); - const cookies = new CookieStore(store); - cookies.forEach((val, key) => { - if (!key.includes('@') || key.slice(key.length - url.hostname.length) != url.hostname) return cookies.delete(key); - cookies.delete(key); - cookies.set(key.substr(0, key.length - url.hostname.length - 1), val); - }); - return cookies.serialize(); - }; - encode(input, config = {}) { - if (Array.isArray(input)) { - const rw = [ ...input ]; - for (let i in rw) rw[i] = this.encode(rw[i], config); - return rw; - }; - const url = new URL(config.url); - const cookie = new SetCookie(input); - if (!cookie.name) return null; - cookie.domain = config.domain; - cookie.secure = config.secure; - cookie.name += `@${url.hostname}`; - cookie.path = this.ctx.prefix; - return cookie.serialize() || ''; - }; -}; - -module.exports = CookieRewriter; - -/***/ }), -/* 10 */ -/***/ ((__unused_webpack_module, exports) => { - -// ------------------- -// This file is shared both by the server and client. -// Do not include any browser or node specific APIs -// ------------------- - -class CookieStore { - constructor(val = ''){ - this.data = {}; - val.split(';').map(cookie => { - var [ name, val = ''] = cookie.trimStart().split('='); - if (name) this.data[name] = val; - }); - }; - has(name){ - if (!name || !this.data[name]) return false; - return true; - }; - get(name){ - return this.has(name) ? this.data[name] : null; - }; - set(name, val){ - if (!name || !val) return; - return this.data[name] = val; - }; - delete(name){ - if (!name) return; - return delete this.data[name]; - }; - forEach(action = (node, key) => null){ - for (let prop in this.data) action(this.data[prop], prop); - }; - serialize(){ - var str = ''; - for (let i in this.data) str += ` ${i}=${this.data[i]};`; - return str.substr(1); - }; -}; - -class SetCookie { - constructor(val = ''){ - - var [ [ name, value = '' ], ...data ] = val.split(';').map(str => str.trimStart().split('=')); - - this.name = name; - this.value = value; - this.expires = null; - this.maxAge = null; - this.domain = null; - this.secure = false; - this.httpOnly = false; - this.path = null; - this.sameSite = null; - - data.forEach(([name = null, value = null]) => { - if (typeof name == 'string') switch(name.toLowerCase()){ - case 'domain': - this.domain = value; - break; - case 'secure': - this.secure = true; - break; - case 'httponly': - this.httpOnly = true; - break; - case 'samesite': - this.sameSite = value; - break; - case 'path': - this.path = value; - break; - case 'expires': - this.expires = value; - break; - case 'maxage': - this.maxAge = value; - break; - }; - }); - }; - serialize(){ - if (!this.name) return; - var str = `${this.name}=${this.value};`; - if (this.expires) str += ` Expires=${this.expires};`; - if (this.maxAge) str += ` Max-Age=${this.max_age};`; - if (this.domain) str += ` Domain=${this.domain};`; - if (this.secure) str += ` Secure;`; - if (this.httpOnly) str += ` HttpOnly;`; - if (this.path) str += ` Path=${this.path};`; - if (this.sameSite) str += ` SameSite=${this.sameSite};`; - return str; - }; -}; - -exports.CookieStore = CookieStore; -exports.SetCookie = SetCookie; - -/***/ }), -/* 11 */ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -const csstree = __webpack_require__(12); - -class CSSRewriter { - constructor(ctx) { - this.ctx = ctx; - }; - process(source, config = {}) { - const ast = csstree.parse(source, { - context: config.context || 'stylesheet', - parseCustomProperty: true, - }); - const urls = csstree.findAll(ast, node => - node.type == 'Url' - ); - const imports = csstree.findAll(ast, node => - node.type == 'Atrule' && node.name == 'import' && node.prelude && node.prelude.type == 'AtrulePrelude' && node.prelude.children.head.data.type == 'String' - ); - urls.forEach(({ value }) => { - switch(value.type) { - case 'String': - const quote = value.value.substring(0, 1); - value.value = quote + this.ctx.url.wrap(value.value.slice(1).slice(0, -1), config) + quote; - break; - case 'Raw': - value.value = this.ctx.url.wrap(value.value, config); - break; - }; - }); - imports.forEach(({ prelude }) => { - const { data } = prelude.children.head; - const quote = data.value.substring(0, 1); - data.value = quote + this.ctx.url.wrap(data.value.slice(1).slice(0, -1), config) + quote; - }); - return csstree.generate(ast); - }; - source(processed, config = {}) { - const ast = csstree.parse(processed, { - context: config.context || 'stylesheet', - parseCustomProperty: true, - }); - const urls = csstree.findAll(ast, node => - node.type == 'Url' - ); - const imports = csstree.findAll(ast, node => - node.type == 'Atrule' && node.name == 'import' && node.prelude && node.prelude.type == 'AtrulePrelude' && node.prelude.children.head.data.type == 'String' - ); - urls.forEach(({ value }) => { - switch(value.type) { - case 'String': - const quote = value.value.substring(0, 1); - value.value = quote + this.ctx.url.unwrap(value.value.slice(1).slice(0, -1), config) + quote; - break; - case 'Raw': - value.value = this.ctx.url.unwrap(value.value, config); - break; - }; - }); - imports.forEach(({ prelude }) => { - const { data } = prelude.children.head; - const quote = data.value.substring(0, 1); - data.value = quote + this.ctx.url.unwrap(data.value.slice(1).slice(0, -1), config) + quote; - }); - return csstree.generate(ast); - }; -}; - -module.exports = CSSRewriter; - -/***/ }), -/* 12 */ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -module.exports = __webpack_require__(13); - - -/***/ }), -/* 13 */ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -function merge() { - var dest = {}; - - for (var i = 0; i < arguments.length; i++) { - var src = arguments[i]; - for (var key in src) { - dest[key] = src[key]; - } - } - - return dest; -} - -module.exports = __webpack_require__(14).create( - merge( - __webpack_require__(57), - __webpack_require__(104), - __webpack_require__(132) - ) -); -module.exports.version = __webpack_require__(133).version; - - -/***/ }), -/* 14 */ -/***/ ((__unused_webpack_module, exports, __webpack_require__) => { - -var List = __webpack_require__(15); -var SyntaxError = __webpack_require__(16); -var TokenStream = __webpack_require__(18); -var Lexer = __webpack_require__(22); -var definitionSyntax = __webpack_require__(41); -var tokenize = __webpack_require__(27); -var createParser = __webpack_require__(42); -var createGenerator = __webpack_require__(45); -var createConvertor = __webpack_require__(53); -var createWalker = __webpack_require__(54); -var clone = __webpack_require__(55); -var names = __webpack_require__(25); -var mix = __webpack_require__(56); - -function createSyntax(config) { - var parse = createParser(config); - var walk = createWalker(config); - var generate = createGenerator(config); - var convert = createConvertor(walk); - - var syntax = { - List: List, - SyntaxError: SyntaxError, - TokenStream: TokenStream, - Lexer: Lexer, - - vendorPrefix: names.vendorPrefix, - keyword: names.keyword, - property: names.property, - isCustomProperty: names.isCustomProperty, - - definitionSyntax: definitionSyntax, - lexer: null, - createLexer: function(config) { - return new Lexer(config, syntax, syntax.lexer.structure); - }, - - tokenize: tokenize, - parse: parse, - walk: walk, - generate: generate, - - find: walk.find, - findLast: walk.findLast, - findAll: walk.findAll, - - clone: clone, - fromPlainObject: convert.fromPlainObject, - toPlainObject: convert.toPlainObject, - - createSyntax: function(config) { - return createSyntax(mix({}, config)); - }, - fork: function(extension) { - var base = mix({}, config); // copy of config - return createSyntax( - typeof extension === 'function' - ? extension(base, Object.assign) - : mix(base, extension) - ); - } - }; - - syntax.lexer = new Lexer({ - generic: true, - types: config.types, - atrules: config.atrules, - properties: config.properties, - node: config.node - }, syntax); - - return syntax; -}; - -exports.create = function(config) { - return createSyntax(mix({}, config)); -}; - - -/***/ }), -/* 15 */ -/***/ ((module) => { - -// -// list -// ┌──────┐ -// ┌──────────────┼─head │ -// │ │ tail─┼──────────────┐ -// │ └──────┘ │ -// ▼ ▼ -// item item item item -// ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ -// null ◀──┼─prev │◀───┼─prev │◀───┼─prev │◀───┼─prev │ -// │ next─┼───▶│ next─┼───▶│ next─┼───▶│ next─┼──▶ null -// ├──────┤ ├──────┤ ├──────┤ ├──────┤ -// │ data │ │ data │ │ data │ │ data │ -// └──────┘ └──────┘ └──────┘ └──────┘ -// - -function createItem(data) { - return { - prev: null, - next: null, - data: data - }; -} - -function allocateCursor(node, prev, next) { - var cursor; - - if (cursors !== null) { - cursor = cursors; - cursors = cursors.cursor; - cursor.prev = prev; - cursor.next = next; - cursor.cursor = node.cursor; - } else { - cursor = { - prev: prev, - next: next, - cursor: node.cursor - }; - } - - node.cursor = cursor; - - return cursor; -} - -function releaseCursor(node) { - var cursor = node.cursor; - - node.cursor = cursor.cursor; - cursor.prev = null; - cursor.next = null; - cursor.cursor = cursors; - cursors = cursor; -} - -var cursors = null; -var List = function() { - this.cursor = null; - this.head = null; - this.tail = null; -}; - -List.createItem = createItem; -List.prototype.createItem = createItem; - -List.prototype.updateCursors = function(prevOld, prevNew, nextOld, nextNew) { - var cursor = this.cursor; - - while (cursor !== null) { - if (cursor.prev === prevOld) { - cursor.prev = prevNew; - } - - if (cursor.next === nextOld) { - cursor.next = nextNew; - } - - cursor = cursor.cursor; - } -}; - -List.prototype.getSize = function() { - var size = 0; - var cursor = this.head; - - while (cursor) { - size++; - cursor = cursor.next; - } - - return size; -}; - -List.prototype.fromArray = function(array) { - var cursor = null; - - this.head = null; - - for (var i = 0; i < array.length; i++) { - var item = createItem(array[i]); - - if (cursor !== null) { - cursor.next = item; - } else { - this.head = item; - } - - item.prev = cursor; - cursor = item; - } - - this.tail = cursor; - - return this; -}; - -List.prototype.toArray = function() { - var cursor = this.head; - var result = []; - - while (cursor) { - result.push(cursor.data); - cursor = cursor.next; - } - - return result; -}; - -List.prototype.toJSON = List.prototype.toArray; - -List.prototype.isEmpty = function() { - return this.head === null; -}; - -List.prototype.first = function() { - return this.head && this.head.data; -}; - -List.prototype.last = function() { - return this.tail && this.tail.data; -}; - -List.prototype.each = function(fn, context) { - var item; - - if (context === undefined) { - context = this; - } - - // push cursor - var cursor = allocateCursor(this, null, this.head); - - while (cursor.next !== null) { - item = cursor.next; - cursor.next = item.next; - - fn.call(context, item.data, item, this); - } - - // pop cursor - releaseCursor(this); -}; - -List.prototype.forEach = List.prototype.each; - -List.prototype.eachRight = function(fn, context) { - var item; - - if (context === undefined) { - context = this; - } - - // push cursor - var cursor = allocateCursor(this, this.tail, null); - - while (cursor.prev !== null) { - item = cursor.prev; - cursor.prev = item.prev; - - fn.call(context, item.data, item, this); - } - - // pop cursor - releaseCursor(this); -}; - -List.prototype.forEachRight = List.prototype.eachRight; - -List.prototype.reduce = function(fn, initialValue, context) { - var item; - - if (context === undefined) { - context = this; - } - - // push cursor - var cursor = allocateCursor(this, null, this.head); - var acc = initialValue; - - while (cursor.next !== null) { - item = cursor.next; - cursor.next = item.next; - - acc = fn.call(context, acc, item.data, item, this); - } - - // pop cursor - releaseCursor(this); - - return acc; -}; - -List.prototype.reduceRight = function(fn, initialValue, context) { - var item; - - if (context === undefined) { - context = this; - } - - // push cursor - var cursor = allocateCursor(this, this.tail, null); - var acc = initialValue; - - while (cursor.prev !== null) { - item = cursor.prev; - cursor.prev = item.prev; - - acc = fn.call(context, acc, item.data, item, this); - } - - // pop cursor - releaseCursor(this); - - return acc; -}; - -List.prototype.nextUntil = function(start, fn, context) { - if (start === null) { - return; - } - - var item; - - if (context === undefined) { - context = this; - } - - // push cursor - var cursor = allocateCursor(this, null, start); - - while (cursor.next !== null) { - item = cursor.next; - cursor.next = item.next; - - if (fn.call(context, item.data, item, this)) { - break; - } - } - - // pop cursor - releaseCursor(this); -}; - -List.prototype.prevUntil = function(start, fn, context) { - if (start === null) { - return; - } - - var item; - - if (context === undefined) { - context = this; - } - - // push cursor - var cursor = allocateCursor(this, start, null); - - while (cursor.prev !== null) { - item = cursor.prev; - cursor.prev = item.prev; - - if (fn.call(context, item.data, item, this)) { - break; - } - } - - // pop cursor - releaseCursor(this); -}; - -List.prototype.some = function(fn, context) { - var cursor = this.head; - - if (context === undefined) { - context = this; - } - - while (cursor !== null) { - if (fn.call(context, cursor.data, cursor, this)) { - return true; - } - - cursor = cursor.next; - } - - return false; -}; - -List.prototype.map = function(fn, context) { - var result = new List(); - var cursor = this.head; - - if (context === undefined) { - context = this; - } - - while (cursor !== null) { - result.appendData(fn.call(context, cursor.data, cursor, this)); - cursor = cursor.next; - } - - return result; -}; - -List.prototype.filter = function(fn, context) { - var result = new List(); - var cursor = this.head; - - if (context === undefined) { - context = this; - } - - while (cursor !== null) { - if (fn.call(context, cursor.data, cursor, this)) { - result.appendData(cursor.data); - } - cursor = cursor.next; - } - - return result; -}; - -List.prototype.clear = function() { - this.head = null; - this.tail = null; -}; - -List.prototype.copy = function() { - var result = new List(); - var cursor = this.head; - - while (cursor !== null) { - result.insert(createItem(cursor.data)); - cursor = cursor.next; - } - - return result; -}; - -List.prototype.prepend = function(item) { - // head - // ^ - // item - this.updateCursors(null, item, this.head, item); - - // insert to the beginning of the list - if (this.head !== null) { - // new item <- first item - this.head.prev = item; - - // new item -> first item - item.next = this.head; - } else { - // if list has no head, then it also has no tail - // in this case tail points to the new item - this.tail = item; - } - - // head always points to new item - this.head = item; - - return this; -}; - -List.prototype.prependData = function(data) { - return this.prepend(createItem(data)); -}; - -List.prototype.append = function(item) { - return this.insert(item); -}; - -List.prototype.appendData = function(data) { - return this.insert(createItem(data)); -}; - -List.prototype.insert = function(item, before) { - if (before !== undefined && before !== null) { - // prev before - // ^ - // item - this.updateCursors(before.prev, item, before, item); - - if (before.prev === null) { - // insert to the beginning of list - if (this.head !== before) { - throw new Error('before doesn\'t belong to list'); - } - - // since head points to before therefore list doesn't empty - // no need to check tail - this.head = item; - before.prev = item; - item.next = before; - - this.updateCursors(null, item); - } else { - - // insert between two items - before.prev.next = item; - item.prev = before.prev; - - before.prev = item; - item.next = before; - } - } else { - // tail - // ^ - // item - this.updateCursors(this.tail, item, null, item); - - // insert to the ending of the list - if (this.tail !== null) { - // last item -> new item - this.tail.next = item; - - // last item <- new item - item.prev = this.tail; - } else { - // if list has no tail, then it also has no head - // in this case head points to new item - this.head = item; - } - - // tail always points to new item - this.tail = item; - } - - return this; -}; - -List.prototype.insertData = function(data, before) { - return this.insert(createItem(data), before); -}; - -List.prototype.remove = function(item) { - // item - // ^ - // prev next - this.updateCursors(item, item.prev, item, item.next); - - if (item.prev !== null) { - item.prev.next = item.next; - } else { - if (this.head !== item) { - throw new Error('item doesn\'t belong to list'); - } - - this.head = item.next; - } - - if (item.next !== null) { - item.next.prev = item.prev; - } else { - if (this.tail !== item) { - throw new Error('item doesn\'t belong to list'); - } - - this.tail = item.prev; - } - - item.prev = null; - item.next = null; - - return item; -}; - -List.prototype.push = function(data) { - this.insert(createItem(data)); -}; - -List.prototype.pop = function() { - if (this.tail !== null) { - return this.remove(this.tail); - } -}; - -List.prototype.unshift = function(data) { - this.prepend(createItem(data)); -}; - -List.prototype.shift = function() { - if (this.head !== null) { - return this.remove(this.head); - } -}; - -List.prototype.prependList = function(list) { - return this.insertList(list, this.head); -}; - -List.prototype.appendList = function(list) { - return this.insertList(list); -}; - -List.prototype.insertList = function(list, before) { - // ignore empty lists - if (list.head === null) { - return this; - } - - if (before !== undefined && before !== null) { - this.updateCursors(before.prev, list.tail, before, list.head); - - // insert in the middle of dist list - if (before.prev !== null) { - // before.prev <-> list.head - before.prev.next = list.head; - list.head.prev = before.prev; - } else { - this.head = list.head; - } - - before.prev = list.tail; - list.tail.next = before; - } else { - this.updateCursors(this.tail, list.tail, null, list.head); - - // insert to end of the list - if (this.tail !== null) { - // if destination list has a tail, then it also has a head, - // but head doesn't change - - // dest tail -> source head - this.tail.next = list.head; - - // dest tail <- source head - list.head.prev = this.tail; - } else { - // if list has no a tail, then it also has no a head - // in this case points head to new item - this.head = list.head; - } - - // tail always start point to new item - this.tail = list.tail; - } - - list.head = null; - list.tail = null; - - return this; -}; - -List.prototype.replace = function(oldItem, newItemOrList) { - if ('head' in newItemOrList) { - this.insertList(newItemOrList, oldItem); - } else { - this.insert(newItemOrList, oldItem); - } - - this.remove(oldItem); -}; - -module.exports = List; - - -/***/ }), -/* 16 */ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -var createCustomError = __webpack_require__(17); -var MAX_LINE_LENGTH = 100; -var OFFSET_CORRECTION = 60; -var TAB_REPLACEMENT = ' '; - -function sourceFragment(error, extraLines) { - function processLines(start, end) { - return lines.slice(start, end).map(function(line, idx) { - var num = String(start + idx + 1); - - while (num.length < maxNumLength) { - num = ' ' + num; - } - - return num + ' |' + line; - }).join('\n'); - } - - var lines = error.source.split(/\r\n?|\n|\f/); - var line = error.line; - var column = error.column; - var startLine = Math.max(1, line - extraLines) - 1; - var endLine = Math.min(line + extraLines, lines.length + 1); - var maxNumLength = Math.max(4, String(endLine).length) + 1; - var cutLeft = 0; - - // column correction according to replaced tab before column - column += (TAB_REPLACEMENT.length - 1) * (lines[line - 1].substr(0, column - 1).match(/\t/g) || []).length; - - if (column > MAX_LINE_LENGTH) { - cutLeft = column - OFFSET_CORRECTION + 3; - column = OFFSET_CORRECTION - 2; - } - - for (var i = startLine; i <= endLine; i++) { - if (i >= 0 && i < lines.length) { - lines[i] = lines[i].replace(/\t/g, TAB_REPLACEMENT); - lines[i] = - (cutLeft > 0 && lines[i].length > cutLeft ? '\u2026' : '') + - lines[i].substr(cutLeft, MAX_LINE_LENGTH - 2) + - (lines[i].length > cutLeft + MAX_LINE_LENGTH - 1 ? '\u2026' : ''); - } - } - - return [ - processLines(startLine, line), - new Array(column + maxNumLength + 2).join('-') + '^', - processLines(line, endLine) - ].filter(Boolean).join('\n'); -} - -var SyntaxError = function(message, source, offset, line, column) { - var error = createCustomError('SyntaxError', message); - - error.source = source; - error.offset = offset; - error.line = line; - error.column = column; - - error.sourceFragment = function(extraLines) { - return sourceFragment(error, isNaN(extraLines) ? 0 : extraLines); - }; - Object.defineProperty(error, 'formattedMessage', { - get: function() { - return ( - 'Parse error: ' + error.message + '\n' + - sourceFragment(error, 2) - ); - } - }); - - // for backward capability - error.parseError = { - offset: offset, - line: line, - column: column - }; - - return error; -}; - -module.exports = SyntaxError; - - -/***/ }), -/* 17 */ -/***/ ((module) => { - -module.exports = function createCustomError(name, message) { - // use Object.create(), because some VMs prevent setting line/column otherwise - // (iOS Safari 10 even throws an exception) - var error = Object.create(SyntaxError.prototype); - var errorStack = new Error(); - - error.name = name; - error.message = message; - - Object.defineProperty(error, 'stack', { - get: function() { - return (errorStack.stack || '').replace(/^(.+\n){1,3}/, name + ': ' + message + '\n'); - } - }); - - return error; -}; - - -/***/ }), -/* 18 */ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -var constants = __webpack_require__(19); -var TYPE = constants.TYPE; -var NAME = constants.NAME; - -var utils = __webpack_require__(20); -var cmpStr = utils.cmpStr; - -var EOF = TYPE.EOF; -var WHITESPACE = TYPE.WhiteSpace; -var COMMENT = TYPE.Comment; - -var OFFSET_MASK = 0x00FFFFFF; -var TYPE_SHIFT = 24; - -var TokenStream = function() { - this.offsetAndType = null; - this.balance = null; - - this.reset(); -}; - -TokenStream.prototype = { - reset: function() { - this.eof = false; - this.tokenIndex = -1; - this.tokenType = 0; - this.tokenStart = this.firstCharOffset; - this.tokenEnd = this.firstCharOffset; - }, - - lookupType: function(offset) { - offset += this.tokenIndex; - - if (offset < this.tokenCount) { - return this.offsetAndType[offset] >> TYPE_SHIFT; - } - - return EOF; - }, - lookupOffset: function(offset) { - offset += this.tokenIndex; - - if (offset < this.tokenCount) { - return this.offsetAndType[offset - 1] & OFFSET_MASK; - } - - return this.source.length; - }, - lookupValue: function(offset, referenceStr) { - offset += this.tokenIndex; - - if (offset < this.tokenCount) { - return cmpStr( - this.source, - this.offsetAndType[offset - 1] & OFFSET_MASK, - this.offsetAndType[offset] & OFFSET_MASK, - referenceStr - ); - } - - return false; - }, - getTokenStart: function(tokenIndex) { - if (tokenIndex === this.tokenIndex) { - return this.tokenStart; - } - - if (tokenIndex > 0) { - return tokenIndex < this.tokenCount - ? this.offsetAndType[tokenIndex - 1] & OFFSET_MASK - : this.offsetAndType[this.tokenCount] & OFFSET_MASK; - } - - return this.firstCharOffset; - }, - - // TODO: -> skipUntilBalanced - getRawLength: function(startToken, mode) { - var cursor = startToken; - var balanceEnd; - var offset = this.offsetAndType[Math.max(cursor - 1, 0)] & OFFSET_MASK; - var type; - - loop: - for (; cursor < this.tokenCount; cursor++) { - balanceEnd = this.balance[cursor]; - - // stop scanning on balance edge that points to offset before start token - if (balanceEnd < startToken) { - break loop; - } - - type = this.offsetAndType[cursor] >> TYPE_SHIFT; - - // check token is stop type - switch (mode(type, this.source, offset)) { - case 1: - break loop; - - case 2: - cursor++; - break loop; - - default: - // fast forward to the end of balanced block - if (this.balance[balanceEnd] === cursor) { - cursor = balanceEnd; - } - - offset = this.offsetAndType[cursor] & OFFSET_MASK; - } - } - - return cursor - this.tokenIndex; - }, - isBalanceEdge: function(pos) { - return this.balance[this.tokenIndex] < pos; - }, - isDelim: function(code, offset) { - if (offset) { - return ( - this.lookupType(offset) === TYPE.Delim && - this.source.charCodeAt(this.lookupOffset(offset)) === code - ); - } - - return ( - this.tokenType === TYPE.Delim && - this.source.charCodeAt(this.tokenStart) === code - ); - }, - - getTokenValue: function() { - return this.source.substring(this.tokenStart, this.tokenEnd); - }, - getTokenLength: function() { - return this.tokenEnd - this.tokenStart; - }, - substrToCursor: function(start) { - return this.source.substring(start, this.tokenStart); - }, - - skipWS: function() { - for (var i = this.tokenIndex, skipTokenCount = 0; i < this.tokenCount; i++, skipTokenCount++) { - if ((this.offsetAndType[i] >> TYPE_SHIFT) !== WHITESPACE) { - break; - } - } - - if (skipTokenCount > 0) { - this.skip(skipTokenCount); - } - }, - skipSC: function() { - while (this.tokenType === WHITESPACE || this.tokenType === COMMENT) { - this.next(); - } - }, - skip: function(tokenCount) { - var next = this.tokenIndex + tokenCount; - - if (next < this.tokenCount) { - this.tokenIndex = next; - this.tokenStart = this.offsetAndType[next - 1] & OFFSET_MASK; - next = this.offsetAndType[next]; - this.tokenType = next >> TYPE_SHIFT; - this.tokenEnd = next & OFFSET_MASK; - } else { - this.tokenIndex = this.tokenCount; - this.next(); - } - }, - next: function() { - var next = this.tokenIndex + 1; - - if (next < this.tokenCount) { - this.tokenIndex = next; - this.tokenStart = this.tokenEnd; - next = this.offsetAndType[next]; - this.tokenType = next >> TYPE_SHIFT; - this.tokenEnd = next & OFFSET_MASK; - } else { - this.tokenIndex = this.tokenCount; - this.eof = true; - this.tokenType = EOF; - this.tokenStart = this.tokenEnd = this.source.length; - } - }, - - forEachToken(fn) { - for (var i = 0, offset = this.firstCharOffset; i < this.tokenCount; i++) { - var start = offset; - var item = this.offsetAndType[i]; - var end = item & OFFSET_MASK; - var type = item >> TYPE_SHIFT; - - offset = end; - - fn(type, start, end, i); - } - }, - - dump() { - var tokens = new Array(this.tokenCount); - - this.forEachToken((type, start, end, index) => { - tokens[index] = { - idx: index, - type: NAME[type], - chunk: this.source.substring(start, end), - balance: this.balance[index] - }; - }); - - return tokens; - } -}; - -module.exports = TokenStream; - - -/***/ }), -/* 19 */ -/***/ ((module) => { - -// CSS Syntax Module Level 3 -// https://www.w3.org/TR/css-syntax-3/ -var TYPE = { - EOF: 0, // - Ident: 1, // - Function: 2, // - AtKeyword: 3, // - Hash: 4, // - String: 5, // - BadString: 6, // - Url: 7, // - BadUrl: 8, // - Delim: 9, // - Number: 10, // - Percentage: 11, // - Dimension: 12, // - WhiteSpace: 13, // - CDO: 14, // - CDC: 15, // - Colon: 16, // : - Semicolon: 17, // ; - Comma: 18, // , - LeftSquareBracket: 19, // <[-token> - RightSquareBracket: 20, // <]-token> - LeftParenthesis: 21, // <(-token> - RightParenthesis: 22, // <)-token> - LeftCurlyBracket: 23, // <{-token> - RightCurlyBracket: 24, // <}-token> - Comment: 25 -}; - -var NAME = Object.keys(TYPE).reduce(function(result, key) { - result[TYPE[key]] = key; - return result; -}, {}); - -module.exports = { - TYPE: TYPE, - NAME: NAME -}; - - -/***/ }), -/* 20 */ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -var charCodeDef = __webpack_require__(21); -var isDigit = charCodeDef.isDigit; -var isHexDigit = charCodeDef.isHexDigit; -var isUppercaseLetter = charCodeDef.isUppercaseLetter; -var isName = charCodeDef.isName; -var isWhiteSpace = charCodeDef.isWhiteSpace; -var isValidEscape = charCodeDef.isValidEscape; - -function getCharCode(source, offset) { - return offset < source.length ? source.charCodeAt(offset) : 0; -} - -function getNewlineLength(source, offset, code) { - if (code === 13 /* \r */ && getCharCode(source, offset + 1) === 10 /* \n */) { - return 2; - } - - return 1; -} - -function cmpChar(testStr, offset, referenceCode) { - var code = testStr.charCodeAt(offset); - - // code.toLowerCase() for A..Z - if (isUppercaseLetter(code)) { - code = code | 32; - } - - return code === referenceCode; -} - -function cmpStr(testStr, start, end, referenceStr) { - if (end - start !== referenceStr.length) { - return false; - } - - if (start < 0 || end > testStr.length) { - return false; - } - - for (var i = start; i < end; i++) { - var testCode = testStr.charCodeAt(i); - var referenceCode = referenceStr.charCodeAt(i - start); - - // testCode.toLowerCase() for A..Z - if (isUppercaseLetter(testCode)) { - testCode = testCode | 32; - } - - if (testCode !== referenceCode) { - return false; - } - } - - return true; -} - -function findWhiteSpaceStart(source, offset) { - for (; offset >= 0; offset--) { - if (!isWhiteSpace(source.charCodeAt(offset))) { - break; - } - } - - return offset + 1; -} - -function findWhiteSpaceEnd(source, offset) { - for (; offset < source.length; offset++) { - if (!isWhiteSpace(source.charCodeAt(offset))) { - break; - } - } - - return offset; -} - -function findDecimalNumberEnd(source, offset) { - for (; offset < source.length; offset++) { - if (!isDigit(source.charCodeAt(offset))) { - break; - } - } - - return offset; -} - -// § 4.3.7. Consume an escaped code point -function consumeEscaped(source, offset) { - // It assumes that the U+005C REVERSE SOLIDUS (\) has already been consumed and - // that the next input code point has already been verified to be part of a valid escape. - offset += 2; - - // hex digit - if (isHexDigit(getCharCode(source, offset - 1))) { - // Consume as many hex digits as possible, but no more than 5. - // Note that this means 1-6 hex digits have been consumed in total. - for (var maxOffset = Math.min(source.length, offset + 5); offset < maxOffset; offset++) { - if (!isHexDigit(getCharCode(source, offset))) { - break; - } - } - - // If the next input code point is whitespace, consume it as well. - var code = getCharCode(source, offset); - if (isWhiteSpace(code)) { - offset += getNewlineLength(source, offset, code); - } - } - - return offset; -} - -// §4.3.11. Consume a name -// Note: This algorithm does not do the verification of the first few code points that are necessary -// to ensure the returned code points would constitute an . If that is the intended use, -// ensure that the stream starts with an identifier before calling this algorithm. -function consumeName(source, offset) { - // Let result initially be an empty string. - // Repeatedly consume the next input code point from the stream: - for (; offset < source.length; offset++) { - var code = source.charCodeAt(offset); - - // name code point - if (isName(code)) { - // Append the code point to result. - continue; - } - - // the stream starts with a valid escape - if (isValidEscape(code, getCharCode(source, offset + 1))) { - // Consume an escaped code point. Append the returned code point to result. - offset = consumeEscaped(source, offset) - 1; - continue; - } - - // anything else - // Reconsume the current input code point. Return result. - break; - } - - return offset; -} - -// §4.3.12. Consume a number -function consumeNumber(source, offset) { - var code = source.charCodeAt(offset); - - // 2. If the next input code point is U+002B PLUS SIGN (+) or U+002D HYPHEN-MINUS (-), - // consume it and append it to repr. - if (code === 0x002B || code === 0x002D) { - code = source.charCodeAt(offset += 1); - } - - // 3. While the next input code point is a digit, consume it and append it to repr. - if (isDigit(code)) { - offset = findDecimalNumberEnd(source, offset + 1); - code = source.charCodeAt(offset); - } - - // 4. If the next 2 input code points are U+002E FULL STOP (.) followed by a digit, then: - if (code === 0x002E && isDigit(source.charCodeAt(offset + 1))) { - // 4.1 Consume them. - // 4.2 Append them to repr. - code = source.charCodeAt(offset += 2); - - // 4.3 Set type to "number". - // TODO - - // 4.4 While the next input code point is a digit, consume it and append it to repr. - - offset = findDecimalNumberEnd(source, offset); - } - - // 5. If the next 2 or 3 input code points are U+0045 LATIN CAPITAL LETTER E (E) - // or U+0065 LATIN SMALL LETTER E (e), ... , followed by a digit, then: - if (cmpChar(source, offset, 101 /* e */)) { - var sign = 0; - code = source.charCodeAt(offset + 1); - - // ... optionally followed by U+002D HYPHEN-MINUS (-) or U+002B PLUS SIGN (+) ... - if (code === 0x002D || code === 0x002B) { - sign = 1; - code = source.charCodeAt(offset + 2); - } - - // ... followed by a digit - if (isDigit(code)) { - // 5.1 Consume them. - // 5.2 Append them to repr. - - // 5.3 Set type to "number". - // TODO - - // 5.4 While the next input code point is a digit, consume it and append it to repr. - offset = findDecimalNumberEnd(source, offset + 1 + sign + 1); - } - } - - return offset; -} - -// § 4.3.14. Consume the remnants of a bad url -// ... its sole use is to consume enough of the input stream to reach a recovery point -// where normal tokenizing can resume. -function consumeBadUrlRemnants(source, offset) { - // Repeatedly consume the next input code point from the stream: - for (; offset < source.length; offset++) { - var code = source.charCodeAt(offset); - - // U+0029 RIGHT PARENTHESIS ()) - // EOF - if (code === 0x0029) { - // Return. - offset++; - break; - } - - if (isValidEscape(code, getCharCode(source, offset + 1))) { - // Consume an escaped code point. - // Note: This allows an escaped right parenthesis ("\)") to be encountered - // without ending the . This is otherwise identical to - // the "anything else" clause. - offset = consumeEscaped(source, offset); - } - } - - return offset; -} - -module.exports = { - consumeEscaped: consumeEscaped, - consumeName: consumeName, - consumeNumber: consumeNumber, - consumeBadUrlRemnants: consumeBadUrlRemnants, - - cmpChar: cmpChar, - cmpStr: cmpStr, - - getNewlineLength: getNewlineLength, - findWhiteSpaceStart: findWhiteSpaceStart, - findWhiteSpaceEnd: findWhiteSpaceEnd -}; - - -/***/ }), -/* 21 */ -/***/ ((module) => { - -var EOF = 0; - -// https://drafts.csswg.org/css-syntax-3/ -// § 4.2. Definitions - -// digit -// A code point between U+0030 DIGIT ZERO (0) and U+0039 DIGIT NINE (9). -function isDigit(code) { - return code >= 0x0030 && code <= 0x0039; -} - -// hex digit -// A digit, or a code point between U+0041 LATIN CAPITAL LETTER A (A) and U+0046 LATIN CAPITAL LETTER F (F), -// or a code point between U+0061 LATIN SMALL LETTER A (a) and U+0066 LATIN SMALL LETTER F (f). -function isHexDigit(code) { - return ( - isDigit(code) || // 0 .. 9 - (code >= 0x0041 && code <= 0x0046) || // A .. F - (code >= 0x0061 && code <= 0x0066) // a .. f - ); -} - -// uppercase letter -// A code point between U+0041 LATIN CAPITAL LETTER A (A) and U+005A LATIN CAPITAL LETTER Z (Z). -function isUppercaseLetter(code) { - return code >= 0x0041 && code <= 0x005A; -} - -// lowercase letter -// A code point between U+0061 LATIN SMALL LETTER A (a) and U+007A LATIN SMALL LETTER Z (z). -function isLowercaseLetter(code) { - return code >= 0x0061 && code <= 0x007A; -} - -// letter -// An uppercase letter or a lowercase letter. -function isLetter(code) { - return isUppercaseLetter(code) || isLowercaseLetter(code); -} - -// non-ASCII code point -// A code point with a value equal to or greater than U+0080 . -function isNonAscii(code) { - return code >= 0x0080; -} - -// name-start code point -// A letter, a non-ASCII code point, or U+005F LOW LINE (_). -function isNameStart(code) { - return isLetter(code) || isNonAscii(code) || code === 0x005F; -} - -// name code point -// A name-start code point, a digit, or U+002D HYPHEN-MINUS (-). -function isName(code) { - return isNameStart(code) || isDigit(code) || code === 0x002D; -} - -// non-printable code point -// A code point between U+0000 NULL and U+0008 BACKSPACE, or U+000B LINE TABULATION, -// or a code point between U+000E SHIFT OUT and U+001F INFORMATION SEPARATOR ONE, or U+007F DELETE. -function isNonPrintable(code) { - return ( - (code >= 0x0000 && code <= 0x0008) || - (code === 0x000B) || - (code >= 0x000E && code <= 0x001F) || - (code === 0x007F) - ); -} - -// newline -// U+000A LINE FEED. Note that U+000D CARRIAGE RETURN and U+000C FORM FEED are not included in this definition, -// as they are converted to U+000A LINE FEED during preprocessing. -// TODO: we doesn't do a preprocessing, so check a code point for U+000D CARRIAGE RETURN and U+000C FORM FEED -function isNewline(code) { - return code === 0x000A || code === 0x000D || code === 0x000C; -} - -// whitespace -// A newline, U+0009 CHARACTER TABULATION, or U+0020 SPACE. -function isWhiteSpace(code) { - return isNewline(code) || code === 0x0020 || code === 0x0009; -} - -// § 4.3.8. Check if two code points are a valid escape -function isValidEscape(first, second) { - // If the first code point is not U+005C REVERSE SOLIDUS (\), return false. - if (first !== 0x005C) { - return false; - } - - // Otherwise, if the second code point is a newline or EOF, return false. - if (isNewline(second) || second === EOF) { - return false; - } - - // Otherwise, return true. - return true; -} - -// § 4.3.9. Check if three code points would start an identifier -function isIdentifierStart(first, second, third) { - // Look at the first code point: - - // U+002D HYPHEN-MINUS - if (first === 0x002D) { - // If the second code point is a name-start code point or a U+002D HYPHEN-MINUS, - // or the second and third code points are a valid escape, return true. Otherwise, return false. - return ( - isNameStart(second) || - second === 0x002D || - isValidEscape(second, third) - ); - } - - // name-start code point - if (isNameStart(first)) { - // Return true. - return true; - } - - // U+005C REVERSE SOLIDUS (\) - if (first === 0x005C) { - // If the first and second code points are a valid escape, return true. Otherwise, return false. - return isValidEscape(first, second); - } - - // anything else - // Return false. - return false; -} - -// § 4.3.10. Check if three code points would start a number -function isNumberStart(first, second, third) { - // Look at the first code point: - - // U+002B PLUS SIGN (+) - // U+002D HYPHEN-MINUS (-) - if (first === 0x002B || first === 0x002D) { - // If the second code point is a digit, return true. - if (isDigit(second)) { - return 2; - } - - // Otherwise, if the second code point is a U+002E FULL STOP (.) - // and the third code point is a digit, return true. - // Otherwise, return false. - return second === 0x002E && isDigit(third) ? 3 : 0; - } - - // U+002E FULL STOP (.) - if (first === 0x002E) { - // If the second code point is a digit, return true. Otherwise, return false. - return isDigit(second) ? 2 : 0; - } - - // digit - if (isDigit(first)) { - // Return true. - return 1; - } - - // anything else - // Return false. - return 0; -} - -// -// Misc -// - -// detect BOM (https://en.wikipedia.org/wiki/Byte_order_mark) -function isBOM(code) { - // UTF-16BE - if (code === 0xFEFF) { - return 1; - } - - // UTF-16LE - if (code === 0xFFFE) { - return 1; - } - - return 0; -} - -// Fast code category -// -// https://drafts.csswg.org/css-syntax/#tokenizer-definitions -// > non-ASCII code point -// > A code point with a value equal to or greater than U+0080 -// > name-start code point -// > A letter, a non-ASCII code point, or U+005F LOW LINE (_). -// > name code point -// > A name-start code point, a digit, or U+002D HYPHEN-MINUS (-) -// That means only ASCII code points has a special meaning and we define a maps for 0..127 codes only -var CATEGORY = new Array(0x80); -charCodeCategory.Eof = 0x80; -charCodeCategory.WhiteSpace = 0x82; -charCodeCategory.Digit = 0x83; -charCodeCategory.NameStart = 0x84; -charCodeCategory.NonPrintable = 0x85; - -for (var i = 0; i < CATEGORY.length; i++) { - switch (true) { - case isWhiteSpace(i): - CATEGORY[i] = charCodeCategory.WhiteSpace; - break; - - case isDigit(i): - CATEGORY[i] = charCodeCategory.Digit; - break; - - case isNameStart(i): - CATEGORY[i] = charCodeCategory.NameStart; - break; - - case isNonPrintable(i): - CATEGORY[i] = charCodeCategory.NonPrintable; - break; - - default: - CATEGORY[i] = i || charCodeCategory.Eof; - } -} - -function charCodeCategory(code) { - return code < 0x80 ? CATEGORY[code] : charCodeCategory.NameStart; -}; - -module.exports = { - isDigit: isDigit, - isHexDigit: isHexDigit, - isUppercaseLetter: isUppercaseLetter, - isLowercaseLetter: isLowercaseLetter, - isLetter: isLetter, - isNonAscii: isNonAscii, - isNameStart: isNameStart, - isName: isName, - isNonPrintable: isNonPrintable, - isNewline: isNewline, - isWhiteSpace: isWhiteSpace, - isValidEscape: isValidEscape, - isIdentifierStart: isIdentifierStart, - isNumberStart: isNumberStart, - - isBOM: isBOM, - charCodeCategory: charCodeCategory -}; - - -/***/ }), -/* 22 */ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -var SyntaxReferenceError = __webpack_require__(23).SyntaxReferenceError; -var SyntaxMatchError = __webpack_require__(23).SyntaxMatchError; -var names = __webpack_require__(25); -var generic = __webpack_require__(26); -var parse = __webpack_require__(31); -var generate = __webpack_require__(24); -var walk = __webpack_require__(34); -var prepareTokens = __webpack_require__(35); -var buildMatchGraph = __webpack_require__(36).buildMatchGraph; -var matchAsTree = __webpack_require__(37).matchAsTree; -var trace = __webpack_require__(38); -var search = __webpack_require__(39); -var getStructureFromConfig = __webpack_require__(40).getStructureFromConfig; -var cssWideKeywords = buildMatchGraph('inherit | initial | unset'); -var cssWideKeywordsWithExpression = buildMatchGraph('inherit | initial | unset | <-ms-legacy-expression>'); - -function dumpMapSyntax(map, compact, syntaxAsAst) { - var result = {}; - - for (var name in map) { - if (map[name].syntax) { - result[name] = syntaxAsAst - ? map[name].syntax - : generate(map[name].syntax, { compact: compact }); - } - } - - return result; -} - -function dumpAtruleMapSyntax(map, compact, syntaxAsAst) { - const result = {}; - - for (const [name, atrule] of Object.entries(map)) { - result[name] = { - prelude: atrule.prelude && ( - syntaxAsAst - ? atrule.prelude.syntax - : generate(atrule.prelude.syntax, { compact }) - ), - descriptors: atrule.descriptors && dumpMapSyntax(atrule.descriptors, compact, syntaxAsAst) - }; - } - - return result; -} - -function valueHasVar(tokens) { - for (var i = 0; i < tokens.length; i++) { - if (tokens[i].value.toLowerCase() === 'var(') { - return true; - } - } - - return false; -} - -function buildMatchResult(match, error, iterations) { - return { - matched: match, - iterations: iterations, - error: error, - getTrace: trace.getTrace, - isType: trace.isType, - isProperty: trace.isProperty, - isKeyword: trace.isKeyword - }; -} - -function matchSyntax(lexer, syntax, value, useCommon) { - var tokens = prepareTokens(value, lexer.syntax); - var result; - - if (valueHasVar(tokens)) { - return buildMatchResult(null, new Error('Matching for a tree with var() is not supported')); - } - - if (useCommon) { - result = matchAsTree(tokens, lexer.valueCommonSyntax, lexer); - } - - if (!useCommon || !result.match) { - result = matchAsTree(tokens, syntax.match, lexer); - if (!result.match) { - return buildMatchResult( - null, - new SyntaxMatchError(result.reason, syntax.syntax, value, result), - result.iterations - ); - } - } - - return buildMatchResult(result.match, null, result.iterations); -} - -var Lexer = function(config, syntax, structure) { - this.valueCommonSyntax = cssWideKeywords; - this.syntax = syntax; - this.generic = false; - this.atrules = {}; - this.properties = {}; - this.types = {}; - this.structure = structure || getStructureFromConfig(config); - - if (config) { - if (config.types) { - for (var name in config.types) { - this.addType_(name, config.types[name]); - } - } - - if (config.generic) { - this.generic = true; - for (var name in generic) { - this.addType_(name, generic[name]); - } - } - - if (config.atrules) { - for (var name in config.atrules) { - this.addAtrule_(name, config.atrules[name]); - } - } - - if (config.properties) { - for (var name in config.properties) { - this.addProperty_(name, config.properties[name]); - } - } - } -}; - -Lexer.prototype = { - structure: {}, - checkStructure: function(ast) { - function collectWarning(node, message) { - warns.push({ - node: node, - message: message - }); - } - - var structure = this.structure; - var warns = []; - - this.syntax.walk(ast, function(node) { - if (structure.hasOwnProperty(node.type)) { - structure[node.type].check(node, collectWarning); - } else { - collectWarning(node, 'Unknown node type `' + node.type + '`'); - } - }); - - return warns.length ? warns : false; - }, - - createDescriptor: function(syntax, type, name, parent = null) { - var ref = { - type: type, - name: name - }; - var descriptor = { - type: type, - name: name, - parent: parent, - syntax: null, - match: null - }; - - if (typeof syntax === 'function') { - descriptor.match = buildMatchGraph(syntax, ref); - } else { - if (typeof syntax === 'string') { - // lazy parsing on first access - Object.defineProperty(descriptor, 'syntax', { - get: function() { - Object.defineProperty(descriptor, 'syntax', { - value: parse(syntax) - }); - - return descriptor.syntax; - } - }); - } else { - descriptor.syntax = syntax; - } - - // lazy graph build on first access - Object.defineProperty(descriptor, 'match', { - get: function() { - Object.defineProperty(descriptor, 'match', { - value: buildMatchGraph(descriptor.syntax, ref) - }); - - return descriptor.match; - } - }); - } - - return descriptor; - }, - addAtrule_: function(name, syntax) { - if (!syntax) { - return; - } - - this.atrules[name] = { - type: 'Atrule', - name: name, - prelude: syntax.prelude ? this.createDescriptor(syntax.prelude, 'AtrulePrelude', name) : null, - descriptors: syntax.descriptors - ? Object.keys(syntax.descriptors).reduce((res, descName) => { - res[descName] = this.createDescriptor(syntax.descriptors[descName], 'AtruleDescriptor', descName, name); - return res; - }, {}) - : null - }; - }, - addProperty_: function(name, syntax) { - if (!syntax) { - return; - } - - this.properties[name] = this.createDescriptor(syntax, 'Property', name); - }, - addType_: function(name, syntax) { - if (!syntax) { - return; - } - - this.types[name] = this.createDescriptor(syntax, 'Type', name); - - if (syntax === generic['-ms-legacy-expression']) { - this.valueCommonSyntax = cssWideKeywordsWithExpression; - } - }, - - checkAtruleName: function(atruleName) { - if (!this.getAtrule(atruleName)) { - return new SyntaxReferenceError('Unknown at-rule', '@' + atruleName); - } - }, - checkAtrulePrelude: function(atruleName, prelude) { - let error = this.checkAtruleName(atruleName); - - if (error) { - return error; - } - - var atrule = this.getAtrule(atruleName); - - if (!atrule.prelude && prelude) { - return new SyntaxError('At-rule `@' + atruleName + '` should not contain a prelude'); - } - - if (atrule.prelude && !prelude) { - return new SyntaxError('At-rule `@' + atruleName + '` should contain a prelude'); - } - }, - checkAtruleDescriptorName: function(atruleName, descriptorName) { - let error = this.checkAtruleName(atruleName); - - if (error) { - return error; - } - - var atrule = this.getAtrule(atruleName); - var descriptor = names.keyword(descriptorName); - - if (!atrule.descriptors) { - return new SyntaxError('At-rule `@' + atruleName + '` has no known descriptors'); - } - - if (!atrule.descriptors[descriptor.name] && - !atrule.descriptors[descriptor.basename]) { - return new SyntaxReferenceError('Unknown at-rule descriptor', descriptorName); - } - }, - checkPropertyName: function(propertyName) { - var property = names.property(propertyName); - - // don't match syntax for a custom property - if (property.custom) { - return new Error('Lexer matching doesn\'t applicable for custom properties'); - } - - if (!this.getProperty(propertyName)) { - return new SyntaxReferenceError('Unknown property', propertyName); - } - }, - - matchAtrulePrelude: function(atruleName, prelude) { - var error = this.checkAtrulePrelude(atruleName, prelude); - - if (error) { - return buildMatchResult(null, error); - } - - if (!prelude) { - return buildMatchResult(null, null); - } - - return matchSyntax(this, this.getAtrule(atruleName).prelude, prelude, false); - }, - matchAtruleDescriptor: function(atruleName, descriptorName, value) { - var error = this.checkAtruleDescriptorName(atruleName, descriptorName); - - if (error) { - return buildMatchResult(null, error); - } - - var atrule = this.getAtrule(atruleName); - var descriptor = names.keyword(descriptorName); - - return matchSyntax(this, atrule.descriptors[descriptor.name] || atrule.descriptors[descriptor.basename], value, false); - }, - matchDeclaration: function(node) { - if (node.type !== 'Declaration') { - return buildMatchResult(null, new Error('Not a Declaration node')); - } - - return this.matchProperty(node.property, node.value); - }, - matchProperty: function(propertyName, value) { - var error = this.checkPropertyName(propertyName); - - if (error) { - return buildMatchResult(null, error); - } - - return matchSyntax(this, this.getProperty(propertyName), value, true); - }, - matchType: function(typeName, value) { - var typeSyntax = this.getType(typeName); - - if (!typeSyntax) { - return buildMatchResult(null, new SyntaxReferenceError('Unknown type', typeName)); - } - - return matchSyntax(this, typeSyntax, value, false); - }, - match: function(syntax, value) { - if (typeof syntax !== 'string' && (!syntax || !syntax.type)) { - return buildMatchResult(null, new SyntaxReferenceError('Bad syntax')); - } - - if (typeof syntax === 'string' || !syntax.match) { - syntax = this.createDescriptor(syntax, 'Type', 'anonymous'); - } - - return matchSyntax(this, syntax, value, false); - }, - - findValueFragments: function(propertyName, value, type, name) { - return search.matchFragments(this, value, this.matchProperty(propertyName, value), type, name); - }, - findDeclarationValueFragments: function(declaration, type, name) { - return search.matchFragments(this, declaration.value, this.matchDeclaration(declaration), type, name); - }, - findAllFragments: function(ast, type, name) { - var result = []; - - this.syntax.walk(ast, { - visit: 'Declaration', - enter: function(declaration) { - result.push.apply(result, this.findDeclarationValueFragments(declaration, type, name)); - }.bind(this) - }); - - return result; - }, - - getAtrule: function(atruleName, fallbackBasename = true) { - var atrule = names.keyword(atruleName); - var atruleEntry = atrule.vendor && fallbackBasename - ? this.atrules[atrule.name] || this.atrules[atrule.basename] - : this.atrules[atrule.name]; - - return atruleEntry || null; - }, - getAtrulePrelude: function(atruleName, fallbackBasename = true) { - const atrule = this.getAtrule(atruleName, fallbackBasename); - - return atrule && atrule.prelude || null; - }, - getAtruleDescriptor: function(atruleName, name) { - return this.atrules.hasOwnProperty(atruleName) && this.atrules.declarators - ? this.atrules[atruleName].declarators[name] || null - : null; - }, - getProperty: function(propertyName, fallbackBasename = true) { - var property = names.property(propertyName); - var propertyEntry = property.vendor && fallbackBasename - ? this.properties[property.name] || this.properties[property.basename] - : this.properties[property.name]; - - return propertyEntry || null; - }, - getType: function(name) { - return this.types.hasOwnProperty(name) ? this.types[name] : null; - }, - - validate: function() { - function validate(syntax, name, broken, descriptor) { - if (broken.hasOwnProperty(name)) { - return broken[name]; - } - - broken[name] = false; - if (descriptor.syntax !== null) { - walk(descriptor.syntax, function(node) { - if (node.type !== 'Type' && node.type !== 'Property') { - return; - } - - var map = node.type === 'Type' ? syntax.types : syntax.properties; - var brokenMap = node.type === 'Type' ? brokenTypes : brokenProperties; - - if (!map.hasOwnProperty(node.name) || validate(syntax, node.name, brokenMap, map[node.name])) { - broken[name] = true; - } - }, this); - } - } - - var brokenTypes = {}; - var brokenProperties = {}; - - for (var key in this.types) { - validate(this, key, brokenTypes, this.types[key]); - } - - for (var key in this.properties) { - validate(this, key, brokenProperties, this.properties[key]); - } - - brokenTypes = Object.keys(brokenTypes).filter(function(name) { - return brokenTypes[name]; - }); - brokenProperties = Object.keys(brokenProperties).filter(function(name) { - return brokenProperties[name]; - }); - - if (brokenTypes.length || brokenProperties.length) { - return { - types: brokenTypes, - properties: brokenProperties - }; - } - - return null; - }, - dump: function(syntaxAsAst, pretty) { - return { - generic: this.generic, - types: dumpMapSyntax(this.types, !pretty, syntaxAsAst), - properties: dumpMapSyntax(this.properties, !pretty, syntaxAsAst), - atrules: dumpAtruleMapSyntax(this.atrules, !pretty, syntaxAsAst) - }; - }, - toString: function() { - return JSON.stringify(this.dump()); - } -}; - -module.exports = Lexer; - - -/***/ }), -/* 23 */ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -const createCustomError = __webpack_require__(17); -const generate = __webpack_require__(24); -const defaultLoc = { offset: 0, line: 1, column: 1 }; - -function locateMismatch(matchResult, node) { - const tokens = matchResult.tokens; - const longestMatch = matchResult.longestMatch; - const mismatchNode = longestMatch < tokens.length ? tokens[longestMatch].node || null : null; - const badNode = mismatchNode !== node ? mismatchNode : null; - let mismatchOffset = 0; - let mismatchLength = 0; - let entries = 0; - let css = ''; - let start; - let end; - - for (let i = 0; i < tokens.length; i++) { - const token = tokens[i].value; - - if (i === longestMatch) { - mismatchLength = token.length; - mismatchOffset = css.length; - } - - if (badNode !== null && tokens[i].node === badNode) { - if (i <= longestMatch) { - entries++; - } else { - entries = 0; - } - } - - css += token; - } - - if (longestMatch === tokens.length || entries > 1) { // last - start = fromLoc(badNode || node, 'end') || buildLoc(defaultLoc, css); - end = buildLoc(start); - } else { - start = fromLoc(badNode, 'start') || - buildLoc(fromLoc(node, 'start') || defaultLoc, css.slice(0, mismatchOffset)); - end = fromLoc(badNode, 'end') || - buildLoc(start, css.substr(mismatchOffset, mismatchLength)); - } - - return { - css, - mismatchOffset, - mismatchLength, - start, - end - }; -} - -function fromLoc(node, point) { - const value = node && node.loc && node.loc[point]; - - if (value) { - return 'line' in value ? buildLoc(value) : value; - } - - return null; -} - -function buildLoc({ offset, line, column }, extra) { - const loc = { - offset, - line, - column - }; - - if (extra) { - const lines = extra.split(/\n|\r\n?|\f/); - - loc.offset += extra.length; - loc.line += lines.length - 1; - loc.column = lines.length === 1 ? loc.column + extra.length : lines.pop().length + 1; - } - - return loc; -} - -const SyntaxReferenceError = function(type, referenceName) { - const error = createCustomError( - 'SyntaxReferenceError', - type + (referenceName ? ' `' + referenceName + '`' : '') - ); - - error.reference = referenceName; - - return error; -}; - -const SyntaxMatchError = function(message, syntax, node, matchResult) { - const error = createCustomError('SyntaxMatchError', message); - const { - css, - mismatchOffset, - mismatchLength, - start, - end - } = locateMismatch(matchResult, node); - - error.rawMessage = message; - error.syntax = syntax ? generate(syntax) : ''; - error.css = css; - error.mismatchOffset = mismatchOffset; - error.mismatchLength = mismatchLength; - error.message = message + '\n' + - ' syntax: ' + error.syntax + '\n' + - ' value: ' + (css || '') + '\n' + - ' --------' + new Array(error.mismatchOffset + 1).join('-') + '^'; - - Object.assign(error, start); - error.loc = { - source: (node && node.loc && node.loc.source) || '', - start, - end - }; - - return error; -}; - -module.exports = { - SyntaxReferenceError, - SyntaxMatchError -}; - - -/***/ }), -/* 24 */ -/***/ ((module) => { - -function noop(value) { - return value; -} - -function generateMultiplier(multiplier) { - if (multiplier.min === 0 && multiplier.max === 0) { - return '*'; - } - - if (multiplier.min === 0 && multiplier.max === 1) { - return '?'; - } - - if (multiplier.min === 1 && multiplier.max === 0) { - return multiplier.comma ? '#' : '+'; - } - - if (multiplier.min === 1 && multiplier.max === 1) { - return ''; - } - - return ( - (multiplier.comma ? '#' : '') + - (multiplier.min === multiplier.max - ? '{' + multiplier.min + '}' - : '{' + multiplier.min + ',' + (multiplier.max !== 0 ? multiplier.max : '') + '}' - ) - ); -} - -function generateTypeOpts(node) { - switch (node.type) { - case 'Range': - return ( - ' [' + - (node.min === null ? '-∞' : node.min) + - ',' + - (node.max === null ? '∞' : node.max) + - ']' - ); - - default: - throw new Error('Unknown node type `' + node.type + '`'); - } -} - -function generateSequence(node, decorate, forceBraces, compact) { - var combinator = node.combinator === ' ' || compact ? node.combinator : ' ' + node.combinator + ' '; - var result = node.terms.map(function(term) { - return generate(term, decorate, forceBraces, compact); - }).join(combinator); - - if (node.explicit || forceBraces) { - result = (compact || result[0] === ',' ? '[' : '[ ') + result + (compact ? ']' : ' ]'); - } - - return result; -} - -function generate(node, decorate, forceBraces, compact) { - var result; - - switch (node.type) { - case 'Group': - result = - generateSequence(node, decorate, forceBraces, compact) + - (node.disallowEmpty ? '!' : ''); - break; - - case 'Multiplier': - // return since node is a composition - return ( - generate(node.term, decorate, forceBraces, compact) + - decorate(generateMultiplier(node), node) - ); - - case 'Type': - result = '<' + node.name + (node.opts ? decorate(generateTypeOpts(node.opts), node.opts) : '') + '>'; - break; - - case 'Property': - result = '<\'' + node.name + '\'>'; - break; - - case 'Keyword': - result = node.name; - break; - - case 'AtKeyword': - result = '@' + node.name; - break; - - case 'Function': - result = node.name + '('; - break; - - case 'String': - case 'Token': - result = node.value; - break; - - case 'Comma': - result = ','; - break; - - default: - throw new Error('Unknown node type `' + node.type + '`'); - } - - return decorate(result, node); -} - -module.exports = function(node, options) { - var decorate = noop; - var forceBraces = false; - var compact = false; - - if (typeof options === 'function') { - decorate = options; - } else if (options) { - forceBraces = Boolean(options.forceBraces); - compact = Boolean(options.compact); - if (typeof options.decorate === 'function') { - decorate = options.decorate; - } - } - - return generate(node, decorate, forceBraces, compact); -}; - - -/***/ }), -/* 25 */ -/***/ ((module) => { - -var hasOwnProperty = Object.prototype.hasOwnProperty; -var keywords = Object.create(null); -var properties = Object.create(null); -var HYPHENMINUS = 45; // '-'.charCodeAt() - -function isCustomProperty(str, offset) { - offset = offset || 0; - - return str.length - offset >= 2 && - str.charCodeAt(offset) === HYPHENMINUS && - str.charCodeAt(offset + 1) === HYPHENMINUS; -} - -function getVendorPrefix(str, offset) { - offset = offset || 0; - - // verdor prefix should be at least 3 chars length - if (str.length - offset >= 3) { - // vendor prefix starts with hyper minus following non-hyper minus - if (str.charCodeAt(offset) === HYPHENMINUS && - str.charCodeAt(offset + 1) !== HYPHENMINUS) { - // vendor prefix should contain a hyper minus at the ending - var secondDashIndex = str.indexOf('-', offset + 2); - - if (secondDashIndex !== -1) { - return str.substring(offset, secondDashIndex + 1); - } - } - } - - return ''; -} - -function getKeywordDescriptor(keyword) { - if (hasOwnProperty.call(keywords, keyword)) { - return keywords[keyword]; - } - - var name = keyword.toLowerCase(); - - if (hasOwnProperty.call(keywords, name)) { - return keywords[keyword] = keywords[name]; - } - - var custom = isCustomProperty(name, 0); - var vendor = !custom ? getVendorPrefix(name, 0) : ''; - - return keywords[keyword] = Object.freeze({ - basename: name.substr(vendor.length), - name: name, - vendor: vendor, - prefix: vendor, - custom: custom - }); -} - -function getPropertyDescriptor(property) { - if (hasOwnProperty.call(properties, property)) { - return properties[property]; - } - - var name = property; - var hack = property[0]; - - if (hack === '/') { - hack = property[1] === '/' ? '//' : '/'; - } else if (hack !== '_' && - hack !== '*' && - hack !== '$' && - hack !== '#' && - hack !== '+' && - hack !== '&') { - hack = ''; - } - - var custom = isCustomProperty(name, hack.length); - - // re-use result when possible (the same as for lower case) - if (!custom) { - name = name.toLowerCase(); - if (hasOwnProperty.call(properties, name)) { - return properties[property] = properties[name]; - } - } - - var vendor = !custom ? getVendorPrefix(name, hack.length) : ''; - var prefix = name.substr(0, hack.length + vendor.length); - - return properties[property] = Object.freeze({ - basename: name.substr(prefix.length), - name: name.substr(hack.length), - hack: hack, - vendor: vendor, - prefix: prefix, - custom: custom - }); -} - -module.exports = { - keyword: getKeywordDescriptor, - property: getPropertyDescriptor, - isCustomProperty: isCustomProperty, - vendorPrefix: getVendorPrefix -}; - - -/***/ }), -/* 26 */ -/***/ ((module, __unused_webpack_exports, __webpack_require__) => { - -var tokenizer = __webpack_require__(27); -var isIdentifierStart = tokenizer.isIdentifierStart; -var isHexDigit = tokenizer.isHexDigit; -var isDigit = tokenizer.isDigit; -var cmpStr = tokenizer.cmpStr; -var consumeNumber = tokenizer.consumeNumber; -var TYPE = tokenizer.TYPE; -var anPlusB = __webpack_require__(29); -var urange = __webpack_require__(30); - -var cssWideKeywords = ['unset', 'initial', 'inherit']; -var calcFunctionNames = ['calc(', '-moz-calc(', '-webkit-calc(']; - -// https://www.w3.org/TR/css-values-3/#lengths -var LENGTH = { - // absolute length units - 'px': true, - 'mm': true, - 'cm': true, - 'in': true, - 'pt': true, - 'pc': true, - 'q': true, - - // relative length units - 'em': true, - 'ex': true, - 'ch': true, - 'rem': true, - - // viewport-percentage lengths - 'vh': true, - 'vw': true, - 'vmin': true, - 'vmax': true, - 'vm': true -}; - -var ANGLE = { - 'deg': true, - 'grad': true, - 'rad': true, - 'turn': true -}; - -var TIME = { - 's': true, - 'ms': true -}; - -var FREQUENCY = { - 'hz': true, - 'khz': true -}; - -// https://www.w3.org/TR/css-values-3/#resolution (https://drafts.csswg.org/css-values/#resolution) -var RESOLUTION = { - 'dpi': true, - 'dpcm': true, - 'dppx': true, - 'x': true // https://github.com/w3c/csswg-drafts/issues/461 -}; - -// https://drafts.csswg.org/css-grid/#fr-unit -var FLEX = { - 'fr': true -}; - -// https://www.w3.org/TR/css3-speech/#mixing-props-voice-volume -var DECIBEL = { - 'db': true -}; - -// https://www.w3.org/TR/css3-speech/#voice-props-voice-pitch -var SEMITONES = { - 'st': true -}; - -// safe char code getter -function charCode(str, index) { - return index < str.length ? str.charCodeAt(index) : 0; -} - -function eqStr(actual, expected) { - return cmpStr(actual, 0, actual.length, expected); -} - -function eqStrAny(actual, expected) { - for (var i = 0; i < expected.length; i++) { - if (eqStr(actual, expected[i])) { - return true; - } - } - - return false; -} - -// IE postfix hack, i.e. 123\0 or 123px\9 -function isPostfixIeHack(str, offset) { - if (offset !== str.length - 2) { - return false; - } - - return ( - str.charCodeAt(offset) === 0x005C && // U+005C REVERSE SOLIDUS (\) - isDigit(str.charCodeAt(offset + 1)) - ); -} - -function outOfRange(opts, value, numEnd) { - if (opts && opts.type === 'Range') { - var num = Number( - numEnd !== undefined && numEnd !== value.length - ? value.substr(0, numEnd) - : value - ); - - if (isNaN(num)) { - return true; - } - - if (opts.min !== null && num < opts.min) { - return true; - } - - if (opts.max !== null && num > opts.max) { - return true; - } - } - - return false; -} - -function consumeFunction(token, getNextToken) { - var startIdx = token.index; - var length = 0; - - // balanced token consuming - do { - length++; - - if (token.balance <= startIdx) { - break; - } - } while (token = getNextToken(length)); - - return length; -} - -// TODO: implement -// can be used wherever , , ,