diff options
| author | Adam Mathes <adam@adammathes.com> | 2026-02-14 14:46:37 -0800 |
|---|---|---|
| committer | Adam Mathes <adam@adammathes.com> | 2026-02-14 14:46:37 -0800 |
| commit | afa87af01c79a9baa539f2992d32154d2a4739bd (patch) | |
| tree | 92c7416db734270a2fee1d72ee9cc119379ff8e1 /vanilla/node_modules/css-tree/lib/utils | |
| parent | 3b927e84d200402281f68181cd4253bc77e5528d (diff) | |
| download | neko-afa87af01c79a9baa539f2992d32154d2a4739bd.tar.gz neko-afa87af01c79a9baa539f2992d32154d2a4739bd.tar.bz2 neko-afa87af01c79a9baa539f2992d32154d2a4739bd.zip | |
task: delete vanilla js prototype\n\n- Removed vanilla/ directory and web/dist/vanilla directory\n- Updated Makefile, Dockerfile, and CI workflow to remove vanilla references\n- Cleaned up web/web.go to remove vanilla embed and routes\n- Verified build and tests pass\n\nCloses NK-2tcnmq
Diffstat (limited to 'vanilla/node_modules/css-tree/lib/utils')
| -rw-r--r-- | vanilla/node_modules/css-tree/lib/utils/List.js | 469 | ||||
| -rw-r--r-- | vanilla/node_modules/css-tree/lib/utils/clone.js | 21 | ||||
| -rw-r--r-- | vanilla/node_modules/css-tree/lib/utils/create-custom-error.js | 14 | ||||
| -rw-r--r-- | vanilla/node_modules/css-tree/lib/utils/ident.js | 101 | ||||
| -rw-r--r-- | vanilla/node_modules/css-tree/lib/utils/index.js | 6 | ||||
| -rw-r--r-- | vanilla/node_modules/css-tree/lib/utils/names.js | 106 | ||||
| -rw-r--r-- | vanilla/node_modules/css-tree/lib/utils/string.js | 99 | ||||
| -rw-r--r-- | vanilla/node_modules/css-tree/lib/utils/url.js | 108 |
8 files changed, 0 insertions, 924 deletions
diff --git a/vanilla/node_modules/css-tree/lib/utils/List.js b/vanilla/node_modules/css-tree/lib/utils/List.js deleted file mode 100644 index 8953264..0000000 --- a/vanilla/node_modules/css-tree/lib/utils/List.js +++ /dev/null @@ -1,469 +0,0 @@ -// -// list -// ┌──────┐ -// ┌──────────────┼─head │ -// │ │ tail─┼──────────────┐ -// │ └──────┘ │ -// ▼ ▼ -// item item item item -// ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ -// null ◀──┼─prev │◀───┼─prev │◀───┼─prev │◀───┼─prev │ -// │ next─┼───▶│ next─┼───▶│ next─┼───▶│ next─┼──▶ null -// ├──────┤ ├──────┤ ├──────┤ ├──────┤ -// │ data │ │ data │ │ data │ │ data │ -// └──────┘ └──────┘ └──────┘ └──────┘ -// - -let releasedCursors = null; - -export class List { - static createItem(data) { - return { - prev: null, - next: null, - data - }; - } - - constructor() { - this.head = null; - this.tail = null; - this.cursor = null; - } - createItem(data) { - return List.createItem(data); - } - - // cursor helpers - allocateCursor(prev, next) { - let cursor; - - if (releasedCursors !== null) { - cursor = releasedCursors; - releasedCursors = releasedCursors.cursor; - cursor.prev = prev; - cursor.next = next; - cursor.cursor = this.cursor; - } else { - cursor = { - prev, - next, - cursor: this.cursor - }; - } - - this.cursor = cursor; - - return cursor; - } - releaseCursor() { - const { cursor } = this; - - this.cursor = cursor.cursor; - cursor.prev = null; - cursor.next = null; - cursor.cursor = releasedCursors; - releasedCursors = cursor; - } - updateCursors(prevOld, prevNew, nextOld, nextNew) { - let { cursor } = this; - - while (cursor !== null) { - if (cursor.prev === prevOld) { - cursor.prev = prevNew; - } - - if (cursor.next === nextOld) { - cursor.next = nextNew; - } - - cursor = cursor.cursor; - } - } - *[Symbol.iterator]() { - for (let cursor = this.head; cursor !== null; cursor = cursor.next) { - yield cursor.data; - } - } - - // getters - get size() { - let size = 0; - - for (let cursor = this.head; cursor !== null; cursor = cursor.next) { - size++; - } - - return size; - } - get isEmpty() { - return this.head === null; - } - get first() { - return this.head && this.head.data; - } - get last() { - return this.tail && this.tail.data; - } - - // convertors - fromArray(array) { - let cursor = null; - this.head = null; - - for (let data of array) { - const item = List.createItem(data); - - if (cursor !== null) { - cursor.next = item; - } else { - this.head = item; - } - - item.prev = cursor; - cursor = item; - } - - this.tail = cursor; - return this; - } - toArray() { - return [...this]; - } - toJSON() { - return [...this]; - } - - // array-like methods - forEach(fn, thisArg = this) { - // push cursor - const cursor = this.allocateCursor(null, this.head); - - while (cursor.next !== null) { - const item = cursor.next; - cursor.next = item.next; - fn.call(thisArg, item.data, item, this); - } - - // pop cursor - this.releaseCursor(); - } - forEachRight(fn, thisArg = this) { - // push cursor - const cursor = this.allocateCursor(this.tail, null); - - while (cursor.prev !== null) { - const item = cursor.prev; - cursor.prev = item.prev; - fn.call(thisArg, item.data, item, this); - } - - // pop cursor - this.releaseCursor(); - } - reduce(fn, initialValue, thisArg = this) { - // push cursor - let cursor = this.allocateCursor(null, this.head); - let acc = initialValue; - let item; - - while (cursor.next !== null) { - item = cursor.next; - cursor.next = item.next; - - acc = fn.call(thisArg, acc, item.data, item, this); - } - - // pop cursor - this.releaseCursor(); - - return acc; - } - reduceRight(fn, initialValue, thisArg = this) { - // push cursor - let cursor = this.allocateCursor(this.tail, null); - let acc = initialValue; - let item; - - while (cursor.prev !== null) { - item = cursor.prev; - cursor.prev = item.prev; - - acc = fn.call(thisArg, acc, item.data, item, this); - } - - // pop cursor - this.releaseCursor(); - - return acc; - } - some(fn, thisArg = this) { - for (let cursor = this.head; cursor !== null; cursor = cursor.next) { - if (fn.call(thisArg, cursor.data, cursor, this)) { - return true; - } - } - - return false; - } - map(fn, thisArg = this) { - const result = new List(); - - for (let cursor = this.head; cursor !== null; cursor = cursor.next) { - result.appendData(fn.call(thisArg, cursor.data, cursor, this)); - } - - return result; - } - filter(fn, thisArg = this) { - const result = new List(); - - for (let cursor = this.head; cursor !== null; cursor = cursor.next) { - if (fn.call(thisArg, cursor.data, cursor, this)) { - result.appendData(cursor.data); - } - } - - return result; - } - - nextUntil(start, fn, thisArg = this) { - if (start === null) { - return; - } - - // push cursor - const cursor = this.allocateCursor(null, start); - - while (cursor.next !== null) { - const item = cursor.next; - cursor.next = item.next; - if (fn.call(thisArg, item.data, item, this)) { - break; - } - } - - // pop cursor - this.releaseCursor(); - } - prevUntil(start, fn, thisArg = this) { - if (start === null) { - return; - } - - // push cursor - const cursor = this.allocateCursor(start, null); - - while (cursor.prev !== null) { - const item = cursor.prev; - cursor.prev = item.prev; - if (fn.call(thisArg, item.data, item, this)) { - break; - } - } - - // pop cursor - this.releaseCursor(); - } - - // mutation - clear() { - this.head = null; - this.tail = null; - } - copy() { - const result = new List(); - - for (let data of this) { - result.appendData(data); - } - - return result; - } - prepend(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; - } - prependData(data) { - return this.prepend(List.createItem(data)); - } - append(item) { - return this.insert(item); - } - appendData(data) { - return this.insert(List.createItem(data)); - } - insert(item, before = null) { - if (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; - } - insertData(data, before) { - return this.insert(List.createItem(data), before); - } - remove(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; - } - push(data) { - this.insert(List.createItem(data)); - } - pop() { - return this.tail !== null ? this.remove(this.tail) : null; - } - unshift(data) { - this.prepend(List.createItem(data)); - } - shift() { - return this.head !== null ? this.remove(this.head) : null; - } - prependList(list) { - return this.insertList(list, this.head); - } - appendList(list) { - return this.insertList(list); - } - insertList(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; - } - replace(oldItem, newItemOrList) { - if ('head' in newItemOrList) { - this.insertList(newItemOrList, oldItem); - } else { - this.insert(newItemOrList, oldItem); - } - - this.remove(oldItem); - } -} diff --git a/vanilla/node_modules/css-tree/lib/utils/clone.js b/vanilla/node_modules/css-tree/lib/utils/clone.js deleted file mode 100644 index 84819c0..0000000 --- a/vanilla/node_modules/css-tree/lib/utils/clone.js +++ /dev/null @@ -1,21 +0,0 @@ -import { List } from './List.js'; - -export function clone(node) { - const result = {}; - - for (const key of Object.keys(node)) { - let value = node[key]; - - if (value) { - if (Array.isArray(value) || value instanceof List) { - value = value.map(clone); - } else if (value.constructor === Object) { - value = clone(value); - } - } - - result[key] = value; - } - - return result; -} diff --git a/vanilla/node_modules/css-tree/lib/utils/create-custom-error.js b/vanilla/node_modules/css-tree/lib/utils/create-custom-error.js deleted file mode 100644 index dba122f..0000000 --- a/vanilla/node_modules/css-tree/lib/utils/create-custom-error.js +++ /dev/null @@ -1,14 +0,0 @@ -export function createCustomError(name, message) { - // use Object.create(), because some VMs prevent setting line/column otherwise - // (iOS Safari 10 even throws an exception) - const error = Object.create(SyntaxError.prototype); - const errorStack = new Error(); - - return Object.assign(error, { - name, - message, - get stack() { - return (errorStack.stack || '').replace(/^(.+\n){1,3}/, `${name}: ${message}\n`); - } - }); -}; diff --git a/vanilla/node_modules/css-tree/lib/utils/ident.js b/vanilla/node_modules/css-tree/lib/utils/ident.js deleted file mode 100644 index 9cbe0f8..0000000 --- a/vanilla/node_modules/css-tree/lib/utils/ident.js +++ /dev/null @@ -1,101 +0,0 @@ -import { - isName, - isValidEscape, - consumeEscaped, - decodeEscaped -} from '../tokenizer/index.js'; - -const REVERSE_SOLIDUS = 0x005c; // U+005C REVERSE SOLIDUS (\) - -export function decode(str) { - const end = str.length - 1; - let decoded = ''; - - for (let i = 0; i < str.length; i++) { - let code = str.charCodeAt(i); - - if (code === REVERSE_SOLIDUS) { - // special case at the ending - if (i === end) { - // if the next input code point is EOF, do nothing - break; - } - - code = str.charCodeAt(++i); - - // consume escaped - if (isValidEscape(REVERSE_SOLIDUS, code)) { - const escapeStart = i - 1; - const escapeEnd = consumeEscaped(str, escapeStart); - - i = escapeEnd - 1; - decoded += decodeEscaped(str.substring(escapeStart + 1, escapeEnd)); - } else { - // \r\n - if (code === 0x000d && str.charCodeAt(i + 1) === 0x000a) { - i++; - } - } - } else { - decoded += str[i]; - } - } - - return decoded; -} - -// https://drafts.csswg.org/cssom/#serialize-an-identifier -// § 2.1. Common Serializing Idioms -export function encode(str) { - let encoded = ''; - - // If the character is the first character and is a "-" (U+002D), - // and there is no second character, then the escaped character. - // Note: That's means a single dash string "-" return as escaped dash, - // so move the condition out of the main loop - if (str.length === 1 && str.charCodeAt(0) === 0x002D) { - return '\\-'; - } - - // To serialize an identifier means to create a string represented - // by the concatenation of, for each character of the identifier: - for (let i = 0; i < str.length; i++) { - const code = str.charCodeAt(i); - - // If the character is NULL (U+0000), then the REPLACEMENT CHARACTER (U+FFFD). - if (code === 0x0000) { - encoded += '\uFFFD'; - continue; - } - - if ( - // If the character is in the range [\1-\1f] (U+0001 to U+001F) or is U+007F ... - // Note: Do not compare with 0x0001 since 0x0000 is precessed before - code <= 0x001F || code === 0x007F || - // [or] ... is in the range [0-9] (U+0030 to U+0039), - (code >= 0x0030 && code <= 0x0039 && ( - // If the character is the first character ... - i === 0 || - // If the character is the second character ... and the first character is a "-" (U+002D) - i === 1 && str.charCodeAt(0) === 0x002D - )) - ) { - // ... then the character escaped as code point. - encoded += '\\' + code.toString(16) + ' '; - continue; - } - - // If the character is not handled by one of the above rules and is greater - // than or equal to U+0080, is "-" (U+002D) or "_" (U+005F), or is in one - // of the ranges [0-9] (U+0030 to U+0039), [A-Z] (U+0041 to U+005A), - // or \[a-z] (U+0061 to U+007A), then the character itself. - if (isName(code)) { - encoded += str.charAt(i); - } else { - // Otherwise, the escaped character. - encoded += '\\' + str.charAt(i); - } - } - - return encoded; -} diff --git a/vanilla/node_modules/css-tree/lib/utils/index.js b/vanilla/node_modules/css-tree/lib/utils/index.js deleted file mode 100644 index 07bf0f9..0000000 --- a/vanilla/node_modules/css-tree/lib/utils/index.js +++ /dev/null @@ -1,6 +0,0 @@ -export * from './clone.js'; -export * as ident from './ident.js'; -export * from './List.js'; -export * from './names.js'; -export * as string from './string.js'; -export * as url from './url.js'; diff --git a/vanilla/node_modules/css-tree/lib/utils/names.js b/vanilla/node_modules/css-tree/lib/utils/names.js deleted file mode 100644 index b4f74b9..0000000 --- a/vanilla/node_modules/css-tree/lib/utils/names.js +++ /dev/null @@ -1,106 +0,0 @@ -const keywords = new Map(); -const properties = new Map(); -const HYPHENMINUS = 45; // '-'.charCodeAt() - -export const keyword = getKeywordDescriptor; -export const property = getPropertyDescriptor; -export const vendorPrefix = getVendorPrefix; -export 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 - const secondDashIndex = str.indexOf('-', offset + 2); - - if (secondDashIndex !== -1) { - return str.substring(offset, secondDashIndex + 1); - } - } - } - - return ''; -} - -function getKeywordDescriptor(keyword) { - if (keywords.has(keyword)) { - return keywords.get(keyword); - } - - const name = keyword.toLowerCase(); - let descriptor = keywords.get(name); - - if (descriptor === undefined) { - const custom = isCustomProperty(name, 0); - const vendor = !custom ? getVendorPrefix(name, 0) : ''; - descriptor = Object.freeze({ - basename: name.substr(vendor.length), - name, - prefix: vendor, - vendor, - custom - }); - } - - keywords.set(keyword, descriptor); - - return descriptor; -} - -function getPropertyDescriptor(property) { - if (properties.has(property)) { - return properties.get(property); - } - - let name = property; - let hack = property[0]; - - if (hack === '/') { - hack = property[1] === '/' ? '//' : '/'; - } else if (hack !== '_' && - hack !== '*' && - hack !== '$' && - hack !== '#' && - hack !== '+' && - hack !== '&') { - hack = ''; - } - - const custom = isCustomProperty(name, hack.length); - - // re-use result when possible (the same as for lower case) - if (!custom) { - name = name.toLowerCase(); - if (properties.has(name)) { - const descriptor = properties.get(name); - properties.set(property, descriptor); - return descriptor; - } - } - - const vendor = !custom ? getVendorPrefix(name, hack.length) : ''; - const prefix = name.substr(0, hack.length + vendor.length); - const descriptor = Object.freeze({ - basename: name.substr(prefix.length), - name: name.substr(hack.length), - hack, - vendor, - prefix, - custom - }); - - properties.set(property, descriptor); - - return descriptor; -} diff --git a/vanilla/node_modules/css-tree/lib/utils/string.js b/vanilla/node_modules/css-tree/lib/utils/string.js deleted file mode 100644 index 928a85b..0000000 --- a/vanilla/node_modules/css-tree/lib/utils/string.js +++ /dev/null @@ -1,99 +0,0 @@ -import { - isHexDigit, - isWhiteSpace, - isValidEscape, - consumeEscaped, - decodeEscaped -} from '../tokenizer/index.js'; - -const REVERSE_SOLIDUS = 0x005c; // U+005C REVERSE SOLIDUS (\) -const QUOTATION_MARK = 0x0022; // " -const APOSTROPHE = 0x0027; // ' - -export function decode(str) { - const len = str.length; - const firstChar = str.charCodeAt(0); - const start = firstChar === QUOTATION_MARK || firstChar === APOSTROPHE ? 1 : 0; - const end = start === 1 && len > 1 && str.charCodeAt(len - 1) === firstChar ? len - 2 : len - 1; - let decoded = ''; - - for (let i = start; i <= end; i++) { - let code = str.charCodeAt(i); - - if (code === REVERSE_SOLIDUS) { - // special case at the ending - if (i === end) { - // if the next input code point is EOF, do nothing - // otherwise include last quote as escaped - if (i !== len - 1) { - decoded = str.substr(i + 1); - } - break; - } - - code = str.charCodeAt(++i); - - // consume escaped - if (isValidEscape(REVERSE_SOLIDUS, code)) { - const escapeStart = i - 1; - const escapeEnd = consumeEscaped(str, escapeStart); - - i = escapeEnd - 1; - decoded += decodeEscaped(str.substring(escapeStart + 1, escapeEnd)); - } else { - // \r\n - if (code === 0x000d && str.charCodeAt(i + 1) === 0x000a) { - i++; - } - } - } else { - decoded += str[i]; - } - } - - return decoded; -} - -// https://drafts.csswg.org/cssom/#serialize-a-string -// § 2.1. Common Serializing Idioms -export function encode(str, apostrophe) { - const quote = apostrophe ? '\'' : '"'; - const quoteCode = apostrophe ? APOSTROPHE : QUOTATION_MARK; - let encoded = ''; - let wsBeforeHexIsNeeded = false; - - for (let i = 0; i < str.length; i++) { - const code = str.charCodeAt(i); - - // If the character is NULL (U+0000), then the REPLACEMENT CHARACTER (U+FFFD). - if (code === 0x0000) { - encoded += '\uFFFD'; - continue; - } - - // If the character is in the range [\1-\1f] (U+0001 to U+001F) or is U+007F, - // the character escaped as code point. - // Note: Do not compare with 0x0001 since 0x0000 is precessed before - if (code <= 0x001f || code === 0x007F) { - encoded += '\\' + code.toString(16); - wsBeforeHexIsNeeded = true; - continue; - } - - // If the character is '"' (U+0022) or "\" (U+005C), the escaped character. - if (code === quoteCode || code === REVERSE_SOLIDUS) { - encoded += '\\' + str.charAt(i); - wsBeforeHexIsNeeded = false; - } else { - if (wsBeforeHexIsNeeded && (isHexDigit(code) || isWhiteSpace(code))) { - encoded += ' '; - } - - // Otherwise, the character itself. - encoded += str.charAt(i); - wsBeforeHexIsNeeded = false; - } - } - - return quote + encoded + quote; -} diff --git a/vanilla/node_modules/css-tree/lib/utils/url.js b/vanilla/node_modules/css-tree/lib/utils/url.js deleted file mode 100644 index cce5709..0000000 --- a/vanilla/node_modules/css-tree/lib/utils/url.js +++ /dev/null @@ -1,108 +0,0 @@ -import { - isHexDigit, - isWhiteSpace, - isValidEscape, - consumeEscaped, - decodeEscaped -} from '../tokenizer/index.js'; - -const SPACE = 0x0020; // U+0020 SPACE -const REVERSE_SOLIDUS = 0x005c; // U+005C REVERSE SOLIDUS (\) -const QUOTATION_MARK = 0x0022; // " -const APOSTROPHE = 0x0027; // ' -const LEFTPARENTHESIS = 0x0028; // U+0028 LEFT PARENTHESIS (() -const RIGHTPARENTHESIS = 0x0029; // U+0029 RIGHT PARENTHESIS ()) - -export function decode(str) { - const len = str.length; - let start = 4; // length of "url(" - let end = str.charCodeAt(len - 1) === RIGHTPARENTHESIS ? len - 2 : len - 1; - let decoded = ''; - - while (start < end && isWhiteSpace(str.charCodeAt(start))) { - start++; - } - - while (start < end && isWhiteSpace(str.charCodeAt(end))) { - end--; - } - - for (let i = start; i <= end; i++) { - let code = str.charCodeAt(i); - - if (code === REVERSE_SOLIDUS) { - // special case at the ending - if (i === end) { - // if the next input code point is EOF, do nothing - // otherwise include last left parenthesis as escaped - if (i !== len - 1) { - decoded = str.substr(i + 1); - } - break; - } - - code = str.charCodeAt(++i); - - // consume escaped - if (isValidEscape(REVERSE_SOLIDUS, code)) { - const escapeStart = i - 1; - const escapeEnd = consumeEscaped(str, escapeStart); - - i = escapeEnd - 1; - decoded += decodeEscaped(str.substring(escapeStart + 1, escapeEnd)); - } else { - // \r\n - if (code === 0x000d && str.charCodeAt(i + 1) === 0x000a) { - i++; - } - } - } else { - decoded += str[i]; - } - } - - return decoded; -} - -export function encode(str) { - let encoded = ''; - let wsBeforeHexIsNeeded = false; - - for (let i = 0; i < str.length; i++) { - const code = str.charCodeAt(i); - - // If the character is NULL (U+0000), then the REPLACEMENT CHARACTER (U+FFFD). - if (code === 0x0000) { - encoded += '\uFFFD'; - continue; - } - - // If the character is in the range [\1-\1f] (U+0001 to U+001F) or is U+007F, - // the character escaped as code point. - // Note: Do not compare with 0x0001 since 0x0000 is precessed before - if (code <= 0x001f || code === 0x007F) { - encoded += '\\' + code.toString(16); - wsBeforeHexIsNeeded = true; - continue; - } - - if (code === SPACE || - code === REVERSE_SOLIDUS || - code === QUOTATION_MARK || - code === APOSTROPHE || - code === LEFTPARENTHESIS || - code === RIGHTPARENTHESIS) { - encoded += '\\' + str.charAt(i); - wsBeforeHexIsNeeded = false; - } else { - if (wsBeforeHexIsNeeded && isHexDigit(code)) { - encoded += ' '; - } - - encoded += str.charAt(i); - wsBeforeHexIsNeeded = false; - } - } - - return 'url(' + encoded + ')'; -} |
