55 * @classdesc A utility class for managing output to the Mac system log from your Sketch plugin.
66 * @constructor
77 *
8- * @property {object } context A generic object Sketch provides with information on the currently running Sketch instance.
9- * @property {object } settings A settings object which tracks configuration options for this class.
10- * @property {string } settings.logPrefix An optional prefix to append to all logs. Useful for filtering system logs.
11- *
128 * @example
139 * var logger = new SketchPluginLog();
14- * logger
15- * .setPrefix('myPluginName')
10+ * logger.setPrefix('myPluginName')
1611 * .setContext(sketchContext);
1712 *
13+ * // System log: simple message
1814 * logger.log('Hello world!');
15+ *
16+ * // System log: CocoaScript object
17+ * logger.logObject(myObject);
18+ *
19+ * // Write CocoaScript object to file:
20+ * logger.debugObject(myObject)
21+ *
22+ * Default path for debugObject is:
23+ * {Your plugin root path}/Sketch/debug/debug.log
1924 */
2025function SketchPluginLog ( ) {
2126 this . context = null ;
2227
2328 this . settings = {
24- logPrefix : ''
29+ logPrefix : ' ' ,
30+ debugLogPath : '/dev/null'
2531 } ;
2632}
2733
@@ -32,7 +38,6 @@ function SketchPluginLog() {
3238 *
3339 * @param {string } prefixString The string to use as prefix.
3440 * @returns {SketchPluginLog }
35- * @method
3641 */
3742SketchPluginLog . prototype . setLogPrefix = function ( prefixString ) {
3843 this . settings . logPrefix = prefixString ;
@@ -52,27 +57,161 @@ SketchPluginLog.prototype.setLogPrefix = function(prefixString) {
5257SketchPluginLog . prototype . setContext = function ( context ) {
5358 this . context = context ;
5459
60+ if ( '/dev/null' == this . settings . debugLogPath ) {
61+ this . settings . debugLogPath = this . context . scriptPath . stringByDeletingLastPathComponent ( ) + '/debug/' ;
62+ }
63+
5564 return this ;
5665} ;
5766
67+ /**
68+ * Set Debug Log Path
69+ *
70+ * Sets the path to a folder where debug dumps will be created at. This is not the path to your system log.
71+ * See the `debugObject` method for more information.
72+ *
73+ * @param {string } logPathString The path to a folder to put log dumps in.
74+ * @returns {SketchPluginLog }
75+ */
76+ SketchPluginLog . prototype . setDebugLogPath = function ( logPathString ) {
77+ // Assert value is a string
78+ if ( typeof logPathString !== 'string' ) {
79+ this . log ( 'Log path must be a string. Called `setLogPath` with non-string value.' ) ;
80+ return this ;
81+ }
82+
83+ // Append a trailing slash if one isn't included
84+ var lastChar = url . substr ( - 1 ) ;
85+ if ( lastChar != '/' ) {
86+ logPathString += '/' ;
87+ }
88+
89+ // Assign value
90+ this . settings . debugLogPath = logpath ;
91+
92+ return this ;
93+ }
94+
5895/**
5996 * Log
6097 *
6198 * Logs a simple message, prepended by the plugin name.
6299 *
63- * @param message
100+ * @param { string } message
64101 * @returns {SketchPluginLog }
65102 * @method
66103 */
67104SketchPluginLog . prototype . log = function ( message ) {
68105 // Check Sketch context exists
69106 if ( ! this . hasOwnProperty ( 'context' ) || typeof this . context !== 'object' ) {
70107 log ( this . settings . logPrefix + ' : ' + 'Context not set for SketchPluginLog! Set it with `setContext`' ) ;
108+ }
71109
110+ // Assert value is a string
111+ if ( typeof message !== 'string' ) {
112+ this . log ( 'Message must be a string. Called `log` with non-string value.' ) ;
72113 return this ;
73114 }
74115
75116 this . context . api ( ) . log ( this . settings . logPrefix + ' : ' + message ) ;
76117
118+ return this ;
119+ } ;
120+
121+ /**
122+ * Log Object
123+ *
124+ * Logs a CocoaScript object to the system log.
125+ * Note that this method does not dump JavaScript objects.
126+ *
127+ * If your object is too large for Console to view, use the `debugObject` to write the log to a debug file instead.
128+ *
129+ * @param obj The object to log.
130+ * @returns {SketchPluginLog }
131+ */
132+ SketchPluginLog . prototype . logObject = function ( obj ) {
133+ this . log ( '#####################################################################################' ) ;
134+ this . log ( '# Dumping object ' + obj ) ;
135+ this . log ( '# Class: ' + [ obj className ] ) ;
136+
137+ this . log ( '### Properties' ) ;
138+ this . log ( [ obj class ] . mocha ( ) . properties ( ) )
139+
140+ this . log ( '### Properties With Ancestors' ) ;
141+ this . log ( [ obj class ] . mocha ( ) . propertiesWithAncestors ( ) )
142+
143+ this . log ( '### Methods' ) ;
144+ this . log ( [ obj class ] . mocha ( ) . classMethods ( ) )
145+
146+ this . log ( '### Methods With Ancestors' ) ;
147+ this . log ( [ obj class ] . mocha ( ) . classMethodsWithAncestors ( ) )
148+
149+ this . log ( '### Instance Methods' ) ;
150+ this . log ( [ obj class ] . mocha ( ) . instanceMethods ( ) )
151+
152+ this . log ( '### Instance Methods With Ancestors' ) ;
153+ this . log ( [ obj class ] . mocha ( ) . instanceMethodsWithAncestors ( ) )
154+
155+ this . log ( '### Protocols' ) ;
156+ this . log ( [ obj class ] . mocha ( ) . protocols ( ) )
157+
158+ this . log ( '### Protocols With Ancestors' ) ;
159+ this . log ( [ obj class ] . mocha ( ) . protocolsWithAncestors ( ) )
160+
161+ this . log ( '### Tree As Dictionary' )
162+ this . log ( obj . treeAsDictionary ( ) )
163+ this . log ( '#####################################################################################' ) ;
164+
165+ return this ;
166+ } ;
167+
168+ /**
169+ * Debug Object
170+ *
171+ * Dumps a CocoaScript object to a `debug.log` file. This is useful for when an object dump is too large
172+ * for the system log viewer Console.
173+ *
174+ * @param {object } obj
175+ * @returns {SketchPluginLog }
176+ */
177+ SketchPluginLog . prototype . debugObject = function ( obj ) {
178+ var newline = "\r\n" ;
179+ var doubleNewLine = newline + newline ;
180+
181+ if ( '/dev/null' == this . settings . debugLogPath || ! this . settings . debugLogPath ) {
182+ this . log ( 'Debug log path not set. Set it with the `setLogPath` method.' ) ;
183+ return this ;
184+ }
185+
186+ var output = 'Dump for object:' + obj + newline + 'Class: ' + [ obj class ] + newline
187+ + '#####################################################################################' + doubleNewLine
188+
189+ + '### Properties' + newline + [ obj class ] . mocha ( ) . properties ( ) + doubleNewLine
190+
191+ + '### Properties With Ancestors' + newline + [ obj class ] . mocha ( ) . propertiesWithAncestors ( ) + doubleNewLine
192+
193+ + '### Methods' + newline + [ obj class ] . mocha ( ) . classMethods ( ) + doubleNewLine
194+
195+ + '### Methods With Ancestors' + newline + [ obj class ] . mocha ( ) . classMethodsWithAncestors ( ) + doubleNewLine
196+
197+ + '### Instance Methods' + newline + [ obj class ] . mocha ( ) . instanceMethods ( ) + doubleNewLine
198+
199+ + '### Instance Methods With Ancestors' + newline + [ obj class ] . mocha ( ) . instanceMethodsWithAncestors ( ) + doubleNewLine
200+
201+ + '### Protocols' + newline + [ obj class ] . mocha ( ) . protocols ( ) + doubleNewLine
202+
203+ + '### Protocols With Ancestors' + newline + [ obj class ] . mocha ( ) . protocolsWithAncestors ( ) + doubleNewLine
204+
205+ + '### Tree As Dictionary' + newline + obj . treeAsDictionary ( ) + doubleNewLine ;
206+
207+ // Create debug folder if it doesn't exist
208+ var debugFolderPath = this . settings . debugLogPath ;
209+ [ [ NSFileManager defaultManager ] createDirectoryAtPath :debugFolderPath withIntermediateDirectories :true attributes :nil error :nil ]
210+
211+ // Write log to the debug file
212+ var outputNSString = [ NSString stringWithFormat :"%@" , output ] ;
213+ var logPath = this . settings . debugLogPath + 'debug.log' ;
214+ [ outputNSString writeToFile :logPath atomically :true encoding :NSUTF8StringEncoding error :nil ] ;
215+
77216 return this ;
78217} ;
0 commit comments