Ajout du choix des utilisateurs sur un événement. Ajout de fichiers dans un événement. (dropzone cassée)

This commit is contained in:
2025-05-26 22:10:40 +02:00
parent 82d77e2b8d
commit 49dffff1bf
1100 changed files with 157519 additions and 113 deletions

View File

@@ -0,0 +1,69 @@
export default class BaseOutputBuilder{
constructor(){
// this.attributes = {};
}
addAttribute(name, value){
if(this.options.onAttribute){
//TODO: better to pass tag path
const v = this.options.onAttribute(name, value, this.tagName);
if(v) this.attributes[v.name] = v.value;
}else{
name = this.options.attributes.prefix + name + this.options.attributes.suffix;
this.attributes[name] = this.parseValue(value, this.options.attributes.valueParsers);
}
}
/**
* parse value by chain of parsers
* @param {string} val
* @returns {any} parsed value if matching parser found
*/
parseValue = function(val, valParsers){
for (let i = 0; i < valParsers.length; i++) {
let valParser = valParsers[i];
if(typeof valParser === "string"){
valParser = this.registeredParsers[valParser];
}
if(valParser){
val = valParser.parse(val);
}
}
return val;
}
/**
* To add a nested empty tag.
* @param {string} key
* @param {any} val
*/
_addChild(key, val){}
/**
* skip the comment if property is not set
*/
addComment(text){
if(this.options.nameFor.comment)
this._addChild(this.options.nameFor.comment, text);
}
//store CDATA separately if property is set
//otherwise add to tag's value
addCdata(text){
if (this.options.nameFor.cdata) {
this._addChild(this.options.nameFor.cdata, text);
} else {
this.addRawValue(text || "");
}
}
addRawValue = text => this.addValue(text);
addDeclaration(){
if(!this.options.declaration){
}else{
this.addPi("?xml");
}
this.attributes = {}
}
}

View File

@@ -0,0 +1,103 @@
import {buildOptions,registerCommonValueParsers} from './ParserOptionsBuilder.js';
export default class OutputBuilder{
constructor(options){
this.options = buildOptions(options);
this.registeredParsers = registerCommonValueParsers(this.options);
}
registerValueParser(name,parserInstance){//existing name will override the parser without warning
this.registeredParsers[name] = parserInstance;
}
getInstance(parserOptions){
return new JsArrBuilder(parserOptions, this.options, this.registeredParsers);
}
}
const rootName = '!js_arr';
import BaseOutputBuilder from './BaseOutputBuilder.js';
class JsArrBuilder extends BaseOutputBuilder{
constructor(parserOptions, options,registeredParsers) {
super();
this.tagsStack = [];
this.parserOptions = parserOptions;
this.options = options;
this.registeredParsers = registeredParsers;
this.root = new Node(rootName);
this.currentNode = this.root;
this.attributes = {};
}
addTag(tag){
//when a new tag is added, it should be added as child of current node
//TODO: shift this check to the parser
if(tag.name === "__proto__") tag.name = "#__proto__";
this.tagsStack.push(this.currentNode);
this.currentNode = new Node(tag.name, this.attributes);
this.attributes = {};
}
/**
* Check if the node should be added by checking user's preference
* @param {Node} node
* @returns boolean: true if the node should not be added
*/
closeTag(){
const node = this.currentNode;
this.currentNode = this.tagsStack.pop(); //set parent node in scope
if(this.options.onClose !== undefined){
//TODO TagPathMatcher
const resultTag = this.options.onClose(node,
new TagPathMatcher(this.tagsStack,node));
if(resultTag) return;
}
this.currentNode.child.push(node); //to parent node
}
//Called by parent class methods
_addChild(key, val){
// if(key === "__proto__") tagName = "#__proto__";
this.currentNode.child.push( {[key]: val });
// this.currentNode.leafType = false;
}
/**
* Add text value child node
* @param {string} text
*/
addValue(text){
this.currentNode.child.push( {[this.options.nameFor.text]: this.parseValue(text, this.options.tags.valueParsers) });
}
addPi(name){
//TODO: set pi flag
if(!this.options.ignorePiTags){
const node = new Node(name, this.attributes);
this.currentNode[":@"] = this.attributes;
this.currentNode.child.push(node);
}
this.attributes = {};
}
getOutput(){
return this.root.child[0];
}
}
class Node{
constructor(tagname, attributes){
this.tagname = tagname;
this.child = []; //nested tags, text, cdata, comments
if(attributes && Object.keys(attributes).length > 0)
this[":@"] = attributes;
}
}
module.exports = OutputBuilder;

