Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | 2x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 2x 2x 1x 2x 9x 9x 9x 7x 9x 2x 1x 1x 1x | import { Capacitor } from '@capacitor/core';
import { FileViewer } from '@capacitor/file-viewer';
import { Directory, Encoding, Filesystem } from '@capacitor/filesystem';
import { FilePicker } from '@capawesome/capacitor-file-picker';
import YAML from 'yaml';
import { keys } from './utils.js';
export async function openFileFromUrl(url: URL | string) {
if (Capacitor.isNativePlatform()) {
await FileViewer.openDocumentFromUrl({
url: url.toString(),
});
} else {
const a = document.createElement('a');
a.href = url.toString();
a.download = 'true';
a.click();
}
}
/**
* **WARNING:** On native platforms, binary data is converted to base64 before writing, which can lag the UI for large files.
* @param contentType defaults to 'text/plain' for strings and 'application/octet-stream' for blobs
* @returns Saved file's URI on native platforms, void on web
*/
export async function downloadAsFile(
content: Blob | ArrayBuffer | string,
filename: string,
contentType: string
): Promise<URL | void> {
if (Capacitor.isNativePlatform()) {
const permission = await Filesystem.checkPermissions();
Iif (permission.publicStorage !== 'granted') {
await Filesystem.requestPermissions();
}
const { path: directoryUri } = await FilePicker.pickDirectory();
console.info('Got directory URI', directoryUri);
// Directory URI looks like: content://com.android.externalstorage.documents/tree/primary%3ADocuments%2Fcigale%20exports
const directory = new URL(
decodeURIComponent(new URL(directoryUri).pathname.split('/').at(-1) || '')
).pathname;
console.info('Saving file to', directory);
/** @type {Pick<import('@capacitor/filesystem').WriteFileOptions, 'data' | 'encoding'>} */
let input: Pick<import('@capacitor/filesystem').WriteFileOptions, 'data' | 'encoding'>;
if (typeof content === 'string') {
input = {
data: content,
encoding: Encoding.UTF8,
};
} else E{
input = {
data: new Uint8Array(
content instanceof Blob ? await content.arrayBuffer() : content
).toBase64(),
};
}
const { uri } = await Filesystem.writeFile({
path: `${directory.replace(/^content:\/\//, '')}/${filename}`,
directory: Directory.ExternalStorage,
...input,
});
console.info('File saved to', uri);
try {
return new URL(uri);
} catch (_err) {
// Some platforms return URIs that the URL constructor doesn't accept in Node/jsdom.
// Fall back to returning the raw string so callers can handle it.
return uri;
}
} else {
const blob =
content instanceof Blob
? content
: new Blob([content], {
type:
contentType ??
(typeof content === 'string'
? 'text/plain'
: 'application/octet-stream'),
});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
a.click();
URL.revokeObjectURL(url);
}
}
/**
*
* @param object the object to serialize
* @param ordering an array of keys in target order, for the top-level object
* @param schema the json schema URL
*/
export function stringifyWithToplevelOrdering<Keys extends string>(
format: 'json' | 'yaml',
schema: string,
object: { [K in Keys]?: unknown },
ordering: readonly Keys[]
) {
let keysOrder = [...ordering];
if (format === 'json') {
// @ts-expect-error $schema is not in Keys but we add it anyways
keysOrder = ['$schema', ...keysOrder];
}
const reviver = (_: unknown, value: unknown) => {
Iif (value === null) return value;
Iif (Array.isArray(value)) return value;
if (typeof value !== 'object') return value;
Eif (keys(value).every((key) => keysOrder.includes(key))) {
// @ts-expect-error key in value thanks to if check above
return Object.fromEntries(keysOrder.map((key) => [key, value[key]]));
}
return value;
};
if (format === 'yaml') {
const yamled = YAML.stringify(object, reviver, 2);
return `# yaml-language-server: $schema=${schema}\n\n${yamled}`;
}
return JSON.stringify({ $schema: schema, ...object }, reviver, 2);
}
|