diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000000..98897c5740 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,18 @@ +name: CI +on: [push, pull_request] +jobs: + Tests: + runs-on: ${{ matrix.os }} + strategy: + matrix: + node-version: [8, 10, 12] + os: [ubuntu-latest, windows-latest, macOS-latest] + steps: + - run: git config --global core.autocrlf false + - uses: actions/checkout@v1 + - uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - run: 'npm i && npm test' + env: + CI: true diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index a4603a26e2..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,20 +0,0 @@ -language: node_js -node_js: - - "8" - - "10" - - "12" -env: - global: - - BUILD_TIMEOUT=20000 - -addons: - apt: - packages: - - xvfb - -install: - - export DISPLAY=':99.0' - - Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & - - npm ci || npm install - -after_success: npm run codecov diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b26b26bbe..51e1e49cba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,16 @@ # Svelte changelog +## Unreleased + +* Fix edge cases in matching selectors against elements ([#1710](https://github.com/sveltejs/svelte/issues/1710)) + +## 3.12.1 + +* Escape `@` symbols in props, again ([#3545](https://github.com/sveltejs/svelte/issues/3545)) + ## 3.12.0 -* Fire events on `document` in development to facilitate dev tooling ([#3005](https://github.com/sveltejs/svelte/pull/3005)]) +* Fire events on `document` in development to facilitate dev tooling ([#3005](https://github.com/sveltejs/svelte/pull/3005)) ## 3.11.0 diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 23a3ac3505..0000000000 --- a/appveyor.yml +++ /dev/null @@ -1,31 +0,0 @@ -# http://www.appveyor.com/docs/appveyor-yml - -version: "{build}" - -clone_depth: 10 - -init: - - git config --global core.autocrlf false - -environment: - matrix: - - nodejs_version: 8 - - nodejs_version: 10 - - nodejs_version: 12 - -install: - - ps: Update-NodeJsInstallation (Get-NodeJsLatestBuild $env:nodejs_version) - - npm ci || npm install - -build: off - -test_script: - - node --version && npm --version - - npm test - -matrix: - fast_finish: false - -# cache: -# - C:\Users\appveyor\AppData\Roaming\npm-cache -> package.json # npm cache -# - node_modules -> package.json # local npm modules diff --git a/package-lock.json b/package-lock.json index 161b540971..88c3353c22 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.12.0", + "version": "3.12.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -203,25 +203,13 @@ "dev": true }, "agadoo": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/agadoo/-/agadoo-1.0.1.tgz", - "integrity": "sha512-rEOSqXQ3ABoxmgvxqEvUfS7mcMJBqRhcMbmJq4j+EpCXN0P1cFHYQT66V7rYSu0C+3jialSk58yHTBqzY0m+Sw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/agadoo/-/agadoo-1.1.0.tgz", + "integrity": "sha512-MiTXQ3As5jARRXa0eZF+ObtzsseQurCXOc1RB19NOGDsimEvoT8DB8iQiC0zAGTfsF/nBhzEle+eV9UpXyWnbw==", "dev": true, "requires": { - "rollup": "^0.64.1", + "rollup": "^1", "rollup-plugin-virtual": "^1.0.1" - }, - "dependencies": { - "rollup": { - "version": "0.64.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-0.64.1.tgz", - "integrity": "sha512-+ThdVXrvonJdOTzyybMBipP0uz605Z8AnzWVY3rf+cSGnLO7uNkJBlN+9jXqWOomkvumXfm/esmBpA5d53qm7g==", - "dev": true, - "requires": { - "@types/estree": "0.0.39", - "@types/node": "*" - } - } } }, "agent-base": { @@ -3074,26 +3062,20 @@ } }, "rollup": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.20.3.tgz", - "integrity": "sha512-/OMCkY0c6E8tleeVm4vQVDz24CkVgvueK3r8zTYu2AQNpjrcaPwO9hE+pWj5LTFrvvkaxt4MYIp2zha4y0lRvg==", + "version": "1.21.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.21.4.tgz", + "integrity": "sha512-Pl512XVCmVzgcBz5h/3Li4oTaoDcmpuFZ+kdhS/wLreALz//WuDAMfomD3QEYl84NkDu6Z6wV9twlcREb4qQsw==", "dev": true, "requires": { "@types/estree": "0.0.39", - "@types/node": "^12.7.2", + "@types/node": "^12.7.5", "acorn": "^7.0.0" }, "dependencies": { "@types/node": { - "version": "12.7.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.4.tgz", - "integrity": "sha512-W0+n1Y+gK/8G2P/piTkBBN38Qc5Q1ZSO6B5H3QmPCUewaiXOo2GCAWZ4ElZCcNhjJuBSUSLGFUJnmlCn5+nxOQ==", - "dev": true - }, - "acorn": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.0.0.tgz", - "integrity": "sha512-PaF/MduxijYYt7unVGRuds1vBC9bFxbNf+VWqhOClfdgy7RlVkQqt610ig1/yxTgsDIfW1cWDel5EBbOy3jdtQ==", + "version": "12.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.5.tgz", + "integrity": "sha512-9fq4jZVhPNW8r+UYKnxF1e2HkDWOWKM5bC2/7c9wPV835I0aOrVbS/Hw/pWPk2uKrNXQqg9Z959Kz+IYDd5p3w==", "dev": true } } diff --git a/package.json b/package.json index 90b926dd52..c103604e4a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.12.0", + "version": "3.12.1", "description": "Cybernetically enhanced web apps", "module": "index.mjs", "main": "index", @@ -61,7 +61,7 @@ "@typescript-eslint/eslint-plugin": "^1.13.0", "@typescript-eslint/parser": "^2.1.0", "acorn": "^7.0.0", - "agadoo": "^1.0.1", + "agadoo": "^1.1.0", "c8": "^5.0.1", "code-red": "0.0.15", "codecov": "^3.5.0", @@ -77,7 +77,7 @@ "magic-string": "^0.25.3", "mocha": "^6.2.0", "puppeteer": "^1.19.0", - "rollup": "^1.20.3", + "rollup": "^1.21.4", "rollup-plugin-commonjs": "^10.1.0", "rollup-plugin-json": "^4.0.0", "rollup-plugin-node-resolve": "^5.2.0", diff --git a/site/content/docs/03-run-time.md b/site/content/docs/03-run-time.md index 976e78cea5..8e56f4ce59 100644 --- a/site/content/docs/03-run-time.md +++ b/site/content/docs/03-run-time.md @@ -696,7 +696,7 @@ out:draw={params} Animates the stroke of an SVG element, like a snake in a tube. `in` transitions begin with the path invisible and draw the path to the screen over time. `out` transitions start in a visible state and gradually erase the path. `draw` only works with elements that have a `getTotalLength` method, like `` and ``. -`scale` accepts the following parameters: +`draw` accepts the following parameters: * `delay` (`number`, default 0) — milliseconds before starting * `speed` (`number`, default undefined) - the speed of the animation, see below. diff --git a/site/content/docs/04-compile-time.md b/site/content/docs/04-compile-time.md index f47fe564af..c6675e8a0b 100644 --- a/site/content/docs/04-compile-time.md +++ b/site/content/docs/04-compile-time.md @@ -315,7 +315,7 @@ walk(ast: Node, { --- -The `walk` function provides a way to walk to abstract syntax trees generated by the parser, using the compiler's own built-in instance of [estree-walker](https://github.com/Rich-Harris/estree-walker). +The `walk` function provides a way to walk the abstract syntax trees generated by the parser, using the compiler's own built-in instance of [estree-walker](https://github.com/Rich-Harris/estree-walker). The walker takes an abstract syntax tree to walk and an object with two optional methods: `enter` and `leave`. For each node, `enter` is called (if present). Then, unless `this.skip()` is called during `enter`, each of the children are traversed, and then `leave` is called on the node. diff --git a/site/content/examples/10-animations/00-animate/App.svelte b/site/content/examples/10-animations/00-animate/App.svelte index faba1dd062..279821491b 100644 --- a/site/content/examples/10-animations/00-animate/App.svelte +++ b/site/content/examples/10-animations/00-animate/App.svelte @@ -109,7 +109,11 @@
- +