View File

@@ -0,0 +1,100 @@
import {buildOptions,registerCommonValueParsers} from"./ParserOptionsBuilder";
export default class OutputBuilder{
constructor(options){
this.options = buildOptions(options);
this.registeredParsers = registerCommonValueParsers(this.options);
}
registerValueParser(name,parserInstance){//existing name will override the parser without warning
this.registeredParsers[name] = parserInstance;
}
getInstance(parserOptions){
return new JsMinArrBuilder(parserOptions, this.options, this.registeredParsers);
}
}
import BaseOutputBuilder from "./BaseOutputBuilder.js";
const rootName = '^';
class JsMinArrBuilder extends BaseOutputBuilder{
constructor(parserOptions, options,registeredParsers) {
super();
this.tagsStack = [];
this.parserOptions = parserOptions;
this.options = options;
this.registeredParsers = registeredParsers;
this.root = {[rootName]: []};
this.currentNode = this.root;
this.currentNodeTagName = rootName;
this.attributes = {};
}
addTag(tag){
//when a new tag is added, it should be added as child of current node
//TODO: shift this check to the parser
if(tag.name === "__proto__") tag.name = "#__proto__";
this.tagsStack.push([this.currentNodeTagName,this.currentNode]); //this.currentNode is parent node here
this.currentNodeTagName = tag.name;
this.currentNode = { [tag.name]:[]}
if(Object.keys(this.attributes).length > 0){
this.currentNode[":@"] = this.attributes;
this.attributes = {};
}
}
/**
* Check if the node should be added by checking user's preference
* @param {Node} node
* @returns boolean: true if the node should not be added
*/
closeTag(){
const node = this.currentNode;
const nodeName = this.currentNodeTagName;
const arr = this.tagsStack.pop(); //set parent node in scope
this.currentNodeTagName = arr[0];
this.currentNode = arr[1];
if(this.options.onClose !== undefined){
//TODO TagPathMatcher
const resultTag = this.options.onClose(node,
new TagPathMatcher(this.tagsStack,node));
if(resultTag) return;
}
this.currentNode[this.currentNodeTagName].push(node); //to parent node
}
//Called by parent class methods
_addChild(key, val){
// if(key === "__proto__") tagName = "#__proto__";
this.currentNode.push( {[key]: val });
// this.currentNode.leafType = false;
}
/**
* Add text value child node
* @param {string} text
*/
addValue(text){
this.currentNode[this.currentNodeTagName].push( {[this.options.nameFor.text]: this.parseValue(text, this.options.tags.valueParsers) });
}
addPi(name){
if(!this.options.ignorePiTags){
const node = { [name]:[]}
if(this.attributes){
node[":@"] = this.attributes;
}
this.currentNode.push(node);
}
this.attributes = {};
}
getOutput(){
return this.root[rootName];
}
}

View File

