import { App , Plugin , PluginSettingTab , Setting , TAbstractFile } from 'obsidian' ; import compareVersions from 'compare-versions' ; interface CustomJSSettings { jsFiles : string ; jsFolder : string ; } const DEFAULT_SETTINGS = { jsFiles : '' , jsFolder : '' , } ; export default class CustomJS extends Plugin { settings : CustomJSSettings ; async onload ( ) { console . log ( 'Loading CustomJS' ) ; await this . loadSettings ( ) ; this . registerEvent ( this . app . vault . on ( 'modify' , this . reloadIfNeeded , this ) ) ; this . app . workspace . onLayoutReady ( ( ) => { this . loadClasses ( ) ; } ) ; this . addSettingTab ( new CustomJSSettingsTab ( this . app , this ) ) ; } onunload ( ) { delete window . customJS ; } async reloadIfNeeded ( f ) { if ( f . path . endsWith ( '.js' ) ) { await this . loadClasses ( ) ; if ( this . app . plugins . enabledPlugins . has ( "dataview" ) ) { const version = this . app . plugins . plugins ?. dataview ?. manifest . version ; if ( compareVersions ( version , '0.4.11' ) < 0 ) return ; this . app . plugins . plugins . dataview ?. api ?. index ?. touch ( ) ; } } } async loadSettings ( ) { const settings = await this . loadData ( ) ; this . settings = { ... DEFAULT_SETTINGS , ... settings } ; } async saveSettings ( ) { await this . saveData ( this . settings ) ; } async evalFile ( f , customjs ) { try { const file = await this . app . vault . adapter . read ( f ) ; const def = eval ( '(' + file + ')' ) ; const cls = new def ( ) ; customjs [ cls . constructor . name ] = cls ; } catch ( e ) { console . error ( `CustomJS couldn\'t import ${ f }` ) ; console . error ( e ) ; } } async loadClasses ( ) { const customjs = { } ; const filesToLoad = [ ] ; if ( this . settings . jsFiles != '' ) { const individualFiles = this . settings . jsFiles . split ( ',' ) . map ( s => s . trim ( ) ) . sort ( ) ; for ( const f of individualFiles ) { if ( f != '' && f . endsWith ( '.js' ) ) { filesToLoad . push ( f ) ; } } } if ( this . settings . jsFolder != '' ) { const prefix = this . settings . jsFolder ; const files = this . app . vault . getFiles ( ) ; const scripts = files . filter ( f => f . path . startsWith ( prefix ) && f . path . endsWith ( '.js' ) ) ; for ( const s of scripts ) { if ( s . path != '' && s . path . endsWith ( '.js' ) ) { filesToLoad . push ( s . path ) ; } } } this . sortByFileName ( filesToLoad ) ; for ( const f of filesToLoad ) { await this . evalFile ( f , customjs ) ; } window . customJS = customjs ; } sortByFileName ( files ) { files . sort ( ( a , b ) => { const nameA = a . split ( '/' ) . last ( ) ; const nameB = b . split ( '/' ) . last ( ) ; return nameA . localeCompare ( nameB ) ; } ) ; } } class CustomJSSettingsTab extends PluginSettingTab { plugin : CustomJS ; constructor ( app , plugin ) { super ( app , plugin ) ; this . plugin = plugin ; } display ( ) { let { containerEl } = this ; containerEl . empty ( ) ; containerEl . createEl ( 'h2' , { text : 'CustomJS' } ) ; new Setting ( containerEl ) . setName ( 'Individual files' ) . setDesc ( 'Comma-separated list of files to load' ) . addText ( text => text . setPlaceholder ( 'jsfile1.js,jsfile2.js' ) . setValue ( this . plugin . settings . jsFiles ) . onChange ( async ( value ) => { this . plugin . settings . jsFiles = value ; await this . plugin . saveSettings ( ) ; await this . plugin . loadClasses ( ) ; } ) ) ; new Setting ( containerEl ) . setName ( 'Folder' ) . setDesc ( 'Path to folder containing JS files to load' ) . addText ( text => text . setPlaceholder ( 'js/scripts' ) . setValue ( this . plugin . settings . jsFolder ) . onChange ( async ( value ) => { this . plugin . settings . jsFolder = value ; await this . plugin . saveSettings ( ) ; await this . plugin . loadClasses ( ) ; } ) ) ; } }