todo

diff --git a/site/content/tutorial/04-logic/05-keyed-each-blocks/text.md b/site/content/tutorial/04-logic/05-keyed-each-blocks/text.md index 3e45abfe3a..4affb89cd6 100644 --- a/site/content/tutorial/04-logic/05-keyed-each-blocks/text.md +++ b/site/content/tutorial/04-logic/05-keyed-each-blocks/text.md @@ -4,13 +4,13 @@ title: Keyed each blocks By default, when you modify the value of an `each` block, it will add and remove items at the *end* of the block, and update any values that have changed. That might not be what you want. -It's easier to show why than to explain. Click the 'Remove first thing' button a few times, and notice that it's removing `` components from the end and updating the `value` for those that remain. Instead, we'd like to remove the first `` component and leave the rest unaffected. +It's easier to show why than to explain. Click the 'Remove first thing' button a few times, and notice that it's removing `` components from the end and updating the `color` for those that remain. Instead, we'd like to remove the first `` component and leave the rest unaffected. To do that, we specify a unique identifier for the `each` block: ```html {#each things as thing (thing.id)} - + {/each} ``` diff --git a/site/package-lock.json b/site/package-lock.json index 8ea70282b9..189068b42d 100644 --- a/site/package-lock.json +++ b/site/package-lock.json @@ -1261,9 +1261,9 @@ "integrity": "sha512-ym6ooqMr09+cV+y52p5kszJ0jYcX+nJfm8POrQb7QYowvpPPuneZ71EclHrQSB7a50lcytgR/xtL6AUFdvyEkg==" }, "@polka/send": { - "version": "1.0.0-next.3", - "resolved": "https://registry.npmjs.org/@polka/send/-/send-1.0.0-next.3.tgz", - "integrity": "sha512-54ftOGSZQMx8Xh8pnPgAj4499wppAEHQ892A7WacYOJ7ySuCWVgFmpODmXC2hU7qD9Scbi0iAu8rZls3ld+Eyg==" + "version": "1.0.0-next.6", + "resolved": "https://registry.npmjs.org/@polka/send/-/send-1.0.0-next.6.tgz", + "integrity": "sha512-4ON4Yf/QcP9I6HmFvn8rspRdBQ6NupSkUvAkUKo4gT2SSSWrrHMqDVQJsvDr4BRGRIVZSg+gr6W3M9Xj3V3JSQ==" }, "@polka/url": { "version": "1.0.0-next.3", @@ -3119,12 +3119,12 @@ "dev": true }, "polka": { - "version": "1.0.0-next.4", - "resolved": "https://registry.npmjs.org/polka/-/polka-1.0.0-next.4.tgz", - "integrity": "sha512-14UAMEVp6UjRepYIjJ/KZcFD0wD4TpDqBGmdgeg5SmhmBHBFR2LdTTXxx/y7GPa4537ZcK28Nsld+hynBE/qDw==", + "version": "1.0.0-next.6", + "resolved": "https://registry.npmjs.org/polka/-/polka-1.0.0-next.6.tgz", + "integrity": "sha512-e3vZm2cMmPPrgn+0J5DO0rrSTfsCHGyh+YS6jjrqYP8BHJkPq8nCVSDxHkaiEN4f0c2dtR6FB+snDmLE/sRz7A==", "requires": { "@polka/url": "^1.0.0-next.3", - "trouter": "^3.0.2" + "trouter": "^3.1.0" } }, "postgres-array": { @@ -3342,9 +3342,9 @@ } }, "rollup": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.21.0.tgz", - "integrity": "sha512-FDIPkcIdLg7262zzqteTWNr7GxU7hw3nJiiKY9P38LE3BAZ7tFC0Di/AzISIxHEQBvneu5bW51a7o50P1NgDCg==", + "version": "1.21.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.21.2.tgz", + "integrity": "sha512-sCAHlcQ/PExU5t/kRwkEWHdhGmQrZ2IgdQzbjPVNfhWbKHMMZGYqkASVTpQqRPLtQKg15xzEscc+BnIK/TE7/Q==", "dev": true, "requires": { "@types/estree": "0.0.39", @@ -3775,9 +3775,9 @@ } }, "svelte": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.10.1.tgz", - "integrity": "sha512-XjXJVHAhnLAXS0P735PiT3is+9Oq8nX8adtiyaLJSeoEbN6TwNxu58jhAHlxG2f9+LAq7QbVJvgHkGdkZTFBog==", + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.12.0.tgz", + "integrity": "sha512-9/broj3bjShrsk3FuVDH0Bho2BchPKT8ubAqRcTqwkqrO9npOS3Vi98Yb5mBaa4bYV+ELTuvPvaQZbCJYMFRdg==", "dev": true }, "tar": { diff --git a/site/package.json b/site/package.json index 967aa5894b..3f362ac891 100644 --- a/site/package.json +++ b/site/package.json @@ -14,7 +14,7 @@ }, "dependencies": { "@polka/redirect": "^1.0.0-next.0", - "@polka/send": "^1.0.0-next.3", + "@polka/send": "^1.0.0-next.6", "cookie": "^0.4.0", "devalue": "^2.0.0", "do-not-zip": "^1.0.0", @@ -23,7 +23,7 @@ "jsonwebtoken": "^8.5.1", "marked": "^0.7.0", "pg": "^7.12.1", - "polka": "^1.0.0-next.4", + "polka": "^1.0.0-next.6", "prismjs": "^1.17.1", "sirv": "^0.4.2", "yootils": "0.0.16" @@ -45,7 +45,7 @@ "node-fetch": "^2.6.0", "node-pg-migrate": "^3.22.0", "npm-run-all": "^4.1.5", - "rollup": "^1.21.0", + "rollup": "^1.21.2", "rollup-plugin-babel": "^4.3.3", "rollup-plugin-commonjs": "^10.1.0", "rollup-plugin-json": "^4.0.0", @@ -55,7 +55,7 @@ "rollup-plugin-terser": "^5.1.1", "sapper": "^0.27.8", "shelljs": "^0.8.3", - "svelte": "^3.10.1" + "svelte": "^3.12.0" }, "engines": { "node": ">=10.0.0" diff --git a/site/src/components/ScreenToggle.svelte b/site/src/components/ScreenToggle.svelte index 8dbebe9c74..a59b685263 100644 --- a/site/src/components/ScreenToggle.svelte +++ b/site/src/components/ScreenToggle.svelte @@ -38,7 +38,7 @@ {#each labels as label, index} diff --git a/site/src/routes/_components/WhosUsingSvelte.svelte b/site/src/routes/_components/WhosUsingSvelte.svelte index 1a0a80f4ac..6444596cc8 100644 --- a/site/src/routes/_components/WhosUsingSvelte.svelte +++ b/site/src/routes/_components/WhosUsingSvelte.svelte @@ -56,6 +56,7 @@ Dextra logo Entriwise logo From-Now-On logo + FusionCharts logo GoDaddy logo Grainger logo HealthTree logo @@ -67,8 +68,10 @@ Neue Zürcher Zeitung logo The New York Times logo OberonSPACE logo + Ofof logo Open State Foundation logo Panascais logo + Pankod logo Razorpay logo Socialist Party logo Stone Payments logo diff --git a/site/src/routes/apps/index.svelte b/site/src/routes/apps/index.svelte index d85f5681f8..36cd1a904c 100644 --- a/site/src/routes/apps/index.svelte +++ b/site/src/routes/apps/index.svelte @@ -4,7 +4,7 @@ let offset = null; if (user) { - var url = 'apps.json'; + let url = 'apps.json'; if (page.query.offset) { url += `?offset=${encodeURIComponent(page.query.offset)}`; } @@ -50,9 +50,9 @@

