scratch-storage 2.2.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.circleci/config.yml +1 -1
- package/dist/node/scratch-storage.js +125 -57
- package/dist/node/scratch-storage.js.map +1 -1
- package/dist/web/scratch-storage.js +125 -57
- package/dist/web/scratch-storage.js.map +1 -1
- package/dist/web/scratch-storage.min.js +125 -57
- package/dist/web/scratch-storage.min.js.map +1 -1
- package/jest.config.js +5 -0
- package/package.json +10 -8
- package/src/BuiltinHelper.js +3 -3
- package/src/FetchWorkerTool.js +8 -1
- package/src/ScratchStorage.js +9 -0
- package/src/scratchFetch.js +51 -11
- package/test/.eslintrc.js +5 -1
- package/test/{mocks/mockFetch.js → __mocks__/cross-fetch.js} +30 -16
- package/test/fixtures/.gitattributes +3 -0
- package/test/fixtures/assets/117504922.json +196 -0
- package/test/fixtures/assets/66895930177178ea01d9e610917f8acf.png +0 -0
- package/test/fixtures/assets/6e8bd9ae68fdb02b7e1e3df656a75635.svg +37 -0
- package/test/fixtures/assets/7e24c99c1b853e52f8e7f9004416fa34.png +0 -0
- package/test/fixtures/assets/83c36d806dc92327b9e7049a565c6bff.wav +0 -0
- package/test/fixtures/assets/f88bf1935daea28f8ca098462a31dbb0.svg +35 -0
- package/test/fixtures/assets/fe5e3566965f9de793beeffce377d054.jpg +0 -0
- package/test/fixtures/known-assets.js +60 -0
- package/test/integration/download-known-assets.test.js +141 -0
- package/test/transformers/.eslintrc.js +8 -0
- package/test/transformers/arraybuffer-loader.js +11 -0
- package/test/unit/{add-helper.js → add-helper.test.js} +16 -20
- package/test/unit/fetch-tool.test.js +56 -0
- package/test/unit/load-default-assets.test.js +59 -0
- package/test/unit/metadata.test.js +129 -0
- package/webpack.config.js +4 -0
- package/.nyc_output/c826ae6b-4ae2-4d8e-bdb2-162df5761fa7.json +0 -1
- package/.nyc_output/ec2d52a1-5131-4dd0-9c23-59106f297082.json +0 -1
- package/.nyc_output/processinfo/c826ae6b-4ae2-4d8e-bdb2-162df5761fa7.json +0 -1
- package/.nyc_output/processinfo/ec2d52a1-5131-4dd0-9c23-59106f297082.json +0 -1
- package/.nyc_output/processinfo/index.json +0 -1
- package/test/integration/download-known-assets.js +0 -111
- package/test/unit/fetch-tool.js +0 -60
- package/test/unit/load-default-assets.js +0 -48
- package/test/unit/metadata.js +0 -136
package/jest.config.js
ADDED
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "scratch-storage",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "Load and store project and asset files for Scratch 3.0",
|
|
5
5
|
"license": "BSD-3-Clause",
|
|
6
6
|
"homepage": "https://github.com/LLK/scratch-storage#readme",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
9
|
"url": "https://github.com/LLK/scratch-storage.git",
|
|
10
|
-
"sha": "
|
|
10
|
+
"sha": "0537bdad85576ae09cf31765bd65b7450f31308b"
|
|
11
11
|
},
|
|
12
12
|
"main": "./dist/node/scratch-storage.js",
|
|
13
13
|
"browser": "./src/index.js",
|
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
"build": "webpack --progress --colors --bail",
|
|
16
16
|
"coverage": "tap ./test/{unit,integration}/*.js --coverage --coverage-report=lcov",
|
|
17
17
|
"commitmsg": "commitlint -e $GIT_PARAMS",
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"test": "
|
|
18
|
+
"test": "npm run test:lint && jest \"test[\\\\/](unit|integration)\"",
|
|
19
|
+
"test:clearCache": "jest --clearCache",
|
|
20
|
+
"test:lint": "eslint .",
|
|
21
|
+
"test:integration": "jest \"test[\\\\/]integration\"",
|
|
22
|
+
"test:unit": "jest \"test[\\\\/]unit\"",
|
|
23
23
|
"version": "json -f package.json -I -e \"this.repository.sha = '$(git log -n1 --pretty=format:%H)'\"",
|
|
24
24
|
"watch": "webpack --progress --colors --watch",
|
|
25
25
|
"semantic-release": "semantic-release"
|
|
@@ -45,17 +45,19 @@
|
|
|
45
45
|
"@commitlint/cli": "8.2.0",
|
|
46
46
|
"@commitlint/config-conventional": "8.2.0",
|
|
47
47
|
"@commitlint/travis-cli": "8.2.0",
|
|
48
|
+
"@types/jest": "29.5.1",
|
|
48
49
|
"babel-eslint": "10.1.0",
|
|
49
50
|
"babel-loader": "8.0.6",
|
|
50
51
|
"cz-conventional-changelog": "3.3.0",
|
|
51
52
|
"eslint": "7.27.0",
|
|
52
53
|
"eslint-config-scratch": "6.0.0",
|
|
54
|
+
"eslint-plugin-jest": "27.2.1",
|
|
53
55
|
"eslint-plugin-react": "7.24.0",
|
|
54
56
|
"file-loader": "4.1.0",
|
|
55
57
|
"husky": "1.3.1",
|
|
58
|
+
"jest": "29.5.0",
|
|
56
59
|
"json": "^9.0.4",
|
|
57
60
|
"semantic-release": "^15.10.5",
|
|
58
|
-
"tap": "16.3.4",
|
|
59
61
|
"uglifyjs-webpack-plugin": "2.2.0",
|
|
60
62
|
"webpack": "4.46.0",
|
|
61
63
|
"webpack-cli": "3.1.2"
|
package/src/BuiltinHelper.js
CHANGED
|
@@ -24,7 +24,7 @@ const DefaultAssets = [
|
|
|
24
24
|
format: DataFormat.PNG,
|
|
25
25
|
id: null,
|
|
26
26
|
data: Buffer.from(
|
|
27
|
-
require('
|
|
27
|
+
require('./builtins/defaultBitmap.png') // eslint-disable-line global-require
|
|
28
28
|
)
|
|
29
29
|
},
|
|
30
30
|
{
|
|
@@ -32,7 +32,7 @@ const DefaultAssets = [
|
|
|
32
32
|
format: DataFormat.WAV,
|
|
33
33
|
id: null,
|
|
34
34
|
data: Buffer.from(
|
|
35
|
-
require('
|
|
35
|
+
require('./builtins/defaultSound.wav') // eslint-disable-line global-require
|
|
36
36
|
)
|
|
37
37
|
},
|
|
38
38
|
{
|
|
@@ -40,7 +40,7 @@ const DefaultAssets = [
|
|
|
40
40
|
format: DataFormat.SVG,
|
|
41
41
|
id: null,
|
|
42
42
|
data: Buffer.from(
|
|
43
|
-
require('
|
|
43
|
+
require('./builtins/defaultVector.svg') // eslint-disable-line global-require
|
|
44
44
|
)
|
|
45
45
|
}
|
|
46
46
|
];
|
package/src/FetchWorkerTool.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const {applyMetadata} = require('./scratchFetch');
|
|
1
|
+
const {Headers, applyMetadata} = require('./scratchFetch');
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Get and send assets with a worker that uses fetch.
|
|
@@ -92,6 +92,13 @@ class PrivateFetchWorkerTool {
|
|
|
92
92
|
const augmentedOptions = applyMetadata(
|
|
93
93
|
Object.assign({method: 'GET'}, options)
|
|
94
94
|
);
|
|
95
|
+
// the Fetch spec says options.headers could be:
|
|
96
|
+
// "A Headers object, an object literal, or an array of two-item arrays to set request's headers."
|
|
97
|
+
// structured clone (postMessage) doesn't support Headers objects
|
|
98
|
+
// so turn it into an array of two-item arrays to make it to the worker intact
|
|
99
|
+
if (augmentedOptions && augmentedOptions.headers instanceof Headers) {
|
|
100
|
+
augmentedOptions.headers = Array.from(augmentedOptions.headers.entries());
|
|
101
|
+
}
|
|
95
102
|
this.worker.postMessage({
|
|
96
103
|
id,
|
|
97
104
|
url,
|
package/src/ScratchStorage.js
CHANGED
|
@@ -6,6 +6,7 @@ const WebHelper = require('./WebHelper');
|
|
|
6
6
|
const _Asset = require('./Asset');
|
|
7
7
|
const _AssetType = require('./AssetType');
|
|
8
8
|
const _DataFormat = require('./DataFormat');
|
|
9
|
+
const _scratchFetch = require('./scratchFetch');
|
|
9
10
|
|
|
10
11
|
class ScratchStorage {
|
|
11
12
|
constructor () {
|
|
@@ -51,6 +52,14 @@ class ScratchStorage {
|
|
|
51
52
|
return _DataFormat;
|
|
52
53
|
}
|
|
53
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Access the `scratchFetch` module within this library.
|
|
57
|
+
* @return {module} the scratchFetch module, with properties for `scratchFetch`, `setMetadata`, etc.
|
|
58
|
+
*/
|
|
59
|
+
get scratchFetch () {
|
|
60
|
+
return _scratchFetch;
|
|
61
|
+
}
|
|
62
|
+
|
|
54
63
|
/**
|
|
55
64
|
* @deprecated Please use the `Asset` member of a storage instance instead.
|
|
56
65
|
* @return {Asset} - the `Asset` class constructor.
|
package/src/scratchFetch.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const crossFetch = require('cross-fetch');
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Metadata header names
|
|
@@ -7,16 +7,40 @@ const {fetch, Headers} = require('cross-fetch');
|
|
|
7
7
|
*/
|
|
8
8
|
const RequestMetadata = {
|
|
9
9
|
/** The ID of the project associated with this request */
|
|
10
|
-
ProjectId: 'X-
|
|
10
|
+
ProjectId: 'X-Project-ID',
|
|
11
11
|
/** The ID of the project run associated with this request */
|
|
12
|
-
RunId: 'X-
|
|
12
|
+
RunId: 'X-Run-ID'
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
|
-
* Metadata for requests
|
|
17
|
-
* @type {
|
|
16
|
+
* Metadata headers for requests
|
|
17
|
+
* @type {Headers}
|
|
18
18
|
*/
|
|
19
|
-
const metadata = new
|
|
19
|
+
const metadata = new crossFetch.Headers();
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Check if there is any metadata to apply.
|
|
23
|
+
* @returns {boolean} true if `metadata` has contents, or false if it is empty.
|
|
24
|
+
*/
|
|
25
|
+
const hasMetadata = () => {
|
|
26
|
+
/* global self */
|
|
27
|
+
const searchParams = (
|
|
28
|
+
typeof self !== 'undefined' &&
|
|
29
|
+
self &&
|
|
30
|
+
self.location &&
|
|
31
|
+
self.location.search &&
|
|
32
|
+
self.location.search.split(/[?&]/)
|
|
33
|
+
) || [];
|
|
34
|
+
if (!searchParams.includes('scratchMetadata=1')) {
|
|
35
|
+
// for now, disable this feature unless scratchMetadata=1
|
|
36
|
+
// TODO: remove this check once we're sure the feature works correctly in production
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
for (const _ of metadata) {
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
return false;
|
|
43
|
+
};
|
|
20
44
|
|
|
21
45
|
/**
|
|
22
46
|
* Non-destructively merge any metadata state (if any) with the provided options object (if any).
|
|
@@ -28,12 +52,15 @@ const metadata = new Map();
|
|
|
28
52
|
* @returns {RequestInit|undefined} the provided options parameter without modification, or a new options object.
|
|
29
53
|
*/
|
|
30
54
|
const applyMetadata = options => {
|
|
31
|
-
if (
|
|
55
|
+
if (hasMetadata()) {
|
|
32
56
|
const augmentedOptions = Object.assign({}, options);
|
|
33
|
-
augmentedOptions.headers = new Headers(
|
|
57
|
+
augmentedOptions.headers = new crossFetch.Headers(metadata);
|
|
34
58
|
if (options && options.headers) {
|
|
35
|
-
|
|
36
|
-
|
|
59
|
+
// the Fetch spec says options.headers could be:
|
|
60
|
+
// "A Headers object, an object literal, or an array of two-item arrays to set request's headers."
|
|
61
|
+
// turn it into a Headers object to be sure of how to interact with it
|
|
62
|
+
const overrideHeaders = options.headers instanceof crossFetch.Headers ?
|
|
63
|
+
options.headers : new crossFetch.Headers(options.headers);
|
|
37
64
|
for (const [name, value] of overrideHeaders.entries()) {
|
|
38
65
|
augmentedOptions.headers.set(name, value);
|
|
39
66
|
}
|
|
@@ -53,7 +80,7 @@ const applyMetadata = options => {
|
|
|
53
80
|
*/
|
|
54
81
|
const scratchFetch = (resource, options) => {
|
|
55
82
|
const augmentedOptions = applyMetadata(options);
|
|
56
|
-
return fetch(resource, augmentedOptions);
|
|
83
|
+
return crossFetch.fetch(resource, augmentedOptions);
|
|
57
84
|
};
|
|
58
85
|
|
|
59
86
|
/**
|
|
@@ -78,9 +105,22 @@ const unsetMetadata = name => {
|
|
|
78
105
|
module.exports = {
|
|
79
106
|
default: scratchFetch,
|
|
80
107
|
|
|
108
|
+
Headers: crossFetch.Headers,
|
|
81
109
|
RequestMetadata,
|
|
82
110
|
applyMetadata,
|
|
83
111
|
scratchFetch,
|
|
84
112
|
setMetadata,
|
|
85
113
|
unsetMetadata
|
|
86
114
|
};
|
|
115
|
+
|
|
116
|
+
if (process.env.NODE_ENV === 'development') {
|
|
117
|
+
/**
|
|
118
|
+
* Retrieve a named request metadata item.
|
|
119
|
+
* Only for use in tests.
|
|
120
|
+
* @param {RequestMetadata} name The name of the metadata item to retrieve.
|
|
121
|
+
* @returns {any} value The value of the metadata item, or `undefined` if it was not found.
|
|
122
|
+
*/
|
|
123
|
+
const getMetadata = name => metadata.get(name);
|
|
124
|
+
|
|
125
|
+
module.exports.getMetadata = getMetadata;
|
|
126
|
+
}
|
package/test/.eslintrc.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
const TextEncoder = require('util').TextEncoder;
|
|
2
|
-
const
|
|
2
|
+
const crossFetch = jest.requireActual('cross-fetch');
|
|
3
|
+
const knownAssets = require('../fixtures/known-assets.js');
|
|
3
4
|
|
|
5
|
+
const Headers = crossFetch.Headers;
|
|
4
6
|
const successText = 'successful response';
|
|
5
7
|
|
|
6
8
|
/**
|
|
@@ -37,28 +39,40 @@ const mockFetch = (resource, options) => {
|
|
|
37
39
|
options.mockFetchTestData.headers = new Headers(options.headers);
|
|
38
40
|
options.mockFetchTestData.headersCount = Array.from(options.mockFetchTestData.headers).length;
|
|
39
41
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
+
|
|
43
|
+
const assetInfo = knownAssets[resource];
|
|
44
|
+
if (assetInfo) {
|
|
42
45
|
results.ok = true;
|
|
43
46
|
results.status = 200;
|
|
44
|
-
results.
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
47
|
+
results.arrayBuffer = () => Promise.resolve(assetInfo.content);
|
|
48
|
+
} else {
|
|
49
|
+
switch (resource) {
|
|
50
|
+
case '200':
|
|
51
|
+
results.ok = true;
|
|
52
|
+
results.status = 200;
|
|
53
|
+
results.text = () => Promise.resolve(successText);
|
|
54
|
+
results.arrayBuffer = () => Promise.resolve(new TextEncoder().encode(successText));
|
|
55
|
+
break;
|
|
56
|
+
case '404':
|
|
57
|
+
results.ok = false;
|
|
58
|
+
results.status = 404;
|
|
59
|
+
break;
|
|
60
|
+
case '500':
|
|
61
|
+
results.ok = false;
|
|
62
|
+
results.status = 500;
|
|
63
|
+
break;
|
|
64
|
+
default:
|
|
65
|
+
throw new Error(`mockFetch doesn't know how to download: ${resource}`);
|
|
66
|
+
}
|
|
57
67
|
}
|
|
58
68
|
return Promise.resolve(results);
|
|
59
69
|
};
|
|
60
70
|
|
|
71
|
+
// Mimic the cross-fetch module, but replace its `fetch` with `mockFetch` and add a few extras
|
|
61
72
|
module.exports = {
|
|
73
|
+
...crossFetch, // Headers, Request, Response, etc.
|
|
74
|
+
default: mockFetch,
|
|
75
|
+
fetch: mockFetch,
|
|
62
76
|
mockFetch,
|
|
63
77
|
successText
|
|
64
78
|
};
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
{
|
|
2
|
+
"objName": "Stage",
|
|
3
|
+
"costumes": [{
|
|
4
|
+
"costumeName": "backdrop1",
|
|
5
|
+
"baseLayerID": -1,
|
|
6
|
+
"baseLayerMD5": "ba5d7bbc200d7925664a0878421c4ed2.png",
|
|
7
|
+
"bitmapResolution": 2,
|
|
8
|
+
"rotationCenterX": 480,
|
|
9
|
+
"rotationCenterY": 360
|
|
10
|
+
}],
|
|
11
|
+
"currentCostumeIndex": 0,
|
|
12
|
+
"penLayerMD5": "5c81a336fab8be57adc039a8a2b33ca9.png",
|
|
13
|
+
"penLayerID": -1,
|
|
14
|
+
"tempoBPM": 60,
|
|
15
|
+
"videoAlpha": 0.5,
|
|
16
|
+
"children": [{
|
|
17
|
+
"objName": "seymour cropped",
|
|
18
|
+
"scripts": [[89, 102, [["whenGreenFlag"], ["setSizeTo:", 85]]]],
|
|
19
|
+
"sounds": [{
|
|
20
|
+
"soundName": "pop",
|
|
21
|
+
"soundID": -1,
|
|
22
|
+
"md5": "83a9787d4cb6f3b7632b4ddfebf74367.wav",
|
|
23
|
+
"sampleCount": 258,
|
|
24
|
+
"rate": 11025,
|
|
25
|
+
"format": ""
|
|
26
|
+
}],
|
|
27
|
+
"costumes": [{
|
|
28
|
+
"costumeName": "SeymourPapert001",
|
|
29
|
+
"baseLayerID": -1,
|
|
30
|
+
"baseLayerMD5": "2c8559602a79c7ec929636c3a5ea0291.png",
|
|
31
|
+
"bitmapResolution": 2,
|
|
32
|
+
"rotationCenterX": 204,
|
|
33
|
+
"rotationCenterY": 262
|
|
34
|
+
}],
|
|
35
|
+
"currentCostumeIndex": 0,
|
|
36
|
+
"scratchX": 115,
|
|
37
|
+
"scratchY": -28,
|
|
38
|
+
"scale": 0.85,
|
|
39
|
+
"direction": 90,
|
|
40
|
+
"rotationStyle": "normal",
|
|
41
|
+
"isDraggable": false,
|
|
42
|
+
"indexInLibrary": 2,
|
|
43
|
+
"visible": true,
|
|
44
|
+
"spriteInfo": {
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"objName": "Sprite1",
|
|
49
|
+
"scripts": [[48,
|
|
50
|
+
24,
|
|
51
|
+
[["whenGreenFlag"],
|
|
52
|
+
["setSizeTo:", 110],
|
|
53
|
+
["wait:elapsed:from:", 1],
|
|
54
|
+
["say:", "Hi. I want to introduce you to Seymour Papert."],
|
|
55
|
+
["doPlaySoundAndWait", "papert1"],
|
|
56
|
+
["say:", "Seymour developed Logo, the first programming language for kids"],
|
|
57
|
+
["doPlaySoundAndWait", "papert2"],
|
|
58
|
+
["say:", "He believed that kids learn best"],
|
|
59
|
+
["doPlaySoundAndWait", "papert3"],
|
|
60
|
+
["say:", "when they are given the chance to create things and express themselves"],
|
|
61
|
+
["doPlaySoundAndWait", "papert4"],
|
|
62
|
+
["say:", "When we developed Scratch, we were very inspired by Seymour's ideas"],
|
|
63
|
+
["doPlaySoundAndWait", "papert5"],
|
|
64
|
+
["say:", "So you might call Seymour the grandfather of Scratch"],
|
|
65
|
+
["doPlaySoundAndWait", "papert6"],
|
|
66
|
+
["say:", "Sadly, Seymour passed away last week, on July 31, 2016"],
|
|
67
|
+
["doPlaySoundAndWait", "papert7"],
|
|
68
|
+
["say:", "But every time you create and share a Scratch project"],
|
|
69
|
+
["doPlaySoundAndWait", "papert8"],
|
|
70
|
+
["say:", "you're helping to keep Seymour's spirit alive"],
|
|
71
|
+
["doPlaySoundAndWait", "papert9"],
|
|
72
|
+
["say:", "So Scratch on!"],
|
|
73
|
+
["doPlaySoundAndWait", "papert10"],
|
|
74
|
+
["say:", "And Papert on!"],
|
|
75
|
+
["doPlaySoundAndWait", "papert11"],
|
|
76
|
+
["wait:elapsed:from:", 5],
|
|
77
|
+
["say:", ""]]]],
|
|
78
|
+
"sounds": [{
|
|
79
|
+
"soundName": "papert1",
|
|
80
|
+
"soundID": -1,
|
|
81
|
+
"md5": "876c45f175060737364334daed9366a1.wav",
|
|
82
|
+
"sampleCount": 84993,
|
|
83
|
+
"rate": 22050,
|
|
84
|
+
"format": ""
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"soundName": "papert2",
|
|
88
|
+
"soundID": -1,
|
|
89
|
+
"md5": "e439ca64ef29692ed611bb769fdbe543.wav",
|
|
90
|
+
"sampleCount": 103425,
|
|
91
|
+
"rate": 22050,
|
|
92
|
+
"format": ""
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"soundName": "papert3",
|
|
96
|
+
"soundID": -1,
|
|
97
|
+
"md5": "0bd55bc2b3ff5741bafe981decdaca5b.wav",
|
|
98
|
+
"sampleCount": 54273,
|
|
99
|
+
"rate": 22050,
|
|
100
|
+
"format": ""
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"soundName": "papert4",
|
|
104
|
+
"soundID": -1,
|
|
105
|
+
"md5": "123abc35f1934ed471436c59f7b99e2f.wav",
|
|
106
|
+
"sampleCount": 93185,
|
|
107
|
+
"rate": 22050,
|
|
108
|
+
"format": ""
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"soundName": "papert5",
|
|
112
|
+
"soundID": -1,
|
|
113
|
+
"md5": "cd9f672266016a0e55152b2a3398c8d9.wav",
|
|
114
|
+
"sampleCount": 113665,
|
|
115
|
+
"rate": 22050,
|
|
116
|
+
"format": ""
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"soundName": "papert6",
|
|
120
|
+
"soundID": -1,
|
|
121
|
+
"md5": "d38287334764b7d4cd2c5db59548234d.wav",
|
|
122
|
+
"sampleCount": 84993,
|
|
123
|
+
"rate": 22050,
|
|
124
|
+
"format": ""
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"soundName": "papert7",
|
|
128
|
+
"soundID": -1,
|
|
129
|
+
"md5": "fab6bf9923265a999bcfea1e62384a2c.wav",
|
|
130
|
+
"sampleCount": 144385,
|
|
131
|
+
"rate": 22050,
|
|
132
|
+
"format": ""
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"soundName": "papert8",
|
|
136
|
+
"soundID": -1,
|
|
137
|
+
"md5": "6826373fa0554c582f920cc65620395e.wav",
|
|
138
|
+
"sampleCount": 82945,
|
|
139
|
+
"rate": 22050,
|
|
140
|
+
"format": ""
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"soundName": "papert9",
|
|
144
|
+
"soundID": -1,
|
|
145
|
+
"md5": "c6b907cbfe0081748ae83cb3bb6aa6d8.wav",
|
|
146
|
+
"sampleCount": 74753,
|
|
147
|
+
"rate": 22050,
|
|
148
|
+
"format": ""
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
"soundName": "papert10",
|
|
152
|
+
"soundID": -1,
|
|
153
|
+
"md5": "f455697888f2e7b36072a2189fc78bbc.wav",
|
|
154
|
+
"sampleCount": 39937,
|
|
155
|
+
"rate": 22050,
|
|
156
|
+
"format": ""
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
"soundName": "papert11",
|
|
160
|
+
"soundID": -1,
|
|
161
|
+
"md5": "fb58460f1cd8629eae3b3c58148984ad.wav",
|
|
162
|
+
"sampleCount": 54273,
|
|
163
|
+
"rate": 22050,
|
|
164
|
+
"format": ""
|
|
165
|
+
}],
|
|
166
|
+
"costumes": [{
|
|
167
|
+
"costumeName": "-mres-cartoon",
|
|
168
|
+
"baseLayerID": -1,
|
|
169
|
+
"baseLayerMD5": "dd88c3596176f24479a8e8ec9b6c8278.png",
|
|
170
|
+
"bitmapResolution": 2,
|
|
171
|
+
"rotationCenterX": 122,
|
|
172
|
+
"rotationCenterY": 204
|
|
173
|
+
}],
|
|
174
|
+
"currentCostumeIndex": 0,
|
|
175
|
+
"scratchX": -137.95,
|
|
176
|
+
"scratchY": -71,
|
|
177
|
+
"scale": 1.1,
|
|
178
|
+
"direction": 90,
|
|
179
|
+
"rotationStyle": "normal",
|
|
180
|
+
"isDraggable": false,
|
|
181
|
+
"indexInLibrary": 1,
|
|
182
|
+
"visible": true,
|
|
183
|
+
"spriteInfo": {
|
|
184
|
+
}
|
|
185
|
+
}],
|
|
186
|
+
"info": {
|
|
187
|
+
"spriteCount": 2,
|
|
188
|
+
"hasCloudData": false,
|
|
189
|
+
"projectID": "117504922",
|
|
190
|
+
"flashVersion": "MAC 22,0,0,209",
|
|
191
|
+
"swfVersion": "v448",
|
|
192
|
+
"userAgent": "Mozilla\/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/51.0.2704.103 Safari\/537.36",
|
|
193
|
+
"scriptCount": 2,
|
|
194
|
+
"videoOn": false
|
|
195
|
+
}
|
|
196
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<svg version="1.1" id="cat" x="0px" y="0px" width="95px" height="111px" viewBox="0 0 95 111" enable-background="new 0 0 95 111" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
2
|
+
<g>
|
|
3
|
+
<g id="Layer_8">
|
|
4
|
+
<path fill="#FAA51D" stroke="#231F20" stroke-width="1.2" d="M23.754,82.506c-2.871-1.402-10.511-2.518-14.771-6.695
		c-9.431-9.246-3.824-21.732,0.704-21.797c3.611-0.061,3.363,5.482,4.622,11.145c0.875,3.939,1.673,6.988,6.407,9.674
		c4.735,2.688,6.918,2.916,6.918,2.916s3.258,0.791,1.596,2.562C27.568,82.076,23.754,82.506,23.754,82.506z"/>
|
|
5
|
+
<path fill="#FFFFFF" d="M14.291,66.369c-0.115-0.459-0.222-0.928-0.33-1.413c-1.172-5.271-0.941-10.432-4.303-10.377
		c-3.433,0.05-7.53,7.771-4.19,15.285c0.193-0.143,0.399-0.336,0.569-0.588c0.451-0.664,0.821-2.969,2.654-3.688
		C9.989,65.082,12.778,65.869,14.291,66.369z"/>
|
|
6
|
+
</g>
|
|
7
|
+
<path fill="#FAA51D" stroke="#231F20" stroke-width="1.2" d="M52.543,61.473c0,0,1.455,2.342,1.519,4.969
	c0.065,2.723-0.351,6.984,1.804,8.158c3.381,1.842,9.959-0.463,10.174,5.191c0.211,5.652-10.152,3.623-13.299,2.547
	c-2.695-0.926-4.559-1.758-5.18-5.182c0,0-3.764-13.969-0.196-15.59C50.933,59.945,52.543,61.473,52.543,61.473z"/>
|
|
8
|
+
<path fill="#FAA51D" stroke="#231F20" stroke-width="1.2" d="M14.61,89.584c0,0,1.504,10.391-5.922,8.387
	c-5.586-1.51-5.705-20.68-0.406-20.691c3.237-0.006,4.425,2.859,4.425,2.859s4.385,4.812,6.95,4.312
	c2.565-0.502,7.978-6.703,7.978-6.703s2.875-2.539,6.146,0.023c3.271,2.561,1.521,6.178,1.521,6.178s-6.07,7.072-11.014,8.072
	c-4.945,1.002-9.375-2.568-11.58-3.451"/>
|
|
9
|
+
<g id="Layer_6">
|
|
10
|
+
<path fill="#FAA51D" stroke="#231F20" stroke-width="1.2" d="M42.435,76.238c0,0,4.866,4.062,8.166,7.52
		c4.384,4.592-3.339,15.039-3.339,15.039s11.234,6.467,2.998,11c-2.657,1.467-15.661-13.225-15.661-13.225s7.979-7.475,4.972-10.172
		c-4.964-4.449-10.771-4.959-11.6-9.824c-0.502-2.957,0.613-4.502,2.658-7.053c1.354-1.689,2.084-3.182,2.084-3.182
		s1.135-7.238,4.289-8.254c3.153-1.014,8.842,0.057,10.758,0.395c1.914,0.338,6.645,1.877,4.617,9.922c0,0-1.451,3.771-2.789,5.762
		c-1.604,2.389-2.854,3.924-4.08,4.867"/>
|
|
11
|
+
<path fill="#FFFFFF" d="M50.182,72.631c0,0,2.55-2.748-2.551-5.494c-5.102-2.746-7.449-0.016-9.024,1.572
		c-2.731,2.742,3.334,7.453,3.334,7.453l3.383,2.564c0,0,1.916-1.582,2.701-2.957C48.807,74.396,50.182,72.631,50.182,72.631"/>
|
|
12
|
+
</g>
|
|
13
|
+
<path fill="#FAA51D" stroke="#231F20" stroke-width="1.2" d="M24.428,65.395c0.939,0.057,3.625,0.213,6.064,0.391
	c3.014,0.217,8.451-0.451,5.801-5.098c-2.649-4.65-6.74-3.674-11.961-3.754c-2.812-0.043-5.785-1.412-7.322,1.895
	c-1.534,3.312-5.051,13.338,2.313,15.396c7.366,2.057,4.618-8.137,4.95-10.457"/>
|
|
14
|
+
<g id="Layer_2">
|
|
15
|
+
<path fill="#FAA51D" stroke="#231F20" stroke-width="1.2" d="M51.709,10.156c-1.54-0.143-4.75-0.316-6.518-0.231
		c-4.728,0.225-9.224,1.928-9.224,1.928L22.949,3.357l2.235,18.906c0.646-0.782-10.555,12.804-3.479,24.224
		c7.08,11.426,22.233,16.518,40.988,12.792c18.755-3.728,23.229-14.531,21.986-20.246c-1.242-5.714-8.322-7.823-8.322-7.823
		s-0.09-4.48-3.328-9.97c-1.926-3.268-8.348-8.041-8.348-8.041L61.822,1.647L54.37,8.851L51.709,10.156z"/>
|
|
16
|
+
<path fill="#FFFFFF" d="M75.42,31.066l-2.483-2.064l-9.115,2.661c0,0,0,3.419-4.367,4.367c-4.37,0.951-11.211-2.277-11.211-2.277
		l-7.784,3.417c0,0-8.437,0.928-8.739,6.081C31.048,54.704,45.1,59.478,50.425,59.783c2.905,0.167,8.235-0.337,12.277-1.14
		c17.752-3.235,22.551-13.92,21.309-19.635c-1.242-5.714-7.977-7.196-7.977-7.196L75.42,31.066z"/>
|
|
17
|
+
<path fill="none" stroke="#231F20" stroke-width="1.2" d="M9.673,42.155c0,0,4.107,0.374,5.974,0.268
		c1.865-0.107,5.492-0.587,5.492-0.587"/>
|
|
18
|
+
<path fill="none" stroke="#231F20" stroke-width="1.2" d="M80.656,36.671c0,0,4.549-0.743,6.859-1.549
		c2.715-0.942,4.543-2.545,4.543-2.545"/>
|
|
19
|
+
<path fill="none" stroke="#231F20" stroke-width="1.2" d="M21.337,37.909c0,0-2.384-1.777-6.117-3.43
		c-4.134-1.831-6.405-2.303-6.405-2.303"/>
|
|
20
|
+
<path fill="none" stroke="#231F20" stroke-width="1.2" d="M81.117,42.622c0,0,2.726,1.104,5.533,1.385
		c2.77,0.276,4.647,0.11,4.647,0.11"/>
|
|
21
|
+
<path fill="none" stroke="#000000" stroke-linecap="round" stroke-miterlimit="10" d="M51.349,10.212
		c2.84,0.7,3.888,1.469,3.888,1.469"/>
|
|
22
|
+
<line fill="none" stroke="#000000" x1="32.898" y1="9.684" x2="38.956" y2="14.042"/>
|
|
23
|
+
</g>
|
|
24
|
+
<g id="Layer_5">
|
|
25
|
+
<path fill="#FFFFFF" stroke="#231F20" d="M70.84,21.366c2.924,4.479,3.033,9.591,0.242,11.415
		c-2.793,1.825-7.426-0.332-10.354-4.813c-2.932-4.48-3.037-9.589-0.244-11.415C63.275,14.73,67.913,16.884,70.84,21.366z"/>
|
|
26
|
+
<path fill="#231F20" d="M70.089,28.522c0,1.08-0.802,1.956-1.8,1.956c-0.993,0-1.803-0.877-1.803-1.956
		c0-1.08,0.81-1.958,1.803-1.958C69.287,26.564,70.089,27.442,70.089,28.522"/>
|
|
27
|
+
</g>
|
|
28
|
+
<g id="Layer_7">
|
|
29
|
+
<path fill="#FFFFFF" stroke="#231F20" d="M46.867,24.619c2.926,4.48,2.619,9.862-0.681,12.015
		c-3.302,2.159-8.351,0.272-11.276-4.208c-2.928-4.48-2.624-9.86,0.678-12.017C38.891,18.253,43.938,20.137,46.867,24.619z"/>
|
|
30
|
+
<path fill="#231F20" d="M45.079,30.507c0,1.081-0.803,1.957-1.801,1.957c-0.992,0-1.803-0.878-1.803-1.957
		c0-1.08,0.811-1.957,1.803-1.957C44.274,28.55,45.079,29.427,45.079,30.507"/>
|
|
31
|
+
</g>
|
|
32
|
+
<path fill="#5E4A42" stroke="#000000" d="M58.766,33.926c1.854,0,4.555-0.284,4.697,0.569c0.143,0.855-1.709,4.203-2.988,4.345
	c-1.283,0.142-6.125-2.353-6.195-3.919C54.206,33.355,57.055,33.926,58.766,33.926z"/>
|
|
33
|
+
<g id="Layer_4">
|
|
34
|
+
<path fill="none" stroke="#231F20" stroke-width="1.2" d="M45.774,41.235c0,0,10.347,3.054,14.217,3.897
		c3.868,0.842,10.851,1.684,10.851,1.684s-7.99,10.245-17.328,7.644C44.176,51.863,44.345,45.975,45.774,41.235z"/>
|
|
35
|
+
</g>
|
|
36
|
+
</g>
|
|
37
|
+
</svg>
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<svg version="1.1" id="Scratch_Cat_A" x="0px" y="0px" width="94.227px" height="104.333px" viewBox="0 -2 94.227 104.333" enable-background="new 0 -2 94.227 104.333" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
2
|
+
<g>
|
|
3
|
+
<path id="Back_Leg" fill="#FAA51D" stroke="#000000" d="M38.988,80.967c0,0-8.832,6.201-17.07,8.412l0.086,0.215
	c1.247,1.824,5.869,7.498-0.334,9.496c-5.333,1.718-15.12-13.104-10.821-15.901c2.626-1.713,4.892-0.252,4.892-0.252
	s3.475-1.069,6.001-2.345c4.304-2.162,5.784-3.453,5.784-3.453s4.185-4.307,6.856-4.137C37.051,73.172,42.44,77.715,38.988,80.967z
	 M19.646,90.09l2.271-0.711"/>
|
|
4
|
+
<g id="Tail">
|
|
5
|
+
<path id="Tail_1_" fill="#FAA51D" stroke="#000000" d="M23.295,73.217c-2.415-0.451-5.305-1.311-7.742-3.504
		c-5.451-4.906-7.194-13-11.048-10.914c-3.856,2.088-3.782,15.166,8.353,19.195c4.182,1.391,7.998,1.395,11.091,1.312
		c0.812-0.026,7.718-0.655,10.079-4.075c2.361-3.419,0.719-4.271-0.09-4.744C33.128,70.016,26.711,73.855,23.295,73.217z"/>
|
|
6
|
+
<path id="Tail_Tip" fill="#FFFFFF" d="M4.641,59.107c-1.437,0.778-2.256,3.397-1.994,6.374c0.141,1.594,1.104,5.652,4.968,9.072
		c0.275-0.545-0.975-2.936,0.742-4.379c1.837-1.543,4.86-1.225,5.853-1.061c-1.663-1.812-3.004-3.812-4.176-5.64
		C7.751,59.922,6.475,58.116,4.641,59.107z"/>
|
|
7
|
+
</g>
|
|
8
|
+
<path id="R_Arm" fill="#FAA51D" stroke="#000000" d="M52.94,69.096c0,0,1.234,0.166,4.744,3.677c3.509,3.509,6.025,2.16,8.911,0.724
	c2.877-1.442,10.536-6.127,6.489-9.817c-4.05-3.688-6.207,1.146-9.716,2.405c-3.511,1.26-5.06-2.487-6.856-4.287
	c-0.59-0.594-1.188-1.098-1.729-1.506c0,0-0.972-0.758-1.905,2.791C51.943,66.624,50.933,67.627,52.94,69.096z"/>
|
|
9
|
+
<g id="Front_Leg_x2F_Body_1_">
|
|
10
|
+
<path id="Front_Leg_x2F_Body" fill="#FAA51D" stroke="#000000" d="M47.524,76.224c1.188-0.912,2.396-2.401,3.951-4.714
		c1.296-1.926,2.699-5.577,2.699-5.577c0.875-2.521,1.935-6.576-1.901-7.296c-1.553-0.291-4.079-0.098-7.67-0.776
		c-3.593-0.681-6.798-2.522-9.517,2.233c-2.719,4.757-9.591,8.271-1.057,16.562c0,0,4.901,3.842,10.765,9.639
		c4.832,4.774,12.044,10.603,12.044,10.603s18.973,2.188,19.534-0.694c1.923-9.789-14.775-6.91-14.775-6.91
		s-4.604-3.933-6.727-5.795c-3.477-3.058-11.125-10.771-11.125-10.771"/>
|
|
11
|
+
<path id="Belly" fill="#FFFFFF" d="M49.74,64.551C44.8,61.895,42.526,64.536,41,66.073c-2.645,2.654,3.442,6.61,3.442,6.61
		l3.062,3.089c2.999-3.496,4.579-5.874,5.292-7.934C52.654,66.897,51.918,65.725,49.74,64.551z"/>
|
|
12
|
+
</g>
|
|
13
|
+
<path id="L_Arm" fill="#FAA51D" stroke="#000000" d="M30.697,67.43c0.749-0.571,2.89-2.202,4.854-3.657
	c2.428-1.799,6.117-5.849,1.077-7.646c-5.04-1.801-7.508,1.604-11.52,4.945c-2.159,1.801-5.308,2.698-4.319,6.209
	c0.993,3.512,4.862,13.407,11.789,10.17c6.93-3.238-1.799-9.181-3.06-11.156"/>
|
|
14
|
+
<g id="Head">
|
|
15
|
+
<g id="Head_1_">
|
|
16
|
+
<path id="Head_Fill" fill="#FAA51D" stroke="#000000" d="M86.452,37.457c-1.472-6.447-8.891-7.579-8.891-7.579
			s0.176-5.351-2.628-10.347c-1.856-3.307-8.351-8.042-8.351-8.042l-2.854-11.55l-7.43,7.32l-2.854,1.105
			c-1.539-0.143-4.718-0.312-6.485-0.227c-4.729,0.225-9.227,2.036-9.227,2.036L24.854,1.649l2.233,18.91
			c0.646-0.786-10.553,12.802-3.477,24.22c3.319,5.36,10.159,10.124,15.599,11.947c4.062,1.36,10.833,1.737,14,1.737
			c2.646,0,7.768-0.541,10.32-0.979c3.021-0.519,6.479-1.629,10.055-3.108C83.081,50.442,87.922,43.904,86.452,37.457z
			 M39.771,12.212l-2.035-2.039 M53.688,8.212c2,0.333,4.333,1.366,4.333,1.366"/>
|
|
17
|
+
<path id="Muzzle" fill="#FFFFFF" d="M77.146,30.129l-2.881-3.107l-9.113,2.661c0,0.01-0.005,1.619-1.42,2.933
			c-0.646,0.6-1.583,1.138-2.948,1.435c-4.371,0.951-11.212-2.277-11.212-2.277l-7.784,3.417c0,0-4.744,0.522-7.244,2.956
			c-0.833,0.812-1.417,1.835-1.492,3.123c-0.493,8.398,8.68,13.252,15.083,15.602c1.778,0.652,2.388,0.851,3.472,1.139
			c0,0,7.424-0.195,10.181-0.588c3.032-0.432,7.578-1.758,11.154-3.236c9.498-3.933,14.601-10.024,13.129-16.471
			C84.597,31.265,77.146,30.129,77.146,30.129z"/>
|
|
18
|
+
</g>
|
|
19
|
+
<g id="L_Eye">
|
|
20
|
+
<path id="Eyeball_1_" fill="#FFFFFF" stroke="#000000" d="M48.638,22.831c2.926,4.48,2.618,9.862-0.682,12.015
			c-3.303,2.159-8.352,0.272-11.275-4.208c-2.928-4.48-2.624-9.86,0.678-12.017C40.661,16.465,45.709,18.349,48.638,22.831"/>
|
|
21
|
+
<path id="Pupil_1_" d="M46.85,28.719c0,1.081-0.803,1.957-1.801,1.957c-0.992,0-1.804-0.878-1.804-1.957
			c0-1.08,0.812-1.957,1.804-1.957C46.045,26.762,46.85,27.639,46.85,28.719"/>
|
|
22
|
+
</g>
|
|
23
|
+
<g id="R_Eye">
|
|
24
|
+
<path id="Eyeball" fill="#FFFFFF" stroke="#000000" d="M72.361,19.75c2.925,4.479,3.283,9.419,0.492,11.243
			c-2.793,1.825-7.181-0.552-10.104-5.034c-2.933-4.48-3.079-9.134-0.286-10.959C65.25,13.177,69.434,15.268,72.361,19.75"/>
|
|
25
|
+
<path id="Pupil" d="M71.86,26.734c0,1.08-0.802,1.956-1.8,1.956c-0.993,0-1.804-0.877-1.804-1.956c0-1.08,0.811-1.958,1.804-1.958
			C71.058,24.776,71.86,25.654,71.86,26.734"/>
|
|
26
|
+
</g>
|
|
27
|
+
<path id="Nose" fill="#5E4A42" stroke="#000000" d="M60.536,32.138c1.854,0,4.556-0.284,4.696,0.569
		c0.145,0.855-1.709,4.203-2.987,4.345c-1.282,0.142-6.125-2.353-6.194-3.919C55.977,31.567,58.825,32.138,60.536,32.138"/>
|
|
28
|
+
<path id="Whisker_3_" d="M22.75,36.602c-0.023-0.017-2.382-1.76-6.002-3.362c-4.012-1.777-6.263-2.26-6.284-2.265l0.245-1.175
		c0.095,0.02,2.381,0.506,6.525,2.342c3.751,1.661,6.133,3.424,6.232,3.498L22.75,36.602L22.75,36.602z"/>
|
|
29
|
+
<path id="Whisker_2_" d="M16.628,41.254c-2.035,0-5.092-0.276-5.238-0.289l0.107-1.195c0.041,0.004,4.088,0.367,5.887,0.266
		c1.82-0.104,5.412-0.578,5.447-0.583l0.157,1.189c-0.148,0.02-3.67,0.484-5.537,0.591C17.209,41.248,16.929,41.254,16.628,41.254
		L16.628,41.254z"/>
|
|
30
|
+
<path id="Whisker_1_" d="M82.524,35.475L82.33,34.29c0.046-0.007,4.524-0.744,6.761-1.523c2.573-0.894,4.326-2.415,4.345-2.43
		l0.791,0.902c-0.078,0.068-1.948,1.691-4.742,2.661C87.151,34.714,82.711,35.444,82.524,35.475L82.524,35.475z"/>
|
|
31
|
+
<path id="Whisker" d="M91.551,42.979c-0.812,0-1.905-0.035-3.189-0.163c-2.858-0.286-5.584-1.379-5.699-1.426l0.45-1.112
		c0.027,0.011,2.686,1.075,5.368,1.344c2.672,0.267,4.518,0.111,4.535,0.11l0.104,1.195C93.077,42.931,92.508,42.979,91.551,42.979
		L91.551,42.979z"/>
|
|
32
|
+
<path id="Mouth" fill="none" stroke="#231F20" stroke-width="1.2" d="M47.545,39.447c0,0,10.347,3.054,14.217,3.896
		c3.867,0.842,10.851,1.684,10.851,1.684s-7.989,10.245-17.327,7.645C45.947,50.075,46.115,44.187,47.545,39.447z"/>
|
|
33
|
+
</g>
|
|
34
|
+
</g>
|
|
35
|
+
</svg>
|
|
Binary file
|