{"action":"created","issue":{"url":"https://api.github.com/repos/sass/node-sass/issues/644","labels_url":"https://api.github.com/repos/sass/node-sass/issues/644/labels{/name}","comments_url":"https://api.github.com/repos/sass/node-sass/issues/644/comments","events_url":"https://api.github.com/repos/sass/node-sass/issues/644/events","html_url":"https://github.com/sass/node-sass/pull/644","id":56121931,"number":644,"title":"Custom functions","user":{"login":"matryo","id":10783858,"avatar_url":"https://avatars.githubusercontent.com/u/10783858?v=3","gravatar_id":"","url":"https://api.github.com/users/matryo","html_url":"https://github.com/matryo","followers_url":"https://api.github.com/users/matryo/followers","following_url":"https://api.github.com/users/matryo/following{/other_user}","gists_url":"https://api.github.com/users/matryo/gists{/gist_id}","starred_url":"https://api.github.com/users/matryo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/matryo/subscriptions","organizations_url":"https://api.github.com/users/matryo/orgs","repos_url":"https://api.github.com/users/matryo/repos","events_url":"https://api.github.com/users/matryo/events{/privacy}","received_events_url":"https://api.github.com/users/matryo/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":6,"created_at":"2015-01-31T11:23:01Z","updated_at":"2015-02-01T03:24:56Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/sass/node-sass/pulls/644","html_url":"https://github.com/sass/node-sass/pull/644","diff_url":"https://github.com/sass/node-sass/pull/644.diff","patch_url":"https://github.com/sass/node-sass/pull/644.patch"},"body":"This is a refactor of #530 (custom importers) to also support #332 (custom functions). \r\n\r\nThe mechanism to synchronize the worker thread that runs libsass and the main v8 loop has been centralized and abstracted into an object called `CallbackBridge` that has two specializations: `CustomImporterBridge` and `CustomFunctionBridge`. The former supports the existing functionality (#530) while the other makes it possible to register custom functions that are backed up by v8 functions and takes care of translating `Sass_Value`s to something that makes sense to the JS runtime and vice versa.\r\n\r\nThe function arguments are relayed to the JS callback by means of wrapping `Sass_Value*` pointers into v8 objects. Those objects mimic the API offered by libsass and as such could be a bit cumbersome to work with on the javascript side. This problem could however be largely mitigated by translating those wrapper objects into JS primitives upon entering the JS callback and back into wrapper objects upon return. The only edge cases that I can think of is that of `SASS_NUMBER` values when they carry units and `SASS_COLOR` where we could parse strings and detect patterns like `\\d+(px|em|%)` and `rgba?\\(...)\\` or resolve to use more JS friendly facades.\r\n\r\nThis is a quick example demonstrating how compass' `headings` function may be implemented:\r\n\r\n```javascript\r\nsass.render({\r\n  data: '#{headings(2,5)} { color: #08c; }',\r\n  functions: {\r\n    'headings($from: 0, $to: 6)': function(from, to) {\r\n      var i, f = from.getValue(), t = to.getValue(),\r\n          list = new sass.types.List(t - f + 1);\r\n\r\n      for (i = f; i <= t; i++) {\r\n        list.setValue(i - f, new sass.types.String('h' + i));\r\n      }\r\n\r\n      return list;\r\n    }\r\n  }\r\n});\r\n```"},"comment":{"url":"https://api.github.com/repos/sass/node-sass/issues/comments/72349517","html_url":"https://github.com/sass/node-sass/pull/644#issuecomment-72349517","issue_url":"https://api.github.com/repos/sass/node-sass/issues/644","id":72349517,"user":{"login":"mgreter","id":282293,"avatar_url":"https://avatars.githubusercontent.com/u/282293?v=3","gravatar_id":"","url":"https://api.github.com/users/mgreter","html_url":"https://github.com/mgreter","followers_url":"https://api.github.com/users/mgreter/followers","following_url":"https://api.github.com/users/mgreter/following{/other_user}","gists_url":"https://api.github.com/users/mgreter/gists{/gist_id}","starred_url":"https://api.github.com/users/mgreter/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mgreter/subscriptions","organizations_url":"https://api.github.com/users/mgreter/orgs","repos_url":"https://api.github.com/users/mgreter/repos","events_url":"https://api.github.com/users/mgreter/events{/privacy}","received_events_url":"https://api.github.com/users/mgreter/received_events","type":"User","site_admin":false},"created_at":"2015-02-01T03:24:56Z","updated_at":"2015-02-01T03:24:56Z","body":"Btw. I find it pretty cool that @matryo was able to pull off this implementation without asking anybody about the internals directly! I hope that the time I've put into the libsass wiki was worth it! @matryo : If you have anything to add to the Wiki, please do so!!"}}