@ibiz-template-plugin/ibiz-file-previewer 0.0.24 → 0.0.26

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/dist/index.es.js CHANGED
@@ -917,6 +917,8 @@ var ImageMode = /* @__PURE__ */ ((ImageMode2) => {
917
917
  var FileType = /* @__PURE__ */ ((FileType2) => {
918
918
  FileType2["HTML"] = "html";
919
919
  FileType2["MD"] = "md";
920
+ FileType2["YAML"] = "yaml";
921
+ FileType2["YML"] = "yml";
920
922
  FileType2["TXT"] = "txt";
921
923
  FileType2["JSON"] = "json";
922
924
  FileType2["XML"] = "xml";
@@ -984,24 +986,32 @@ const FileTypeEngineMap = /* @__PURE__ */ new Map([
984
986
  ]],
985
987
  // ET类型文件
986
988
  // ------TXT类型文件服务端暂未支持START------
987
- // [FileType.TXT, [EngineType.TXT]], // TXT类型文件
988
- // [FileType.JSON, [EngineType.TXT]], // JSON类型文件
989
- // [FileType.XML, [EngineType.TXT]], // XML类型文件
990
- ["txt", [
991
- "MD"
992
- /* MD */
989
+ ["yaml", [
990
+ "TXT"
991
+ /* TXT */
993
992
  ]],
994
- // TXT类型文件
993
+ // YAML类型文件
994
+ ["yml", [
995
+ "TXT"
996
+ /* TXT */
997
+ ]],
998
+ // YML类型文件
995
999
  ["json", [
996
- "MD"
997
- /* MD */
1000
+ "TXT"
1001
+ /* TXT */
998
1002
  ]],
999
1003
  // JSON类型文件
1000
1004
  ["xml", [
1005
+ "TXT"
1006
+ /* TXT */
1007
+ ]],
1008
+ // XML类型文件
1009
+ // [FileType.TXT, [EngineType.TXT]], // TXT类型文件
1010
+ ["txt", [
1001
1011
  "MD"
1002
1012
  /* MD */
1003
1013
  ]],
1004
- // XML类型文件
1014
+ // TXT类型文件
1005
1015
  // ------TXT类型文件服务端暂未支持END------
1006
1016
  ["pdf", [
1007
1017
  "PDF"
@@ -1178,6 +1188,12 @@ const fileNameToFileType = (fileName) => {
1178
1188
  case "csv":
1179
1189
  fileType = FileType.CSV;
1180
1190
  break;
1191
+ case "yaml":
1192
+ fileType = FileType.YAML;
1193
+ break;
1194
+ case "yml":
1195
+ fileType = FileType.YML;
1196
+ break;
1181
1197
  default:
1182
1198
  fileType = FileType.UNKNOWN;
1183
1199
  }
@@ -1644,6 +1660,42 @@ var posix = {
1644
1660
  posix: null
1645
1661
  };
1646
1662
  posix.posix = posix;
1663
+ class EventEmitter {
1664
+ constructor() {
1665
+ __publicField(this, "handlers", {});
1666
+ }
1667
+ /**
1668
+ * 订阅事件
1669
+ * @param event 事件名
1670
+ * @param handler 处理函数
1671
+ * @returns 取消订阅函数
1672
+ */
1673
+ on(event, handler) {
1674
+ if (!this.handlers[event]) {
1675
+ this.handlers[event] = /* @__PURE__ */ new Set();
1676
+ }
1677
+ this.handlers[event].add(handler);
1678
+ return () => this.off(event, handler);
1679
+ }
1680
+ /**
1681
+ * 取消订阅事件
1682
+ * @param event 事件名
1683
+ * @param handler 处理函数
1684
+ */
1685
+ off(event, handler) {
1686
+ var _a;
1687
+ (_a = this.handlers[event]) == null ? void 0 : _a.delete(handler);
1688
+ }
1689
+ /**
1690
+ * 派发事件
1691
+ * @param event 事件名
1692
+ * @param payload 载荷
1693
+ */
1694
+ emit(event, payload) {
1695
+ var _a;
1696
+ (_a = this.handlers[event]) == null ? void 0 : _a.forEach((handler) => handler(payload));
1697
+ }
1698
+ }
1647
1699
  var f = 0;
1648
1700
  function u(e2, t2, n2, o2, i2, u2) {
1649
1701
  t2 || (t2 = {});
@@ -2253,7 +2305,7 @@ const FilePreviewImage = (props) => {
2253
2305
  onMouseDown: (evt) => controller.handleMouseDown(evt)
2254
2306
  }
2255
2307
  ),
2256
- /* @__PURE__ */ u(Teleport, { to: "#custom-controls", children: /* @__PURE__ */ u("div", { className: "image-toolbar-container", children: [
2308
+ /* @__PURE__ */ u(Teleport, { to: "#".concat(controller.controlsId), children: /* @__PURE__ */ u("div", { className: "image-toolbar-container", children: [
2257
2309
  /* @__PURE__ */ u(
2258
2310
  "button",
2259
2311
  {
@@ -16955,7 +17007,7 @@ const FilePreviewMD = (props) => {
16955
17007
  }, []);
16956
17008
  return /* @__PURE__ */ u("div", { className: "file-preview-md ".concat(c2.state.value.theme), children: [
16957
17009
  /* @__PURE__ */ u("div", { ref: previewRef }),
16958
- /* @__PURE__ */ u(Teleport, { to: "#custom-controls", children: /* @__PURE__ */ u("button", { title: "目录", className: "control-btn", onClick: onOutline, children: /* @__PURE__ */ u("span", { className: "icon", children: /* @__PURE__ */ u(ThumbnailSvg, {}) }) }) })
17010
+ /* @__PURE__ */ u(Teleport, { to: "#".concat(c2.controlsId), children: /* @__PURE__ */ u("button", { title: "目录", className: "control-btn", onClick: onOutline, children: /* @__PURE__ */ u("span", { className: "icon", children: /* @__PURE__ */ u(ThumbnailSvg, {}) }) }) })
16959
17011
  ] });
16960
17012
  };
16961
17013
  function deepFreeze(obj) {
@@ -18753,14 +18805,223 @@ function xml(hljs) {
18753
18805
  ]
18754
18806
  };
18755
18807
  }
18808
+ function yaml(hljs) {
18809
+ const LITERALS = "true false yes no null";
18810
+ const URI_CHARACTERS = "[\\w#;/?:@&=+$,.~*'()[\\]]+";
18811
+ const KEY = {
18812
+ className: "attr",
18813
+ variants: [
18814
+ // added brackets support and special char support
18815
+ { begin: /[\w*@][\w*@ :()\./-]*:(?=[ \t]|$)/ },
18816
+ {
18817
+ // double quoted keys - with brackets and special char support
18818
+ begin: /"[\w*@][\w*@ :()\./-]*":(?=[ \t]|$)/
18819
+ },
18820
+ {
18821
+ // single quoted keys - with brackets and special char support
18822
+ begin: /'[\w*@][\w*@ :()\./-]*':(?=[ \t]|$)/
18823
+ }
18824
+ ]
18825
+ };
18826
+ const TEMPLATE_VARIABLES = {
18827
+ className: "template-variable",
18828
+ variants: [
18829
+ {
18830
+ // jinja templates Ansible
18831
+ begin: /\{\{/,
18832
+ end: /\}\}/
18833
+ },
18834
+ {
18835
+ // Ruby i18n
18836
+ begin: /%\{/,
18837
+ end: /\}/
18838
+ }
18839
+ ]
18840
+ };
18841
+ const SINGLE_QUOTE_STRING = {
18842
+ className: "string",
18843
+ relevance: 0,
18844
+ begin: /'/,
18845
+ end: /'/,
18846
+ contains: [
18847
+ {
18848
+ match: /''/,
18849
+ scope: "char.escape",
18850
+ relevance: 0
18851
+ }
18852
+ ]
18853
+ };
18854
+ const STRING = {
18855
+ className: "string",
18856
+ relevance: 0,
18857
+ variants: [
18858
+ {
18859
+ begin: /"/,
18860
+ end: /"/
18861
+ },
18862
+ { begin: /\S+/ }
18863
+ ],
18864
+ contains: [
18865
+ hljs.BACKSLASH_ESCAPE,
18866
+ TEMPLATE_VARIABLES
18867
+ ]
18868
+ };
18869
+ const CONTAINER_STRING = hljs.inherit(STRING, { variants: [
18870
+ {
18871
+ begin: /'/,
18872
+ end: /'/,
18873
+ contains: [
18874
+ {
18875
+ begin: /''/,
18876
+ relevance: 0
18877
+ }
18878
+ ]
18879
+ },
18880
+ {
18881
+ begin: /"/,
18882
+ end: /"/
18883
+ },
18884
+ { begin: /[^\s,{}[\]]+/ }
18885
+ ] });
18886
+ const DATE_RE = "[0-9]{4}(-[0-9][0-9]){0,2}";
18887
+ const TIME_RE = "([Tt \\t][0-9][0-9]?(:[0-9][0-9]){2})?";
18888
+ const FRACTION_RE = "(\\.[0-9]*)?";
18889
+ const ZONE_RE = "([ \\t])*(Z|[-+][0-9][0-9]?(:[0-9][0-9])?)?";
18890
+ const TIMESTAMP = {
18891
+ className: "number",
18892
+ begin: "\\b" + DATE_RE + TIME_RE + FRACTION_RE + ZONE_RE + "\\b"
18893
+ };
18894
+ const VALUE_CONTAINER = {
18895
+ end: ",",
18896
+ endsWithParent: true,
18897
+ excludeEnd: true,
18898
+ keywords: LITERALS,
18899
+ relevance: 0
18900
+ };
18901
+ const OBJECT = {
18902
+ begin: /\{/,
18903
+ end: /\}/,
18904
+ contains: [VALUE_CONTAINER],
18905
+ illegal: "\\n",
18906
+ relevance: 0
18907
+ };
18908
+ const ARRAY = {
18909
+ begin: "\\[",
18910
+ end: "\\]",
18911
+ contains: [VALUE_CONTAINER],
18912
+ illegal: "\\n",
18913
+ relevance: 0
18914
+ };
18915
+ const MODES2 = [
18916
+ KEY,
18917
+ {
18918
+ className: "meta",
18919
+ begin: "^---\\s*$",
18920
+ relevance: 10
18921
+ },
18922
+ {
18923
+ // multi line string
18924
+ // Blocks start with a | or > followed by a newline
18925
+ //
18926
+ // Indentation of subsequent lines must be the same to
18927
+ // be considered part of the block
18928
+ className: "string",
18929
+ begin: "[\\|>]([1-9]?[+-])?[ ]*\\n( +)[^ ][^\\n]*\\n(\\2[^\\n]+\\n?)*"
18930
+ },
18931
+ {
18932
+ // Ruby/Rails erb
18933
+ begin: "<%[%=-]?",
18934
+ end: "[%-]?%>",
18935
+ subLanguage: "ruby",
18936
+ excludeBegin: true,
18937
+ excludeEnd: true,
18938
+ relevance: 0
18939
+ },
18940
+ {
18941
+ // named tags
18942
+ className: "type",
18943
+ begin: "!\\w+!" + URI_CHARACTERS
18944
+ },
18945
+ // https://yaml.org/spec/1.2/spec.html#id2784064
18946
+ {
18947
+ // verbatim tags
18948
+ className: "type",
18949
+ begin: "!<" + URI_CHARACTERS + ">"
18950
+ },
18951
+ {
18952
+ // primary tags
18953
+ className: "type",
18954
+ begin: "!" + URI_CHARACTERS
18955
+ },
18956
+ {
18957
+ // secondary tags
18958
+ className: "type",
18959
+ begin: "!!" + URI_CHARACTERS
18960
+ },
18961
+ {
18962
+ // fragment id &ref
18963
+ className: "meta",
18964
+ begin: "&" + hljs.UNDERSCORE_IDENT_RE + "$"
18965
+ },
18966
+ {
18967
+ // fragment reference *ref
18968
+ className: "meta",
18969
+ begin: "\\*" + hljs.UNDERSCORE_IDENT_RE + "$"
18970
+ },
18971
+ {
18972
+ // array listing
18973
+ className: "bullet",
18974
+ // TODO: remove |$ hack when we have proper look-ahead support
18975
+ begin: "-(?=[ ]|$)",
18976
+ relevance: 0
18977
+ },
18978
+ hljs.HASH_COMMENT_MODE,
18979
+ {
18980
+ beginKeywords: LITERALS,
18981
+ keywords: { literal: LITERALS }
18982
+ },
18983
+ TIMESTAMP,
18984
+ // numbers are any valid C-style number that
18985
+ // sit isolated from other words
18986
+ {
18987
+ className: "number",
18988
+ begin: hljs.C_NUMBER_RE + "\\b",
18989
+ relevance: 0
18990
+ },
18991
+ OBJECT,
18992
+ ARRAY,
18993
+ SINGLE_QUOTE_STRING,
18994
+ STRING
18995
+ ];
18996
+ const VALUE_MODES = [...MODES2];
18997
+ VALUE_MODES.pop();
18998
+ VALUE_MODES.push(CONTAINER_STRING);
18999
+ VALUE_CONTAINER.contains = VALUE_MODES;
19000
+ return {
19001
+ name: "YAML",
19002
+ case_insensitive: true,
19003
+ aliases: ["yml"],
19004
+ contains: MODES2
19005
+ };
19006
+ }
18756
19007
  HighlightJS.registerLanguage("xml", xml);
18757
19008
  HighlightJS.registerLanguage("json", json);
19009
+ HighlightJS.registerLanguage("yaml", yaml);
18758
19010
  const FilePreviewText = (props) => {
18759
19011
  const c2 = props.controller;
18760
19012
  const previewRef = A(null);
18761
19013
  y$1(() => {
18762
19014
  try {
18763
- previewRef.current.textContent = c2.state.value.content;
19015
+ if (c2.state.value.fileType === FileType.JSON) {
19016
+ try {
19017
+ const jsonObject = JSON.parse(c2.state.value.content);
19018
+ previewRef.current.textContent = JSON.stringify(jsonObject, null, 2);
19019
+ } catch (error2) {
19020
+ previewRef.current.textContent = c2.state.value.content;
19021
+ }
19022
+ } else {
19023
+ previewRef.current.textContent = c2.state.value.content;
19024
+ }
18764
19025
  HighlightJS.highlightElement(previewRef.current);
18765
19026
  } catch (error2) {
18766
19027
  console.error(error2);
@@ -19214,6 +19475,14 @@ const FilePreviewImageGroup = (props) => {
19214
19475
  observer.disconnect();
19215
19476
  };
19216
19477
  }, []);
19478
+ y$1(() => {
19479
+ const unsubscribe = controller.events.on("goToPage", (page) => {
19480
+ scrollToPage(page);
19481
+ });
19482
+ return () => {
19483
+ unsubscribe();
19484
+ };
19485
+ }, []);
19217
19486
  return /* @__PURE__ */ u("div", { className: "file-preview-image-group", children: [
19218
19487
  /* @__PURE__ */ u(
19219
19488
  "div",
@@ -19276,7 +19545,7 @@ const FilePreviewImageGroup = (props) => {
19276
19545
  ]
19277
19546
  }
19278
19547
  ),
19279
- /* @__PURE__ */ u(Teleport, { to: "#custom-controls", children: /* @__PURE__ */ u("div", { className: "image-toolbar-container", children: [
19548
+ /* @__PURE__ */ u(Teleport, { to: "#".concat(controller.controlsId), children: /* @__PURE__ */ u("div", { className: "image-toolbar-container", children: [
19280
19549
  /* @__PURE__ */ u(
19281
19550
  "button",
19282
19551
  {
@@ -19497,7 +19766,7 @@ const FilePreviewShell = (props) => {
19497
19766
  ] })
19498
19767
  ] }),
19499
19768
  /* @__PURE__ */ u("div", { className: "preview-controls", children: [
19500
- /* @__PURE__ */ u("div", { className: "custom-controls", id: "custom-controls" }),
19769
+ /* @__PURE__ */ u("div", { className: "custom-controls", id: controller.controlsId }),
19501
19770
  /* @__PURE__ */ u(
19502
19771
  "button",
19503
19772
  {
@@ -19541,7 +19810,9 @@ const FilePreviewShell = (props) => {
19541
19810
  children: state.value.isCreated && controller.preViewComp && controller.preViewController ? _$2(controller.preViewComp, {
19542
19811
  controller: controller.preViewController,
19543
19812
  onInitialization: () => {
19813
+ var _a, _b;
19544
19814
  controller.updateState({ isLoading: false });
19815
+ (_b = (_a = controller.getOptions()).onInitialized) == null ? void 0 : _b.call(_a);
19545
19816
  }
19546
19817
  }) : null
19547
19818
  }
@@ -19560,9 +19831,19 @@ class FilePreviewItemController {
19560
19831
  * 状态
19561
19832
  */
19562
19833
  __publicField(this, "state", d$1({}));
19834
+ /**
19835
+ * 事件对象,用于向组件派发瞬时动作事件
19836
+ */
19837
+ __publicField(this, "events", new EventEmitter());
19563
19838
  this.filePreviewShell = filePreviewShell;
19564
19839
  this.initState();
19565
19840
  }
19841
+ /**
19842
+ * 工具栏容器唯一 id(代理自 shell controller)
19843
+ */
19844
+ get controlsId() {
19845
+ return this.filePreviewShell.controlsId;
19846
+ }
19566
19847
  /**
19567
19848
  * 更新状态
19568
19849
  * - 所有的状态更新必须调用该方法,以便界面响应
@@ -19741,6 +20022,22 @@ class FilePreviewImageGroupController extends FilePreviewImageController {
19741
20022
  const { showThumbnailPanel } = this.state.value;
19742
20023
  this.updateState({ showThumbnailPanel: !showThumbnailPanel });
19743
20024
  }
20025
+ /**
20026
+ * 跳转至指定页(0-based)
20027
+ * - 越界或内容未加载时静默忽略
20028
+ * - 同步更新 currentPage,并派发 goToPage 事件由组件执行滚动
20029
+ * @param page 目标页索引
20030
+ */
20031
+ goToPage(page) {
20032
+ setTimeout(() => {
20033
+ const { total } = this.state.value;
20034
+ if (!Number.isInteger(page) || total <= 0 || page < 0 || page >= total) {
20035
+ return;
20036
+ }
20037
+ this.updateState({ currentPage: page });
20038
+ this.events.emit("goToPage", page);
20039
+ }, 0);
20040
+ }
19744
20041
  /**
19745
20042
  * 处理旋转角度改变
19746
20043
  * @param value
@@ -20650,6 +20947,7 @@ class FilePreviewItemDispatcher {
20650
20947
  * 引擎预览组件映射表
20651
20948
  */
20652
20949
  __publicField(FilePreviewItemDispatcher, "enginePreviewMap", /* @__PURE__ */ new Map());
20950
+ let filePreviewInstanceId = 0;
20653
20951
  class FilePreviewShellController {
20654
20952
  /**
20655
20953
  * 构造函数
@@ -20668,6 +20966,11 @@ class FilePreviewShellController {
20668
20966
  * 文件预览控制器
20669
20967
  */
20670
20968
  __publicField(this, "preViewController");
20969
+ /**
20970
+ * 当前实例工具栏容器唯一 id(不带 #)
20971
+ * - 构造时确定,生命周期内不变
20972
+ */
20973
+ __publicField(this, "controlsId");
20671
20974
  /**
20672
20975
  * 文件预览器状态对象
20673
20976
  */
@@ -20689,6 +20992,8 @@ class FilePreviewShellController {
20689
20992
  if (options.theme) this.updateState({ theme: options.theme });
20690
20993
  FilePreviewItemDispatcher.initialize();
20691
20994
  this.getState = this.getState.bind(this);
20995
+ filePreviewInstanceId += 1;
20996
+ this.controlsId = "custom-controls-".concat(filePreviewInstanceId);
20692
20997
  }
20693
20998
  /**
20694
20999
  * 更新状态
@@ -20874,6 +21179,17 @@ class FilePreviewShellController {
20874
21179
  this.mountComponent();
20875
21180
  this.updateState({ isCreated: true });
20876
21181
  }
21182
+ /**
21183
+ * 跳转至目标页
21184
+ * - 仅对图片组场景生效,其它场景忽略
21185
+ * - 页码为 0-based
21186
+ * @param page 目标页索引
21187
+ */
21188
+ goToPage(page) {
21189
+ if (this.preViewController instanceof FilePreviewImageGroupController) {
21190
+ this.preViewController.goToPage(page);
21191
+ }
21192
+ }
20877
21193
  }
20878
21194
  export {
20879
21195
  ActionType,