selkie 1.0.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/README.md +19 -0
- package/index.js +114 -0
- package/package.json +25 -0
- package/package_details.js +20 -0
- package/templates.js +80 -0
package/README.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Selkie
|
|
2
|
+
|
|
3
|
+
In Celtic mythology, selkies are beings that can transform from seals into humans by shedding their seal skins. They often feature in stories of love and longing, where a selkie's human form is hidden away or discovered by a human.
|
|
4
|
+
|
|
5
|
+
This library is heavily influenced as a template starter for generative projects. For now it only works with p5. I'll be extending it to also include other templates.
|
|
6
|
+
|
|
7
|
+
This is a project to help better understand the process of streamlining my sketches in p5. I've been able to quickly iternate using Processing for years now. But I want to really get a grasp on creating a system that will generate the work that I will be able to use.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install selkie
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
In order to create a new project, use the following after it has been installed.
|
|
15
|
+
```bash
|
|
16
|
+
selkie -t default
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
|
package/index.js
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import inquirer from 'inquirer';
|
|
4
|
+
import fs from 'fs-extra';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import { Command } from 'commander';
|
|
7
|
+
import { fileURLToPath } from 'url';
|
|
8
|
+
import { exec, execSync } from 'child_process';
|
|
9
|
+
import { template as defaultTemplate } from './templates.js';
|
|
10
|
+
import { packageJsonContent } from './package_details.js';
|
|
11
|
+
|
|
12
|
+
// Convert import.meta.url to a file path
|
|
13
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
14
|
+
const __dirname = path.dirname(__filename);
|
|
15
|
+
|
|
16
|
+
// Initialize commander
|
|
17
|
+
const program = new Command();
|
|
18
|
+
program
|
|
19
|
+
.version('1.0.0')
|
|
20
|
+
.option('-t, --template <type>', 'specify the template type')
|
|
21
|
+
.parse(process.argv);
|
|
22
|
+
|
|
23
|
+
const options = program.opts();
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
// Function to create the project
|
|
28
|
+
async function createProject() {
|
|
29
|
+
// Prompt the user for the folder name
|
|
30
|
+
const { folderName } = await inquirer.prompt([
|
|
31
|
+
{
|
|
32
|
+
type: 'input',
|
|
33
|
+
name: 'folderName',
|
|
34
|
+
message: 'Enter the name of the new folder:',
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
]);
|
|
38
|
+
|
|
39
|
+
// Construct the paths
|
|
40
|
+
const folderPath = path.join(process.cwd(), folderName);
|
|
41
|
+
const scriptsPath = path.join(folderPath, 'scripts');
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
// Create folders
|
|
45
|
+
await fs.ensureDir(scriptsPath);
|
|
46
|
+
|
|
47
|
+
// Choose the template
|
|
48
|
+
let htmlContent, sketchContent, randomContent;
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
if (options.template === 'default' || !options.template) {
|
|
52
|
+
htmlContent = defaultTemplate.htmlContent;
|
|
53
|
+
sketchContent = defaultTemplate.sketchContent;
|
|
54
|
+
randomContent = defaultTemplate.randomContent;
|
|
55
|
+
} else {
|
|
56
|
+
throw new Error('Unknown template type');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Create index.html
|
|
60
|
+
await fs.writeFile(path.join(folderPath, 'index.html'), htmlContent.trim());
|
|
61
|
+
|
|
62
|
+
// Create package.json
|
|
63
|
+
const packageJsonPath = path.join(folderPath, 'package.json');
|
|
64
|
+
const packageJson = packageJsonContent.replace(/"project-name"/, `"${folderName}"`);
|
|
65
|
+
await fs.writeFile(packageJsonPath, packageJson.trim());
|
|
66
|
+
|
|
67
|
+
// Install dependencies
|
|
68
|
+
console.log('Installing dependencies...');
|
|
69
|
+
execSync('npm install -s', { cwd: folderPath, stdio: 'inherit' });
|
|
70
|
+
|
|
71
|
+
// Check if p5.min.js exists and copy it to the scripts folder
|
|
72
|
+
const p5Path = path.join(__dirname, 'node_modules', 'p5', 'lib', 'p5.min.js');
|
|
73
|
+
if (await fs.pathExists(p5Path)) {
|
|
74
|
+
await fs.copyFile(p5Path, path.join(scriptsPath, 'p5.js'));
|
|
75
|
+
console.log('p5.js copied successfully.');
|
|
76
|
+
} else {
|
|
77
|
+
throw new Error(`p5.min.js not found at ${p5Path}`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Create sketch.js
|
|
81
|
+
await fs.writeFile(path.join(scriptsPath, 'sketch.js'), sketchContent.trim());
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
// Create random.js
|
|
85
|
+
await fs.writeFile(path.join(scriptsPath, 'random.js'), randomContent.trim());
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
// Create index.html
|
|
89
|
+
await fs.writeFile(path.join(folderPath, 'index.html'), htmlContent.trim());
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
console.log(`Project ${folderName} created successfully.`);
|
|
93
|
+
|
|
94
|
+
// Ask if the user wants to start the development server
|
|
95
|
+
const { startServer } = await inquirer.prompt([
|
|
96
|
+
{
|
|
97
|
+
type: 'confirm',
|
|
98
|
+
name: 'startServer',
|
|
99
|
+
message: 'Do you want to start the development server?',
|
|
100
|
+
default: true,
|
|
101
|
+
},
|
|
102
|
+
]);
|
|
103
|
+
|
|
104
|
+
if (startServer) {
|
|
105
|
+
console.log('Starting development server...');
|
|
106
|
+
execSync('npm start', { cwd: folderPath, stdio: 'inherit' });
|
|
107
|
+
}
|
|
108
|
+
} catch (error) {
|
|
109
|
+
console.error('Error creating project:', error);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Execute the function
|
|
114
|
+
createProject();
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "selkie",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Simple generative template creation",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"selkie": "./index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [],
|
|
14
|
+
"author": "generatecoll",
|
|
15
|
+
"license": "ISC",
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"commander": "^12.1.0",
|
|
18
|
+
"fs-extra": "^11.2.0",
|
|
19
|
+
"inquirer": "^9.2.22",
|
|
20
|
+
"p5": "^1.9.4"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"live-server": "^1.2.2"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
|
|
2
|
+
export const packageJsonContent = `{
|
|
3
|
+
"name": "project-name",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"description": "",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"start": "live-server"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"p5": "^1.4.0"
|
|
12
|
+
},
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"live-server": "^1.2.1"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [],
|
|
17
|
+
"author": "",
|
|
18
|
+
"license": "ISC"
|
|
19
|
+
}
|
|
20
|
+
`;
|
package/templates.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
export const template = {
|
|
2
|
+
htmlContent:
|
|
3
|
+
`<!DOCTYPE html>
|
|
4
|
+
<html>
|
|
5
|
+
<head>
|
|
6
|
+
<title>p5.js Sketch</title>
|
|
7
|
+
<script src="scripts/p5.js"></script>
|
|
8
|
+
<script src="scripts/sketch.js"></script>
|
|
9
|
+
<script src="scripts/random.js"></script>
|
|
10
|
+
</head>
|
|
11
|
+
<body>
|
|
12
|
+
</body>
|
|
13
|
+
</html>`,
|
|
14
|
+
sketchContent: `function setup() {
|
|
15
|
+
createCanvas(400, 400);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function draw() {
|
|
19
|
+
background(220);
|
|
20
|
+
}`,
|
|
21
|
+
randomContent: `
|
|
22
|
+
// RANDOM Class ////////////////////////////////////////////////////////////
|
|
23
|
+
class Random {
|
|
24
|
+
constructor () {
|
|
25
|
+
this.useA = false;
|
|
26
|
+
let sfc32 = function (uint128Hex) {
|
|
27
|
+
let a = parseInt (uint128Hex.substr (0, 8), 16);
|
|
28
|
+
let b = parseInt (uint128Hex.substr (8, 8), 16);
|
|
29
|
+
let c = parseInt (uint128Hex.substr (16, 8), 16);
|
|
30
|
+
let d = parseInt (uint128Hex.substr (24, 8), 16);
|
|
31
|
+
return function () {
|
|
32
|
+
a |= 0;
|
|
33
|
+
b |= 0;
|
|
34
|
+
c |= 0;
|
|
35
|
+
d |= 0;
|
|
36
|
+
let t = (((a + b) | 0) + d) | 0;
|
|
37
|
+
d = (d + 1) | 0;
|
|
38
|
+
a = b ^ (b >>> 9);
|
|
39
|
+
b = (c + (c << 3)) | 0;
|
|
40
|
+
c = (c << 21) | (c >>> 11);
|
|
41
|
+
c = (c + t) | 0;
|
|
42
|
+
return (t >>> 0) / 4294967296;
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
// seed prngA with first half of tokenData.hash
|
|
46
|
+
this.prngA = new sfc32 (tokenData.hash.substr (2, 32));
|
|
47
|
+
// seed prngB with second half of tokenData.hash
|
|
48
|
+
this.prngB = new sfc32 (tokenData.hash.substr (34, 32));
|
|
49
|
+
for (let i = 0; i < 1e6; i += 2) {
|
|
50
|
+
this.prngA ();
|
|
51
|
+
this.prngB ();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// random number between 0 (inclusive) and 1 (exclusive)
|
|
55
|
+
random_dec () {
|
|
56
|
+
this.useA = !this.useA;
|
|
57
|
+
return this.useA ? this.prngA () : this.prngB ();
|
|
58
|
+
}
|
|
59
|
+
// random number between a (inclusive) and b (exclusive)
|
|
60
|
+
random_num (a, b) {
|
|
61
|
+
return a + (b - a) * this.random_dec ();
|
|
62
|
+
}
|
|
63
|
+
// random integer between a (inclusive) and b (inclusive)
|
|
64
|
+
// requires a < b for proper probability distribution
|
|
65
|
+
random_int (a, b) {
|
|
66
|
+
return Math.floor (this.random_num (a, b + 1));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// random boolean with p as percent liklihood of true
|
|
70
|
+
random_bool (p) {
|
|
71
|
+
return this.random_dec () < p;
|
|
72
|
+
}
|
|
73
|
+
// random value in an array of items
|
|
74
|
+
random_choice (list) {
|
|
75
|
+
return list[this.random_int (0, list.length - 1)];
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
`
|
|
80
|
+
}
|