yanki 2.0.12 → 2.0.14
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/bin/cli.js +154 -154
- package/dist/bin/open-X1dozMxs.js +2 -0
- package/dist/lib/index.js +173 -187
- package/dist/standalone/index.d.ts +1 -1
- package/dist/standalone/index.js +67 -67
- package/dist/standalone/open-Co6eM9oM.js +2 -0
- package/package.json +16 -16
- package/readme.md +5 -5
- package/dist/bin/open-PkGTdlsi.js +0 -2
- package/dist/standalone/open-DnUwqK4E.js +0 -2
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import e from"node:process";import t from"node:fs";import n from"node:path";import{promisify as r}from"node:util";import i,{execFile as a}from"node:child_process";import{fileURLToPath as o}from"node:url";import s,{constants as c}from"node:fs/promises";import l from"node:os";import{Buffer as u}from"node:buffer";let d;function f(){try{return t.statSync(`/.dockerenv`),!0}catch{return!1}}function ee(){try{return t.readFileSync(`/proc/self/cgroup`,`utf8`).includes(`docker`)}catch{return!1}}function p(){return d===void 0&&(d=f()||ee()),d}let m;const h=()=>{try{return t.statSync(`/run/.containerenv`),!0}catch{return!1}};function g(){return m===void 0&&(m=h()||p()),m}const _=()=>{if(e.platform!==`linux`)return!1;if(l.release().toLowerCase().includes(`microsoft`))return!g();try{if(t.readFileSync(`/proc/version`,`utf8`).toLowerCase().includes(`microsoft`))return!g()}catch{}return t.existsSync(`/proc/sys/fs/binfmt_misc/WSLInterop`)||t.existsSync(`/run/WSL`)?!g():!1};var v=e.env.__IS_WSL_TEST__?_:_();const y=r(i.execFile),b=()=>`${e.env.SYSTEMROOT||e.env.windir||String.raw`C:\Windows`}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`,x=async(e,t={})=>{let{powerShellPath:n,...r}=t,i=x.encodeCommand(e);return y(n??b(),[...x.argumentsPrefix,i],{encoding:`utf8`,...r})};x.argumentsPrefix=[`-NoProfile`,`-NonInteractive`,`-ExecutionPolicy`,`Bypass`,`-EncodedCommand`],x.encodeCommand=e=>u.from(e,`utf16le`).toString(`base64`),x.escapeArgument=e=>`'${String(e).replaceAll(`'`,`''`)}'`;function S(e){for(let t of e.split(`
|
|
2
|
+
`)){if(/^\s*#/.test(t))continue;let e=/^\s*root\s*=\s*(?<mountPoint>"[^"]*"|'[^']*'|[^#]*)/.exec(t);if(e)return e.groups.mountPoint.trim().replaceAll(/^["']|["']$/g,``)}}const C=r(i.execFile),te=(()=>{let e=`/mnt/`,t;return async function(){if(t)return t;let n=`/etc/wsl.conf`,r=!1;try{await s.access(n,c.F_OK),r=!0}catch{}if(!r)return e;let i=S(await s.readFile(n,{encoding:`utf8`}));return i===void 0?e:(t=i,t=t.endsWith(`/`)?t:`${t}/`,t)}})(),w=v?async()=>`${await te()}c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe`:b;let T;const E=async()=>(T??=(async()=>{try{let e=await w();return await s.access(e,c.X_OK),!0}catch{return!1}})(),T),D=async()=>{let e=await w(),t=String.raw`(Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice").ProgId`,{stdout:n}=await x(t,{powerShellPath:e});return n.trim()},O=async e=>{if(/^[a-z]+:\/\//i.test(e))return e;try{let{stdout:t}=await C(`wslpath`,[`-aw`,e],{encoding:`utf8`});return t.trim()}catch{return e}};function k(e,t,n){let r=n=>Object.defineProperty(e,t,{value:n,enumerable:!0,writable:!0});return Object.defineProperty(e,t,{configurable:!0,enumerable:!0,get(){let e=n();return r(e),e},set(e){r(e)}}),e}const A=r(a);async function j(){if(e.platform!==`darwin`)throw Error(`macOS only`);let{stdout:t}=await A(`defaults`,[`read`,`com.apple.LaunchServices/com.apple.launchservices.secure`,`LSHandlers`]),n=/LSHandlerRoleAll = "(?!-)(?<id>[^"]+?)";\s+?LSHandlerURLScheme = (?:http|https);/.exec(t)?.groups.id??`com.apple.Safari`;return n===`com.apple.safari`?`com.apple.Safari`:n}const M=r(a);async function N(t,{humanReadableOutput:n=!0,signal:r}={}){if(e.platform!==`darwin`)throw Error(`macOS only`);let i=n?[]:[`-ss`],a={};r&&(a.signal=r);let{stdout:o}=await M(`osascript`,[`-e`,t,i],a);return o.trim()}async function P(e){return N(`tell application "Finder" to set app_path to application file id "${e}" as string\ntell application "System Events" to get value of property list item "CFBundleName" of property list file (app_path & ":Contents:Info.plist")`)}const F=r(a),I={MSEdgeHTM:{name:`Edge`,id:`com.microsoft.edge`},MSEdgeBHTML:{name:`Edge Beta`,id:`com.microsoft.edge.beta`},MSEdgeDHTML:{name:`Edge Dev`,id:`com.microsoft.edge.dev`},AppXq0fevzme2pys62n3e0fbqa7peapykr8v:{name:`Edge`,id:`com.microsoft.edge.old`},ChromeHTML:{name:`Chrome`,id:`com.google.chrome`},ChromeBHTML:{name:`Chrome Beta`,id:`com.google.chrome.beta`},ChromeDHTML:{name:`Chrome Dev`,id:`com.google.chrome.dev`},ChromiumHTM:{name:`Chromium`,id:`org.chromium.Chromium`},BraveHTML:{name:`Brave`,id:`com.brave.Browser`},BraveBHTML:{name:`Brave Beta`,id:`com.brave.Browser.beta`},BraveDHTML:{name:`Brave Dev`,id:`com.brave.Browser.dev`},BraveSSHTM:{name:`Brave Nightly`,id:`com.brave.Browser.nightly`},FirefoxURL:{name:`Firefox`,id:`org.mozilla.firefox`},OperaStable:{name:`Opera`,id:`com.operasoftware.Opera`},VivaldiHTM:{name:`Vivaldi`,id:`com.vivaldi.Vivaldi`},"IE.HTTP":{name:`Internet Explorer`,id:`com.microsoft.ie`}},L=new Map(Object.entries(I));var R=class extends Error{};async function z(e=F){let{stdout:t}=await e(`reg`,[`QUERY`,` HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\http\\UserChoice`,`/v`,`ProgId`]),n=/ProgId\s*REG_SZ\s*(?<id>\S+)/.exec(t);if(!n)throw new R(`Cannot find Windows browser in stdout: ${JSON.stringify(t)}`);let{id:r}=n.groups,i=r.lastIndexOf(`.`),a=r.lastIndexOf(`-`),o=i===-1?void 0:r.slice(0,i),s=a===-1?void 0:r.slice(0,a);return I[r]??I[o]??I[s]??{name:r,id:r}}const B=r(a),V=e=>e.toLowerCase().replaceAll(/(?:^|\s|-)\S/g,e=>e.toUpperCase());async function H(){if(e.platform===`darwin`){let e=await j();return{name:await P(e),id:e}}if(e.platform===`linux`){let{stdout:e}=await B(`xdg-mime`,[`query`,`default`,`x-scheme-handler/http`]),t=e.trim();return{name:V(t.replace(/.desktop$/,``).replace(`-`,` `)),id:t}}if(e.platform===`win32`)return z();throw Error(`Only macOS, Linux, and Windows are supported`)}const U=!!(e.env.SSH_CONNECTION||e.env.SSH_CLIENT||e.env.SSH_TTY),W=Symbol(`fallbackAttempt`),G=import.meta.url?n.dirname(o(import.meta.url)):``,K=n.join(G,`xdg-open`),{platform:q,arch:J}=e,Y=async(e,t)=>{if(e.length===0)return;let n=[];for(let r of e)try{return await t(r)}catch(e){n.push(e)}throw AggregateError(n,`Failed to open in all supported apps`)},X=async t=>{t={wait:!1,background:!1,newInstance:!1,allowNonzeroExitCode:!1,...t};let n=t[W]===!0;if(delete t[W],Array.isArray(t.app))return Y(t.app,e=>X({...t,app:e,[W]:!0}));let{name:r,arguments:a=[]}=t.app??{};if(a=[...a],Array.isArray(r))return Y(r,e=>X({...t,app:{name:e,arguments:a},[W]:!0}));if(r===`browser`||r===`browserPrivate`){let e={"com.google.chrome":`chrome`,"google-chrome.desktop":`chrome`,"com.brave.browser":`brave`,"org.mozilla.firefox":`firefox`,"firefox.desktop":`firefox`,"com.microsoft.msedge":`edge`,"com.microsoft.edge":`edge`,"com.microsoft.edgemac":`edge`,"microsoft-edge.desktop":`edge`,"com.apple.safari":`safari`},n={chrome:`--incognito`,brave:`--incognito`,firefox:`--private-window`,edge:`--inPrivate`},i;if(v){let e=await D();i=L.get(e)??{}}else i=await H();if(i.id in e){let o=e[i.id.toLowerCase()];if(r===`browserPrivate`){if(o===`safari`)throw Error(`Safari doesn't support opening in private mode via command line`);a.push(n[o])}return X({...t,app:{name:$[o],arguments:a}})}throw Error(`${i.name} is not supported as a default browser`)}let o,l=[],u={},d=!1;if(v&&!g()&&!U&&!r&&(d=await E()),q===`darwin`)o=`open`,t.wait&&l.push(`--wait-apps`),t.background&&l.push(`--background`),t.newInstance&&l.push(`--new`),r&&l.push(`-a`,r);else if(q===`win32`||d){o=await w(),l.push(...x.argumentsPrefix),v||(u.windowsVerbatimArguments=!0),v&&t.target&&(t.target=await O(t.target));let e=[`$ProgressPreference = 'SilentlyContinue';`,`Start`];t.wait&&e.push(`-Wait`),r?(e.push(x.escapeArgument(r)),t.target&&a.push(t.target)):t.target&&e.push(x.escapeArgument(t.target)),a.length>0&&(a=a.map(e=>x.escapeArgument(e)),e.push(`-ArgumentList`,a.join(`,`))),t.target=x.encodeCommand(e.join(` `)),t.wait||(u.stdio=`ignore`)}else{if(r)o=r;else{let t=!G||G===`/`,n=!1;try{await s.access(K,c.X_OK),n=!0}catch{}o=e.versions.electron??(q===`android`||t||!n)?`xdg-open`:K}a.length>0&&l.push(...a),t.wait||(u.stdio=`ignore`,u.detached=!0)}q===`darwin`&&a.length>0&&l.push(`--args`,...a),t.target&&l.push(t.target);let f=i.spawn(o,l,u);return t.wait?new Promise((e,n)=>{f.once(`error`,n),f.once(`close`,r=>{if(!t.allowNonzeroExitCode&&r!==0){n(Error(`Exited with code ${r}`));return}e(f)})}):n?new Promise((e,t)=>{f.once(`error`,t),f.once(`spawn`,()=>{f.once(`close`,n=>{if(f.off(`error`,t),n!==0){t(Error(`Exited with code ${n}`));return}f.unref(),e(f)})})}):(f.unref(),new Promise((e,t)=>{f.once(`error`,t),f.once(`spawn`,()=>{f.off(`error`,t),e(f)})}))},ne=(e,t)=>{if(typeof e!=`string`&&!Array.isArray(e))throw TypeError("Expected a valid `name`");let{arguments:n=[]}=t??{};if(n!=null&&!Array.isArray(n))throw TypeError("Expected `appArguments` as Array type");return X({...t,app:{name:e,arguments:n}})};function Z(e){if(typeof e==`string`||Array.isArray(e))return e;let{[J]:t}=e;if(!t)throw Error(`${J} is not supported`);return t}function Q({[q]:e},{wsl:t}={}){if(t&&v)return Z(t);if(!e)throw Error(`${q} is not supported`);return Z(e)}const $={browser:`browser`,browserPrivate:`browserPrivate`};k($,`chrome`,()=>Q({darwin:`google chrome`,win32:`chrome`,linux:[`google-chrome`,`google-chrome-stable`,`chromium`,`chromium-browser`]},{wsl:{ia32:`/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe`,x64:[`/mnt/c/Program Files/Google/Chrome/Application/chrome.exe`,`/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe`]}})),k($,`brave`,()=>Q({darwin:`brave browser`,win32:`brave`,linux:[`brave-browser`,`brave`]},{wsl:{ia32:`/mnt/c/Program Files (x86)/BraveSoftware/Brave-Browser/Application/brave.exe`,x64:[`/mnt/c/Program Files/BraveSoftware/Brave-Browser/Application/brave.exe`,`/mnt/c/Program Files (x86)/BraveSoftware/Brave-Browser/Application/brave.exe`]}})),k($,`firefox`,()=>Q({darwin:`firefox`,win32:String.raw`C:\Program Files\Mozilla Firefox\firefox.exe`,linux:`firefox`},{wsl:`/mnt/c/Program Files/Mozilla Firefox/firefox.exe`})),k($,`edge`,()=>Q({darwin:`microsoft edge`,win32:`msedge`,linux:[`microsoft-edge`,`microsoft-edge-dev`]},{wsl:`/mnt/c/Program Files (x86)/Microsoft/Edge/Application/msedge.exe`})),k($,`safari`,()=>Q({darwin:`Safari`}));export{ne as openApp};
|
package/dist/lib/index.js
CHANGED
|
@@ -91,7 +91,7 @@ function truncateOnWordBoundary(text, maxLength, truncationString = "...", wordB
|
|
|
91
91
|
return `${words.join(wordBoundary).slice(0, maxLengthSafe)}${truncationString}`;
|
|
92
92
|
}
|
|
93
93
|
function cleanClassName(className) {
|
|
94
|
-
return className.toLowerCase().replaceAll(
|
|
94
|
+
return className.toLowerCase().replaceAll(new RegExp("[^\\dA-Za-z]", "gv"), " ").trim().replaceAll(new RegExp(" +", "gv"), "-");
|
|
95
95
|
}
|
|
96
96
|
function emptyIsUndefined(text) {
|
|
97
97
|
if (text === void 0) return;
|
|
@@ -106,8 +106,8 @@ function emptyIsUndefined(text) {
|
|
|
106
106
|
function css$1(strings, ...values) {
|
|
107
107
|
return trimLeadingIndentation(strings, ...values);
|
|
108
108
|
}
|
|
109
|
-
const NEWLINE_REGEX$1 =
|
|
110
|
-
const LEADING_WHITESPACE_REGEX =
|
|
109
|
+
const NEWLINE_REGEX$1 = new RegExp("\\r?\\n", "v");
|
|
110
|
+
const LEADING_WHITESPACE_REGEX = new RegExp("^(\\s+)", "v");
|
|
111
111
|
function trimLeadingIndentation(strings, ...values) {
|
|
112
112
|
const lines = strings.reduce((result, text, i) => `${result}${text}${String(values[i] ?? "")}`, "").split(NEWLINE_REGEX$1).filter((line) => line.trim() !== "");
|
|
113
113
|
const leadingSpace = LEADING_WHITESPACE_REGEX.exec(lines[0] ?? "")?.[0] ?? "";
|
|
@@ -235,8 +235,7 @@ const MEDIA_SUPPORTED_AUDIO_VIDEO_EXTENSIONS = [
|
|
|
235
235
|
];
|
|
236
236
|
/**
|
|
237
237
|
* Anki seems happy to open PDF files and download markdown files that have been
|
|
238
|
-
* added to the assets folder...
|
|
239
|
-
* https://help.obsidian.md/Files+and+folders/Accepted+file+formats
|
|
238
|
+
* added to the assets folder... https://obsidian.md/help/file-formats
|
|
240
239
|
*/
|
|
241
240
|
const MEDIA_SUPPORTED_FILE_EXTENSIONS = ["md", "pdf"];
|
|
242
241
|
const MEDIA_SUPPORTED_EXTENSIONS = [
|
|
@@ -247,7 +246,7 @@ const MEDIA_SUPPORTED_EXTENSIONS = [
|
|
|
247
246
|
//#endregion
|
|
248
247
|
//#region src/lib/utilities/platform.ts
|
|
249
248
|
const ENVIRONMENT = typeof window === "undefined" ? typeof process === "undefined" ? "other" : "node" : "browser";
|
|
250
|
-
ENVIRONMENT === "browser" ?
|
|
249
|
+
ENVIRONMENT === "browser" ? new RegExp("windows", "iv").test(navigator.userAgent) || new RegExp("mac", "iv").test(navigator.userAgent) || new RegExp("linux", "iv").test(navigator.userAgent) || new RegExp("ubuntu", "iv").test(navigator.userAgent) : ENVIRONMENT === "node" && (process.platform === "win32" || process.platform === "darwin" || process.platform);
|
|
251
250
|
//#endregion
|
|
252
251
|
//#region src/lib/shared/types.ts
|
|
253
252
|
const defaultGlobalOptions = {
|
|
@@ -308,7 +307,10 @@ async function fileExists(absoluteFilePath, fileAdapter) {
|
|
|
308
307
|
}
|
|
309
308
|
async function getFileContentHash(absoluteFilePath, fileAdapter, mode = MEDIA_DEFAULT_HASH_MODE_FILE) {
|
|
310
309
|
switch (mode) {
|
|
311
|
-
case "content":
|
|
310
|
+
case "content": {
|
|
311
|
+
const fileContent = await fileAdapter.readFileBuffer(absoluteFilePath);
|
|
312
|
+
return (await sha256(fileContent)).slice(0, 16);
|
|
313
|
+
}
|
|
312
314
|
case "metadata": {
|
|
313
315
|
const { mtimeMs, size } = await fileAdapter.stat(absoluteFilePath);
|
|
314
316
|
const stringToHash = `${mtimeMs ?? ""}${size ?? ""}`;
|
|
@@ -320,88 +322,88 @@ async function getFileContentHash(absoluteFilePath, fileAdapter, mode = MEDIA_DE
|
|
|
320
322
|
}
|
|
321
323
|
//#endregion
|
|
322
324
|
//#region src/lib/utilities/namespace.ts
|
|
323
|
-
const CONSECUTIVE_HYPHENS_REGEX =
|
|
324
|
-
const ASTERISK_REGEX =
|
|
325
|
+
const CONSECUTIVE_HYPHENS_REGEX = new RegExp("-+", "gv");
|
|
326
|
+
const ASTERISK_REGEX = new RegExp("\\*", "v");
|
|
325
327
|
const FORBIDDEN_CHARACTERS = [
|
|
326
|
-
[
|
|
327
|
-
[
|
|
328
|
-
[
|
|
329
|
-
[
|
|
330
|
-
[
|
|
331
|
-
[
|
|
332
|
-
[
|
|
333
|
-
[
|
|
334
|
-
[
|
|
335
|
-
[
|
|
336
|
-
[
|
|
337
|
-
[
|
|
338
|
-
[
|
|
339
|
-
[
|
|
340
|
-
[
|
|
341
|
-
[
|
|
342
|
-
[
|
|
343
|
-
[
|
|
344
|
-
[
|
|
345
|
-
[
|
|
346
|
-
[
|
|
347
|
-
[
|
|
348
|
-
[
|
|
349
|
-
[
|
|
350
|
-
[
|
|
351
|
-
[
|
|
352
|
-
[
|
|
353
|
-
[
|
|
354
|
-
[
|
|
355
|
-
[
|
|
356
|
-
[
|
|
357
|
-
[
|
|
358
|
-
[
|
|
359
|
-
[
|
|
360
|
-
[
|
|
361
|
-
[
|
|
362
|
-
[
|
|
363
|
-
[
|
|
364
|
-
[
|
|
365
|
-
[
|
|
366
|
-
[
|
|
367
|
-
[
|
|
368
|
-
[
|
|
369
|
-
[
|
|
370
|
-
[
|
|
371
|
-
[
|
|
372
|
-
[
|
|
373
|
-
[
|
|
374
|
-
[
|
|
375
|
-
[
|
|
376
|
-
[
|
|
377
|
-
[
|
|
378
|
-
[
|
|
379
|
-
[
|
|
380
|
-
[
|
|
381
|
-
[
|
|
382
|
-
[
|
|
383
|
-
[
|
|
384
|
-
[
|
|
385
|
-
[
|
|
386
|
-
[
|
|
387
|
-
[
|
|
388
|
-
[
|
|
389
|
-
[
|
|
390
|
-
[
|
|
391
|
-
[
|
|
392
|
-
[
|
|
393
|
-
[
|
|
394
|
-
[
|
|
395
|
-
[
|
|
396
|
-
[
|
|
397
|
-
[
|
|
398
|
-
[
|
|
399
|
-
[
|
|
400
|
-
[
|
|
401
|
-
[
|
|
402
|
-
[
|
|
403
|
-
[
|
|
404
|
-
[
|
|
328
|
+
[new RegExp(":", "v"), "Colon"],
|
|
329
|
+
[new RegExp("\\u{0000}", "v"), "Null"],
|
|
330
|
+
[new RegExp("\\u{0001}", "v"), "Start of Heading"],
|
|
331
|
+
[new RegExp("\\u{0002}", "v"), "Start of Text"],
|
|
332
|
+
[new RegExp("\\u{0003}", "v"), "End of Text"],
|
|
333
|
+
[new RegExp("\\u{0004}", "v"), "End of Transmission"],
|
|
334
|
+
[new RegExp("\\u{0005}", "v"), "Enquiry"],
|
|
335
|
+
[new RegExp("\\u{0006}", "v"), "Acknowledge"],
|
|
336
|
+
[new RegExp("\\u{0007}", "v"), "Bell"],
|
|
337
|
+
[new RegExp("\\u{0008}", "v"), "Backspace"],
|
|
338
|
+
[new RegExp("\\u{0009}", "v"), "Horizontal Tab"],
|
|
339
|
+
[new RegExp("\\u{000A}", "v"), "Line Feed"],
|
|
340
|
+
[new RegExp("\\u{000B}", "v"), "Vertical Tab"],
|
|
341
|
+
[new RegExp("\\u{000C}", "v"), "Form Feed"],
|
|
342
|
+
[new RegExp("\\u{000D}", "v"), "Carriage Return"],
|
|
343
|
+
[new RegExp("\\u{000E}", "v"), "Shift Out"],
|
|
344
|
+
[new RegExp("\\u{000F}", "v"), "Shift In"],
|
|
345
|
+
[new RegExp("\\u{0010}", "v"), "Data Link Escape"],
|
|
346
|
+
[new RegExp("\\u{0011}", "v"), "Device Control 1"],
|
|
347
|
+
[new RegExp("\\u{0012}", "v"), "Device Control 2"],
|
|
348
|
+
[new RegExp("\\u{0013}", "v"), "Device Control 3"],
|
|
349
|
+
[new RegExp("\\u{0014}", "v"), "Device Control 4"],
|
|
350
|
+
[new RegExp("\\u{0015}", "v"), "Negative Acknowledge"],
|
|
351
|
+
[new RegExp("\\u{0016}", "v"), "Synchronous Idle"],
|
|
352
|
+
[new RegExp("\\u{0017}", "v"), "End of Transmission Block"],
|
|
353
|
+
[new RegExp("\\u{0018}", "v"), "Cancel"],
|
|
354
|
+
[new RegExp("\\u{0019}", "v"), "End of Medium"],
|
|
355
|
+
[new RegExp("\\u{001A}", "v"), "Substitute"],
|
|
356
|
+
[new RegExp("\\u{001B}", "v"), "Escape"],
|
|
357
|
+
[new RegExp("\\u{001C}", "v"), "File Separator"],
|
|
358
|
+
[new RegExp("\\u{001D}", "v"), "Group Separator"],
|
|
359
|
+
[new RegExp("\\u{001E}", "v"), "Record Separator"],
|
|
360
|
+
[new RegExp("\\u{001F}", "v"), "Unit Separator"],
|
|
361
|
+
[new RegExp("\\u{007F}", "v"), "Delete"],
|
|
362
|
+
[new RegExp("\\u{0080}", "v"), "Padding Character"],
|
|
363
|
+
[new RegExp("\\u{0081}", "v"), "High Octet Preset"],
|
|
364
|
+
[new RegExp("\\u{0082}", "v"), "Break Permitted Here"],
|
|
365
|
+
[new RegExp("\\u{0083}", "v"), "No Break Here"],
|
|
366
|
+
[new RegExp("\\u{0084}", "v"), "Index"],
|
|
367
|
+
[new RegExp("\\u{0085}", "v"), "Next Line"],
|
|
368
|
+
[new RegExp("\\u{0086}", "v"), "Start of Selected Area"],
|
|
369
|
+
[new RegExp("\\u{0087}", "v"), "End of Selected Area"],
|
|
370
|
+
[new RegExp("\\u{0088}", "v"), "Character Tabulation Set"],
|
|
371
|
+
[new RegExp("\\u{0089}", "v"), "Character Tabulation with Justification"],
|
|
372
|
+
[new RegExp("\\u{008A}", "v"), "Line Tabulation Set"],
|
|
373
|
+
[new RegExp("\\u{008B}", "v"), "Partial Line Forward"],
|
|
374
|
+
[new RegExp("\\u{008C}", "v"), "Partial Line Backward"],
|
|
375
|
+
[new RegExp("\\u{008D}", "v"), "Reverse Line Feed"],
|
|
376
|
+
[new RegExp("\\u{008E}", "v"), "Single Shift Two"],
|
|
377
|
+
[new RegExp("\\u{008F}", "v"), "Single Shift Three"],
|
|
378
|
+
[new RegExp("\\u{0090}", "v"), "Device Control String"],
|
|
379
|
+
[new RegExp("\\u{0091}", "v"), "Private Use One"],
|
|
380
|
+
[new RegExp("\\u{0092}", "v"), "Private Use Two"],
|
|
381
|
+
[new RegExp("\\u{0093}", "v"), "Set Transmit State"],
|
|
382
|
+
[new RegExp("\\u{0094}", "v"), "Cancel Character"],
|
|
383
|
+
[new RegExp("\\u{0095}", "v"), "Message Waiting"],
|
|
384
|
+
[new RegExp("\\u{0096}", "v"), "Start of Protected Area"],
|
|
385
|
+
[new RegExp("\\u{0097}", "v"), "End of Protected Area"],
|
|
386
|
+
[new RegExp("\\u{0098}", "v"), "Start of String"],
|
|
387
|
+
[new RegExp("\\u{0099}", "v"), "Single Graphic Character Introducer"],
|
|
388
|
+
[new RegExp("\\u{009A}", "v"), "Single Character Introducer"],
|
|
389
|
+
[new RegExp("\\u{009B}", "v"), "Control Sequence Introducer"],
|
|
390
|
+
[new RegExp("\\u{009C}", "v"), "String Terminator"],
|
|
391
|
+
[new RegExp("\\u{009D}", "v"), "Operating System Command"],
|
|
392
|
+
[new RegExp("\\u{009E}", "v"), "Privacy Message"],
|
|
393
|
+
[new RegExp("\\u{009F}", "v"), "Application Program Command"],
|
|
394
|
+
[new RegExp("\\u{00A0}", "v"), "Non-breaking Space"],
|
|
395
|
+
[new RegExp("\\u{00AD}", "v"), "Soft Hyphen"],
|
|
396
|
+
[new RegExp("\\u{200B}", "v"), "Zero-width Space"],
|
|
397
|
+
[new RegExp("\\u{200C}", "v"), "Zero-width Non-joiner"],
|
|
398
|
+
[new RegExp("\\u{200D}", "v"), "Zero-width Joiner"],
|
|
399
|
+
[new RegExp("\\u{200E}", "v"), "Left-to-right Mark"],
|
|
400
|
+
[new RegExp("\\u{200F}", "v"), "Right-to-left Mark"],
|
|
401
|
+
[new RegExp("\\u{202A}", "v"), "Left-to-right Embedding"],
|
|
402
|
+
[new RegExp("\\u{202B}", "v"), "Right-to-left Embedding"],
|
|
403
|
+
[new RegExp("\\u{202C}", "v"), "Pop Directional Formatting"],
|
|
404
|
+
[new RegExp("\\u{202D}", "v"), "Left-to-right Override"],
|
|
405
|
+
[new RegExp("\\u{202E}", "v"), "Right-to-left Override"],
|
|
406
|
+
[new RegExp("\\u{FEFF}", "v"), "Byte Order Mark (BOM)"]
|
|
405
407
|
];
|
|
406
408
|
/**
|
|
407
409
|
* Convenience
|
|
@@ -508,8 +510,8 @@ function getFileExtensionForMimeType(mimeType) {
|
|
|
508
510
|
}
|
|
509
511
|
//#endregion
|
|
510
512
|
//#region src/lib/utilities/path.ts
|
|
511
|
-
const WINDOWS_DRIVE_LETTER_REGEX =
|
|
512
|
-
const QUERY_FRAGMENT_START_REGEX =
|
|
513
|
+
const WINDOWS_DRIVE_LETTER_REGEX = new RegExp("^[A-Z]:", "iv");
|
|
514
|
+
const QUERY_FRAGMENT_START_REGEX = new RegExp("[#^]", "v");
|
|
513
515
|
/**
|
|
514
516
|
* The browserify polyfill doesn't implement win32 absolute path detection...
|
|
515
517
|
*
|
|
@@ -520,7 +522,7 @@ const QUERY_FRAGMENT_START_REGEX = /* @__PURE__ */ new RegExp("[#^]", "v");
|
|
|
520
522
|
function isAbsolute(filePath) {
|
|
521
523
|
return isAbsolutePath.posix(filePath) || isAbsolutePath.win32(filePath);
|
|
522
524
|
}
|
|
523
|
-
const RE_WINDOWS_EXTENDED_LENGTH_PATH =
|
|
525
|
+
const RE_WINDOWS_EXTENDED_LENGTH_PATH = new RegExp("^\\\\\\\\\\?\\\\.+", "v");
|
|
524
526
|
/**
|
|
525
527
|
* Converts all paths to cross-platform 'mixed' style with forward slashes.
|
|
526
528
|
* Warns on unsupported Windows extended length paths.
|
|
@@ -576,27 +578,26 @@ function getBaseAndQueryParts(filePath) {
|
|
|
576
578
|
return [path.join(directoryPath, base), query];
|
|
577
579
|
}
|
|
578
580
|
/**
|
|
579
|
-
* Get every plausible base and anchor interpretation of a
|
|
580
|
-
* may contain anchor delimiter characters (`#`, `^`), ordered from the
|
|
581
|
-
* literal
|
|
582
|
-
* first delimiter
|
|
583
|
-
*
|
|
584
|
-
*
|
|
585
|
-
*
|
|
586
|
-
*
|
|
587
|
-
*
|
|
581
|
+
* Get every plausible base and anchor interpretation of a local link target
|
|
582
|
+
* that may contain anchor delimiter characters (`#`, `^`), ordered from the
|
|
583
|
+
* longest literal path (no anchor at all) to the shortest (anchor starts at the
|
|
584
|
+
* first delimiter, matching Obsidian's anchor syntax).
|
|
585
|
+
*
|
|
586
|
+
* This operates on the unnormalized link target and deliberately considers
|
|
587
|
+
* delimiters before slashes. A slash after a delimiter belongs to the anchor,
|
|
588
|
+
* not the file path. File and directory names may also legitimately contain
|
|
589
|
+
* these characters, so callers must normalize only each candidate's `filePath`
|
|
590
|
+
* and try candidates in order against a list of real files.
|
|
588
591
|
* https://github.com/kitschpatrol/yanki/issues/20
|
|
589
592
|
*/
|
|
590
|
-
function
|
|
591
|
-
const directoryPath = path.dirname(filePath);
|
|
592
|
-
const fileName = path.basename(filePath);
|
|
593
|
+
function getLocalPathCandidates(linkTarget) {
|
|
593
594
|
const candidates = [{
|
|
594
|
-
|
|
595
|
-
|
|
595
|
+
anchor: void 0,
|
|
596
|
+
filePath: linkTarget
|
|
596
597
|
}];
|
|
597
|
-
for (let index =
|
|
598
|
-
|
|
599
|
-
|
|
598
|
+
for (let index = linkTarget.length - 1; index >= 0; index--) if (QUERY_FRAGMENT_START_REGEX.test(linkTarget.charAt(index))) candidates.push({
|
|
599
|
+
anchor: linkTarget.slice(index),
|
|
600
|
+
filePath: linkTarget.slice(0, index)
|
|
600
601
|
});
|
|
601
602
|
return candidates;
|
|
602
603
|
}
|
|
@@ -608,8 +609,8 @@ function getQuery(filePath) {
|
|
|
608
609
|
}
|
|
609
610
|
//#endregion
|
|
610
611
|
//#region src/lib/utilities/url.ts
|
|
611
|
-
const DRIVE_LETTER_REGEX =
|
|
612
|
-
const FILE_PREFIX_REGEX =
|
|
612
|
+
const DRIVE_LETTER_REGEX = new RegExp("^[a-z]:", "iv");
|
|
613
|
+
const FILE_PREFIX_REGEX = new RegExp("^file:", "iv");
|
|
613
614
|
function safeDecodeURI(text) {
|
|
614
615
|
try {
|
|
615
616
|
return decodeURI(text);
|
|
@@ -789,7 +790,7 @@ async function getContentHash(absolutePathOrUrl, fileAdapter, fetchAdapter) {
|
|
|
789
790
|
}
|
|
790
791
|
//#endregion
|
|
791
792
|
//#region src/lib/parse/rehype-mathjax-anki.ts
|
|
792
|
-
const CONSECUTIVE_BRACES_REGEX =
|
|
793
|
+
const CONSECUTIVE_BRACES_REGEX = new RegExp("([\\{\\}])(?=[\\{\\}])", "gv");
|
|
793
794
|
function sanitizeBraces(value) {
|
|
794
795
|
return value.replaceAll(CONSECUTIVE_BRACES_REGEX, "$1 ");
|
|
795
796
|
}
|
|
@@ -843,7 +844,7 @@ const plugin$2 = function() {
|
|
|
843
844
|
};
|
|
844
845
|
//#endregion
|
|
845
846
|
//#region src/lib/parse/rehype-utilities.ts
|
|
846
|
-
const DIMENSION_CHARS_REGEX =
|
|
847
|
+
const DIMENSION_CHARS_REGEX = new RegExp("^[\\dx]+$", "v");
|
|
847
848
|
const highlighter = createHighlighterCoreSync({
|
|
848
849
|
engine: createJavaScriptRegexEngine(),
|
|
849
850
|
langs: [
|
|
@@ -919,9 +920,7 @@ async function mdastToHtml(mdast, options) {
|
|
|
919
920
|
case "localFileUrl":
|
|
920
921
|
absolutePathOrUrl = node.properties.src;
|
|
921
922
|
break;
|
|
922
|
-
case "remoteHttpUrl":
|
|
923
|
-
absolutePathOrUrl = node.properties.src;
|
|
924
|
-
break;
|
|
923
|
+
case "remoteHttpUrl": absolutePathOrUrl = node.properties.src;
|
|
925
924
|
}
|
|
926
925
|
treeMutationPromises.push(async () => {
|
|
927
926
|
const extension = await getAnkiMediaFilenameExtension(absolutePathOrUrl, srcType === "obsidianVaultUrl" ? void 0 : fetchAdapter);
|
|
@@ -1691,8 +1690,8 @@ function formatListResult(result) {
|
|
|
1691
1690
|
}
|
|
1692
1691
|
//#endregion
|
|
1693
1692
|
//#region src/lib/utilities/filenames.ts
|
|
1694
|
-
const CLOZE_CONTENT_REGEX =
|
|
1695
|
-
const FILENAME_INCREMENT_SUFFIX_REGEX =
|
|
1693
|
+
const CLOZE_CONTENT_REGEX = new RegExp("\\{\\{\\w\\d*\\s?:{0,2}([^:\\}]+)", "v");
|
|
1694
|
+
const FILENAME_INCREMENT_SUFFIX_REGEX = new RegExp("\\s\\(\\d+\\)$", "v");
|
|
1696
1695
|
function getSafeTitleForNote(note, manageFilenames, maxLength) {
|
|
1697
1696
|
if (manageFilenames === "off") throw new Error("manageFilenames must not be off");
|
|
1698
1697
|
switch (note.modelName) {
|
|
@@ -1731,7 +1730,7 @@ function getSafeFilename(text, maxLength) {
|
|
|
1731
1730
|
let basicSafeFilename = filenamify(getFirstLineOfHtmlAsPlainText(text).trim(), {
|
|
1732
1731
|
maxLength: Number.MAX_SAFE_INTEGER,
|
|
1733
1732
|
replacement: " "
|
|
1734
|
-
}).replaceAll(
|
|
1733
|
+
}).replaceAll(new RegExp("\\s+", "gv"), " ").trim();
|
|
1735
1734
|
if (basicSafeFilename.length === 0) basicSafeFilename = MEDIA_DEFAULT_EMPTY_FILENAME;
|
|
1736
1735
|
basicSafeFilename = basicSafeFilename.normalize("NFC");
|
|
1737
1736
|
if (maxLength === void 0) return basicSafeFilename;
|
|
@@ -1774,7 +1773,7 @@ function getTemporarilyUniqueFilePath(filePath) {
|
|
|
1774
1773
|
}
|
|
1775
1774
|
//#endregion
|
|
1776
1775
|
//#region src/lib/utilities/resolve-link.ts
|
|
1777
|
-
const MD_EXTENSION_REGEX =
|
|
1776
|
+
const MD_EXTENSION_REGEX = new RegExp("\\.md$", "v");
|
|
1778
1777
|
const defaultResolveLinkOptions = {
|
|
1779
1778
|
allFilePaths: [],
|
|
1780
1779
|
basePath: void 0,
|
|
@@ -1813,48 +1812,25 @@ const defaultResolveLinkOptions = {
|
|
|
1813
1812
|
* parameters)
|
|
1814
1813
|
*/
|
|
1815
1814
|
function resolveLink(filePathOrUrl, options) {
|
|
1816
|
-
const
|
|
1815
|
+
const resolvedOptions = deepmerge(defaultResolveLinkOptions, options ?? {});
|
|
1816
|
+
const { allFilePaths, convertFilePathsToProtocol, cwd, obsidianVaultName } = resolvedOptions;
|
|
1817
1817
|
if (convertFilePathsToProtocol === "obsidian" && obsidianVaultName === void 0) console.warn(`convertFilePathsToProtocol is 'obsidian', but no obsidianVaultName provided`);
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
const resolvedUrl = resolveNameLink(normalize(decodedUrl), cwd, allFilePaths ?? []) ?? resolveWithBasePath(decodedUrl, {
|
|
1824
|
-
basePath,
|
|
1825
|
-
cwd
|
|
1826
|
-
});
|
|
1827
|
-
if (getSrcType(resolvedUrl) === "localFilePath") {
|
|
1828
|
-
currentPathOrUrl = resolvedUrl;
|
|
1829
|
-
continue;
|
|
1830
|
-
}
|
|
1831
|
-
console.warn(`Failed to convert local file wiki-style name to path: ${currentPathOrUrl} --> ${resolvedUrl}`);
|
|
1832
|
-
return resolvedUrl;
|
|
1833
|
-
}
|
|
1834
|
-
if (sourceType === "localFileUrl") {
|
|
1835
|
-
const resolvedUrl = normalize(fileUrlToPath(currentPathOrUrl));
|
|
1836
|
-
if (getSrcType(resolvedUrl) === "localFilePath") {
|
|
1837
|
-
currentPathOrUrl = resolvedUrl;
|
|
1838
|
-
continue;
|
|
1839
|
-
}
|
|
1840
|
-
console.warn(`Failed to convert file URL to path: ${currentPathOrUrl} --> ${resolvedUrl}`);
|
|
1841
|
-
return resolvedUrl;
|
|
1818
|
+
const decodedUrl = safeDecodeURI(filePathOrUrl) ?? filePathOrUrl;
|
|
1819
|
+
switch (getSrcType(decodedUrl)) {
|
|
1820
|
+
case "localFileName": {
|
|
1821
|
+
const resolvedNameLink = resolveNameLink(decodedUrl, cwd, allFilePaths ?? []);
|
|
1822
|
+
return resolvedNameLink === void 0 ? resolveLocalFilePath(decodedUrl, resolvedOptions) : resolveMatchedLocalLink(resolvedNameLink, resolvedOptions);
|
|
1842
1823
|
}
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
convertFilePathsToProtocol,
|
|
1848
|
-
cwd,
|
|
1849
|
-
obsidianVaultName,
|
|
1850
|
-
type
|
|
1851
|
-
});
|
|
1852
|
-
case "obsidianVaultUrl": return currentPathOrUrl;
|
|
1853
|
-
case "remoteHttpUrl": return currentPathOrUrl;
|
|
1854
|
-
case "unsupportedProtocolUrl":
|
|
1855
|
-
console.warn(`Unsupported URL protocol: ${currentPathOrUrl}`);
|
|
1856
|
-
return currentPathOrUrl;
|
|
1824
|
+
case "localFilePath": return resolveLocalFilePath(decodedUrl, resolvedOptions);
|
|
1825
|
+
case "localFileUrl": {
|
|
1826
|
+
const encodedFilePath = fileUrlToPath(filePathOrUrl);
|
|
1827
|
+
return resolveLocalFilePath(safeDecodeURI(encodedFilePath) ?? encodedFilePath, resolvedOptions);
|
|
1857
1828
|
}
|
|
1829
|
+
case "obsidianVaultUrl":
|
|
1830
|
+
case "remoteHttpUrl": return filePathOrUrl;
|
|
1831
|
+
case "unsupportedProtocolUrl":
|
|
1832
|
+
console.warn(`Unsupported URL protocol: ${filePathOrUrl}`);
|
|
1833
|
+
return filePathOrUrl;
|
|
1858
1834
|
}
|
|
1859
1835
|
}
|
|
1860
1836
|
/**
|
|
@@ -1863,28 +1839,33 @@ function resolveLink(filePathOrUrl, options) {
|
|
|
1863
1839
|
* `max-depth` lint rule).
|
|
1864
1840
|
*/
|
|
1865
1841
|
function resolveLocalFilePath(decodedUrl, options) {
|
|
1866
|
-
const { allFilePaths, basePath,
|
|
1867
|
-
const
|
|
1842
|
+
const { allFilePaths, basePath, cwd } = options;
|
|
1843
|
+
const candidates = getLocalPathCandidates(decodedUrl);
|
|
1844
|
+
for (const { anchor, filePath } of candidates) {
|
|
1845
|
+
const resolvedBase = resolveWithBasePath(normalize(filePath), {
|
|
1846
|
+
basePath,
|
|
1847
|
+
cwd
|
|
1848
|
+
});
|
|
1849
|
+
const matchedPath = (path.extname(resolvedBase) === "" ? [`${resolvedBase}.md`] : [resolvedBase, `${resolvedBase}.md`]).find((candidate) => pathExistsInAllFiles(candidate, allFilePaths ?? []));
|
|
1850
|
+
if (matchedPath !== void 0) return resolveMatchedLocalLink({
|
|
1851
|
+
anchor,
|
|
1852
|
+
filePath: matchedPath
|
|
1853
|
+
}, options);
|
|
1854
|
+
}
|
|
1855
|
+
return resolveWithBasePath(normalize(candidates.at(-1)?.filePath ?? decodedUrl), {
|
|
1868
1856
|
basePath,
|
|
1869
1857
|
cwd
|
|
1870
1858
|
});
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
}
|
|
1879
|
-
}
|
|
1880
|
-
if (matchedPath !== void 0) {
|
|
1881
|
-
if (convertFilePathsToProtocol !== "none" && (type === "link" || type === "embed" && [".md", ".pdf"].includes(path.extname(matchedPath)))) {
|
|
1882
|
-
if (convertFilePathsToProtocol === "obsidian" && obsidianVaultName !== void 0) return createObsidianVaultLink(`${matchedPath}${matchedQuery ?? ""}`, basePath ?? "", obsidianVaultName);
|
|
1883
|
-
if (convertFilePathsToProtocol === "file") return createFileLink(`${matchedPath}${matchedQuery ?? ""}`);
|
|
1884
|
-
}
|
|
1885
|
-
return matchedPath;
|
|
1859
|
+
}
|
|
1860
|
+
/** Render a matched local file and its still-unmodified Obsidian anchor. */
|
|
1861
|
+
function resolveMatchedLocalLink(link, options) {
|
|
1862
|
+
const { anchor, filePath } = link;
|
|
1863
|
+
const { basePath, convertFilePathsToProtocol, obsidianVaultName, type } = options;
|
|
1864
|
+
if (convertFilePathsToProtocol !== "none" && (type === "link" || type === "embed" && [".md", ".pdf"].includes(path.extname(filePath)))) {
|
|
1865
|
+
if (convertFilePathsToProtocol === "obsidian" && obsidianVaultName !== void 0) return createObsidianVaultLink(link, basePath ?? "", obsidianVaultName);
|
|
1866
|
+
if (convertFilePathsToProtocol === "file") return createFileLink(`${filePath}${anchor ?? ""}`);
|
|
1886
1867
|
}
|
|
1887
|
-
return
|
|
1868
|
+
return filePath;
|
|
1888
1869
|
}
|
|
1889
1870
|
/**
|
|
1890
1871
|
* Convert from a (usually wiki-style) named link to an absolute path to an
|
|
@@ -1904,14 +1885,18 @@ function resolveLocalFilePath(decodedUrl, options) {
|
|
|
1904
1885
|
* @param allFilePaths Array of absolute paths to all other files in the paths
|
|
1905
1886
|
* to be considered. (POSIX-style paths.)
|
|
1906
1887
|
*
|
|
1907
|
-
* @returns
|
|
1908
|
-
* undefined if there's no valid match. (POSIX-style
|
|
1888
|
+
* @returns The absolute path to the best matching file and its unmodified
|
|
1889
|
+
* anchor, or undefined if there's no valid match. (POSIX-style path.)
|
|
1909
1890
|
*/
|
|
1910
1891
|
function resolveNameLink(name, cwd, allFilePaths) {
|
|
1911
1892
|
if (allFilePaths.length === 0) return;
|
|
1912
|
-
for (const {
|
|
1913
|
-
const
|
|
1914
|
-
|
|
1893
|
+
for (const { anchor, filePath } of getLocalPathCandidates(name)) {
|
|
1894
|
+
const normalizedBase = normalize(filePath);
|
|
1895
|
+
const match = findBestNameMatch(path.extname(normalizedBase) === "" ? `${normalizedBase}.md` : normalizedBase, cwd, allFilePaths);
|
|
1896
|
+
if (match !== void 0) return {
|
|
1897
|
+
anchor,
|
|
1898
|
+
filePath: match
|
|
1899
|
+
};
|
|
1915
1900
|
}
|
|
1916
1901
|
}
|
|
1917
1902
|
/**
|
|
@@ -1965,9 +1950,9 @@ function pathExistsInAllFiles(filePath, allFilePaths) {
|
|
|
1965
1950
|
function createFileLink(absolutePath) {
|
|
1966
1951
|
return `file://${absolutePath}`;
|
|
1967
1952
|
}
|
|
1968
|
-
function createObsidianVaultLink(
|
|
1969
|
-
const
|
|
1970
|
-
return `obsidian://open?vault=${encodeURIComponent(obsidianVault)}&file=${encodeURIComponent(
|
|
1953
|
+
function createObsidianVaultLink(link, basePath, obsidianVault) {
|
|
1954
|
+
const linkPath = `${stripBasePath(link.filePath, basePath)}${link.anchor ?? ""}`;
|
|
1955
|
+
return `obsidian://open?vault=${encodeURIComponent(obsidianVault)}&file=${encodeURIComponent(linkPath)}`;
|
|
1971
1956
|
}
|
|
1972
1957
|
//#endregion
|
|
1973
1958
|
//#region src/lib/parse/remark-resolve-links.ts
|
|
@@ -2321,7 +2306,7 @@ const plugin = function() {
|
|
|
2321
2306
|
};
|
|
2322
2307
|
//#endregion
|
|
2323
2308
|
//#region src/lib/parse/remark-utilities.ts
|
|
2324
|
-
const CLOZE_NUMBER_PREFIX_REGEX =
|
|
2309
|
+
const CLOZE_NUMBER_PREFIX_REGEX = new RegExp("^[\\(\\|]?(\\d{1,2})(?:[\\s\\).\\|]|$)(.*)$", "v");
|
|
2325
2310
|
const defaultAstFromMarkdownOptions = { ...defaultGlobalOptions };
|
|
2326
2311
|
async function getAstFromMarkdown(markdown, options) {
|
|
2327
2312
|
const { allFilePaths, basePath, cwd, obsidianVault, resolveUrls } = deepmerge(defaultAstFromMarkdownOptions, options ?? {});
|
|
@@ -2878,7 +2863,7 @@ function formatSetStyleResult(result, verbose = false) {
|
|
|
2878
2863
|
}
|
|
2879
2864
|
//#endregion
|
|
2880
2865
|
//#region src/lib/model/frontmatter.ts
|
|
2881
|
-
const NEWLINE_REGEX =
|
|
2866
|
+
const NEWLINE_REGEX = new RegExp("\\r?\\n", "v");
|
|
2882
2867
|
/**
|
|
2883
2868
|
* Update the noteId in the frontmatter of a markdown string.
|
|
2884
2869
|
*
|
|
@@ -2906,7 +2891,8 @@ async function setNoteIdInFrontmatter(markdown, noteId) {
|
|
|
2906
2891
|
...lines
|
|
2907
2892
|
].join("\n");
|
|
2908
2893
|
}
|
|
2909
|
-
const
|
|
2894
|
+
const frontmatter = lines.slice(frontmatterStart + 1, frontmatterEnd).join("\n");
|
|
2895
|
+
const parsedFrontmatter = await parse(frontmatter) ?? {};
|
|
2910
2896
|
if (noteId === void 0) {
|
|
2911
2897
|
delete parsedFrontmatter.noteId;
|
|
2912
2898
|
if (Object.keys(parsedFrontmatter).length === 0) {
|
|
@@ -805,7 +805,7 @@ Same as `PartialDeep`, but accepts only `object`s as inputs. Internal helper for
|
|
|
805
805
|
*/
|
|
806
806
|
type PartialObjectDeep<ObjectType extends object, Options extends Required<PartialDeepOptions>> = { [KeyType in keyof ObjectType]?: _PartialDeep<ObjectType[KeyType], Options>; };
|
|
807
807
|
//#endregion
|
|
808
|
-
//#region node_modules/.pnpm/yanki-connect@4.0.
|
|
808
|
+
//#region node_modules/.pnpm/yanki-connect@4.0.8/node_modules/yanki-connect/dist/index.d.ts
|
|
809
809
|
//#region src/types/deck.d.ts
|
|
810
810
|
type DeckStats = {
|
|
811
811
|
deck_id: number;
|