Skip to content
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

Feature request: Enhancing the node object itself before rendering a react component #38

Open
koenvg opened this issue Jun 19, 2017 · 4 comments

Comments

@koenvg
Copy link

koenvg commented Jun 19, 2017

I would like to have your input if this feature would be a sensible addition to the library.
You can definitely do this with the current implementation it is just not as straight forward.

Problem:
I have multiple ProcessInstructions which rely on shared code.
e.g. rewriting classes, custom handling for on-handlers, custom handling of root/leaf nodes,...

Suggested change:

const enhancers = [
  {
    shouldEnhanceNode: (node) => {
      return node.attribs && node.attribs['data-test'] === 'foo';
    },
    enhanceNode: (node, children, index) => {
      return { ...node, attribs: { ...node.attribs, ...extraAttribs } };
    }
  },
  {
    shouldEnhanceNode: (node) => {
      return true;
    },
    enhanceNode: (node, children, index) => {
      if (node.attribs && node.attribs.class) {
        const prefixedNode = { ...node };
        prefixedNode.attribs.class = prefixedNode.attribs.class.split(' ').map((className) => `${prefix}-${className}`).join(' ');
      }
      return node;
    },
  },
];

let reactComponent = parser.parseWithInstructions(
  htmlInput, isValidNode, processingInstructions, enhancers);
// Or maby change the api a bit?
reactComponent = parser.parse({
  html: htmlInput, // mandatory
  isValidNode, // optional
  processingInstructions, // optional
  enhancers, // optional
});
@aknuds1
Copy link
Owner

aknuds1 commented Jun 27, 2017

Your best bet is to write a PR with a test for the scenario you're trying to solve, and preferably a corresponding implementation.

@nickpalmer
Copy link

nickpalmer commented Sep 26, 2017

You can get the same result by enhancing the node and then passing to the default render. You can modify anything including the node 'name' to swap say <h1> tags for <p> tags with a given class.

const defaults = new ProcessNodeDefinitions(React);
// ...
shouldProcessNode: (node) => node.type == 'tag' && node.name == 'h1',
processNode: (node, ...args) => {
  node.attribs.class = 'non-h1-title';
  node.name = 'p';
  return defaults.processDefaultNode(node, ...args);
}

@aknuds1
Copy link
Owner

aknuds1 commented Sep 27, 2017

@nickpalmer Do you think we can close this?

@nickpalmer
Copy link

I think this is still a reasonable feature suggestion in that it would give you a pre-process pass in the pipeline, which would be a nice enhancement to the single pass processing now. I would personally think of it as a pre-process step instead of "enhance", but that is just verbiage.

I would label it as a 'feature-request' and 'needs-help' and leave it open if I were managing the project, but up to you. Alternatively I would update the documentation to discuss being able to insert a 'pre-process' transformation step in any processNode handler to address the use case and then close it.

Basically this request wants processDefaultNode to be enhanced with a single line and a trivial function, so I think it is a small PR overall and a nice addition to the API but can be accomplished with the default mechanism at the expense of adding one line to EVERY processNode step in the users pipeline.

An implementation is almost trivial. Without looking at the existing code:

// ... existing object definition above ...
processDefaultNode: (node, children, index) => {
  // Ignoring lousy re-assignment of parameter for simplicity
  node = preProcessNode(node);
  // ... existing processDefaultNode
}
preProcessNode: (node, children, index): => {
  let preProcessed = node;
  if (this.preProcessInstructions) {
    this.preProcessInstructions.map((instruction) => {
      if(instruction.shouldPreProcessNode(preProcessed)) {
        preProcessed = instruction.preProcessNode(preProcessed, children, index);
      }
   });
  }
  return preProcessed;
}
// ... more object implementation ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants