componentDocblockHandler.js 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546
  1. import { getDocblock } from '../utils/docblock.js';
  2. import isReactForwardRefCall from '../utils/isReactForwardRefCall.js';
  3. import resolveToValue from '../utils/resolveToValue.js';
  4. function getDocblockFromComponent(path) {
  5. let description = null;
  6. if (path.isClassDeclaration() || path.isClassExpression()) {
  7. const decorators = path.get('decorators');
  8. // If we have a class declaration or expression, then the comment might be
  9. // attached to the last decorator instead as trailing comment.
  10. if (decorators && decorators.length > 0) {
  11. description = getDocblock(decorators[decorators.length - 1], true);
  12. }
  13. }
  14. if (description == null) {
  15. // Find parent statement (e.g. var Component = React.createClass(<path>);)
  16. let searchPath = path;
  17. while (searchPath && !searchPath.isStatement()) {
  18. searchPath = searchPath.parentPath;
  19. }
  20. if (searchPath) {
  21. // If the parent is an export statement, we have to traverse one more up
  22. if (searchPath.parentPath.isExportNamedDeclaration() ||
  23. searchPath.parentPath.isExportDefaultDeclaration()) {
  24. searchPath = searchPath.parentPath;
  25. }
  26. description = getDocblock(searchPath);
  27. }
  28. }
  29. if (!description) {
  30. const searchPath = isReactForwardRefCall(path)
  31. ? path.get('arguments')[0]
  32. : path;
  33. const inner = resolveToValue(searchPath);
  34. if (inner.node !== path.node) {
  35. return getDocblockFromComponent(inner);
  36. }
  37. }
  38. return description;
  39. }
  40. /**
  41. * Finds the nearest block comment before the component definition.
  42. */
  43. const componentDocblockHandler = function (documentation, componentDefinition) {
  44. documentation.set('description', getDocblockFromComponent(componentDefinition) || '');
  45. };
  46. export default componentDocblockHandler;