Skip to content

Commit 98cef6d

Browse files
authored
Merge pull request #933 from sketch-hq/chore/update-15629876426
Update with release/2025.2 (beta)
2 parents 1430c22 + 09194b5 commit 98cef6d

File tree

11 files changed

+4318
-2628
lines changed

11 files changed

+4318
-2628
lines changed

.github/workflows/check.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
- name: Setup Node
1313
uses: actions/setup-node@master
1414
with:
15-
node-version: '10.16.3'
15+
node-version: 'lts/*'
1616
- name: Install Dependencies
1717
run: npm ci
1818
- name: Build

.nvmrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
16.1.0
1+
lts/*

.vscode/tasks.json

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
{
2+
"version": "2.0.0",
3+
"tasks": [
4+
{
5+
"label": "Build & lint",
6+
"group": {
7+
"kind": "build",
8+
"isDefault": true
9+
},
10+
"dependsOrder": "sequence",
11+
"dependsOn": ["Lint", "Build"]
12+
},
13+
{
14+
"label": "Build",
15+
"type": "npm",
16+
"script": "build",
17+
"group": {
18+
"kind": "build"
19+
}
20+
},
21+
{
22+
"label": "Lint",
23+
"type": "npm",
24+
"script": "lint",
25+
"group": {
26+
"kind": "build"
27+
}
28+
},
29+
{
30+
"label": "Build and run tests",
31+
"dependsOrder": "sequence",
32+
"dependsOn": ["Build", "Please choose target Xcode variant", "Run tests"],
33+
"group": {
34+
"kind": "test",
35+
"isDefault": true
36+
}
37+
},
38+
{
39+
"label": "Please choose target Xcode variant",
40+
"type": "shell",
41+
"command": "echo -e '\\033[0;34m=====================================================================\nSelect the Sketch variant to test against in the VSCode popup above ☝️\n(or just press Enter)\n=====================================================================\\033[0m'",
42+
"group": {
43+
"kind": "test"
44+
}
45+
},
46+
{
47+
"label": "Run tests",
48+
"type": "npm",
49+
"script": "test",
50+
"options": {
51+
"env": {
52+
"TARGET_SKETCH_VARIANT_BUNDLE_ID": "${input:sketchTarget}"
53+
}
54+
}
55+
}
56+
],
57+
"inputs": [
58+
{
59+
"id": "sketchTarget",
60+
"description": "Choose the target Sketch variant",
61+
"type": "pickString",
62+
"options": [
63+
"com.bohemiancoding.sketch3.xcode",
64+
"com.bohemiancoding.sketch3.beta",
65+
"com.bohemiancoding.sketch3"
66+
],
67+
"default": "com.bohemiancoding.sketch3.xcode"
68+
}
69+
]
70+
}

Source/dom/__tests__/find.test.js

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,39 @@ test('should find by name beginning with', (_context, document) => {
111111
])
112112
})
113113

114+
test('should find by full name match ignoring case', (_context, document) => {
115+
// eslint-disable-next-line no-param-reassign
116+
document.pages = [
117+
{
118+
layers: [
119+
{ type: 'Artboard' },
120+
{ type: 'Shape', name: 'test' },
121+
{ type: 'Shape', name: 'test2' },
122+
],
123+
},
124+
]
125+
expect(find('[name~="tEsT"]', document).map((x) => x.id)).toEqual([
126+
document.pages[0].layers[1].id,
127+
])
128+
})
129+
130+
test('should find by partial name ignoring case', (_context, document) => {
131+
// eslint-disable-next-line no-param-reassign
132+
document.pages = [
133+
{
134+
layers: [
135+
{ type: 'Artboard' },
136+
{ type: 'Shape', name: 'test' },
137+
{ type: 'Shape', name: 'test2' },
138+
],
139+
},
140+
]
141+
expect(find('[name~*="tEsT"]', document).map((x) => x.id)).toEqual([
142+
document.pages[0].layers[1].id,
143+
document.pages[0].layers[2].id,
144+
])
145+
})
146+
114147
test('should find by frame.x greater than', (_context, document) => {
115148
// eslint-disable-next-line no-param-reassign
116149
document.pages = [
@@ -158,3 +191,62 @@ test('should find with id', (_context, document) => {
158191
find(`#${document.pages[0].layers[1].id}`, document).map((x) => x.id)
159192
).toEqual([document.pages[0].layers[1].id])
160193
})
194+
195+
test('should find within root progeny', (_context, document) => {
196+
// eslint-disable-next-line no-param-reassign
197+
document.pages = [
198+
{
199+
layers: [
200+
{
201+
type: 'Artboard',
202+
frame: new Rectangle(400, 0, 100, 100),
203+
layers: [
204+
{
205+
type: 'Shape',
206+
name: 'test',
207+
frame: new Rectangle(400, 0, 50, 50),
208+
},
209+
],
210+
},
211+
{ type: 'Shape', name: 'test' },
212+
],
213+
},
214+
]
215+
216+
const root = document.pages[0].layers[0]
217+
expect(find("[name='test']", root).map((x) => x.id)).toEqual([
218+
root.layers[0].id,
219+
])
220+
221+
expect(
222+
find("[name='test']", root, { inclusive: false }).map((x) => x.id)
223+
).toEqual([root.layers[0].id])
224+
})
225+
226+
test('should find within root progeny + root itself', (_context, document) => {
227+
// eslint-disable-next-line no-param-reassign
228+
document.pages = [
229+
{
230+
layers: [
231+
{
232+
type: 'Artboard',
233+
name: 'test',
234+
frame: new Rectangle(400, 0, 100, 100),
235+
layers: [
236+
{
237+
type: 'Shape',
238+
name: 'test',
239+
frame: new Rectangle(400, 0, 50, 50),
240+
},
241+
],
242+
},
243+
{ type: 'Shape', name: 'test' },
244+
],
245+
},
246+
]
247+
248+
const root = document.pages[0].layers[0]
249+
expect(
250+
find("[name='test']", root, { inclusive: true }).map((x) => x.id)
251+
).toEqual([root.id, root.layers[0].id])
252+
})

Source/dom/find.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@ const attributesMap = {
7070

7171
const operatorMap = {
7272
'=': '=',
73+
'~=': 'LIKE[c]',
7374
'*=': 'CONTAINS',
75+
'~*=': 'CONTAINS[c]',
7476
'$=': 'ENDSWITH',
7577
'!=': '!=',
7678
'^=': 'BEGINSWITH',
@@ -89,7 +91,7 @@ const whitespace = '[\\x20\\t\\r\\n\\f]'
8991
// with a small twist: we accept `.` for nested property path
9092
const identifier = '(?:\\\\.|[\\w-]|[^\0-\\xa0]|\\.)+'
9193

92-
const operator = `(?:[*^$!]?=|>=|>|<|<=)`
94+
const operator = `(?:[~]*[*^$!]?=|>=|>|<|<=)`
9395

9496
const attributes = `\\[${whitespace}*(${identifier})(?:${whitespace}*(${operator})${whitespace}*(?:'((?:\\\\.|[^\\\\'])*)'|"((?:\\\\.|[^\\\\"])*)"|(${identifier}))|)${whitespace}*\\]`
9597
const booleans = 'locked|hidden|selected'
@@ -111,7 +113,7 @@ function parseValue(value) {
111113
return Number(value)
112114
}
113115

114-
export function find(predicate, root) {
116+
export function find(predicate, root, options = {}) {
115117
if (!root) {
116118
// eslint-disable-next-line no-param-reassign
117119
root = Document.getSelectedDocument()
@@ -211,13 +213,15 @@ export function find(predicate, root) {
211213
predicateVars
212214
)
213215

216+
const { inclusive = false } = options || {}
217+
214218
const children =
215219
root.type == Types.Document
216220
? root.sketchObject.pages().reduce((prev, page) => {
217221
prev.addObjectsFromArray(page.childrenIncludingSelf(true))
218222
return prev
219223
}, NSMutableArray.new())
220-
: root.sketchObject.childrenIncludingSelf(false)
224+
: root.sketchObject.childrenIncludingSelf(inclusive)
221225

222226
// Different filter strategies are used for backwards compatibility with plugins and
223227
// scripts that work on the concept of artboards.

Source/dom/models/Selection.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ export class Selection {
6161
return this.layers.reduce(fn, initial)
6262
}
6363

64+
filter(fn) {
65+
return this.layers.filter(fn)
66+
}
67+
6468
/**
6569
* Clear the selection.
6670
*/

Source/dom/models/__tests__/Selection.test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,4 +91,5 @@ test('should define convenience array methods', (_context, document) => {
9191
expect(selection.forEach).toBeDefined()
9292
expect(selection.map).toBeDefined()
9393
expect(selection.reduce).toBeDefined()
94+
expect(selection.filter).toBeDefined()
9495
})

0 commit comments

Comments
 (0)