@nextcloud/files 3.8.0 → 3.9.1

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.
@@ -5,7 +5,7 @@ export declare enum DefaultType {
5
5
  DEFAULT = "default",
6
6
  HIDDEN = "hidden"
7
7
  }
8
- interface FileActionData {
8
+ export interface FileActionData {
9
9
  /** Unique ID */
10
10
  id: string;
11
11
  /** Translatable string displayed in the menu */
@@ -32,6 +32,11 @@ interface FileActionData {
32
32
  execBatch?: (files: Node[], view: View, dir: string) => Promise<(boolean | null)[]>;
33
33
  /** This action order in the list */
34
34
  order?: number;
35
+ /**
36
+ * Set to true if this action is a destructive action, like "delete".
37
+ * This will change the appearance in the action menu more prominent (e.g. red colored)
38
+ */
39
+ destructive?: boolean;
35
40
  /**
36
41
  * This action's parent id in the list.
37
42
  * If none found, will be displayed as a top-level action.
@@ -70,10 +75,10 @@ export declare class FileAction {
70
75
  get order(): number | undefined;
71
76
  get parent(): string | undefined;
72
77
  get default(): DefaultType | undefined;
78
+ get destructive(): boolean | undefined;
73
79
  get inline(): ((file: Node, view: View) => boolean) | undefined;
74
80
  get renderInline(): ((file: Node, view: View) => Promise<HTMLElement | null>) | undefined;
75
81
  private validateAction;
76
82
  }
77
83
  export declare const registerFileAction: (action: FileAction) => void;
78
84
  export declare const getFileActions: () => FileAction[];
79
- export {};
@@ -14,6 +14,10 @@ export interface IFileListFilterChip {
14
14
  * Optional icon to be used on the chip (inline SVG as string)
15
15
  */
16
16
  icon?: string;
17
+ /**
18
+ * Optional pass a user id to use a user avatar instead of an icon
19
+ */
20
+ user?: string;
17
21
  /**
18
22
  * Handler to be called on click
19
23
  */
@@ -3,6 +3,10 @@ import { INode, Node } from './node';
3
3
 
4
4
  export declare class File extends Node {
5
5
  get type(): FileType;
6
+ /**
7
+ * Returns a clone of the file
8
+ */
9
+ clone(): File;
6
10
  }
7
11
  /**
8
12
  * Interface of the File class
@@ -7,6 +7,10 @@ export declare class Folder extends Node {
7
7
  get type(): FileType;
8
8
  get extension(): string | null;
9
9
  get mime(): string;
10
+ /**
11
+ * Returns a clone of the folder
12
+ */
13
+ clone(): Node;
10
14
  }
11
15
  /**
12
16
  * Interface of the folder class
@@ -134,6 +134,10 @@ export declare abstract class Node {
134
134
  * Set the node status.
135
135
  */
136
136
  set status(status: NodeStatus | undefined);
137
+ /**
138
+ * Get the node data
139
+ */
140
+ get data(): NodeData;
137
141
  /**
138
142
  * Move the node to a new destination
139
143
  *
@@ -159,6 +163,10 @@ export declare abstract class Node {
159
163
  * @param attributes The new attributes to update on the Node attributes
160
164
  */
161
165
  update(attributes: Attribute): void;
166
+ /**
167
+ * Returns a clone of the node
168
+ */
169
+ abstract clone(): Node;
162
170
  }
163
171
  /**
164
172
  * Interface of the node class
package/dist/index.cjs CHANGED
@@ -119,6 +119,9 @@ class FileAction {
119
119
  get default() {
120
120
  return this._action.default;
121
121
  }
122
+ get destructive() {
123
+ return this._action.destructive;
124
+ }
122
125
  get inline() {
123
126
  return this._action.inline;
124
127
  }
@@ -150,6 +153,9 @@ class FileAction {
150
153
  if ("order" in action && typeof action.order !== "number") {
151
154
  throw new Error("Invalid order");
152
155
  }
156
+ if (action.destructive !== void 0 && typeof action.destructive !== "boolean") {
157
+ throw new Error("Invalid destructive flag");
158
+ }
153
159
  if ("parent" in action && typeof action.parent !== "string") {
154
160
  throw new Error("Invalid parent");
155
161
  }
@@ -714,6 +720,12 @@ class Node {
714
720
  set status(status) {
715
721
  this._data.status = status;
716
722
  }
723
+ /**
724
+ * Get the node data
725
+ */
726
+ get data() {
727
+ return structuredClone(this._data);
728
+ }
717
729
  /**
718
730
  * Move the node to a new destination
719
731
  *
@@ -776,6 +788,12 @@ class File extends Node {
776
788
  get type() {
777
789
  return FileType.File;
778
790
  }
791
+ /**
792
+ * Returns a clone of the file
793
+ */
794
+ clone() {
795
+ return new File(this.data);
796
+ }
779
797
  }
