Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

scratch-analysis

Package Overview
Dependencies
Maintainers
0
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

scratch-analysis - npm Package Compare versions

Comparing version 2.2.0 to 2.2.1

.github/CODEOWNERS.md

24

lib/sb2.js

@@ -71,2 +71,24 @@ const utility = require('./utility');

/**
* Extract summary information about backdrops including
* count, list of backdrop names and list of backdrop hashes.
* Backdrops are a subset of all costumes.
* Backdrops are a costumes from the stage object.
* @param {object} project Project object (SB2 format)
* @return {object} Summary information
*/
const backdrops = function (project) {
let stageCostumes = project.costumes;
if (!Array.isArray(stageCostumes)) {
return {count: 0, id: [], hash: []};
}
return {
count: stageCostumes.length,
id: stageCostumes.map((sc) => sc.costumeName),
hash: stageCostumes.map((sc) => sc.baseLayerMD5)
};
};
/**
* Extract number of sprites from a project object. Will attempt to ignore

@@ -231,2 +253,4 @@ * "children" which are not sprites.

meta.backdrops = backdrops(project);
meta.cloud = cloud(project, meta.variables.id);

@@ -233,0 +257,0 @@

47

lib/sb3.js

@@ -19,2 +19,27 @@ const utility = require('./utility');

const costumes = function (targets) {
// Storage objects
let occurrences = 0;
let nameList = [];
let hashList = [];
for (let t in targets) {
for (let a in targets[t].costumes) {
const costume = targets[t].costumes[a];
occurrences++;
nameList.push(costume.name);
let hash = costume.md5ext || `${costume.assetId}.${costume.dataFormat}`;
hashList.push(hash);
}
}
// field are named this way to keep backward compatibility
return {
count: occurrences,
id: nameList,
hash: hashList
};
};
const variables = function (targets, attribute) {

@@ -96,6 +121,18 @@ // Storage objects

const block = targets[t].blocks[a];
let opcode = block.opcode;
// Check for primitive blocks which don't have the opcode field
if (typeof opcode === 'undefined') {
switch (block[0]) {
case (12):
opcode = 'data_variable';
break;
case (13):
opcode = 'data_listcontents';
break;
}
}
// Get opcode and check variable manipulation for the presence of
// cloud variables
let opcode = block.opcode;
if (opcode === 'data_setvariableto' || opcode === 'data_changevariableby') {

@@ -138,2 +175,6 @@ if (isArgCloudVar(block.fields.VARIABLE[1])) {

const stageTargets = function (targets) {
return targets.filter((target) => target.isStage);
};
module.exports = function (project, callback) {

@@ -147,3 +188,5 @@ const meta = {

sounds: extract(project.targets, 'sounds', 'name', 'md5ext'),
costumes: extract(project.targets, 'costumes', 'name', 'md5ext'),
costumes: costumes(project.targets),
// backdrops are costumes on the stage target
backdrops: costumes(stageTargets(project.targets)),
sprites: sprites(project.targets),

@@ -150,0 +193,0 @@ blocks: blocks(project.targets),

3

package.json
{
"name": "scratch-analysis",
"version": "2.2.0",
"version": "2.2.1",
"description": "Analysis tool for summarizing the structure, composition, and complexity of Scratch programs.",

@@ -24,4 +24,5 @@ "main": "lib/index.js",

"eslint-config-scratch": "^7.0.0",
"scratch-semantic-release-config": "1.0.8",
"tap": "^16.2.0"
}
}

@@ -72,2 +72,10 @@ {

"rotationCenterY": 53
},
{
"assetId": "d27716e022fb5f747d7b09fe6eeeca06",
"name": "costume_without_md5ext",
"bitmapResolution": 1,
"dataFormat": "svg",
"rotationCenterX": 71,
"rotationCenterY": 107
}

@@ -74,0 +82,0 @@ ],

@@ -5,2 +5,5 @@ const fs = require('fs');

const analysis = require('../../lib/index');
// using the sb2 directly to bypass scratch-parser and excersise
// logic targeting broken project files
const sb2 = require('../../lib/sb2');

@@ -17,2 +20,6 @@ const defaultObject = fs.readFileSync(

const invalidCostumes = fs.readFileSync(
path.resolve(__dirname, '../fixtures/sb2/invalid-costumes.json')
);
test('default (object)', t => {

@@ -61,2 +68,11 @@ analysis(defaultObject, (err, result) => {

t.type(result.backdrops, 'object');
t.equal(result.backdrops.count, 1);
t.same(result.backdrops.id, [
'backdrop1'
]);
t.same(result.backdrops.hash, [
'739b5e2a2435f6e1ec2993791b423146.png'
]);
t.type(result.sprites, 'object');

@@ -125,2 +141,11 @@ t.equal(result.sprites.count, 1);

t.type(result.backdrops, 'object');
t.equal(result.backdrops.count, 1);
t.same(result.backdrops.id, [
'backdrop1'
]);
t.same(result.backdrops.hash, [
'739b5e2a2435f6e1ec2993791b423146.png'
]);
t.type(result.sprites, 'object');

@@ -192,2 +217,11 @@ t.equal(result.sprites.count, 1);

t.type(result.backdrops, 'object');
t.equal(result.backdrops.count, 1);
t.same(result.backdrops.id, [
'backdrop1'
]);
t.same(result.backdrops.hash, [
'5b465b3b07d39019109d8dc6d6ee6593.svg'
]);
t.type(result.sprites, 'object');

@@ -265,1 +299,16 @@ t.equal(result.sprites.count, 1);

});
test('stage with invalid costumes', t => {
const project = JSON.parse(invalidCostumes);
sb2(project, (err, result) => {
t.ok(typeof err === 'undefined' || err === null);
t.type(result, 'object');
t.type(result.backdrops, 'object');
t.equal(result.backdrops.count, 0);
t.same(result.backdrops.id, []);
t.same(result.backdrops.hash, []);
t.end();
});
});

@@ -24,2 +24,6 @@ const fs = require('fs');

const primitiveVariableAndListBlocks = fs.readFileSync(
path.resolve(__dirname, '../fixtures/sb3/primitiveVariableAndListBlocks.json')
);
test('default (object)', t => {

@@ -58,7 +62,8 @@ analysis(defaultObject, (err, result) => {

t.type(result.costumes, 'object');
t.equal(result.costumes.count, 3);
t.equal(result.costumes.count, 4);
t.same(result.costumes.id, [
'backdrop1',
'costume1',
'costume2'
'costume2',
'costume_without_md5ext'
]);

@@ -68,5 +73,15 @@ t.same(result.costumes.hash, [

'b7853f557e4426412e64bb3da6531a99.svg',
'e6ddc55a6ddd9cc9d84fe0b4c21e016f.svg'
'e6ddc55a6ddd9cc9d84fe0b4c21e016f.svg',
'd27716e022fb5f747d7b09fe6eeeca06.svg'
]);
t.type(result.backdrops, 'object');
t.equal(result.backdrops.count, 1);
t.same(result.backdrops.id, [
'backdrop1'
]);
t.same(result.backdrops.hash, [
'cd21514d0531fdffb22204e0ec5ed84a.svg'
]);
t.type(result.sprites, 'object');

@@ -124,7 +139,8 @@ t.equal(result.sprites.count, 1);

t.type(result.costumes, 'object');
t.equal(result.costumes.count, 3);
t.equal(result.costumes.count, 4);
t.same(result.costumes.id, [
'backdrop1',
'costume1',
'costume2'
'costume2',
'costume_without_md5ext'
]);

@@ -134,5 +150,15 @@ t.same(result.costumes.hash, [

'b7853f557e4426412e64bb3da6531a99.svg',
'e6ddc55a6ddd9cc9d84fe0b4c21e016f.svg'
'e6ddc55a6ddd9cc9d84fe0b4c21e016f.svg',
'd27716e022fb5f747d7b09fe6eeeca06.svg'
]);
t.type(result.backdrops, 'object');
t.equal(result.backdrops.count, 1);
t.same(result.backdrops.id, [
'backdrop1'
]);
t.same(result.backdrops.hash, [
'cd21514d0531fdffb22204e0ec5ed84a.svg'
]);
t.type(result.sprites, 'object');

@@ -207,2 +233,11 @@ t.equal(result.sprites.count, 1);

t.type(result.backdrops, 'object');
t.equal(result.backdrops.count, 1);
t.same(result.backdrops.id, [
'backdrop1'
]);
t.same(result.backdrops.hash, [
'7633d36de03d1df75808f581bbccc742.svg'
]);
t.type(result.sprites, 'object');

@@ -342,2 +377,11 @@ t.equal(result.sprites.count, 1);

t.type(result.backdrops, 'object');
t.equal(result.backdrops.count, 1);
t.same(result.backdrops.id, [
'backdrop1'
]);
t.same(result.backdrops.hash, [
'cd21514d0531fdffb22204e0ec5ed84a.svg'
]);
t.type(result.sprites, 'object');

@@ -361,1 +405,35 @@ t.equal(result.sprites.count, 1);

});
test('correctly handling primitve reporter blocks: list and variable', t => {
analysis(primitiveVariableAndListBlocks, (err, result) => {
t.ok(typeof err === 'undefined' || err === null);
t.type(result, 'object');
t.type(result.variables, 'object');
t.equal(result.variables.count, 1);
t.same(result.variables.id, [
'my_variable'
]);
t.type(result.lists, 'object');
t.equal(result.lists.count, 1);
t.same(result.lists.id, [
'my_list'
]);
t.type(result.blocks, 'object');
t.equal(result.blocks.count, 3);
t.equal(result.blocks.unique, 3);
t.same(result.blocks.id, [
'data_listcontents',
'motion_changexby',
'data_variable'
]);
t.same(result.blocks.frequency, {
data_listcontents: 1,
motion_changexby: 1,
data_variable: 1
});
t.end();
});
});

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc