merge ph sm25 printhead | vendor files | aux modules | scripts | tasks
89
Gruntfile.js
Normal file
20864
cad/components/print-bed-sprcb-650/cad/200_PressPlate-650.step
Normal file
21722
cad/components/print-bed-sprcb-650/cad/200_PressPlate-Global-650.step
Normal file
7178
cad/components/print-bed-sprcb-650/cad/200_PressPlate-Global-650.x_t
Normal file
8367
cad/components/print-bed-sprcb-650/cad/200_pressplate-650.html
Normal file
@ -0,0 +1,37 @@
|
||||
[
|
||||
{
|
||||
"File Path": "C:\\Users\\mc007\\Desktop\\ph3\\products\\products\\sheetpress\\components\\sprcb-650\\cad\\200_PressPlate-Global-650.SLDASM",
|
||||
"IsLaser": "1"
|
||||
},
|
||||
{
|
||||
"File Path": "C:\\Users\\mc007\\Desktop\\ph3\\products\\products\\sheetpress\\components\\sprcb-650\\cad\\303_TriMount_x8_5mm_FERRO.SLDPRT"
|
||||
},
|
||||
{
|
||||
"File Path": "C:\\Users\\mc007\\Desktop\\ph3\\products\\products\\sheetpress\\components\\sprcb-650\\cad\\304_SideMount_x4_5mm_FERRO.SLDPRT"
|
||||
},
|
||||
{
|
||||
"File Path": "C:\\Users\\mc007\\Desktop\\ph3\\products\\products\\sheetpress\\components\\sprcb-650\\cad\\201_PlateCoverTri_x8_1mm_INOX.SLDPRT"
|
||||
},
|
||||
{
|
||||
"File Path": "C:\\Users\\mc007\\Desktop\\ph3\\products\\products\\sheetpress\\components\\sprcb-650\\cad\\8_Rib_x2_5mm_FERRO.SLDPRT"
|
||||
},
|
||||
{
|
||||
"File Path": "C:\\Users\\mc007\\Desktop\\ph3\\products\\products\\sheetpress\\components\\sprcb-650\\cad\\7_Rib_x2_5mm_FERRO.SLDPRT"
|
||||
},
|
||||
{
|
||||
"File Path": "C:\\Users\\mc007\\Desktop\\ph3\\products\\products\\sheetpress\\components\\sprcb-650\\cad\\6_Side_x2_5mm_FERRO.SLDPRT"
|
||||
},
|
||||
{
|
||||
"File Path": "C:\\Users\\mc007\\Desktop\\ph3\\products\\products\\sheetpress\\components\\sprcb-650\\cad\\7_Side_x2_5mm_FERRO.SLDPRT"
|
||||
},
|
||||
{
|
||||
"File Path": "C:\\Users\\mc007\\Desktop\\ph3\\products\\products\\sheetpress\\components\\sprcb-650\\cad\\Lower Platen Matrix Assembly Light.SLDASM",
|
||||
"IsLaser": "1"
|
||||
},
|
||||
{
|
||||
"File Path": "C:\\Users\\mc007\\Desktop\\ph3\\products\\products\\sheetpress\\components\\sprcb-650\\cad\\sp-artition-cell.SLDPRT"
|
||||
},
|
||||
{
|
||||
"File Path": "C:\\Users\\mc007\\Desktop\\ph3\\products\\products\\sheetpress\\components\\sprcb-650\\cad\\20_80_60.SLDPRT"
|
||||
}
|
||||
]
|
||||
BIN
cad/components/print-bed-sprcb-650/cad/20_80_60.SLDPRT
Normal file
BIN
cad/components/print-bed-sprcb-650/cad/7_Rib_x2_5mm_FERRO.SLDPRT
Normal file
BIN
cad/components/print-bed-sprcb-650/cad/8_Rib_x2_5mm_FERRO.SLDPRT
Normal file
BIN
cad/components/print-bed-sprcb-650/cad/Heater Block.SLDPRT
Normal file
BIN
cad/components/print-bed-sprcb-650/cad/Heatproof Puck.SLDPRT
Normal file
BIN
cad/components/print-bed-sprcb-650/cad/LowerRibs.SLDASM
Normal file
BIN
cad/components/print-bed-sprcb-650/cad/PressPlate-RCB.SLDASM
Normal file
5778
cad/components/print-bed-sprcb-650/cad/laser/6_Side_x2_5mm_FERRO.DXF
Normal file
6370
cad/components/print-bed-sprcb-650/cad/laser/7_Rib_x2_5mm_FERRO.DXF
Normal file
5482
cad/components/print-bed-sprcb-650/cad/laser/7_Side_x2_5mm_FERRO.DXF
Normal file
5090
cad/components/print-bed-sprcb-650/cad/laser/8_Rib_x2_5mm_FERRO.DXF
Normal file
BIN
cad/components/print-bed-sprcb-650/cad/sp-artition-cell.SLDPRT
Normal file
30
cad/components/print-bed-sprcb-650/config.json
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"slug": "sprcb650",
|
||||
"name": "Sheetpress cell module - 650",
|
||||
"category": "sheetpress",
|
||||
"code": "SPRCB650",
|
||||
"parts": "parts.csv",
|
||||
"opensource": true,
|
||||
"bestseller": false,
|
||||
"Preview3d": true,
|
||||
"version": "1.0",
|
||||
"status": "mature",
|
||||
"cscartId": 75,
|
||||
"shipping_eu": "100 Euro",
|
||||
"shipping_oversea": "300 Euro",
|
||||
"price": 4800,
|
||||
"showParts": false,
|
||||
"showDimensions": false,
|
||||
"hasSpec": false,
|
||||
"forumCategory": 50,
|
||||
"osr": {
|
||||
"version": "0.3"
|
||||
},
|
||||
"production": {},
|
||||
"authors": [
|
||||
{
|
||||
"name": "PlasticHub S.L.",
|
||||
"url": "${author_link}"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 530 KiB |
BIN
cad/components/print-bed-sprcb-650/renderings/exploded.jpg
Normal file
|
After Width: | Height: | Size: 604 KiB |
8367
cad/components/print-bed-sprcb-650/resources/edrawings.html
Normal file
7
config/machines.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"current2":[
|
||||
],
|
||||
"current":[
|
||||
"cad/components/extruder/sm-25"
|
||||
]
|
||||
}
|
||||
|
Before Width: | Height: | Size: 391 KiB |
83
package.json
@ -1,45 +1,42 @@
|
||||
{
|
||||
"name": "@plastichub/template",
|
||||
"description": "",
|
||||
"version": "0.3.1",
|
||||
"main": "main.js",
|
||||
"typings": "index.d.ts",
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"bin": {
|
||||
"osr-bin": "main.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/node": "^14.17.5",
|
||||
"@types/yargs": "^17.0.2",
|
||||
"chalk": "^2.4.1",
|
||||
"convert-units": "^2.3.4",
|
||||
"env-var": "^7.0.1",
|
||||
"typescript": "^4.3.5",
|
||||
"yargs": "^14.2.3",
|
||||
"yargs-parser": "^15.0.3"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "tsc; mocha --full-trace mocha \"spec/**/*.spec.js\"",
|
||||
"test-with-coverage": "istanbul cover node_modules/.bin/_mocha -- 'spec/**/*.spec.js'",
|
||||
"lint": "tslint --project=./tsconfig.json",
|
||||
"build": "tsc -p .",
|
||||
"dev": "tsc -p . --declaration -w",
|
||||
"typings": "tsc --declaration",
|
||||
"docs": "npx typedoc src/index.ts",
|
||||
"dev-test-watch": "mocha-typescript-watch"
|
||||
},
|
||||
"homepage": "https://git.osr-plastic.org/plastichub/lib-content",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://git.osr-plastic.org/plastichub/lib-content.git"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14.0.0"
|
||||
},
|
||||
"license": "BSD-3-Clause",
|
||||
"keywords": [
|
||||
"typescript"
|
||||
]
|
||||
"name": "osr-printhead-lydia",
|
||||
"version": "0.1.0",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"dev-grunt": "tsc -p . -w",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@plastichub/core": "^0.2.6",
|
||||
"@plastichub/fs": "^0.13.37",
|
||||
"@plastichub/osr-cache": "^0.4.4",
|
||||
"@plastichub/osr-cli-commons": "^0.4.3",
|
||||
"@plastichub/osr-sync": "^0.3.1",
|
||||
"@plastichub/osr-tasks": "^0.4.5",
|
||||
"@plastichub/osrl": "^0.5.3",
|
||||
"@types/lodash": "^4.14.148",
|
||||
"@types/node": "^12.12.8",
|
||||
"@types/showdown": "^2.0.0",
|
||||
"bluebird": "^3.7.2",
|
||||
"cheerio": "^1.0.0-rc.10",
|
||||
"chokidar": "^3.5.3",
|
||||
"cscart-sdk": "^1.110.1",
|
||||
"electron-pdf": "^7.0.0",
|
||||
"fast-glob": "^3.2.7",
|
||||
"find-up": "^6.2.0",
|
||||
"grunt": "^1.4.1",
|
||||
"grunt-contrib-clean": "^2.0.0",
|
||||
"grunt-extend-config": "^0.9.7",
|
||||
"grunt-parallel": "^0.5.1",
|
||||
"grunt-shell": "^3.0.1",
|
||||
"js-beautify": "^1.14.7",
|
||||
"lodash": "^4.17.21",
|
||||
"mysql2": "^2.3.3",
|
||||
"recursive-merge": "^1.2.1",
|
||||
"request": "^2.76.0",
|
||||
"showdown": "^2.1.0",
|
||||
"tslog": "^4.8.2"
|
||||
}
|
||||
}
|
||||
|
||||
2
scripts/update-dir.sh
Normal file
@ -0,0 +1,2 @@
|
||||
osr-cad sw --src="./$1/**/*Global*.+(SLDASM)" --dst='${SRC_DIR}/${SRC_NAME}.+(x_t)' --verbose --debug
|
||||
osr-cad sw --src="./$1/**/*Global*.+(SLDASM)" --dst='${SRC_DIR}/${SRC_NAME}.+(pdf|jpg|html|step)' --verbose --debug
|
||||
2
scripts/update-machines.sh
Normal file
@ -0,0 +1,2 @@
|
||||
script_dir=$(dirname "$0")
|
||||
$script_dir/update-dir.sh "./cad/"
|
||||
107
tasks/Gruntfile.ts
Normal file
@ -0,0 +1,107 @@
|
||||
import * as path from 'path'
|
||||
import { sync as read } from "@plastichub/fs/read"
|
||||
|
||||
import {
|
||||
products,
|
||||
products_test
|
||||
} from './machines'
|
||||
|
||||
import {
|
||||
productLaserTask,
|
||||
productCADTask
|
||||
} from './product'
|
||||
|
||||
|
||||
const getProducts = (branch: string) => {
|
||||
const all = read("./config/machines.json", "json") || {}
|
||||
if(branch){
|
||||
return all[branch] || []
|
||||
}else{
|
||||
return Object.values(all).flat()
|
||||
}
|
||||
}
|
||||
|
||||
export const grunt = (grunt) => {
|
||||
grunt.initConfig({
|
||||
pkg: grunt.file.readJSON("package.json"),
|
||||
'cad': {
|
||||
json: {
|
||||
src: products,
|
||||
output: '${SRC_DIR}/${SRC_NAME}.+(json)'
|
||||
},
|
||||
html: {
|
||||
src: products,
|
||||
output: '${SRC_DIR}/../resources/${SRC_NAME}.+(html)',
|
||||
},
|
||||
step: {
|
||||
src: products,
|
||||
output: '${SRC_DIR}/${SRC_NAME}.+(step)'
|
||||
},
|
||||
bom: {
|
||||
src: products,
|
||||
output: '${SRC_DIR}/../resources/${SRC_NAME}.+(xlsx)'
|
||||
},
|
||||
one: [grunt.option('product')]
|
||||
},
|
||||
'laser': {
|
||||
products: {
|
||||
src: products_test,
|
||||
options: {
|
||||
clear: false,
|
||||
debug: true,
|
||||
verbose: true
|
||||
}
|
||||
}
|
||||
},
|
||||
sshexec: {
|
||||
update: {
|
||||
debug: true,
|
||||
verbose: true,
|
||||
commands: 'sh update-osr.sh'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
grunt.loadNpmTasks('grunt-parallel')
|
||||
grunt.loadNpmTasks("grunt-extend-config")
|
||||
|
||||
grunt.registerTask('laser', [
|
||||
'laser:products'
|
||||
])
|
||||
const product_sync_tasks = []
|
||||
const product_laser_tasks = []
|
||||
const product_cad_tasks = []
|
||||
const product_git_tasks = []
|
||||
const product_all_tasks = []
|
||||
|
||||
const productTasks = (items) => {
|
||||
items.forEach((i) => {
|
||||
productCADTask(grunt, i, {}, product_cad_tasks)
|
||||
productLaserTask(grunt, i, {}, product_laser_tasks)
|
||||
})
|
||||
}
|
||||
|
||||
const all = getProducts("current")
|
||||
productTasks(all)
|
||||
|
||||
|
||||
|
||||
grunt.registerTask('products_update', [
|
||||
'products-cad',
|
||||
'products-laser'
|
||||
])
|
||||
|
||||
grunt.registerTask('products_sync', [
|
||||
'sshexec:update'
|
||||
])
|
||||
|
||||
grunt.registerTask('products_full', [
|
||||
'products_update',
|
||||
'products_sync'
|
||||
])
|
||||
|
||||
require("@plastichub/osr-tasks").initConfig(grunt, {})
|
||||
};
|
||||
|
||||
module.exports = grunt
|
||||
7
tasks/clear_history.sh
Normal file
@ -0,0 +1,7 @@
|
||||
git checkout --orphan latest_branch
|
||||
git add -A
|
||||
git commit -am "Sprint 26 teardown"
|
||||
git branch -D master
|
||||
git branch -m master
|
||||
git push -f origin master
|
||||
git gc --aggressive --prune=all
|
||||
97
tasks/compileOptions.ts
Normal file
@ -0,0 +1,97 @@
|
||||
export interface ICompileOptions {
|
||||
language: string;
|
||||
debug: number;
|
||||
profile: Profile;
|
||||
output: string;
|
||||
plugins: string[];
|
||||
env: string;
|
||||
cwd: string;
|
||||
source: string;
|
||||
variables: PathVariablesClass;
|
||||
srcInfo: Info;
|
||||
targetInfo: Info;
|
||||
pathVariables: PathVariablesClass;
|
||||
}
|
||||
|
||||
export interface PathVariablesClass {
|
||||
OSR_ROOT: string;
|
||||
PRODUCT_ROOT: string;
|
||||
OA_ROOT: string;
|
||||
KB_ROOT: string;
|
||||
OSR_CACHE: string;
|
||||
OSR_LIBRARY_MACHINES: string;
|
||||
OSR_USER_ASSETS: string;
|
||||
OSR_PRIVATE: string;
|
||||
OSR_TEMPLATES: string;
|
||||
OSR_CONTENT: string;
|
||||
root: string;
|
||||
cwd: string;
|
||||
product: string;
|
||||
debug: number;
|
||||
env: string;
|
||||
SRC_PATH: string;
|
||||
SRC_DIR: string;
|
||||
SRC_NAME: string;
|
||||
SRC_FILE_NAME: string;
|
||||
SRC_FILE_EXT: string;
|
||||
SRC_IS_FILE: boolean;
|
||||
SRC_IS_FOLDER: boolean;
|
||||
SRC_IS_EXPRESSION: boolean;
|
||||
SRC_IS_GLOB: boolean;
|
||||
SRC_FILES: string[];
|
||||
abs_url: string;
|
||||
CACHE: string;
|
||||
CACHE_URL: string;
|
||||
GIT_REPO: string;
|
||||
DST_PATH: string;
|
||||
DST_DIR: string;
|
||||
DST_NAME: string;
|
||||
DST_FILE_NAME: string;
|
||||
DST_FILE_EXT: string;
|
||||
DST_IS_FILE: boolean;
|
||||
DST_IS_FOLDER: boolean;
|
||||
DST_IS_EXPRESSION: boolean;
|
||||
DST_IS_GLOB: boolean;
|
||||
DST_FILES: string[];
|
||||
}
|
||||
|
||||
export interface Profile {
|
||||
includes: string[];
|
||||
variables: ProfileVariables;
|
||||
env: Env;
|
||||
}
|
||||
|
||||
export interface Env {
|
||||
bazar: Bazar;
|
||||
"bazar-release": Bazar;
|
||||
}
|
||||
|
||||
export interface Bazar {
|
||||
includes: string[];
|
||||
variables: BazarVariables;
|
||||
}
|
||||
|
||||
export interface BazarVariables {
|
||||
abs_url: string;
|
||||
}
|
||||
|
||||
export interface ProfileVariables {
|
||||
PRODUCT_ROOT: string;
|
||||
abs_url: string;
|
||||
CACHE: string;
|
||||
CACHE_URL: string;
|
||||
GIT_REPO: string;
|
||||
}
|
||||
|
||||
export interface Info {
|
||||
PATH: string;
|
||||
DIR: string;
|
||||
NAME: string;
|
||||
FILE_NAME: string;
|
||||
FILE_EXT: string;
|
||||
IS_FILE: boolean;
|
||||
IS_FOLDER: boolean;
|
||||
IS_EXPRESSION: boolean;
|
||||
IS_GLOB: boolean;
|
||||
FILES: string[];
|
||||
}
|
||||
1
tasks/constants.ts
Normal file
@ -0,0 +1 @@
|
||||
export const MODULE_NAME = `OSR-Products`;
|
||||
10
tasks/index.ts
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
import { logger as _logger } from '@plastichub/core/debug'
|
||||
import { MODULE_NAME } from './constants'
|
||||
|
||||
export const logger = _logger(MODULE_NAME)
|
||||
|
||||
import { substitute as _substitute , substituteAlt as _substituteAlt } from "@plastichub/core/strings"
|
||||
import { IObjectLiteral } from "@plastichub/core"
|
||||
|
||||
export const substitute = (alt:boolean, template:string, vars:IObjectLiteral) => alt ? _substituteAlt(template,vars) : _substitute(template, vars);
|
||||
151
tasks/library.ts
Normal file
@ -0,0 +1,151 @@
|
||||
import * as path from 'path'
|
||||
|
||||
const fg = require('fast-glob')
|
||||
|
||||
import { sync as read } from '@plastichub/fs/read'
|
||||
import { sync as write } from '@plastichub/fs/write'
|
||||
import { sync as exists } from '@plastichub/fs/exists'
|
||||
import { html_beautify } from 'js-beautify'
|
||||
import { CONFIG_DEFAULT, IOSRConfig } from '@plastichub/osr-cli-commons'
|
||||
import { } from '@plastichub/osr-cli-commons/fs'
|
||||
|
||||
const cheerio = require('cheerio')
|
||||
|
||||
const mysql = require('mysql2')
|
||||
|
||||
import { logger } from './'
|
||||
|
||||
import { Converter } from 'showdown'
|
||||
|
||||
export const addAssembly = (item) => `${item}/cad/**/Global*.+(SLDASM)`
|
||||
|
||||
export const md2html = (content) => {
|
||||
let converter = new Converter({ tables: true });
|
||||
converter.setOption('literalMidWordUnderscores', 'true');
|
||||
return converter.makeHtml(content);
|
||||
}
|
||||
|
||||
export const productContentOptions = (product) => {
|
||||
|
||||
console.log('Create product compile options for ', product)
|
||||
|
||||
product = '' + product
|
||||
|
||||
const product_rel = product.replace('products/','')
|
||||
|
||||
return {
|
||||
debug: false,
|
||||
watch: false,
|
||||
root: '.',
|
||||
env: 'bazar-release',
|
||||
profile: '${root}/.osrl.json',
|
||||
output: '${product}/bazar/raw.html',
|
||||
format: 'html',
|
||||
module: 'plastichub-products',
|
||||
cwd: path.resolve('.'),
|
||||
cache: false,
|
||||
onCompiled: onProduct,
|
||||
onCompileDone: onProductCompiled,
|
||||
variables: {
|
||||
product,
|
||||
product_rel,
|
||||
root: path.resolve('.'),
|
||||
product_relative: '' + product_rel
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const forward_slash = (path) => {
|
||||
const isExtendedLengthPath = /^\\\\\?\\/.test(path);
|
||||
const hasNonAscii = /[^\u0000-\u0080]+/.test(path); // eslint-disable-line no-control-regex
|
||||
|
||||
if (isExtendedLengthPath || hasNonAscii) {
|
||||
return path;
|
||||
}
|
||||
|
||||
return path.replace(/\\/g, '/');
|
||||
};
|
||||
|
||||
export const files = (dir, glob) => fg.sync(glob, {
|
||||
dot: true,
|
||||
cwd: dir,
|
||||
absolute: true
|
||||
});
|
||||
|
||||
export const MainAssembly = (dir) => {
|
||||
const mains = files(dir, '**/cad/**/*Global*.+(SLDASM)');
|
||||
return mains[0];
|
||||
}
|
||||
|
||||
export const file_path_with_ext = (file, ext) => {
|
||||
const parts = path.parse(file);
|
||||
return path.join(parts.dir, parts.name + '.' + ext);
|
||||
}
|
||||
|
||||
export const unique_by = (arr, key) => {
|
||||
return [...new Map(arr.map(item => [item[key], item])).values()]
|
||||
}
|
||||
|
||||
export const onProduct = (src, dst, content) => {
|
||||
const $ = cheerio.load(content, {
|
||||
xmlMode: true
|
||||
});
|
||||
|
||||
$('a').each(function () {
|
||||
$(this).attr("style", "color:#4C74B9");
|
||||
})
|
||||
|
||||
$('table').each(function () {
|
||||
$(this).attr("style", "display:table;width:auto;margin-left:auto;margin-right:auto");
|
||||
})
|
||||
|
||||
return Promise.resolve($.html())
|
||||
}
|
||||
|
||||
const update = async (dbconfig, description, id) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const connection = mysql.createConnection(dbconfig);
|
||||
var sql = mysql.format('UPDATE cscart_product_descriptions SET full_description = ? WHERE cscart_product_descriptions.product_id = ?',
|
||||
[description, id]
|
||||
);
|
||||
connection.query(
|
||||
sql,
|
||||
function (err, results) {
|
||||
if (err) {
|
||||
logger.error('SQL Error', err.message);
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(results)
|
||||
}
|
||||
}
|
||||
);
|
||||
})
|
||||
}
|
||||
|
||||
export const onProductCompiled = (src, dst, options, content) => {
|
||||
const config: any = read(path.resolve(options.variables.product + '/config.json'), 'json');
|
||||
|
||||
content = html_beautify(md2html(content))
|
||||
write(path.resolve(options.variables.product + '/bazar/output.html'), content)
|
||||
|
||||
const cscartId = config.cscartId
|
||||
if (!cscartId) {
|
||||
logger.error(`Have no cscart id for ${config.slug}`)
|
||||
return
|
||||
}
|
||||
const osrConfig = CONFIG_DEFAULT() as IOSRConfig
|
||||
|
||||
if (osrConfig.cscart.mysql) {
|
||||
return new Promise((resolve) => {
|
||||
update(osrConfig.cscart.mysql, content, cscartId).then((result) => {
|
||||
logger.debug('updated cscart ' + config.name)
|
||||
resolve(1)
|
||||
}).catch((e) => {
|
||||
logger.error('Error updating CSCart', e)
|
||||
})
|
||||
})
|
||||
}else{
|
||||
logger.error('Have no CSCart Mysql config !')
|
||||
}
|
||||
return Promise.resolve()
|
||||
}
|
||||
122
tasks/machines.ts
Normal file
@ -0,0 +1,122 @@
|
||||
import { addAssembly } from "./library";
|
||||
|
||||
|
||||
export const products_ = [
|
||||
'products/extrusion/lydia-v3.5',
|
||||
'products/extrusion/lydia-v4.5',
|
||||
'products/shredder/components/shredder_v33',
|
||||
'products/injection/elena',
|
||||
'products/injection/elena-xmax',
|
||||
'products/zoe'
|
||||
];
|
||||
|
||||
const product = (item) => addAssembly(item)
|
||||
|
||||
export const products_test = [
|
||||
// 'products/sheetpress/cassandra-mini',
|
||||
//'products/extrusion/lydia-v3.5',
|
||||
//'products/injection/katbot'
|
||||
// 'products/sheetpress/sheetpress-cell-rcA-x'
|
||||
"products/injection/elena-zmax-motor-mod3"
|
||||
]
|
||||
|
||||
export const products = [
|
||||
product('products/sheetpress/cassandra-mini'),
|
||||
// 'products/injection/myriad-spring',
|
||||
// 'products/zoe',
|
||||
// 'products/sheetpress/cassandra-light',
|
||||
// 'products/sheetpress/sheetpress-cell',
|
||||
// 'products/components/700_UniversalHousing'
|
||||
// 'products/extrusion/components/202_FilamentHousing'
|
||||
// 'products/extrusion/components/102_lucy-mini',
|
||||
// 'products/extrusion/lydia-print-head',
|
||||
// 'products/injection/myriad',
|
||||
// 'products/shredder/asterix-pp'
|
||||
// 'products/sheetpress/cassandra',
|
||||
//'products/shredder/components/shredder_v33',
|
||||
// 'products/shredder/components/shredder_v31-light',
|
||||
// 'products/shredder/asterix-sm',
|
||||
// 'products/shredder/asterix-sm-morren',
|
||||
// 'products/zoe'
|
||||
// 'products/shredder/idefix',
|
||||
//'products/injection/elena',
|
||||
//'products/extrusion/lydia-mini'
|
||||
];
|
||||
|
||||
export const bazar_products_all = [
|
||||
'products/injection/elena'
|
||||
/*,
|
||||
'products/injection/elena-xmax',
|
||||
'products/injection/myriad',
|
||||
'products/zoe',
|
||||
'products/sheetpress/cassandra',
|
||||
'products/sheetpress/cassandra-light',
|
||||
'products/sheetpress/sheetpress-cell',
|
||||
'products/extrusion/lydia-v3.5',
|
||||
'products/extrusion/lydia-v4.5',
|
||||
'products/extrusion/lydia-mini',
|
||||
'products/shredder/obelix',
|
||||
'products/shredder/asterix-sm',
|
||||
'products/shredder/asterix-pp',
|
||||
'products/shredder/asterix-sm-morren',
|
||||
'products/extrusion/components/202_FilamentHousing',
|
||||
'products/shredder/idefix',
|
||||
//'products/injection/elena',
|
||||
//'products/extrusion/lydia-mini'
|
||||
*/
|
||||
];
|
||||
|
||||
export const shredders = [
|
||||
// 'products/shredder/asterix-sm-morren',
|
||||
];
|
||||
|
||||
export const products_bazar = [
|
||||
// 'products/shredder/idefix',
|
||||
// 'products/shredder/Obelix-XM-300',
|
||||
// 'products/extrusion/components/102_lucy-mini'
|
||||
// 'products/shredder/components/shredder_v31-light'
|
||||
// 'products/shredder/asterix-sm-morren',
|
||||
// 'products/shredder/asterix-pp'
|
||||
// 'products/sheetpress/cassandra',
|
||||
'products/injection/katbot',
|
||||
//'products/injection/myriad-spring'
|
||||
//'products/zoe',
|
||||
//'products/sheetpress/cassandra-light',
|
||||
// 'products/zoe',
|
||||
//'products/sheetpress/sheetpress-cell',
|
||||
// 'products/components/700_UniversalHousing'
|
||||
//'products/shredder/components/shredder_v33',
|
||||
// 'products/shredder/asterix-sm',
|
||||
// 'products/extrusion/lydia-v3.5',
|
||||
//'products/extrusion/lydia-v4.5',
|
||||
//'products/extrusion/lydia-mini',
|
||||
// 'products/extrusion/components/202_FilamentHousing',
|
||||
//'products/injection/elena',
|
||||
// 'products/injection/elena-xmax',
|
||||
// 'products/shredder/obelix'
|
||||
];
|
||||
|
||||
export const osr_sync_items_injection = [
|
||||
'injection/myriad-spring',
|
||||
'injection/elena',
|
||||
'injection/elena-xmax',
|
||||
'injection/katbot'
|
||||
]
|
||||
|
||||
export const osr_sync_items_products = [
|
||||
//...osr_sync_items_injection,
|
||||
'shredder/obelix',
|
||||
'shredder/asterix-sm',
|
||||
'shredder/asterix-sm-morren',
|
||||
'shredder/asterix-pp',
|
||||
'shredder/idefix',
|
||||
'zoe',
|
||||
'extrusion/lydia-mini',
|
||||
'extrusion/lydia-print-head',
|
||||
'extrusion/lydia-v3.5',
|
||||
'extrusion/lydia-v4.5',
|
||||
'extrusion/defaults.json',
|
||||
'sheetpress/cassandra',
|
||||
'sheetpress/cassandra-light',
|
||||
'sheetpress/sheetpress-cell'
|
||||
]
|
||||
95
tasks/meta.jsb
Normal file
@ -0,0 +1,95 @@
|
||||
var path = require('path');
|
||||
var os = require('os');
|
||||
var _ = require('lodash');
|
||||
const fg = require('fast-glob');
|
||||
|
||||
const cad = require('@plastichub/osr-cad/cad/sw-lib');
|
||||
const cadArgsSanitize = require('@plastichub/osr-cad/argv').sanitize;
|
||||
/*
|
||||
const read = require('@plastichub/fs/read').sync;
|
||||
const write = require('@plastichub/fs/write').sync;
|
||||
const sync = require('@plastichub/osr-sync/lib/sync').sync;
|
||||
*/
|
||||
const BPromise = require('bluebird');
|
||||
|
||||
var isWindows = process.platform === 'win32';
|
||||
|
||||
const files = (dir, glob) => fg.sync(glob, {
|
||||
dot: true,
|
||||
cwd: dir,
|
||||
absolute: true
|
||||
});
|
||||
|
||||
const main_model = (dir) => {
|
||||
const mains = files(dir, 'cad/*Global*.+(json)');
|
||||
return mains[0];
|
||||
}
|
||||
|
||||
const file_path_with_ext = (file, ext) => {
|
||||
const parts = path.parse(file);
|
||||
return path.join(parts.dir, parts.name + '.' + ext);
|
||||
}
|
||||
|
||||
const laser_parts = (model) => {
|
||||
return model.filter((m) => m.IsLaser === '1');
|
||||
}
|
||||
|
||||
const GLOB_MAIN_ASSEMBLY = "cad/*Global*.+(SLDASM)";
|
||||
|
||||
const GLOB_OUTPUT = "${SRC_DIR}/${SRC_NAME}.+(json)";
|
||||
|
||||
|
||||
const create_sync_args = (root, product, input_glob, output_glob) => {
|
||||
const src = `${root}/${product}/${input_glob}`;
|
||||
const dst = output_glob;
|
||||
return {
|
||||
src,
|
||||
dst,
|
||||
debug: 'true',
|
||||
args: "",
|
||||
hash: true,
|
||||
verbose: 'true',
|
||||
skip: 'true'
|
||||
}
|
||||
}
|
||||
const createMeta = (root, product, options) => {
|
||||
const args = create_sync_args(root, product, GLOB_MAIN_ASSEMBLY, GLOB_OUTPUT);
|
||||
const syncArgs = cadArgsSanitize({
|
||||
...args,
|
||||
...options
|
||||
});
|
||||
return cad.convert(syncArgs).then(() => {
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
const convert = async (items, options) => {
|
||||
return BPromise.resolve(items).map((target) => {
|
||||
return createMeta(options.cwd || '.', target, options);
|
||||
}, {
|
||||
concurrency: 1
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = function (grunt) {
|
||||
const log = grunt.verbose.writeln;
|
||||
const error = grunt.log.error;
|
||||
grunt.registerMultiTask('cad-meta', 'Creates meta files from Solidwork assemblies', function () {
|
||||
const done = this.async();
|
||||
this.files.forEach(function (filePair) {
|
||||
const items = filePair.orig.src.map(function (src) {
|
||||
return src;
|
||||
});
|
||||
log('Convert to JSON : ', items);
|
||||
convert(items, {
|
||||
verbose: grunt.option('verbose') !== undefined ? grunt.option('verbose') : false,
|
||||
skip: grunt.option('skip') !== undefined ? grunt.option('skip') : true,
|
||||
cwd: grunt.option('cwd')
|
||||
}).then((e) => {
|
||||
done();
|
||||
});
|
||||
})
|
||||
|
||||
});
|
||||
};
|
||||
85
tasks/product.ts
Normal file
@ -0,0 +1,85 @@
|
||||
import * as path from 'path'
|
||||
|
||||
import { resolve } from '@plastichub/osr-cli-commons/fs'
|
||||
|
||||
import { sync as cp } from '@plastichub/fs/copy'
|
||||
import { sync as exists } from '@plastichub/fs/exists'
|
||||
import { sync as rm } from '@plastichub/fs/remove'
|
||||
|
||||
import {
|
||||
|
||||
} from './machines'
|
||||
|
||||
import { logger } from './'
|
||||
|
||||
const HTML_DEFAULT_PATH = 'resources/edrawings.html'
|
||||
|
||||
const debug = true
|
||||
const verbose = true
|
||||
|
||||
export const productAllTask = (grunt, product, options: any = {}, product_tasks) => {
|
||||
const slug = path.parse(product).base
|
||||
grunt.registerTask(`product-${slug}`, `laser:product-${slug}`)
|
||||
product_tasks.push(`laser:product-${slug}`)
|
||||
grunt.registerTask(`products-laser`, product_tasks)
|
||||
}
|
||||
|
||||
export const productLaserTask = (grunt, product, options: any = {}, product_laser_tasks) => {
|
||||
const config = {}
|
||||
const slug = path.parse(product).base
|
||||
|
||||
config[`product-${slug}`] = {
|
||||
src: [product],
|
||||
options: {
|
||||
clear: false,
|
||||
debug: false,
|
||||
verbose
|
||||
}
|
||||
}
|
||||
grunt.extendConfig({
|
||||
laser: config
|
||||
})
|
||||
grunt.registerTask(`product-${slug}`, `laser:product-${slug}`)
|
||||
|
||||
product_laser_tasks.push(`laser:product-${slug}`)
|
||||
|
||||
grunt.registerTask(`products-laser`, product_laser_tasks)
|
||||
}
|
||||
|
||||
export const productCADTask = (grunt, product, options: any = {}, product_cad_tasks) => {
|
||||
const config = {}
|
||||
const slug = path.parse(product).base
|
||||
|
||||
product = path.resolve(path.join(process.cwd(), product))
|
||||
config[`product-${slug}`] = {
|
||||
src: [`${product}/cad*/*Global*.+(SLDASM)`],
|
||||
output: '${SRC_DIR}/${SRC_NAME}.+(json|html|step|x_t)',
|
||||
options: {
|
||||
debug,
|
||||
verbose,
|
||||
onNode: (data => {
|
||||
try {
|
||||
options.debug && logger.info(`Converted ${data.src} to ${data.target}`)
|
||||
const parts = path.parse(data.target)
|
||||
|
||||
if (parts.ext === '.html' && parts.name.toLowerCase().indexOf('global') !== -1) {
|
||||
if (exists(path.join(product, HTML_DEFAULT_PATH))) {
|
||||
rm(path.join(product, HTML_DEFAULT_PATH))
|
||||
}
|
||||
cp(data.target, path.join(product, HTML_DEFAULT_PATH), {})
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(`Error copying ${data.src} to ${HTML_DEFAULT_PATH}`, error)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
grunt.extendConfig({
|
||||
cad: config
|
||||
})
|
||||
grunt.registerTask(`product-${slug}`, `cad:product-${slug}`)
|
||||
|
||||
product_cad_tasks.push(`cad:product-${slug}`)
|
||||
|
||||
grunt.registerTask(`products-cad`, product_cad_tasks)
|
||||
}
|
||||
69
tasks/sync-osr.js
Normal file
@ -0,0 +1,69 @@
|
||||
var path = require('path');
|
||||
var _ = require('lodash');
|
||||
const fg = require('fast-glob');
|
||||
|
||||
const _resolve = require('@plastichub/osr-cli-commons/fs').resolve;
|
||||
|
||||
const sync = require('@plastichub/osr-sync/lib/sync').sync;
|
||||
|
||||
const BPromise = require('bluebird');
|
||||
|
||||
const osr = path.resolve('../pp-next2/machines/');
|
||||
|
||||
const files = (dir, glob) => fg.sync(glob, {
|
||||
dot: true,
|
||||
cwd: dir,
|
||||
absolute: true
|
||||
});
|
||||
|
||||
|
||||
const create_sync_args = (root, source, target, profile) => {
|
||||
return {
|
||||
source,
|
||||
target,
|
||||
debug: 'false',
|
||||
verbose: 'false',
|
||||
clear: 'false',
|
||||
profile: profile
|
||||
}
|
||||
}
|
||||
const syncItem = (root, product, options) => {
|
||||
const src = path.resolve(`./products/${product}/`);
|
||||
const target = path.resolve(`${options.dst}/users/plastichub/products/${product}/`);
|
||||
const args = create_sync_args(root, src, target, options.profile);
|
||||
console.log(root, product, options, args);
|
||||
return sync(args);
|
||||
|
||||
}
|
||||
|
||||
|
||||
const convert = async (items, options) => {
|
||||
return BPromise.resolve(items).map((target) => {
|
||||
return syncItem(options.cwd || '.', target, options);
|
||||
}, {
|
||||
concurrency: 1
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = function (grunt) {
|
||||
const log = grunt.verbose.writeln;
|
||||
const error = grunt.log.error;
|
||||
grunt.registerMultiTask('sync-osr-assets', 'Sync to OSR', function () {
|
||||
const done = this.async();
|
||||
this.files.forEach(function (filePair) {
|
||||
const items = filePair.orig.src.map(function (src) {
|
||||
return src;
|
||||
});
|
||||
convert(items, {
|
||||
verbose: grunt.option('verbose') !== undefined ? grunt.option('verbose') : false,
|
||||
skip: grunt.option('skip') !== undefined ? grunt.option('skip') : true,
|
||||
cwd: grunt.option('cwd'),
|
||||
profile: path.resolve(filePair.profile),
|
||||
dst: _resolve(filePair.dst)
|
||||
}).then((e) => {
|
||||
done();
|
||||
});
|
||||
})
|
||||
|
||||
});
|
||||
};
|
||||
81
tasks/sync.js
Normal file
@ -0,0 +1,81 @@
|
||||
var path = require('path');
|
||||
// var os = require('os');
|
||||
var _ = require('lodash');
|
||||
const fg = require('fast-glob');
|
||||
/*
|
||||
const cad = require('@plastichub/osr-cad/cad/sw-lib');
|
||||
const cadArgsSanitize = require('@plastichub/osr-cad/argv').sanitize;
|
||||
const read = require('@plastichub/fs/read').sync;
|
||||
const write = require('@plastichub/fs/write').sync;
|
||||
*/
|
||||
const sync = require('@plastichub/osr-sync/lib/sync').sync;
|
||||
|
||||
const BPromise = require('bluebird');
|
||||
|
||||
var isWindows = process.platform === 'win32';
|
||||
|
||||
const osr = path.resolve('../../osr/osr-machines/');
|
||||
|
||||
const files = (dir, glob) => fg.sync(glob, {
|
||||
dot: true,
|
||||
cwd: dir,
|
||||
absolute: true
|
||||
});
|
||||
|
||||
|
||||
const GLOB_MAIN_ASSEMBLY = "cad/*Global*.+(SLDASM)";
|
||||
|
||||
const GLOB_OUTPUT = "${SRC_DIR}/${SRC_NAME}.+(json)";
|
||||
|
||||
|
||||
const create_sync_args = (root, source, target, profile) => {
|
||||
return {
|
||||
source,
|
||||
target,
|
||||
debug: 'false',
|
||||
verbose: 'false',
|
||||
clear: 'false',
|
||||
profile: profile
|
||||
}
|
||||
}
|
||||
const createMeta = (root, product, options) => {
|
||||
const src = path.resolve(`./products/${product}/`);
|
||||
const target = path.resolve(`${osr}/${product}/`);
|
||||
const args = create_sync_args(root, src, target, options.profile);
|
||||
console.log(root, product, options, args);
|
||||
return sync(args);
|
||||
|
||||
}
|
||||
|
||||
|
||||
const convert = async (items, options) => {
|
||||
return BPromise.resolve(items).map((target) => {
|
||||
return createMeta(options.cwd || '.', target, options);
|
||||
}, {
|
||||
concurrency: 1
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = function (grunt) {
|
||||
const log = grunt.verbose.writeln;
|
||||
const error = grunt.log.error;
|
||||
grunt.registerMultiTask('sync-osr', 'Sync to OSR', function () {
|
||||
const done = this.async();
|
||||
this.files.forEach(function (filePair) {
|
||||
const items = filePair.orig.src.map(function (src) {
|
||||
return src;
|
||||
});
|
||||
//log('sync items ', items);
|
||||
//log('sync pair ', filePair);
|
||||
convert(items, {
|
||||
verbose: grunt.option('verbose') !== undefined ? grunt.option('verbose') : false,
|
||||
skip: grunt.option('skip') !== undefined ? grunt.option('skip') : true,
|
||||
cwd: grunt.option('cwd'),
|
||||
profile: filePair.profile || './.osr-sync.json'
|
||||
}).then((e) => {
|
||||
done();
|
||||
});
|
||||
})
|
||||
|
||||
});
|
||||
};
|
||||
66
tasks/utils.js
Normal file
@ -0,0 +1,66 @@
|
||||
var path = require('path');
|
||||
const fg = require('fast-glob');
|
||||
const read = require('@plastichub/fs/read').sync;
|
||||
const write = require('@plastichub/fs/write').sync;
|
||||
|
||||
const exists = require('@plastichub/fs/exists').sync;
|
||||
|
||||
const forward_slash = (path) => {
|
||||
const isExtendedLengthPath = /^\\\\\?\\/.test(path);
|
||||
const hasNonAscii = /[^\u0000-\u0080]+/.test(path); // eslint-disable-line no-control-regex
|
||||
|
||||
if (isExtendedLengthPath || hasNonAscii) {
|
||||
return path;
|
||||
}
|
||||
|
||||
return path.replace(/\\/g, '/');
|
||||
};
|
||||
|
||||
const files = (dir, glob) => fg.sync(glob, {
|
||||
dot: true,
|
||||
cwd: dir,
|
||||
absolute: true
|
||||
});
|
||||
|
||||
const MainAssembly = (dir) => {
|
||||
const mains = files(dir, '**/cad/**/Global*.+(SLDASM)');
|
||||
return mains[0];
|
||||
}
|
||||
|
||||
const file_path_with_ext = (file, ext) => {
|
||||
const parts = path.parse(file);
|
||||
return path.join(parts.dir, parts.name + '.' + ext);
|
||||
}
|
||||
|
||||
function unique_by(arr, key) {
|
||||
return [...new Map(arr.map(item => [item[key], item])).values()]
|
||||
}
|
||||
|
||||
const onProduct = (src, dst, content) => {
|
||||
debugger;
|
||||
const $ = cheerio.load(content, {
|
||||
xmlMode: true
|
||||
});
|
||||
|
||||
$('a').each(function () {
|
||||
$(this).attr("style", "color:#4C74B9");
|
||||
})
|
||||
|
||||
$('table').each(function () {
|
||||
$(this).attr("style", "display:table;width:auto;margin-left:auto;margin-right:auto");
|
||||
})
|
||||
|
||||
return $.html();
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
MainAssembly,
|
||||
file_path_with_ext,
|
||||
unique_by,
|
||||
files,
|
||||
forward_slash,
|
||||
read,
|
||||
write,
|
||||
exists,
|
||||
onProduct
|
||||
}
|
||||
20
tsconfig.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "ES2020",
|
||||
"allowJs": true,
|
||||
"noImplicitAny": false,
|
||||
"noImplicitThis": false,
|
||||
"alwaysStrict": true,
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"inlineSources": true,
|
||||
"inlineSourceMap": true,
|
||||
"pretty": true,
|
||||
"outDir": "./",
|
||||
"allowSyntheticDefaultImports": true
|
||||
},
|
||||
"files": [
|
||||
"./tasks/Gruntfile.ts"
|
||||
]
|
||||
}
|
||||
BIN
vendor/abb/Technical reference manual_RAPID_3HAC16581-1_revJ_en.pdf
vendored
Normal file
BIN
vendor/abb/join_layout.jpg
vendored
Normal file
|
After Width: | Height: | Size: 67 KiB |
BIN
vendor/cead/media/SPARK-port.mp4
vendored
Normal file
BIN
vendor/cead/media/Tu-Dresden-Portfolio.mp4
vendored
Normal file
3
vendor/cead/notes.md
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
https://www.youtube.com/watch?v=PFVlCuCh504&ab_channel=ETHZ%C3%BCrich
|
||||
|
||||
https://www.youtube.com/watch?v=2d3nJjbunIg&ab_channel=CEADGroup tu-dd :)
|
||||
BIN
vendor/kuga/Documents.zip
vendored
Normal file
BIN
vendor/kuga/KR16-II/cad/Body_1.1.SLDPRT
vendored
Normal file
BIN
vendor/kuga/KR16-II/cad/Carpal Extender..SLDPRT
vendored
Normal file
BIN
vendor/kuga/KR16-II/cad/Carpal Knuckle_1.SLDPRT
vendored
Normal file
BIN
vendor/kuga/KR16-II/cad/Carpal-Connection..SLDPRT
vendored
Normal file
BIN
vendor/kuga/KR16-II/cad/Carpal-Tendon.SLDPRT
vendored
Normal file
BIN
vendor/kuga/KR16-II/cad/Center Probe Guide_1.SLDPRT
vendored
Normal file
BIN
vendor/kuga/KR16-II/cad/Claw Base Mount_1.SLDPRT
vendored
Normal file
BIN
vendor/kuga/KR16-II/cad/Claw Bone_1.SLDPRT
vendored
Normal file
BIN
vendor/kuga/KR16-II/cad/Claw Cap Left_1.SLDPRT
vendored
Normal file
BIN
vendor/kuga/KR16-II/cad/Claw Cap Right_1.SLDPRT
vendored
Normal file
BIN
vendor/kuga/KR16-II/cad/Claw Gripper_1.SLDPRT
vendored
Normal file
BIN
vendor/kuga/KR16-II/cad/Claw Set Screw..SLDPRT
vendored
Normal file
BIN
vendor/kuga/KR16-II/cad/Claw Wrist Screw.SLDPRT
vendored
Normal file
BIN
vendor/kuga/KR16-II/cad/Claw Wrist.1.SLDPRT
vendored
Normal file
BIN
vendor/kuga/KR16-II/cad/Montaj1.SLDASM
vendored
Normal file
BIN
vendor/kuga/KR16-II/cad/Montaj3.SLDASM
vendored
Normal file
BIN
vendor/kuga/KR16-II/cad/P2.1.SLDPRT
vendored
Normal file
BIN
vendor/kuga/KR16-II/cad/Render/render 1.JPG
vendored
Normal file
|
After Width: | Height: | Size: 2.3 MiB |
BIN
vendor/kuga/KR16-II/cad/Render/render 2.JPG
vendored
Normal file
|
After Width: | Height: | Size: 2.3 MiB |
BIN
vendor/kuga/KR16-II/cad/Render/render 3.JPG
vendored
Normal file
|
After Width: | Height: | Size: 2.8 MiB |
BIN
vendor/kuga/KR16-II/cad/Render/render 4.JPG
vendored
Normal file
|
After Width: | Height: | Size: 2.4 MiB |