1#!/usr/bin/env node 2/** 3 * Copyright (c) Meta Platforms, Inc. and affiliates. 4 * 5 * This source code is licensed under the MIT license found in the 6 * LICENSE file in the root directory of this source tree. 7 * 8 * @format 9 */ 10 11'use strict'; 12 13const SignedSource = require('signedsource'); 14const fs = require('fs'); 15const glob = require('glob'); 16const path = require('path'); 17const reactDocs = require('react-docgen'); 18 19const GENERATE_ANNOTATION = '@' + 'generate-docs'; 20const RN_ROOT = path.join(__dirname, '..'); 21const OUTPUT_PATH = path.join(RN_ROOT, 'docs', 'generatedComponentApiDocs.js'); 22 23const TEMPLATE = `/** 24 * Copyright (c) Meta Platforms, Inc. and affiliates. 25 * 26 * This source code is licensed under the MIT license found in the 27 * LICENSE file in the root directory of this source tree. 28 * 29 * This file is used by the React Native website to show the props of core components 30 * This file was generated by running scripts/generate-api-docs.js 31 * 32 * ::_SIGNING_TOKEN_:: 33 */ 34 35'use strict'; 36 37module.exports = ::_CONTENT_:: 38`; 39 40const allComponentFiles = glob.sync( 41 path.join(RN_ROOT, '/Libraries/Components/**/*.js'), 42 { 43 nodir: true, 44 }, 45); 46 47const docs = allComponentFiles.reduce((acc, file) => { 48 const contents = fs.readFileSync(file, {encoding: 'utf-8'}); 49 if (!contents.includes(GENERATE_ANNOTATION)) { 50 return acc; 51 } 52 53 const result = reactDocs.parse( 54 contents, 55 reactDocs.resolver.findExportedComponentDefinition, 56 ); 57 58 acc.push(cleanComponentResult(result)); 59 60 return acc; 61}, []); 62 63const content = TEMPLATE.replace( 64 '::_CONTENT_::', 65 JSON.stringify(docs, null, 2), 66).replace('::_SIGNING_TOKEN_::', SignedSource.getSigningToken()); 67 68const signedContent = SignedSource.signFile(content); 69 70if (process.env.NODE_ENV === 'test') { 71 const existingContent = fs.readFileSync(OUTPUT_PATH, 'utf8'); 72 if (signedContent !== existingContent) { 73 console.error( 74 path.relative(RN_ROOT, OUTPUT_PATH), 75 'is not up to date. Run', 76 'scripts/generate-api-docs.js', 77 'to regenerate the file.', 78 ); 79 process.exit(1); 80 } 81} else { 82 fs.writeFileSync(OUTPUT_PATH, SignedSource.signFile(content)); 83} 84 85function cleanComponentResult(component) { 86 return { 87 ...component, 88 methods: component.methods.filter(method => !method.name.startsWith('_')), 89 }; 90} 91