Add metadata to zipArchives (display Github links in explorer)

This commit is contained in:
ochafik 2023-03-27 19:34:52 +01:00
commit 0ed2d658d0
5 changed files with 186 additions and 56 deletions

View file

@ -31,9 +31,11 @@ Licenses: see [LICENSES](./LICENSE).
- Proper PWA w/ File opening / association to *.scad files
- Animation rendering (And other formats than STL)
- Compress URL fragment
- Customizer support. Probably by adding --export-json or --export-format=customizer-json to OpenSCAD.
- Customizer support. Probably by adding --export-json or --export-format=customizer-json to OpenSCAD. And use React Hook Forms maybe? https://react-hook-form.com/
- Mobile (iOS) editing support: switch to https://www.npmjs.com/package/react-codemirror ?
- Proper Preview rendering: have OpenSCAD export the preview scene to a rich format (e.g. glTF, with some parts being translucent when prefixed w/ % modifier) and display it using https://modelviewer.dev/ maybe)
- Detect which bundled libraries are included / used in the sources and only download these rather than wait for all of the zips. Means the file explorer would need to be more lazy or have some prebuilt hierarchy.
- Preparse builtin libraries definitions at compile time, ship the JSON.
## Building

View file

@ -7,6 +7,7 @@ import { ModelContext, FSContext } from './contexts';
// import { isFileWritable } from '../state/model';
import { join } from '../fs/filesystem';
import { defaultSourcePath } from '../state/initial-state';
import { zipArchives } from '../fs/zip-archives';
function listFilesAsNodes(fs: FS, path: string, accept?: (path: string) => boolean): TreeNode[] {
const files: [string, string][] = []
@ -15,7 +16,7 @@ function listFilesAsNodes(fs: FS, path: string, accept?: (path: string) => boole
if (name.startsWith('.')) {
continue;
}
const childPath = join(path, name);//`${path}/${name}`;
const childPath = join(path, name);
if (accept && !accept(childPath)) {
continue;
}
@ -31,19 +32,47 @@ function listFilesAsNodes(fs: FS, path: string, accept?: (path: string) => boole
const nodes: TreeNode[] = []
for (const [arr, isDirectory] of [[files, false], [dirs, true]] as [[string, string][], boolean][]) {
for (const [name, path] of arr) {
const children = isDirectory ? listFilesAsNodes(fs, path) : undefined;
if (isDirectory && children!.length == 0) {
continue;
let children: TreeNode[] = [];
let label = name;
if (path.lastIndexOf('/') === 0) {
const config = zipArchives[name];
if (config && config.gitOrigin) {
const repoUrl = config.gitOrigin.repoUrl;
if (!children) children = [];
children.push({
icon: 'pi pi-github',
label: repoUrl,
key: repoUrl,
selectable: true,
});
for (const [label, link] of Object.entries(config.docs ?? [])) {
children.push({
icon: 'pi pi-book',
label,
key: link,
selectable: true,
});
}
}
}
if (isDirectory) {
children = [...children, ...listFilesAsNodes(fs, path, accept)];
if (children.length == 0) {
continue;
}
}
nodes.push({
// icon: path == '/home' ? 'pi-home' : ...
// icon: isDirectory ? 'pi pi-folder' : isFileWritable(path) ? 'pi pi-file' : 'pi pi-lock',
icon: isDirectory ? 'pi pi-folder' : path === defaultSourcePath ? 'pi pi-home' : 'pi pi-file',
label: name,
label,
data: path,
key: path,
children,
selectable: !isDirectory // && (name == 'LICENSE' || name.endsWith('.scad') || name.endsWith('.scad')
selectable: !isDirectory
});
}
}
@ -58,34 +87,26 @@ export default function FilePicker({className, style}: {className?: string, styl
const fs = useContext(FSContext);
const fsItems = fs && listFilesAsNodes(fs, '/')
// [
// {
// icon: 'pi pi-home',
// label: 'User files',
// key: '/',
// children: listFilesAsNodes(fs, '/'),//
// // children: listFilesAsNodes(fs, '/', f => f != librariesFolder && !f.startsWith(`${librariesFolder}/`)),
// selectable: false
// },
// {
// icon: 'pi pi-database',
// label: 'Builtin libraries',
// key: '/libraries',
// children: listFilesAsNodes(fs, '/libraries'),
// selectable: false
// },
// ] || [];
return (
<TreeSelect
className={className}
title='OpenSCAD Playground Files'
value={state.params.sourcePath}
onChange={(e) => model.openFile(String(e.value))}
// dropdownIcon="pi pi-folder-open"
resetFilterOnHide={true}
filterBy="key"
onChange={e => {
const key = e.value;
if (typeof key === 'string') {
if (key.startsWith('https://')) {
window.open(key, '_blank')
} else {
model.openFile(key);
}
}
}}
filter
style={style}
// style={{style}}
options={fsItems} />
)
}

View file

@ -1,6 +1,6 @@
// Portions of this file are Copyright 2021 Google LLC, and licensed under GPL2+. See COPYING.
import { zipArchives } from "./zip-archives";
import { deployedArchiveNames, zipArchives } from "./zip-archives";
declare var BrowserFS: BrowserFSInterface
@ -56,7 +56,7 @@ export async function symlinkLibraries(archiveNames: string[], fs: FS, prefix='/
};
await Promise.all(archiveNames.map(n => (async () => {
if (!(n in zipArchives)) throw new Error(`Archive named ${n} invalid (valid ones: ${Object.keys(zipArchives).join(', ')})`);
if (!(n in zipArchives)) throw new Error(`Archive named ${n} invalid (valid ones: ${deployedArchiveNames.join(', ')})`);
const {symlinks} = (zipArchives)[n];
if (symlinks) {
for (const from in symlinks) {
@ -87,7 +87,7 @@ function configureAndInstallFS(windowOrSelf: Window, options: any) {
}
export async function createEditorFS(prefix: string): Promise<FS> {
const archiveNames = Object.keys(zipArchives);
const archiveNames = deployedArchiveNames;
const librariesMounts = await getBrowserFSLibrariesMounts(archiveNames);
const allMounts: FSMounts = {};
for (const n in librariesMounts) {

View file

@ -4,47 +4,152 @@ import { Symlinks } from "./filesystem";
export type ZipArchives = {
[name: string]: {
symlinks?: Symlinks
deployed?: boolean,
description?: string,
gitOrigin?: {
repoUrl: string,
branch: string,
include: {
glob: string | string[],
ignore?: string | string[],
replacePrefix?: {[path: string]: string},
}[]
}
symlinks?: Symlinks,
docs?: {[name: string]: string}
}
};
export const zipArchives: ZipArchives = {
'fonts': {},
// @openscad
'MCAD': {},
// @revarbat
'BOSL': {},
'BOSL2': {
// "includes": {
// "BOSL2/std.scad": "The Belfry OpenScad Library, v2.0. An OpenSCAD library of shapes, masks, and manipulators to make working with OpenSCAD easier. BETA"
// }
'MCAD': {
description: 'OpenSCAD Parametric CAD Library',
gitOrigin: {
branch: 'master',
repoUrl: 'https://github.com/openscad/MCAD',
include: [{glob: ['*.scad', 'bitmap/*.scad', 'LICENSE']}],
},
},
'BOSL': {
description: 'The Belfry OpenScad Library',
gitOrigin: {
branch: 'master',
repoUrl: 'https://github.com/revarbat/BOSL',
include: [{glob: ['**/*.scad', 'LICENSE']}],
},
},
'BOSL2': {
description: 'The Belfry OpenScad Library, v2.0',
gitOrigin: {
branch: 'master',
repoUrl: 'https://github.com/revarbat/BOSL2',
include: [{glob: ['**/*.scad', 'LICENSE']}],
},
docs: {
'CheatSheet': 'https://github.com/revarbat/BOSL2/wiki/CheatSheet',
'Wiki': 'https://github.com/revarbat/BOSL2/wiki',
},
},
'NopSCADlib': {
gitOrigin: {
branch: 'master',
repoUrl: 'https://github.com/nophead/NopSCADlib',
include: [{
glob: '**/*.scad',
ignore: 'test/**',
}],
},
},
'FunctionalOpenSCAD': {
description: 'Implementing OpenSCAD in OpenSCAD',
gitOrigin: {
branch: 'master',
repoUrl: 'https://github.com/thehans/FunctionalOpenSCAD',
include: [{glob: ['**/*.scad', 'LICENSE']}],
},
},
'funcutils': {
description: 'OpenSCAD collection of functional programming utilities, making use of function-literals.',
gitOrigin: {
branch: 'master',
repoUrl: 'https://github.com/thehans/funcutils',
include: [{glob: '**/*.scad'}],
},
},
// @nophead
'NopSCADlib': {},
// @thehans
'FunctionalOpenSCAD': {},
'funcutils': {},
// @colyer
'smooth-prim': {
description: 'OpenSCAD smooth primitives library',
gitOrigin: {
branch: 'master',
repoUrl: 'https://github.com/rcolyer/smooth-prim',
include: [{glob: ['**/*.scad', 'LICENSE.txt']}],
},
symlinks: {'smooth_prim.scad': 'smooth_prim.scad'},
},
'closepoints': {
description: 'OpenSCAD ClosePoints Library',
gitOrigin: {
branch: 'master',
repoUrl: 'https://github.com/rcolyer/closepoints',
include: [{glob: ['**/*.scad', 'LICENSE.txt']}],
},
symlinks: {'closepoints.scad': 'closepoints.scad'},
},
'plot-function': {
description: 'OpenSCAD Function Plotting Library',
gitOrigin: {
branch: 'master',
repoUrl: 'https://github.com/colyer/plot-function',
include: [{glob: ['**/*.scad', 'LICENSE.txt']}],
},
symlinks: {'plot_function.scad': 'plot_function.scad'},
},
// 'threads': {},
// @sofian
// 'threads': {
// deployed: false,
// gitOrigin: {
// branch: 'master',
// repoUrl: 'https://github.com/colyer/threads',
// include: [{glob: ['**/*.scad', 'LICENSE.txt']}],
// },
// },
'openscad-tray': {
description: 'OpenSCAD library to create rounded rectangular trays with optional subdividers.',
gitOrigin: {
branch: 'main',
repoUrl: 'https://github.com/sofian/openscad-tray',
include: [{glob: ['**/*.scad', 'LICENSE']}],
},
symlinks: {'tray.scad': 'tray.scad'},
},
// @mrWheel
'YAPP_Box': {},
// @Cantareus
'Stemfie_OpenSCAD': {},
// @UBaer21
'YAPP_Box': {
description: 'Yet Another Parametric Projectbox Box',
gitOrigin: {
branch: 'main',
repoUrl: 'https://github.com/mrWheel/YAPP_Box',
include: [{glob: ['**/*.scad', 'LICENSE']}],
},
},
'Stemfie_OpenSCAD': {
description: 'OpenSCAD Stemfie Library',
gitOrigin: {
branch: 'main',
repoUrl: 'https://github.com/Cantareus/Stemfie_OpenSCAD',
include: [{glob: ['**/*.scad', 'LICENSE']}],
},
},
'UB.scad': {
symlinks: {"ub.scad": "libraries/ub.scad"},
gitOrigin: {
branch: 'main',
repoUrl: 'https://github.com/UBaer21/UB.scad',
include: [{glob: ['libraries/*.scad', 'LICENSE', 'examples/UBexamples/*.scad'], replacePrefix: {
'libraries/': '',
'examples/UBexamples/': 'examples/',
}}],
},
symlinks: {"ub.scad": "libraries/ub.scad"}, // TODO change this after the replaces work
},
};
export const deployedArchiveNames =
Object.entries(zipArchives)
.filter(([_, {deployed}]) => deployed == null || deployed)
.map(([n]) => n);

View file

@ -76,11 +76,13 @@ export async function buildOpenSCADCompletionItemProvider(fs: FS, workingDir: st
const toAbsolutePath = (path: string) => path.startsWith('/') ? path : `${workingDir}/${path}`;
const allSymlinks: Symlinks = {};
for (const n of Object.keys(zipArchives)) {
for (const [n, {deployed, symlinks}] of Object.entries(zipArchives)) {
if (n == 'fonts') {
continue;
}
const { symlinks } = zipArchives[n];
if (deployed === false) {
continue;
}
for (const s in symlinks) {
allSymlinks[s] = `${n}/${symlinks[s]}`;
}