Your apps

- {user.name} avatar + {user.name || user.username} avatar - {user.name} + {user.name || user.username} (log out)
diff --git a/site/src/routes/docs/_sections.js b/site/src/routes/docs/_sections.js index b6da2315f0..35edc16cfa 100644 --- a/site/src/routes/docs/_sections.js +++ b/site/src/routes/docs/_sections.js @@ -7,23 +7,6 @@ import marked from 'marked'; import PrismJS from 'prismjs'; import 'prismjs/components/prism-bash'; -const escaped = { - '"': '"', - "'": ''', - '&': '&', - '<': '<', - '>': '>', -}; - -const unescaped = Object.keys(escaped).reduce( - (unescaped, key) => ((unescaped[escaped[key]] = key), unescaped), - {} -); - -function unescape(str) { - return String(str).replace(/&.+?;/g, match => unescaped[match] || match); -} - const blockTypes = [ 'blockquote', 'html', diff --git a/site/src/routes/repl/[id]/index.json.js b/site/src/routes/repl/[id]/index.json.js index 8c7dabb14a..e34329a0e2 100644 --- a/site/src/routes/repl/[id]/index.json.js +++ b/site/src/routes/repl/[id]/index.json.js @@ -95,7 +95,8 @@ export async function patch(req, res) { const { user } = req; if (!user) return; - let id, uid = req.params.id; + let id; + const uid = req.params.id; try { const [row] = await query(`select * from gists where uid = $1 limit 1`, [uid]); @@ -110,7 +111,9 @@ export async function patch(req, res) { try { const obj = await body(req); obj.updated_at = 'now()'; - let k, cols=[], vals=[]; + let k; + const cols = []; + const vals = []; for (k in obj) { cols.push(k); vals.push(k === 'files' ? JSON.stringify(obj[k]) : obj[k]); diff --git a/site/src/routes/tutorial/[slug]/index.svelte b/site/src/routes/tutorial/[slug]/index.svelte index 20cc34ab6b..ec23906057 100644 --- a/site/src/routes/tutorial/[slug]/index.svelte +++ b/site/src/routes/tutorial/[slug]/index.svelte @@ -18,7 +18,6 @@ import { getContext } from 'svelte'; import ScreenToggle from '../../../components/ScreenToggle.svelte'; - import { Icon } from '@sveltejs/site-kit'; import TableOfContents from './_TableOfContents.svelte'; import { diff --git a/site/static/favicon.png b/site/static/favicon.png index b8b26e3044..ddbebf3b4f 100644 Binary files a/site/static/favicon.png and b/site/static/favicon.png differ diff --git a/site/static/images/twitter-card.png b/site/static/images/twitter-card.png index 5e0a55e570..1e8271f655 100644 Binary files a/site/static/images/twitter-card.png and b/site/static/images/twitter-card.png differ diff --git a/site/static/organisations/bekchy.png b/site/static/organisations/bekchy.png index 737e3f95d9..011553cb42 100644 Binary files a/site/static/organisations/bekchy.png and b/site/static/organisations/bekchy.png differ diff --git a/site/static/organisations/dextra.png b/site/static/organisations/dextra.png index a550304adf..725f9bd511 100644 Binary files a/site/static/organisations/dextra.png and b/site/static/organisations/dextra.png differ diff --git a/site/static/organisations/entriwise.png b/site/static/organisations/entriwise.png index f8e3e80e91..be305e1300 100644 Binary files a/site/static/organisations/entriwise.png and b/site/static/organisations/entriwise.png differ diff --git a/site/static/organisations/fusioncharts.svg b/site/static/organisations/fusioncharts.svg new file mode 100644 index 0000000000..6712115de8 --- /dev/null +++ b/site/static/organisations/fusioncharts.svg @@ -0,0 +1,18 @@ + + + + logo colour + Created with Sketch. + + + + + + + + + + + + + \ No newline at end of file diff --git a/site/static/organisations/ofof.png b/site/static/organisations/ofof.png new file mode 100644 index 0000000000..5ecde9b0fd Binary files /dev/null and b/site/static/organisations/ofof.png differ diff --git a/site/static/organisations/pankod.svg b/site/static/organisations/pankod.svg new file mode 100644 index 0000000000..34578a7739 --- /dev/null +++ b/site/static/organisations/pankod.svg @@ -0,0 +1,33 @@ + + + + Dark + Created with Sketch. + + + + + + + + \ No newline at end of file diff --git a/site/static/tutorial/kitten.png b/site/static/tutorial/kitten.png index 6ef37691bc..6b0cedc945 100644 Binary files a/site/static/tutorial/kitten.png and b/site/static/tutorial/kitten.png differ diff --git a/src/compiler/compile/css/Selector.ts b/src/compiler/compile/css/Selector.ts index e6a00435d9..2f539baf4b 100644 --- a/src/compiler/compile/css/Selector.ts +++ b/src/compiler/compile/css/Selector.ts @@ -138,8 +138,9 @@ function apply_selector(stylesheet: Stylesheet, blocks: Block[], node: CssNode, while (i--) { const selector = block.selectors[i]; + const name = typeof selector.name === 'string' && selector.name.replace(/\\(.)/g, '$1'); - if (selector.type === 'PseudoClassSelector' && selector.name === 'global') { + if (selector.type === 'PseudoClassSelector' && name === 'global') { // TODO shouldn't see this here... maybe we should enforce that :global(...) // cannot be sandwiched between non-global selectors? return false; @@ -150,11 +151,11 @@ function apply_selector(stylesheet: Stylesheet, blocks: Block[], node: CssNode, } if (selector.type === 'ClassSelector') { - if (!attribute_matches(node, 'class', selector.name, '~=', false) && !class_matches(node, selector.name)) return false; + if (!attribute_matches(node, 'class', name, '~=', false) && !node.classes.some(c => c.name === name)) return false; } else if (selector.type === 'IdSelector') { - if (!attribute_matches(node, 'id', selector.name, '=', false)) return false; + if (!attribute_matches(node, 'id', name, '=', false)) return false; } else if (selector.type === 'AttributeSelector') { @@ -162,8 +163,7 @@ function apply_selector(stylesheet: Stylesheet, blocks: Block[], node: CssNode, } else if (selector.type === 'TypeSelector') { - // remove toLowerCase() in v2, when uppercase elements will be forbidden - if (node.name.toLowerCase() !== selector.name.toLowerCase() && selector.name !== '*') return false; + if (node.name.toLowerCase() !== name.toLowerCase() && name !== '*') return false; } else { @@ -206,14 +206,21 @@ function apply_selector(stylesheet: Stylesheet, blocks: Block[], node: CssNode, return true; } -const operators = { - '=' : (value: string, flags: string) => new RegExp(`^${value}$`, flags), - '~=': (value: string, flags: string) => new RegExp(`\\b${value}\\b`, flags), - '|=': (value: string, flags: string) => new RegExp(`^${value}(-.+)?$`, flags), - '^=': (value: string, flags: string) => new RegExp(`^${value}`, flags), - '$=': (value: string, flags: string) => new RegExp(`${value}$`, flags), - '*=': (value: string, flags: string) => new RegExp(value, flags) -}; +function test_attribute(operator, expected_value, case_insensitive, value) { + if (case_insensitive) { + expected_value = expected_value.toLowerCase(); + value = value.toLowerCase(); + } + switch (operator) { + case '=': return value === expected_value; + case '~=': return ` ${value} `.includes(` ${expected_value} `); + case '|=': return `${value}-`.startsWith(`${expected_value}-`); + case '^=': return value.startsWith(expected_value); + case '$=': return value.endsWith(expected_value); + case '*=': return value.includes(expected_value); + default: throw new Error(`this shouldn't happen`); + } +} function attribute_matches(node: CssNode, name: string, expected_value: string, operator: string, case_insensitive: boolean) { const spread = node.attributes.find(attr => attr.type === 'Spread'); @@ -227,18 +234,17 @@ function attribute_matches(node: CssNode, name: string, expected_value: string, if (attr.chunks.length > 1) return true; if (!expected_value) return true; - const pattern = operators[operator](expected_value, case_insensitive ? 'i' : ''); const value = attr.chunks[0]; if (!value) return false; - if (value.type === 'Text') return pattern.test(value.data); + if (value.type === 'Text') return test_attribute(operator, expected_value, case_insensitive, value.data); const possible_values = new Set(); gather_possible_values(value.node, possible_values); if (possible_values.has(UNKNOWN)) return true; - for (const x of Array.from(possible_values)) { // TypeScript for-of is slightly unlike JS - if (pattern.test(x)) return true; + for (const value of possible_values) { + if (test_attribute(operator, expected_value, case_insensitive, value)) return true; } return false; diff --git a/test/css/samples/weird-selectors/expected.css b/test/css/samples/weird-selectors/expected.css new file mode 100644 index 0000000000..d4ead16751 --- /dev/null +++ b/test/css/samples/weird-selectors/expected.css @@ -0,0 +1 @@ +.-foo.svelte-xyz{color:red}[title='['].svelte-xyz{color:blue} \ No newline at end of file diff --git a/test/css/samples/weird-selectors/input.svelte b/test/css/samples/weird-selectors/input.svelte new file mode 100644 index 0000000000..65db029bbd --- /dev/null +++ b/test/css/samples/weird-selectors/input.svelte @@ -0,0 +1,12 @@ +
foo
+ +
bar
+ + diff --git a/test/runtime/samples/sigil-component-attribute/Widget.svelte b/test/runtime/samples/sigil-component-prop/Widget.svelte similarity index 100% rename from test/runtime/samples/sigil-component-attribute/Widget.svelte rename to test/runtime/samples/sigil-component-prop/Widget.svelte diff --git a/test/runtime/samples/sigil-component-attribute/_config.js b/test/runtime/samples/sigil-component-prop/_config.js similarity index 69% rename from test/runtime/samples/sigil-component-attribute/_config.js rename to test/runtime/samples/sigil-component-prop/_config.js index 066505cfa4..2f467bb9d4 100644 --- a/test/runtime/samples/sigil-component-attribute/_config.js +++ b/test/runtime/samples/sigil-component-prop/_config.js @@ -1,4 +1,7 @@ export default { + compileOptions: { + dev: true + }, props: { foo: 'foo' }, html: `
foo @ foo # foo
`, }; diff --git a/test/runtime/samples/sigil-component-attribute/main.svelte b/test/runtime/samples/sigil-component-prop/main.svelte similarity index 63% rename from test/runtime/samples/sigil-component-attribute/main.svelte rename to test/runtime/samples/sigil-component-prop/main.svelte index 07c36d3a41..28c66c5bd6 100644 --- a/test/runtime/samples/sigil-component-attribute/main.svelte +++ b/test/runtime/samples/sigil-component-prop/main.svelte @@ -3,4 +3,5 @@ export let foo; - + + \ No newline at end of file