@wenyan-md/core 1.0.15 → 1.0.16

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/publish.js CHANGED
@@ -64,22 +64,44 @@ async function publishArticle(title, content, thumbMediaId, accessToken) {
64
64
  return await response.json();
65
65
  }
66
66
  function normalizePath(p) {
67
- if (!p) return "";
68
- let res = p.replace(/\\/g, "/");
69
- if (res.endsWith("/")) {
70
- res = res.slice(0, -1);
71
- }
72
- return res;
67
+ return p.replace(/\\/g, "/").replace(/\/+$/, "");
68
+ }
69
+ function isAbsolutePath(path2) {
70
+ if (!path2) return false;
71
+ const winAbsPattern = /^[a-zA-Z]:\//;
72
+ const linuxAbsPattern = /^\//;
73
+ return winAbsPattern.test(path2) || linuxAbsPattern.test(path2);
73
74
  }
74
75
  const RuntimeEnv = {
75
76
  isContainer: !!process.env.CONTAINERIZED,
76
77
  hostFilePath: normalizePath(process.env.HOST_FILE_PATH || ""),
77
78
  containerFilePath: normalizePath(process.env.CONTAINER_FILE_PATH || "/mnt/host-downloads"),
78
- resolveLocalPath(inputPath) {
79
- if (!this.isContainer || !this.hostFilePath) {
80
- return path.resolve(inputPath);
79
+ resolveLocalPath(inputPath, relativeBase) {
80
+ if (!this.isContainer) {
81
+ if (relativeBase) {
82
+ return path.resolve(relativeBase, inputPath);
83
+ } else {
84
+ if (!path.isAbsolute(inputPath)) {
85
+ throw new Error(
86
+ `Invalid input: '${inputPath}'. When relativeBase is not provided, inputPath must be an absolute path.`
87
+ );
88
+ }
89
+ return path.normalize(inputPath);
90
+ }
91
+ }
92
+ let normalizedInput = normalizePath(inputPath);
93
+ relativeBase = normalizePath(relativeBase || "");
94
+ if (relativeBase) {
95
+ if (!isAbsolutePath(normalizedInput)) {
96
+ normalizedInput = relativeBase + (normalizedInput.startsWith("/") ? "" : "/") + normalizedInput;
97
+ }
98
+ } else {
99
+ if (!isAbsolutePath(normalizedInput)) {
100
+ throw new Error(
101
+ `Invalid input: '${inputPath}'. When relativeBase is not provided, inputPath must be an absolute path.`
102
+ );
103
+ }
81
104
  }
82
- const normalizedInput = normalizePath(inputPath);
83
105
  if (normalizedInput.startsWith(this.hostFilePath)) {
84
106
  let relativePart = normalizedInput.slice(this.hostFilePath.length);
85
107
  if (relativePart && !relativePart.startsWith("/")) {
@@ -93,7 +115,7 @@ const RuntimeEnv = {
93
115
  return normalizedInput;
94
116
  }
95
117
  };
96
- async function uploadImage(imageUrl, accessToken, fileName) {
118
+ async function uploadImage(imageUrl, accessToken, fileName, relativePath) {
97
119
  let fileData;
98
120
  let finalName;
99
121
  if (imageUrl.startsWith("http")) {
@@ -111,16 +133,15 @@ async function uploadImage(imageUrl, accessToken, fileName) {
111
133
  const contentType = response.headers.get("content-type") || "image/jpeg";
112
134
  fileData = new Blob([buffer], { type: contentType });
113
135
  } else {
114
- const resolvedPath = RuntimeEnv.resolveLocalPath(imageUrl);
115
- const safePath = path$1.resolve(resolvedPath);
116
- const stats = await stat(safePath);
136
+ const resolvedPath = RuntimeEnv.resolveLocalPath(imageUrl, relativePath);
137
+ const stats = await stat(resolvedPath);
117
138
  if (stats.size === 0) {
118
- throw new Error(`本地图片大小为0,无法上传: ${safePath}`);
139
+ throw new Error(`本地图片大小为0,无法上传: ${resolvedPath}`);
119
140
  }
120
141
  const fileNameFromLocal = path$1.basename(resolvedPath);
121
142
  const ext = path$1.extname(fileNameFromLocal);
122
143
  finalName = fileName ?? (ext === "" ? `${fileNameFromLocal}.jpg` : fileNameFromLocal);
123
- fileData = await fileFromPath(safePath);
144
+ fileData = await fileFromPath(resolvedPath);
124
145
  }
125
146
  const data = await uploadMaterial("image", fileData, finalName, accessToken);
126
147
  if (data.errcode) {
@@ -128,7 +149,7 @@ async function uploadImage(imageUrl, accessToken, fileName) {
128
149
  }
129
150
  return data;
130
151
  }
131
- async function uploadImages(content, accessToken) {
152
+ async function uploadImages(content, accessToken, relativePath) {
132
153
  if (!content.includes("<img")) {
133
154
  return { html: content, firstImageId: "" };
134
155
  }
@@ -139,7 +160,7 @@ async function uploadImages(content, accessToken) {
139
160
  const dataSrc = element.getAttribute("src");
140
161
  if (dataSrc) {
141
162
  if (!dataSrc.startsWith("https://mmbiz.qpic.cn")) {
142
- const resp = await uploadImage(dataSrc, accessToken);
163
+ const resp = await uploadImage(dataSrc, accessToken, void 0, relativePath);
143
164
  element.setAttribute("src", resp.url);
144
165
  return resp.media_id;
145
166
  } else {
@@ -153,7 +174,7 @@ async function uploadImages(content, accessToken) {
153
174
  const updatedHtml = dom.serialize();
154
175
  return { html: updatedHtml, firstImageId };
155
176
  }
156
- async function publishToDraft(title, content, cover, appId, appSecret) {
177
+ async function publishToDraft(title, content, cover, appId, appSecret, relativePath) {
157
178
  const accessToken = await fetchAccessToken(appId, appSecret);
158
179
  if (!accessToken.access_token) {
159
180
  if (accessToken.errcode) {
@@ -162,14 +183,14 @@ async function publishToDraft(title, content, cover, appId, appSecret) {
162
183
  throw new Error(`获取 Access Token 失败: ${accessToken}`);
163
184
  }
164
185
  }
165
- const { html, firstImageId } = await uploadImages(content, accessToken.access_token);
186
+ const { html, firstImageId } = await uploadImages(content, accessToken.access_token, relativePath);
166
187
  let thumbMediaId = "";
167
188
  if (cover) {
168
- const resp = await uploadImage(cover, accessToken.access_token, "cover.jpg");
189
+ const resp = await uploadImage(cover, accessToken.access_token, "cover.jpg", relativePath);
169
190
  thumbMediaId = resp.media_id;
170
191
  } else {
171
192
  if (firstImageId.startsWith("https://mmbiz.qpic.cn")) {
172
- const resp = await uploadImage(firstImageId, accessToken.access_token, "cover.jpg");
193
+ const resp = await uploadImage(firstImageId, accessToken.access_token, "cover.jpg", relativePath);
173
194
  thumbMediaId = resp.media_id;
174
195
  } else {
175
196
  thumbMediaId = firstImageId;
@@ -1 +1 @@
1
- export declare function publishToDraft(title: string, content: string, cover: string, appId?: string, appSecret?: string): Promise<any>;
1
+ export declare function publishToDraft(title: string, content: string, cover: string, appId?: string, appSecret?: string, relativePath?: string): Promise<any>;
@@ -2,5 +2,5 @@ export declare const RuntimeEnv: {
2
2
  isContainer: boolean;
3
3
  hostFilePath: string;
4
4
  containerFilePath: string;
5
- resolveLocalPath(inputPath: string): string;
5
+ resolveLocalPath(inputPath: string, relativeBase?: string): string;
6
6
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wenyan-md/core",
3
- "version": "1.0.15",
3
+ "version": "1.0.16",
4
4
  "description": "Core library for Wenyan markdown rendering & publishing",
5
5
  "author": "Lei <caol64@gmail.com> (https://github.com/caol64)",
6
6
  "license": "Apache-2.0",