SketchAPI icon indicating copy to clipboard operation
SketchAPI copied to clipboard

Custom context params problem due to running plugin via cli

Open AlexGusew opened this issue 6 years ago • 2 comments

Hello there!

Task: To send param from Sketch CLI when running the Sketch plugin. Issue: the derived value of the JSON dictionary is of type object(expected string).

That's code of my plugin with commented output:

import { Document } from 'sketch/dom';

export default ({ documentPath }) => {
  const hardcodedUrl =          '/Users/alexander.gusev/QSE/infrastructure/repositories/qordoba-sketch-editor-renderer/sketches/zip.sketch';
  console.log(documentPath); // '/Users/alexander.gusev/QSE/infrastructure/repositories/qordoba-sketch-editor-renderer/sketches/zip.sketch'
  console.log(documentPath == hardcodedUrl); // true
  console.log(documentPath === hardcodedUrl); // false
  console.log(typeof documentPath); // 'object'
  
  console.log(typeof documentPath.toString()); // 'object'
  console.log(typeof documentPath.valueOf()); // Type error
  // TypeError: Type error
  //   at valueOf[native code] (/)
  //   at /Users/alexander.gusev/QSE/sketch-plugin/sketch-plugin/sketch-plugin.sketchplugin/Contents/Sketch/__fitText.js:123:43
  //   at __skpm_run (/Users/alexander.gusev/QSE/sketch-plugin/sketch-plugin/sketch-plugin.sketchplugin/Contents/Sketch/__fitText.js:151:19)
  //   at __skpm_run[native code] (/)% 
 
  console.log(Object.entries(documentPath)); // []
  console.log(Object.getOwnPropertyNames(documentPath)); // []

  const document = Document.open(documentPath); // Error
  // Error: An Obj-C exception occurred.
  //   at [native code] (/)
  //   at value (/Applications/Sketch.app/Contents/Resources/SketchAPI_dom.js:1:82729)
  //   at /Users/alexander.gusev/QSE/sketch-plugin/sketch-plugin/sketch-plugin.sketchplugin/Contents/Sketch/__fitText.js:133:74
  //   at __skpm_run (/Users/alexander.gusev/QSE/sketch-plugin/sketch-plugin/sketch-plugin.sketchplugin/Contents/Sketch/__fitText.js:155:19)
  //   at __skpm_run[native code] (/)
  // nativeException: -[__NSCFString isFileURL]: unrecognized selector sent to instance 0x600002f78b80% 
}

That's a bash command to run the plugin:

path/to/sketchtool run path/to/sketchplugin identifier --context='{"documentPath": "/Users/alexander.gusev/QSE/infrastructure/repositories/qordoba-sketch-editor-renderer/sketches/zip.sketch"}'

The solution I found is to use a String object explicitly:

import { Document } from 'sketch/dom';

export default ({ documentPath }) => {
  const parsedDocumentPath = new String(documentPath).toString();
  const document = Document.open(parsedDocumentPath); // works fine
}

Question: Is it the most preferable way to cast context value to string?

PS: by the way, as I understand, you override Object.prototype props for some reason. If so, do you think that overriding default behaviour is a good idea?

AlexGusew avatar Nov 06 '19 12:11 AlexGusew

Yes I agree, there are a few pitfalls when using plugin context values this way. I got tripped up myself with this a few weeks ago, but it resolved itself in my case since I was using the values in a template literal, which also works ok:

export default ({ value }) => {
  Document.open(`${value}/foo.sketch`); // also works
}

It would be nice to fix this so its less surprising, and the context values are usable directly.

jedrichards avatar Nov 06 '19 13:11 jedrichards

the values from the context are native Obj-C objects. So you have an NSString instead of a String. Casting it to a string using \${value}`` or String(value) works fine.

The error in Document.open(documentPath) is probably because the value isn't casted correctly in the API (and that should be fixed)

mathieudutour avatar Nov 06 '19 17:11 mathieudutour