780
798
  class Folder extends Node {
781
799
  constructor(data) {
@@ -793,6 +811,12 @@ class Folder extends Node {
793
811
  get mime() {
794
812
  return "httpd/unix-directory";
795
813
  }
814
+ /**
815
+ * Returns a clone of the folder
816
+ */
817
+ clone() {
818
+ return new Folder(this.data);
819
+ }
796
820
  }
797
821
  function davGetRootPath() {
798
822
  if (_public.isPublicShare()) {
@@ -1074,7 +1098,7 @@ function sortNodes(nodes, options = {}) {
1074
1098
  // 3: Use sorting mode if NOT basename (to be able to use display name too)
1075
1099
  ...sortingOptions.sortingMode !== "basename" ? [(v) => v[sortingOptions.sortingMode]] : [],
1076
1100
  // 4: Use display name if available, fallback to name
1077
- (v) => basename(v.attributes?.displayname || v.basename),
1101
+ (v) => basename(v.displayname || v.attributes?.displayname || v.basename),
1078
1102
  // 5: Finally, use basename if all previous sorting methods failed
1079
1103
  (v) => v.basename
1080
1104
  ];
@@ -1787,10 +1811,30 @@ function trimZeros(numStr) {
1787
1811
  return numStr;
1788
1812
  }
1789
1813
  var strnum = toNumber$1;
1814
+ function getIgnoreAttributesFn$2(ignoreAttributes2) {
1815
+ if (typeof ignoreAttributes2 === "function") {
1816
+ return ignoreAttributes2;
1817
+ }
1818
+ if (Array.isArray(ignoreAttributes2)) {
1819
+ return (attrName) => {
1820
+ for (const pattern of ignoreAttributes2) {
1821
+ if (typeof pattern === "string" && attrName === pattern) {
1822
+ return true;
1823
+ }
1824
+ if (pattern instanceof RegExp && pattern.test(attrName)) {
1825
+ return true;
1826
+ }
1827
+ }
1828
+ };
1829
+ }
1830
+ return () => false;
1831
+ }
1832
+ var ignoreAttributes = getIgnoreAttributesFn$2;
1790
1833
  const util = util$3;
1791
1834
  const xmlNode = xmlNode$1;
1792
1835
  const readDocType = DocTypeReader;
1793
1836
  const toNumber = strnum;
1837
+ const getIgnoreAttributesFn$1 = ignoreAttributes;
1794
1838
  let OrderedObjParser$1 = class OrderedObjParser {
1795
1839
  constructor(options) {
1796
1840
  this.options = options;
@@ -1831,6 +1875,7 @@ let OrderedObjParser$1 = class OrderedObjParser {
1831
1875
  this.readStopNodeData = readStopNodeData;
1832
1876
  this.saveTextToParentTag = saveTextToParentTag;
1833
1877
  this.addChild = addChild;
1878
+ this.ignoreAttributesFn = getIgnoreAttributesFn$1(this.options.ignoreAttributes);
1834
1879
  }
1835
1880
  };
1836
1881
  function addExternalEntities(externalEntities) {
@@ -1883,12 +1928,15 @@ function resolveNameSpace(tagname) {
1883
1928
  }
1884
1929
  const attrsRegx = new RegExp(`([^\\s=]+)\\s*(=\\s*(['"])([\\s\\S]*?)\\3)?`, "gm");
1885
1930
  function buildAttributesMap(attrStr, jPath, tagName) {
1886
- if (!this.options.ignoreAttributes && typeof attrStr === "string") {
1931
+ if (this.options.ignoreAttributes !== true && typeof attrStr === "string") {
1887
1932
  const matches = util.getAllMatches(attrStr, attrsRegx);
1888
1933
  const len = matches.length;
1889
1934
  const attrs = {};
1890
1935
  for (let i = 0; i < len; i++) {
1891
1936
  const attrName = this.resolveNameSpace(matches[i][1]);
1937
+ if (this.ignoreAttributesFn(attrName, jPath)) {
1938
+ continue;
1939
+ }
1892
1940
  let oldVal = matches[i][4];
1893
1941
  let aName = this.options.attributeNamePrefix + attrName;
1894
1942
  if (attrName.length) {
@@ -2523,6 +2571,7 @@ function replaceEntitiesValue(textValue, options) {
2523
2571
  }
2524
2572
  var orderedJs2Xml = toXml;
2525
2573
  const buildFromOrderedJs = orderedJs2Xml;
2574
+ const getIgnoreAttributesFn = ignoreAttributes;
2526
2575
  const defaultOptions = {
2527
2576
  attributeNamePrefix: "@_",
2528
2577
  attributesGroupName: false,
@@ -2559,11 +2608,12 @@ const defaultOptions = {
2559
2608
  };
2560
2609
  function Builder(options) {
2561
2610
  this.options = Object.assign({}, defaultOptions, options);
2562
- if (this.options.ignoreAttributes || this.options.attributesGroupName) {
2611
+ if (this.options.ignoreAttributes === true || this.options.attributesGroupName) {
2563
2612
  this.isAttribute = function() {
2564
2613
  return false;
2565
2614
  };
2566
2615
  } else {
2616
+ this.ignoreAttributesFn = getIgnoreAttributesFn(this.options.ignoreAttributes);
2567
2617
  this.attrPrefixLen = this.options.attributeNamePrefix.length;
2568
2618
  this.isAttribute = isAttribute;
2569
2619
  }
@@ -2589,12 +2639,13 @@ Builder.prototype.build = function(jObj) {
2589
2639
  [this.options.arrayNodeName]: jObj
2590
2640
  };
2591
2641
  }
2592
- return this.j2x(jObj, 0).val;
2642
+ return this.j2x(jObj, 0, []).val;
2593
2643
  }
2594
2644
  };
2595
- Builder.prototype.j2x = function(jObj, level) {
2645
+ Builder.prototype.j2x = function(jObj, level, ajPath) {
2596
2646
  let attrStr = "";
2597
2647
  let val2 = "";
2648
+ const jPath = ajPath.join(".");
2598
2649
  for (let key in jObj) {
2599
2650
  if (!Object.prototype.hasOwnProperty.call(jObj, key)) continue;
2600
2651
  if (typeof jObj[key] === "undefined") {
@@ -2613,9 +2664,9 @@ Builder.prototype.j2x = function(jObj, level) {
2613
2664
  val2 += this.buildTextValNode(jObj[key], key, "", level);
2614
2665
  } else if (typeof jObj[key] !== "object") {
2615
2666
  const attr = this.isAttribute(key);
2616
- if (attr) {
2667
+ if (attr && !this.ignoreAttributesFn(attr, jPath)) {
2617
2668
  attrStr += this.buildAttrPairStr(attr, "" + jObj[key]);
2618
- } else {
2669
+ } else if (!attr) {
2619
2670
  if (key === this.options.textNodeName) {
2620
2671
  let newval = this.options.tagValueProcessor(key, "" + jObj[key]);
2621
2672
  val2 += this.replaceEntitiesValue(newval);
@@ -2635,13 +2686,13 @@ Builder.prototype.j2x = function(jObj, level) {
2635
2686
  else val2 += this.indentate(level) + "<" + key + "/" + this.tagEndChar;
2636
2687
  } else if (typeof item === "object") {
2637
2688
  if (this.options.oneListGroup) {
2638
- const result = this.j2x(item, level + 1);
2689
+ const result = this.j2x(item, level + 1, ajPath.concat(key));
2639
2690
  listTagVal += result.val;
2640
2691
  if (this.options.attributesGroupName && item.hasOwnProperty(this.options.attributesGroupName)) {
2641
2692
  listTagAttr += result.attrStr;
2642
2693
  }
2643
2694
  } else {
2644
- listTagVal += this.processTextOrObjNode(item, key, level);
2695
+ listTagVal += this.processTextOrObjNode(item, key, level, ajPath);
2645
2696
  }
2646
2697
  } else {
2647
2698
  if (this.options.oneListGroup) {
@@ -2665,7 +2716,7 @@ Builder.prototype.j2x = function(jObj, level) {
2665
2716
  attrStr += this.buildAttrPairStr(Ks[j], "" + jObj[key][Ks[j]]);
2666
2717
  }
2667
2718
  } else {
2668
- val2 += this.processTextOrObjNode(jObj[key], key, level);
2719
+ val2 += this.processTextOrObjNode(jObj[key], key, level, ajPath);
2669
2720
  }
2670
2721
  }
2671
2722
  }
@@ -2678,8 +2729,8 @@ Builder.prototype.buildAttrPairStr = function(attrName, val2) {
2678
2729
  return " " + attrName;
2679
2730
  } else return " " + attrName + '="' + val2 + '"';
2680
2731
  };
2681
- function processTextOrObjNode(object, key, level) {
2682
- const result = this.j2x(object, level + 1);
2732
+ function processTextOrObjNode(object, key, level, ajPath) {
2733
+ const result = this.j2x(object, level + 1, ajPath.concat(key));
2683
2734
  if (object[this.options.textNodeName] !== void 0 && Object.keys(object).length === 1) {
2684
2735
  return this.buildTextValNode(object[this.options.textNodeName], key, result.attrStr, level);
2685
2736
  } else {
@@ -2873,8 +2924,8 @@ const isValidView = function(view) {
2873
2924
  if (!view.icon || typeof view.icon !== "string" || !isSvg(view.icon)) {
2874
2925
  throw new Error("View icon is required and must be a valid svg string");
2875
2926
  }
2876
- if (!("order" in view) || typeof view.order !== "number") {
2877
- throw new Error("View order is required and must be a number");
2927
+ if ("order" in view && typeof view.order !== "number") {
2928
+ throw new Error("View order must be a number");
2878
2929
  }
2879
2930
  if (view.columns) {
2880
2931
  view.columns.forEach((column) => {