@@ -0,0 +1,154 @@
import {buildOptions,registerCommonValueParsers} from './ParserOptionsBuilder.js';
export default class OutputBuilder{
constructor(builderOptions){
this.options = buildOptions(builderOptions);
this.registeredParsers = registerCommonValueParsers(this.options);
}
registerValueParser(name,parserInstance){//existing name will override the parser without warning
this.registeredParsers[name] = parserInstance;
}
getInstance(parserOptions){
return new JsObjBuilder(parserOptions, this.options, this.registeredParsers);
}
}
import BaseOutputBuilder from './BaseOutputBuilder.js';
const rootName = '^';
class JsObjBuilder extends BaseOutputBuilder{
constructor(parserOptions, builderOptions,registeredParsers) {
super();
//hold the raw detail of a tag and sequence with reference to the output
this.tagsStack = [];
this.parserOptions = parserOptions;
this.options = builderOptions;
this.registeredParsers = registeredParsers;
this.root = {};
this.parent = this.root;
this.tagName = rootName;
this.value = {};
this.textValue = "";
this.attributes = {};
}
addTag(tag){
let value = "";
if( !isEmpty(this.attributes)){
value = {};
if(this.options.attributes.groupBy){
value[this.options.attributes.groupBy] = this.attributes;
}else{
value = this.attributes;
}
}
this.tagsStack.push([this.tagName, this.textValue, this.value]); //parent tag, parent text value, parent tag value (jsobj)
this.tagName = tag.name;
this.value = value;
this.textValue = "";
this.attributes = {};
}
/**
* Check if the node should be added by checking user's preference
* @param {Node} node
* @returns boolean: true if the node should not be added
*/
closeTag(){
const tagName = this.tagName;
let value = this.value;
let textValue = this.textValue;
//update tag text value
if(typeof value !== "object" && !Array.isArray(value)){
value = this.parseValue(textValue.trim(), this.options.tags.valueParsers);
}else if(textValue.length > 0){
value[this.options.nameFor.text] = this.parseValue(textValue.trim(), this.options.tags.valueParsers);
}
let resultTag= {
tagName: tagName,
value: value
};
if(this.options.onTagClose !== undefined){
//TODO TagPathMatcher
resultTag = this.options.onClose(tagName, value, this.textValue, new TagPathMatcher(this.tagsStack,node));
if(!resultTag) return;
}
//set parent node in scope
let arr = this.tagsStack.pop();
let parentTag = arr[2];
parentTag=this._addChildTo(resultTag.tagName, resultTag.value, parentTag);
this.tagName = arr[0];
this.textValue = arr[1];
this.value = parentTag;
}
_addChild(key, val){
if(typeof this.value === "string"){
this.value = { [this.options.nameFor.text] : this.value };
}
this._addChildTo(key, val, this.value);
// this.currentNode.leafType = false;
this.attributes = {};
}
_addChildTo(key, val, node){
if(typeof node === 'string') node = {};
if(!node[key]){
node[key] = val;
}else{ //Repeated
if(!Array.isArray(node[key])){ //but not stored as array
node[key] = [node[key]];
}
node[key].push(val);
}
return node;
}
/**
* Add text value child node
* @param {string} text
*/
addValue(text){
//TODO: use bytes join
if(this.textValue.length > 0) this.textValue += " " + text;
else this.textValue = text;
}
addPi(name){
let value = "";
if( !isEmpty(this.attributes)){
value = {};
if(this.options.attributes.groupBy){
value[this.options.attributes.groupBy] = this.attributes;
}else{
value = this.attributes;
}
}
this._addChild(name, value);
}
getOutput(){
return this.value;
}
}
function isEmpty(obj) {
return Object.keys(obj).length === 0;
}

View File

@@ -0,0 +1,94 @@
import trimParser from "../valueParsers/trim";
import booleanParser from "../valueParsers/booleanParser";
import currencyParser from "../valueParsers/currency";
import numberParser from "../valueParsers/number";
const defaultOptions={
nameFor:{
text: "#text",
comment: "",
cdata: "",
},
// onTagClose: () => {},
// onAttribute: () => {},
piTag: false,
declaration: false, //"?xml"
tags: {
valueParsers: [
// "trim",
// "boolean",
// "number",
// "currency",
// "date",
]
},
attributes:{
prefix: "@_",
suffix: "",
groupBy: "",
valueParsers: [
// "trim",
// "boolean",
// "number",
// "currency",
// "date",
]
},
dataType:{
}
}
//TODO
const withJoin = ["trim","join", /*"entities",*/"number","boolean","currency"/*, "date"*/]
const withoutJoin = ["trim", /*"entities",*/"number","boolean","currency"/*, "date"*/]
export function buildOptions(options){
//clone
const finalOptions = { ... defaultOptions};
//add config missed in cloning
finalOptions.tags.valueParsers.push(...withJoin)
if(!this.preserveOrder)
finalOptions.tags.valueParsers.push(...withoutJoin);
//add config missed in cloning
finalOptions.attributes.valueParsers.push(...withJoin)
//override configuration
copyProperties(finalOptions,options);
return finalOptions;
}
function copyProperties(target, source) {
for (let key in source) {
if (source.hasOwnProperty(key)) {
if (typeof source[key] === 'object' && !Array.isArray(source[key])) {
// Recursively copy nested properties
if (typeof target[key] === 'undefined') {
target[key] = {};
}
copyProperties(target[key], source[key]);
} else {
// Copy non-nested properties
target[key] = source[key];
}
}
}
}
export function registerCommonValueParsers(options){
return {
"trim": new trimParser(),
// "join": this.entityParser.parse,
"boolean": new booleanParser(),
"number": new numberParser({
hex: true,
leadingZeros: true,
eNotation: true
}),
"currency": new currencyParser(),
// "date": this.entityParser.parse,
}
}