-
-
Notifications
You must be signed in to change notification settings - Fork 19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Pass handler list to overriden handlers #34
Comments
What do you think of instead, in |
That wouldn't handle extensions like GFM (table, rows, etc) though right? If i re-exported those handlers then only the base ones would be there? Or are you suggesting something else, sorry I don't follow? I care about the handlers from these in particular: mdast-util-to-markdown/lib/configure.js Line 19 in d51bf74
|
Good catch, I missed that! We could do the same for those packages. Especially for GFM features, |
That would work, but the downside to that is that there's lots of nested exports to export due to the structure of the GFM stuff. To avoid that the handlers passed into options by users could be renamed 'handlerOverrides' and then this library could prefer to dispatch overridden handlers vs the original 'handlers'. Due to how the data binding works the original handlers are already available via the context parameter. |
Does your code actually do that? I haven’t tested with this package and the GFM packages, but it looks like the actual handlers are the same as “ |
My PR will make it so that all of the handlers registerd by extensions & default list are put on the key 'originalHandlers'. The user overrides are not put into this list due to this line: mdast-util-to-markdown/lib/index.js Line 35 in fa06b79
Above I'm suggesting a change to this logic. Instead of making an originalHandlers key, the line I highlighted above would be changed to something like this:
Then during dispatch the library would internally prefer handlerOverrides. Up to you what's preferred. |
What you‘re trying to achieve seems to be get a “previous” handler: One extension defines a table handler A, another defines a table handler B. B wants to get access to A. This is interesting, but what if:
There are so many ifs, it sounds like trouble, and that depending on one of the extensions yourself and taking the handler from there, is explicit and versioned and perhaps better? |
I actually don't care at all about extensions overriding each other. I only want the 'previous' handler before the user options.handlers override the registered (extensions + built-in) ones. For this both solutions I propose should work in all cases. I.E 'if I were to override table via options.handlers, allow me to invoke the original logic that existed as if I did not provide a user options table handler'. |
That would fail in the case of my second and third examples though? Because either there would not be a table formatter, or a completely different table formatter was set as “previous”? From your previous comment:
I missed this, thanks for explaining I’m not a fan of And I think |
Here is what I actually do right now with the current live version, where none of the suggested features are available:
As you can see I have to re-create the implementation of how the GFM plugin's toString works. I'd like instead to be able to write:
You're correct this code would not work if the originalHandlers.table wasn't defined. However, my own pipeline knows that I use the GFM plugin so will exist. And this is all defined at the callsite so it's not hidden anywhere. This feature is up to the user to know in which context what type of handler is expected, any undefined keys or anything don't matter at all until a user tries to call them:
As an aside the GFM plugin would be awesome if it had a table header type so the user could customize the stringification of just the header (then I wouldn't have to do this at all!). But I generally believe allowing the user to hook back into previous logic is important, this is how user GUIs commonly implement inheritance of events for example. Without a feature like this extendability of existing handlers is not really possible without re-creating the original implementation as my example above shows. Ex GUI event inheritance:
|
I don't think it's reasonable to implement this feature to treat extensions the same as user options. To do this would require a stack/array that knows at which level is the current registered handlers. Each extension would have to then use the shared data context like this: This isn't required if you treat just the user handlers as special, since there is only one level, the level just before when the user options.handlers are applied. And finally, only the user handlers know the full pipeline and the necessary context to use this feature. |
Thanks for your patience, I’ve been busy updating everything to ESM. Your GUI events example, which you (and I) appreciate, is very close to what you in the next example explain as a wasteful, complex system. I agree that it is too complex, too. But it otherwise is a nice way of solving nesting. Events bubble up unless they’re handled. In this case, you don’t want to bubble at all. You don‘t want import {gfmTableHandle} from 'mdast-util-gfm-table'
handlers: {
table: (node, parent, context) => {
let txt = gfmTableHandle(node, parent, context);
// regexes
return txt;
},
} But even better, you could publish this as I think an acceptable solution would be to start exposing handlers from packages, where possible? |
in the end that's what i did. I was hoping for a better interface though because I have to mimick how the plugin sets up its own handler and if that changes ill be chasing the interface. This might be the best way though, not sure I care much anymore since i've got it working ahah. Here is my total converter btw, actually ends up being pretty simple, except that i took a shortcut and used NodeToString which doesn't work in all cases properly with nested constructs (since custom jira stringifiers don't get called in NodeToString), but is good enough for me as most of my stuff is not nested:
|
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Seems the current state is okay-ish! Glad its working fine for now! |
Initial checklist
Problem
Remark stringify currently accepts a list of handler overrides for how to stringify a node:
This table acts as a full override, however, it's sometimes useful to use the original behavior but apply some post processing. An example is for tables, where RemarkGFM does quite some work to serialize to string, I have code that just need to apply a particular regex to that output, but this is currently not possible.
Solution
Provide an additional argument to the handler callbacks so that they can observe the handler array BEFORE user applied applied overrides. Example desired interface:
Alternatives
Change the RemarkStringify interface to have a new type of callback that is invoked after each stringify handlers runs. This new handler would be passed the string value output where it may transform it, then return a final value.
ex:
The text was updated successfully, but these errors were encountered: