18864b1cdSBrent Vatne#!/usr/bin/env node
28864b1cdSBrent Vatne'use strict';
38864b1cdSBrent Vatne
48864b1cdSBrent Vatneconst fs = require('fs');
58864b1cdSBrent Vatneconst glob = require('glob');
6a9e9eb76SJames Ideconst path = require('path');
78864b1cdSBrent Vatne
88864b1cdSBrent Vatnefunction replaceAll(current, replacement, content) {
9a9e9eb76SJames Ide  const regexp = new RegExp(escapeRegExp('${' + current + '}'), 'g');
108864b1cdSBrent Vatne  return content.replace(regexp, replacement);
118864b1cdSBrent Vatne}
128864b1cdSBrent Vatne
138864b1cdSBrent Vatnefunction escapeRegExp(string) {
148864b1cdSBrent Vatne  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
158864b1cdSBrent Vatne}
168864b1cdSBrent Vatne
178864b1cdSBrent Vatnefunction removeUnapplicableSections(name, content) {
18a9e9eb76SJames Ide  const opener = `<!--- remove for ${name} --->`;
19a9e9eb76SJames Ide  const closer = `<!--- end remove for ${name} --->`;
208864b1cdSBrent Vatne  let nextContent = content;
218864b1cdSBrent Vatne
228864b1cdSBrent Vatne  while (nextContent.includes(opener)) {
23a9e9eb76SJames Ide    const openIndex = nextContent.indexOf(opener);
248864b1cdSBrent Vatne    let closeIndex = nextContent.indexOf(closer);
258864b1cdSBrent Vatne    if (!closeIndex) {
268864b1cdSBrent Vatne      console.warn(`Can't find section closer for ${name}`);
278864b1cdSBrent Vatne      closeIndex = openIndex + opener.length;
288864b1cdSBrent Vatne    }
29a9e9eb76SJames Ide    const section = nextContent.substring(openIndex, closeIndex + closer.length);
308864b1cdSBrent Vatne    nextContent = nextContent.replace(section, '');
318864b1cdSBrent Vatne  }
328864b1cdSBrent Vatne  return nextContent;
338864b1cdSBrent Vatne}
348864b1cdSBrent Vatne
358864b1cdSBrent Vatnefunction removeOptionals(content) {
36a9e9eb76SJames Ide  const regexp = new RegExp(escapeRegExp('<!---') + '.*' + escapeRegExp('--->') + '\n', 'g');
378864b1cdSBrent Vatne  return content.replace(regexp, '');
388864b1cdSBrent Vatne}
398864b1cdSBrent Vatne
40b52e368fSJames Ideconst DEFAULT_HOMEPAGE = 'https://docs.expo.dev/versions/latest/';
418864b1cdSBrent Vatne
428864b1cdSBrent Vatnefunction generateREADME() {
43a9e9eb76SJames Ide  const template = path.join(__dirname, '..', 'templates', 'README.md');
448864b1cdSBrent Vatne  let readme = fs.readFileSync(template, 'utf8');
45a9e9eb76SJames Ide  const pkg = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'package.json'), 'utf8'));
46a9e9eb76SJames Ide  const packageName = pkg.name;
47a9e9eb76SJames Ide  const homepage = pkg.homepage || DEFAULT_HOMEPAGE;
48a9e9eb76SJames Ide  const description = pkg.description || 'Put a description of your Unimodule here';
498864b1cdSBrent Vatne
508864b1cdSBrent Vatne  // This isn't really accurate, but these all behave the same as far as READMEs go
51a9e9eb76SJames Ide  const isInterface = packageName.endsWith('-interface') || packageName.endsWith('-provider');
528864b1cdSBrent Vatne
53a9e9eb76SJames Ide  const isAndroid = fs.existsSync(path.join(process.cwd(), 'android'));
54a9e9eb76SJames Ide  const isIOS = fs.existsSync(path.join(process.cwd(), 'ios'));
558864b1cdSBrent Vatne
568864b1cdSBrent Vatne  // Search in docs/versions/unversioned/sdk/*.md - can't find it? Ask what it should be and initialize for them
578864b1cdSBrent Vatne  readme = replaceAll('packageName', packageName, readme);
588864b1cdSBrent Vatne  readme = replaceAll('description', description, readme);
598864b1cdSBrent Vatne
608864b1cdSBrent Vatne  if (isIOS) {
61a9e9eb76SJames Ide    const podspecs = glob.sync('{ios/**/,}*.podspec');
62a9e9eb76SJames Ide    const podspecPath = podspecs[0];
63a9e9eb76SJames Ide    const podName = (() => {
64a9e9eb76SJames Ide      const parts = podspecPath.split('/');
658864b1cdSBrent Vatne      return parts[parts.length - 1].replace('.podspec', '');
668864b1cdSBrent Vatne    })();
678864b1cdSBrent Vatne
688864b1cdSBrent Vatne    readme = replaceAll('podName', podName, readme);
698864b1cdSBrent Vatne  } else {
708864b1cdSBrent Vatne    readme = removeUnapplicableSections('no-ios', readme);
718864b1cdSBrent Vatne  }
728864b1cdSBrent Vatne
738864b1cdSBrent Vatne  if (isInterface) {
748864b1cdSBrent Vatne    readme = removeUnapplicableSections('interfaces', readme);
758864b1cdSBrent Vatne  } else {
768864b1cdSBrent Vatne    let docName;
778864b1cdSBrent Vatne    if (homepage === DEFAULT_HOMEPAGE || homepage.startsWith('https://github.com')) {
788864b1cdSBrent Vatne      docName = packageName.replace('expo-', '');
798864b1cdSBrent Vatne      console.warn(
800623af9eSJames Ide        `Tried to guess the docs homepage for ${packageName}; add it under the "homepage" entry in package.json`
818864b1cdSBrent Vatne      );
828864b1cdSBrent Vatne    } else {
838864b1cdSBrent Vatne      docName = (() => {
84a9e9eb76SJames Ide        const parts = homepage.split('/');
858864b1cdSBrent Vatne        // Handle both with and without trailing slash
868864b1cdSBrent Vatne        let name = parts[parts.length - 1];
878864b1cdSBrent Vatne        if (name === '') {
888864b1cdSBrent Vatne          name = parts[parts.length - 2];
898864b1cdSBrent Vatne        }
908864b1cdSBrent Vatne        return name;
918864b1cdSBrent Vatne      })();
928864b1cdSBrent Vatne    }
938864b1cdSBrent Vatne    readme = replaceAll('docName', docName, readme);
948864b1cdSBrent Vatne    if (isAndroid) {
95*748ab554SKudo Chien      const androidPackages = glob.sync('android/src/**/*Package.{java,kt}');
968864b1cdSBrent Vatne      let androidPackage;
978864b1cdSBrent Vatne      let androidPackagePath = 'expo.modules.yourModule.YourPackage';
988864b1cdSBrent Vatne      let androidPackageName = 'YourPackage';
998864b1cdSBrent Vatne      if (!androidPackages) {
1008864b1cdSBrent Vatne        console.warn(
1018864b1cdSBrent Vatne          `No Android package classes found, using: ${androidPackageName} - be sure to update this`
1028864b1cdSBrent Vatne        );
1038864b1cdSBrent Vatne      } else {
1048864b1cdSBrent Vatne        androidPackage = androidPackages[0];
1058864b1cdSBrent Vatne        if (androidPackages.length > 1) {
1068864b1cdSBrent Vatne          console.warn('Found multiple packages, which one should we use?');
1078864b1cdSBrent Vatne          androidPackage = androidPackages[0];
1088864b1cdSBrent Vatne        }
1098864b1cdSBrent Vatne
1108864b1cdSBrent Vatne        if (androidPackage) {
1118864b1cdSBrent Vatne          // From: android/src/main/java/expo/modules/localization/LocalizationPackage.java'
1128864b1cdSBrent Vatne          // To:   expo.modules.localization.LocalizationPackage
1138864b1cdSBrent Vatne          androidPackagePath = androidPackage
1148864b1cdSBrent Vatne            .split('/java/')[1]
1158864b1cdSBrent Vatne            .replace(/\//g, '.')
1168864b1cdSBrent Vatne            .replace('.java', '');
1178864b1cdSBrent Vatne          androidPackageName = (() => {
118a9e9eb76SJames Ide            const parts = androidPackagePath.split('.');
1198864b1cdSBrent Vatne            return parts[parts.length - 1];
1208864b1cdSBrent Vatne          })();
1218864b1cdSBrent Vatne
1228864b1cdSBrent Vatne          readme = replaceAll('androidPackageName', androidPackageName, readme);
1238864b1cdSBrent Vatne        } else {
1248864b1cdSBrent Vatne          readme = removeUnapplicableSections('no-package', readme);
1258864b1cdSBrent Vatne        }
1268864b1cdSBrent Vatne      }
1278864b1cdSBrent Vatne
1288864b1cdSBrent Vatne      readme = replaceAll('androidPackagePath', androidPackagePath, readme);
1298864b1cdSBrent Vatne    } else {
1308864b1cdSBrent Vatne      readme = removeUnapplicableSections('no-android', readme);
1318864b1cdSBrent Vatne    }
1328864b1cdSBrent Vatne  }
1338864b1cdSBrent Vatne  return removeOptionals(readme);
1348864b1cdSBrent Vatne}
1358864b1cdSBrent Vatne
136a9e9eb76SJames Ideconst readme = generateREADME();
137a9e9eb76SJames Ideconst readmePath = path.join(process.cwd(), 'README.md');
1388864b1cdSBrent Vatneif (fs.existsSync(readmePath)) {
1398d441c7eSStanisław Chmiela  console.log('expo-module-scripts: README.md exists, not updating');
1408864b1cdSBrent Vatne} else {
1418864b1cdSBrent Vatne  fs.writeFileSync(readmePath, readme, { encoding: 'utf8' });
1428864b1cdSBrent Vatne}
143