| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296 |
- import path from 'path/path.js'
- if (typeof window === 'undefined') {
- global.window = {}
- }
- // Copy from https://github.com/primetwig/react-nestable/blob/dacea9dc191399a3520f5dc7623f5edebc83e7b7/dist/utils.js
- export const closest = (target, selector) => {
- // closest(e.target, '.field')
- while (target) {
- if (target.matches && target.matches(selector)) return target
- target = target.parentNode
- }
- return null
- }
- export const getOffsetRect = (elem) => {
- // (1)
- const box = elem.getBoundingClientRect(),
- body = document.body,
- docElem = document.documentElement,
- // (2)
- scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop,
- scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft,
- // (3)
- clientTop = docElem.clientTop || body.clientTop || 0,
- clientLeft = docElem.clientLeft || body.clientLeft || 0,
- // (4)
- top = box.top + scrollTop - clientTop,
- left = box.left + scrollLeft - clientLeft;
- return {
- top: Math.round(top),
- left: Math.round(left)
- }
- }
- // jquery focus
- export const focus = (elem) => {
- return elem === document.activeElement &&
- document.hasFocus() &&
- !!(elem.type || elem.href || ~elem.tabIndex)
- }
- // copied from https://stackoverflow.com/a/32180863
- export const timeConversion = (millisec) => {
- let seconds = (millisec / 1000).toFixed(0),
- minutes = (millisec / (1000 * 60)).toFixed(0),
- hours = (millisec / (1000 * 60 * 60)).toFixed(1),
- days = (millisec / (1000 * 60 * 60 * 24)).toFixed(1);
- if (seconds < 60) {
- return seconds + 's'
- } else if (minutes < 60) {
- return minutes + 'm'
- } else if (hours < 24) {
- return hours + 'h'
- } else {
- return days + 'd'
- }
- }
- export const getSelectionText = () => {
- const selection = (window.getSelection() || '').toString().trim()
- if (selection) {
- return selection
- }
- // Firefox fix
- const activeElement = window.document.activeElement
- if (activeElement) {
- if (activeElement.tagName === 'INPUT' || activeElement.tagName === 'TEXTAREA') {
- const el = activeElement
- return el.value.slice(el.selectionStart || 0, el.selectionEnd || 0)
- }
- }
- return ''
- }
- // Modified from https://github.com/GoogleChromeLabs/browser-nativefs
- // because shadow-cljs doesn't handle this babel transform
- export const getFiles = async (dirHandle, recursive, cb, path = dirHandle.name) => {
- const dirs = []
- const files = []
- for await (const entry of dirHandle.values()) {
- const nestedPath = `${path}/${entry.name}`
- if (entry.kind === 'file') {
- cb(nestedPath, entry)
- files.push(
- entry.getFile().then((file) => {
- Object.defineProperty(file, 'webkitRelativePath', {
- configurable: true,
- enumerable: true,
- get: () => nestedPath,
- })
- Object.defineProperty(file, 'handle', {
- configurable: true,
- enumerable: true,
- get: () => entry,
- })
- return file
- })
- )
- } else if (entry.kind === 'directory' && recursive) {
- cb(nestedPath, entry)
- dirs.push(getFiles(entry, recursive, cb, nestedPath))
- }
- }
- return [(await Promise.all(dirs)), (await Promise.all(files))]
- }
- export const verifyPermission = async (handle, readWrite) => {
- const options = {}
- if (readWrite) {
- options.mode = 'readwrite'
- }
- // Check if permission was already granted.
- if ((await handle.queryPermission(options)) === 'granted') {
- return
- }
- // Request permission. If the user grants permission, just return.
- if ((await handle.requestPermission(options)) === 'granted') {
- return
- }
- // The user didn't grant permission, throw an error.
- throw new Error('Permission is not granted')
- }
- // NOTE: Need externs to prevent `options.recursive` been munged
- // When building with release.
- export const openDirectory = async (options = {}, cb) => {
- options.recursive = options.recursive || false;
- const handle = await window.showDirectoryPicker({
- mode: 'readwrite'
- });
- const _ask = await verifyPermission(handle, true);
- return [handle, getFiles(handle, options.recursive, cb)];
- };
- export const writeFile = async (fileHandle, contents) => {
- // Create a FileSystemWritableFileStream to write to.
- const writable = await fileHandle.createWritable()
- if (contents instanceof ReadableStream) {
- await contents.pipeTo(writable)
- } else {
- // Write the contents of the file to the stream.
- await writable.write(contents)
- // Close the file and write the contents to disk.
- await writable.close()
- }
- }
- export const nfsSupported = () => {
- if ('chooseFileSystemEntries' in self) {
- return 'chooseFileSystemEntries'
- } else if ('showOpenFilePicker' in self) {
- return 'showOpenFilePicker'
- }
- return false
- }
- const inputTypes = [
- window.HTMLInputElement,
- window.HTMLSelectElement,
- window.HTMLTextAreaElement,
- ]
- export const triggerInputChange = (node, value = '', name = 'change') => {
- // only process the change on elements we know have a value setter in their constructor
- if (inputTypes.indexOf(node.__proto__.constructor) > -1) {
- const setValue = Object.getOwnPropertyDescriptor(node.__proto__, 'value').set
- const event = new Event('change', {
- bubbles: true
- })
- setValue.call(node, value)
- node.dispatchEvent(event)
- }
- }
- // Copied from https://github.com/google/diff-match-patch/issues/29#issuecomment-647627182
- export const reversePatch = patch => {
- return patch.map(patchObj => ({
- diffs: patchObj.diffs.map(([op, val]) => [
- op * -1, // The money maker
- val
- ]),
- start1: patchObj.start2,
- start2: patchObj.start1,
- length1: patchObj.length2,
- length2: patchObj.length1
- }));
- };
- // Copied from https://github.com/sindresorhus/path-is-absolute/blob/main/index.js
- export const win32 = path => {
- // https://github.com/nodejs/node/blob/b3fcc245fb25539909ef1d5eaa01dbf92e168633/lib/path.js#L56
- const splitDeviceRe = /^([a-zA-Z]:|[\\/]{2}[^\\/]+[\\/]+[^\\/]+)?([\\/])?([\s\S]*?)$/,
- result = splitDeviceRe.exec(path),
- device = result[1] || '',
- isUnc = Boolean(device && device.charAt(1) !== ':');
- // UNC paths are always absolute
- return Boolean(result[2] || isUnc);
- };
- export const ios = () => {
- return [
- 'iPad Simulator',
- 'iPhone Simulator',
- 'iPod Simulator',
- 'iPad',
- 'iPhone',
- 'iPod'
- ].includes(navigator.platform)
- // iPad on iOS 13 detection
- ||
- (navigator.userAgent.includes("Mac") && "ontouchend" in document)
- }
- export const getClipText = (cb, errorHandler) => {
- navigator.permissions.query({
- name: "clipboard-read"
- }).then((result) => {
- if (result.state == "granted" || result.state == "prompt") {
- navigator.clipboard.readText()
- .then(text => {
- cb(text);
- })
- .catch(err => {
- errorHandler(err)
- });
- }
- })
- }
- export const writeClipboard = (text, isHtml) => {
- let blob = new Blob([text], {
- type: ["text/plain"]
- });
- let data = [new ClipboardItem({
- ["text/plain"]: blob
- })];
- if (isHtml) {
- blob = new Blob([text], {
- type: ["text/plain", "text/html"]
- })
- data = [new ClipboardItem({
- ["text/plain"]: blob,
- ["text/html"]: blob
- })];
- }
- navigator.permissions.query({
- name: "clipboard-write"
- }).then((result) => {
- if (result.state == "granted" || result.state == "prompt") {
- navigator.clipboard.write(data).then(() => {
- /* success */
- }).catch(e => {
- console.log(e, "fail")
- })
- }
- })
- }
- export const toPosixPath = (input) => {
- return input && input.replace(/\\+/g, '/')
- }
- export const nodePath = Object.assign({}, path, {
- basename (input) {
- input = toPosixPath(input)
- return path.basename(input)
- },
- name (input) {
- input = toPosixPath(input)
- return path.parse(input).name
- },
- dirname (input) {
- input = toPosixPath(input)
- return path.dirname(input)
- },
- extname (input) {
- input = toPosixPath(input)
- return path.extname(input)
- }
- })
|