diff --git a/.eslintignore b/.eslintignore index f84ff5b2d..f868bfeba 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,2 +1,17 @@ **/node_modules/* -parser/out.js +parser/react-native-live-markdown-parser.js + +# any js file inside android and ios folders +**/android/**/*.js +**/ios/**/*.js + +# Output of the build process & scripts +lib/**/* +scripts/**/* + +babel.config.js +metro.config.js +react-native.config.js +jest.config.js +webpack.config.js +.eslintrc.js diff --git a/.eslintrc.js b/.eslintrc.js index 5e871dd23..ef20f0bc3 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -4,10 +4,15 @@ module.exports = { project: true, tsconfigRootDir: __dirname, }, + env: { + jest: true, + }, extends: [ + 'expensify', 'plugin:@typescript-eslint/recommended', - 'prettier', + 'plugin:@typescript-eslint/stylistic', 'plugin:import/typescript', + 'prettier', 'plugin:prettier/recommended', ], plugins: [ @@ -19,39 +24,29 @@ module.exports = { ], settings: { 'import/resolver': { - alias: [['react-native-markdown-text-input', './src/index.tsx']], + alias: [['@expensify/react-native-live-markdown', './src/index.tsx']], }, }, root: true, rules: { - 'prettier/prettier': [ - 'error', + 'rulesdir/prefer-underscore-method': 'off', + 'react/jsx-props-no-spreading': 'off', + 'react/require-default-props': 'off', + 'react/jsx-filename-extension': ['error', { extensions: ['.tsx', '.jsx'] }], + "import/extensions": [ + "error", + "ignorePackages", { - quoteProps: 'consistent', - singleQuote: true, - tabWidth: 2, - trailingComma: 'es5', - useTabs: false, - }, - ], - 'curly': 'error', + "jsx": "never", + "ts": "never", + "tsx": "never" + } + ], 'import/no-unresolved': 'error', 'import/consistent-type-specifier-style': ['error', 'prefer-top-level'], - 'react/jsx-uses-vars': 'error', - 'react/jsx-uses-react': 'error', 'no-use-before-define': 'off', '@typescript-eslint/no-use-before-define': 'off', // TODO consider enabling this (currently it reports styles defined at the bottom of the file) - '@typescript-eslint/ban-ts-comment': [ - 'error', - { - 'ts-ignore': 'allow-with-description', - 'ts-expect-error': 'allow-with-description', - }, - ], '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }], - '@typescript-eslint/no-var-requires': 'warn', - 'eqeqeq': 'error', - 'no-unreachable': 'error', '@typescript-eslint/consistent-type-imports': [ 'error', { prefer: 'type-imports' }, @@ -62,5 +57,7 @@ module.exports = { ], 'tsdoc/syntax': 'error', '@typescript-eslint/no-non-null-assertion': 'off', + '@typescript-eslint/array-type': ['error', {default: 'array-simple'}], + '@typescript-eslint/consistent-type-definitions': 'off', }, }; diff --git a/.gitattributes b/.gitattributes index 030ef1448..e27f70fa4 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,3 @@ *.pbxproj -text # specific for windows script files -*.bat text eol=crlf \ No newline at end of file +*.bat text eol=crlf diff --git a/.github/OSBotify-private-key.asc.gpg b/.github/OSBotify-private-key.asc.gpg new file mode 100644 index 000000000..c19d5c978 Binary files /dev/null and b/.github/OSBotify-private-key.asc.gpg differ diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..a103adfa9 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,18 @@ + + +### Details + + +### Related Issues + +GH_LINK + +### Manual Tests + + +### Linked PRs + \ No newline at end of file diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml new file mode 100644 index 000000000..2937e935f --- /dev/null +++ b/.github/workflows/build-android.yml @@ -0,0 +1,42 @@ +name: Test Android build +on: + pull_request: + paths: + - .github/workflows/android-build.yml + - android/** + - example/package.json + - example/android/** + merge_group: + branches: + - main + push: + branches: + - main + paths: + - .github/workflows/android-build.yml + - android/** + - example/package.json + - example/android/** + +jobs: + build_android: + runs-on: ubuntu-latest + strategy: + matrix: {dir: ['example']} + fail-fast: false + steps: + - name: Check out Git repository + uses: actions/checkout@v4 + + - name: Setup Java 17 + uses: actions/setup-java@v4 + with: + distribution: 'zulu' + java-version: 17 + + - name: Install root & example node dependencies + run: yarn install --immutable + + - name: Build app + working-directory: ${{ matrix.dir }}/android + run: ./gradlew assembleDebug --build-cache -PreactNativeArchitectures=arm64-v8a \ No newline at end of file diff --git a/.github/workflows/build-ios.yml b/.github/workflows/build-ios.yml new file mode 100644 index 000000000..6557caab1 --- /dev/null +++ b/.github/workflows/build-ios.yml @@ -0,0 +1,53 @@ +name: Test iOS build +on: + pull_request: + paths: + - .github/workflows/ios-build.yml + - Example/package.json + - Example/ios/** + merge_group: + branches: + - main + push: + branches: + - main + paths: + - .github/workflows/ios-build.yml + - Example/package.json + - Example/ios/** + +jobs: + build_ios: + runs-on: macos-12 + strategy: + matrix: {dir: [Example]} + steps: + - name: Check out Git repository + uses: actions/checkout@v3 + + - name: Install app node_modules + working-directory: ${{ matrix.dir }} + run: yarn install --frozen-lockfile + + - name: Restore Pods from cache + uses: actions/cache@v3 + with: + path: | + ${{ matrix.dir }}/ios/Pods + ~/Library/Caches/CocoaPods + ~/.cocoapods + key: ${{ runner.os }}-pods-${{ matrix.dir }}-${{ hashFiles(format('{0}/ios/Podfile.lock', matrix.dir)) }} + + - name: Install Pods + working-directory: ${{ matrix.dir }}/ios + run: pod install + + - name: Restore build artifacts from cache + uses: actions/cache@v3 + with: + path: ~/Library/Developer/Xcode/DerivedData + key: ${{ runner.os }}-ios-derived-data-${{ matrix.dir }}-${{ hashFiles(format('{0}/ios/Podfile.lock', matrix.dir)) }} + + - name: Build app + working-directory: ${{ matrix.dir }} + run: npx react-native run-ios \ No newline at end of file diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml new file mode 100644 index 000000000..32bd52431 --- /dev/null +++ b/.github/workflows/cla.yml @@ -0,0 +1,39 @@ +name: CLA Assistant + +on: + issue_comment: + types: [created] + pull_request_target: + types: [opened, closed, synchronize] + +jobs: + CLA: + runs-on: ubuntu-latest + # This job only runs for pull request comments or pull request target events (not issue comments) + if: github.event.issue.pull_request || github.event_name == 'pull_request_target' + steps: + - uses: actions-ecosystem/action-regex-match@9c35fe9ac1840239939c59e5db8839422eed8a73 + id: sign + with: + text: ${{ github.event.comment.body }} + regex: '\s*I have read the CLA Document and I hereby sign the CLA\s*' + - uses: actions-ecosystem/action-regex-match@9c35fe9ac1840239939c59e5db8839422eed8a73 + id: recheck + with: + text: ${{ github.event.comment.body }} + regex: '\s*recheck\s*' + - name: CLA Assistant + if: ${{ steps.recheck.outputs.match != '' || steps.sign.outputs.match != '' }} || github.event_name == 'pull_request_target' + # Version: 2.1.2-beta + uses: cla-assistant/github-action@948230deb0d44dd38957592f08c6bd934d96d0cf + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PERSONAL_ACCESS_TOKEN : ${{ secrets.CLA_BOTIFY_TOKEN }} + with: + path-to-signatures: '${{ github.repository }}/cla.json' + path-to-document: 'https://github.com/${{ github.repository }}/blob/main/CLA.md' + branch: 'main' + remote-organization-name: 'Expensify' + remote-repository-name: 'CLA' + lock-pullrequest-aftermerge: false + allowlist: 'snyk-bot,OSBotify' diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 000000000..252b646d4 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,39 @@ +name: Lint JavaScript + +on: + pull_request: + types: [opened, synchronize] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - uses: actions/cache@v2 + with: + path: ~/.yarn + key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-yarn- + + - name: Setup Node + uses: actions/setup-node@v1 + with: + node-version: "16.x" + + - name: Setup web example + run: npm ci + working-directory: ./WebExample + + - run: yarn install --immutable + + + - name: Verify there's no Prettier diff + run: | + yarn lint --fix --quiet + if ! git diff --name-only --exit-code; then + # shellcheck disable=SC2016 + echo 'Error: Prettier diff detected! Please run `npm run prettier` and commit the changes.' + exit 1 + fi diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 000000000..cd465c934 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,87 @@ +# name: Publish package to npmjs + +# # This workflow runs when code is pushed to `main` (i.e: when a pull request is merged) +# on: +# push: +# branches: [main] + +# # Ensure that only once instance of this workflow executes at a time. +# # If multiple PRs are merged in quick succession, there will only ever be one publish workflow running and one pending. +# concurrency: ${{ github.workflow }} + +# jobs: +# version: +# runs-on: ubuntu-latest + +# # OSBotify will update the version on `main`, so this check is important to prevent an infinite loop +# if: ${{ github.actor != 'OSBotify' }} + +# steps: +# - uses: actions/checkout@v3 +# with: +# ref: main + +# - name: Decrypt & Import OSBotify GPG key +# run: | +# cd .github +# gpg --quiet --batch --yes --decrypt --passphrase="$LARGE_SECRET_PASSPHRASE" --output OSBotify-private-key.asc OSBotify-private-key.asc.gpg +# gpg --import OSBotify-private-key.asc +# env: +# LARGE_SECRET_PASSPHRASE: ${{ secrets.LARGE_SECRET_PASSPHRASE }} + +# - name: Set up git for OSBotify +# run: | +# git config --global user.signingkey 367811D53E34168C +# git config --global commit.gpgsign true +# git config --global user.name OSBotify +# git config --global user.email infra+osbotify@expensify.com + +# - uses: actions/setup-node@v3 +# with: +# node-version: '16.x' +# registry-url: 'https://registry.npmjs.org' + +# - name: Generate branch name +# run: echo "BRANCH_NAME=OSBotify-bump-version-$(uuidgen)" >> $GITHUB_ENV + +# - name: Create branch for version-bump pull request +# run: git checkout -b ${{ env.BRANCH_NAME }} + +# - name: Install npm packages +# run: npm ci + +# - name: Update npm version +# run: npm version patch + +# - name: Set new version in GitHub ENV +# run: echo "NEW_VERSION=$(jq '.version' package.json)" >> $GITHUB_ENV + +# - name: Push branch and publish tags +# run: git push --set-upstream origin ${{ env.BRANCH_NAME }} && git push --tags + +# - name: Create pull request +# run: | +# gh pr create \ +# --title "Update version to ${{ env.NEW_VERSION }}" \ +# --body "Update version to ${{ env.NEW_VERSION }}" +# sleep 5 +# env: +# GITHUB_TOKEN: ${{ secrets.OS_BOTIFY_TOKEN }} + +# - name: Auto-approve pull request +# run: gh pr review --approve ${{ env.BRANCH_NAME }} +# env: +# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + +# - name: Auto-merge pull request +# run: gh pr merge --merge --delete-branch ${{ env.BRANCH_NAME }} +# env: +# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + +# - name: Build package +# run: npm run build + +# - name: Publish to npm +# run: npm publish +# env: +# NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/static-checks-src.yml b/.github/workflows/static-checks-src.yml new file mode 100644 index 000000000..b490493cd --- /dev/null +++ b/.github/workflows/static-checks-src.yml @@ -0,0 +1,26 @@ +name: TypeScript & EsLint & Tests - src +on: + pull_request: + merge_group: + branches: + - main + push: + branches: + - main +jobs: + static-analysis: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Use Node.js 18 + uses: actions/setup-node@v4 + with: + node-version: 18 + - name: Install root node dependencies + run: yarn + - name: Check types + run: npx tsc --project tsconfig.json --noEmit + - name: Lint + run: yarn lint:root + - name: run tests + run: yarn test diff --git a/.github/workflows/static-checks-subdirectories.yml b/.github/workflows/static-checks-subdirectories.yml new file mode 100644 index 000000000..66731119f --- /dev/null +++ b/.github/workflows/static-checks-subdirectories.yml @@ -0,0 +1,36 @@ +name: TypeScript & EsLint & Tests - subdirectories +on: + pull_request: + merge_group: + branches: + - main + push: + branches: + - main +jobs: + static-analysis: + runs-on: ubuntu-latest + strategy: + matrix: {dir: ['parser', 'example', 'WebExample']} + steps: + - uses: actions/checkout@v4 + - name: Use Node.js 18 + uses: actions/setup-node@v4 + with: + node-version: 18 + - name: Install root node dependencies + run: yarn + - name: Install ${{ matrix.dir }} app node dependencies + if: ${{ matrix.dir != 'example' }} + working-directory: ${{ matrix.dir }} + run: npm ci + - name: Check types + working-directory: ${{ matrix.dir }} + run: npx tsc -p ./tsconfig.json --noEmit + - name: Lint + run: yarn lint:${{ matrix.dir }} + - name: run tests + # no tests inside example and WebExample + if: ${{ matrix.dir != 'example' && matrix.dir != 'WebExample' }} + working-directory: ${{ matrix.dir }} + run: npm run test diff --git a/.gitignore b/.gitignore index 127e3fe83..1c31ccdde 100644 --- a/.gitignore +++ b/.gitignore @@ -1,16 +1,17 @@ # OSX -# .DS_Store -# XDE -.expo/ +# IDE +.idea # VSCode .vscode/ jsconfig.json +# NPM file created by GitHub actions +.npmrc + # Xcode -# build/ *.pbxuser !default.pbxuser @@ -30,7 +31,6 @@ DerivedData project.xcworkspace # Android/IJ -# .classpath .cxx .gradle @@ -48,11 +48,11 @@ example/ios/Pods example/vendor/ # node.js -# node_modules/ npm-debug.log yarn-debug.log yarn-error.log +dist/ # BUCK buck-out/ @@ -77,5 +77,5 @@ android/keystores/debug.keystore # generated by bob lib/ -# react-native-markdown-text-input -android/src/main/assets/out.js +# react-native-live-markdown +android/src/main/assets/react-native-live-markdown-parser.js diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 000000000..baf5d9867 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,3 @@ +scripts/**/* +CODE_OF_CONDUCT.md +.eslintrc.js diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 000000000..3ed37e3b5 --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,9 @@ +module.exports = { + tabWidth: 2, + singleQuote: true, + trailingComma: 'all', + bracketSpacing: false, + arrowParens: 'always', + printWidth: 190, + singleAttributePerLine: true, +}; diff --git a/.watchmanconfig b/.watchmanconfig index 9e26dfeeb..0967ef424 100644 --- a/.watchmanconfig +++ b/.watchmanconfig @@ -1 +1 @@ -{} \ No newline at end of file +{} diff --git a/.yarnrc.yml b/.yarnrc.yml index d95b48b98..bdab70a5b 100644 --- a/.yarnrc.yml +++ b/.yarnrc.yml @@ -4,8 +4,8 @@ nmHoistingLimits: workspaces plugins: - path: scripts/pod-install.cjs - path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs - spec: "@yarnpkg/plugin-interactive-tools" + spec: '@yarnpkg/plugin-interactive-tools' - path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs - spec: "@yarnpkg/plugin-workspace-tools" + spec: '@yarnpkg/plugin-workspace-tools' yarnPath: .yarn/releases/yarn-3.6.1.cjs diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 970bba824..b521be6d9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -23,9 +23,9 @@ The [example app](/example/) demonstrates usage of the library. You need to run It is configured to use the local version of the library, so any changes you make to the library's source code will be reflected in the example app. Changes to the library's JavaScript code will be reflected in the example app without a rebuild, but native code changes will require a rebuild of the example app. -If you want to use Android Studio or XCode to edit the native code, you can open the `example/android` or `example/ios` directories respectively in those editors. To edit the Objective-C or Swift files, open `example/ios/MarkdownTextInputExample.xcworkspace` in XCode and find the source files at `Pods > Development Pods > react-native-markdown-text-input`. +If you want to use Android Studio or XCode to edit the native code, you can open the `example/android` or `example/ios` directories respectively in those editors. To edit the Objective-C or Swift files, open `example/ios/LiveMarkdownExample.xcworkspace` in XCode and find the source files at `Pods > Development Pods > react-native-live-markdown`. -To edit the Java or Kotlin files, open `example/android` in Android studio and find the source files at `react-native-markdown-text-input` under `Android`. +To edit the Java or Kotlin files, open `example/android` in Android studio and find the source files at `react-native-live-markdown` under `Android`. You can use various commands from the root directory to work with the project. @@ -71,7 +71,7 @@ yarn clean To confirm that the app is running with the new architecture, you can check the Metro logs for a message like this: ```sh -Running "MarkdownTextInputExample" with {"fabric":true,"initialProps":{"concurrentRoot":true},"rootTag":1} +Running "LiveMarkdownExample" with {"fabric":true,"initialProps":{"concurrentRoot":true},"rootTag":1} ``` Note the `"fabric":true` and `"concurrentRoot":true` properties. diff --git a/LICENSE b/LICENSE index 2f2221b20..83f4796cc 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 Tomasz Zawadzki +Copyright (c) 2024 Expensify, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights diff --git a/README.md b/README.md index 8ee781d04..375df4e3a 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,127 @@ -# react-native-markdown-text-input +# @expensify/react-native-live-markdown -Lorem ipsum sit dolor amet. +## Features + +- ⚛️ Drop-in replacement for `` component +- ⌨️ Live synchronous formatting on every keystroke +- ⚡ Fully native experience (selection, spellcheck, autocomplete) +- 🎨 Customizable styles +- 🌐 Universal support (Android, iOS, web) +- 🏗️ Supports New Architecture ## Installation +First, install the library from npm with the package manager of your choice: + ```sh -npm install react-native-markdown-text-input +yarn add @expensify/react-native-live-markdown +npm install @expensify/react-native-live-markdown --save +npx expo install @expensify/react-native-live-markdown ``` +Then, install the iOS dependencies with CocoaPods: + +```sh +cd ios && pod install +``` + +The library includes native code so you will need to re-build the native app. + +> [!NOTE] +> The library does not support Expo Go, you will need to setup Expo Dev Client (see [here](https://docs.expo.dev/workflow/prebuild/)). + ## Usage -```js -import { MarkdownTextInputView } from "react-native-markdown-text-input"; +```tsx +import {MarkdownTextInput} from '@expensify/react-native-live-markdown'; +import React from 'react'; -// ... +export default function App() { + const [text, setText] = React.useState('Hello, *world*!'); - + return ( + + ); +} ``` -## Contributing +## Styling -See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow. +`MarkdownTextInput` can be styled using `style` prop just like regular `TextInput` component. -## License +It is also possible to customize the styling of the formatted contents of `MarkdownTextInput` component. The style object supports all color representations from React Native including `PlatformColor` and `DynamicColorIOS` according to the [color reference](https://reactnative.dev/docs/colors). Currently, a limited set of styles is customizable but this is subject to change in the future. -MIT +```tsx +import type {MarkdownStyle} from '@expensify/react-native-live-markdown'; ---- +const markdownStyle: MarkdownStyle = { + syntax: { + color: 'gray', + }, + link: { + color: 'blue', + }, + h1: { + fontSize: 25, + }, + blockquote: { + borderColor: 'gray', + borderWidth: 6, + marginLeft: 6, + paddingLeft: 6, + }, + code: { + fontFamily: 'monospace', + color: 'black', + backgroundColor: 'lightgray', + }, + pre: { + fontFamily: 'monospace', + color: 'black', + backgroundColor: 'lightgray', + }, + mentionHere: { + backgroundColor: 'yellow', + }, + mentionUser: { + backgroundColor: 'cyan', + }, +}; +``` + +The style object can be passed to multiple `MarkdownTextInput` components using `markdownStyle` prop: -Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob) +```tsx + +``` + +> [!TIP] +> We recommend to store the style object outside of a component body or memoize the style object with `React.useMemo`. + +## Markdown flavors support + +Currently, `react-native-live-markdown` supports only [ExpensiMark](https://github.com/Expensify/expensify-common/blob/main/lib/ExpensiMark.js) flavor. We are working on CommonMark support as well as possibility to use other Markdown parsers. + +## API reference + +`MarkdownTextInput` inherits all props of React Native's `TextInput` component. + +| Prop | Type | Default | Note | +| --------------- | --------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `markdownStyle` | `MarkdownStyle` | `undefined` | Adds custom styling to Markdown text. The provided value is merged with default style object. See [Styling](https://github.com/expensify/react-native-live-markdown/blob/main/README.md#styling) for more information. | + +## Compatibility + +`react-native-live-markdown` requires React Native 0.71 or newer. + +## License + +MIT diff --git a/WebExample/app.json b/WebExample/app.json index bb70e18bd..72f02f685 100644 --- a/WebExample/app.json +++ b/WebExample/app.json @@ -11,9 +11,7 @@ "resizeMode": "contain", "backgroundColor": "#ffffff" }, - "assetBundlePatterns": [ - "**/*" - ], + "assetBundlePatterns": ["**/*"], "ios": { "supportsTablet": true }, diff --git a/WebExample/babel.config.js b/WebExample/babel.config.js index 054ccfa58..23a65e628 100644 --- a/WebExample/babel.config.js +++ b/WebExample/babel.config.js @@ -11,12 +11,8 @@ module.exports = function (api) { { extensions: ['.tsx', '.ts', '.js', '.json'], alias: { - 'react': path.join(__dirname, 'node_modules', 'react'), - 'react-native': path.join( - __dirname, - 'node_modules', - 'react-native-web' - ), + react: path.join(__dirname, 'node_modules', 'react'), + 'react-native': path.join(__dirname, 'node_modules', 'react-native-web'), [pak.name]: path.join(__dirname, '..', pak.source), }, }, diff --git a/WebExample/webpack.config.js b/WebExample/webpack.config.js index c904dc29f..66344e0f5 100644 --- a/WebExample/webpack.config.js +++ b/WebExample/webpack.config.js @@ -1,15 +1,14 @@ const createExpoWebpackConfigAsync = require('@expo/webpack-config'); -const pak = require('../package.json'); module.exports = async function (env, argv) { const config = await createExpoWebpackConfigAsync( { ...env, babel: { - dangerouslyAddModulePathsToTranspile: [pak.name], + dangerouslyAddModulePathsToTranspile: ['react-native-live-markdown'], }, }, - argv + argv, ); return config; }; diff --git a/android/build.gradle b/android/build.gradle index a0ceb7f02..86dcfd2e2 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -20,11 +20,11 @@ if (isNewArchitectureEnabled()) { } def getExtOrDefault(name) { - return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["MarkdownTextInput_" + name] + return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["LiveMarkdown_" + name] } def getExtOrIntegerDefault(name) { - return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["MarkdownTextInput_" + name]).toInteger() + return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["LiveMarkdown_" + name]).toInteger() } def supportsNamespace() { @@ -38,7 +38,7 @@ def supportsNamespace() { android { if (supportsNamespace()) { - namespace "com.markdowntextinput" + namespace "com.expensify.livemarkdown" sourceSets { main { @@ -128,13 +128,13 @@ dependencies { if (isNewArchitectureEnabled()) { react { jsRootDir = file("../src/") - libraryName = "MarkdownTextInputView" - codegenJavaPackageName = "com.markdowntextinput" + libraryName = "LiveMarkdown" + codegenJavaPackageName = "com.expensify.livemarkdown" } } task copyJS(type: Copy) { - from '../parser/out.js' + from '../parser/react-native-live-markdown-parser.js' into 'src/main/assets' } diff --git a/android/gradle.properties b/android/gradle.properties index f197ef06d..5deda746f 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,5 +1,5 @@ -MarkdownTextInput_kotlinVersion=1.7.0 -MarkdownTextInput_minSdkVersion=21 -MarkdownTextInput_targetSdkVersion=31 -MarkdownTextInput_compileSdkVersion=31 -MarkdownTextInput_ndkversion=21.4.7075529 +LiveMarkdown_kotlinVersion=1.7.0 +LiveMarkdown_minSdkVersion=21 +LiveMarkdown_targetSdkVersion=31 +LiveMarkdown_compileSdkVersion=31 +LiveMarkdown_ndkversion=21.4.7075529 diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index 20a3d8435..e5004c026 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -1,3 +1,3 @@ + package="com.expensify.livemarkdown"> diff --git a/android/src/main/cpp/CMakeLists.txt b/android/src/main/cpp/CMakeLists.txt index 4d81a6d80..f846aa338 100644 --- a/android/src/main/cpp/CMakeLists.txt +++ b/android/src/main/cpp/CMakeLists.txt @@ -1,4 +1,4 @@ -project("markdowntextinput") +project("livemarkdown") cmake_minimum_required(VERSION 3.13) @@ -6,9 +6,9 @@ set(CMAKE_VERBOSE_MAKEFILE on) add_compile_options(-fvisibility=hidden -fexceptions -frtti) -file(GLOB markdowntextinput_SRC CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) +file(GLOB livemarkdown_SRC CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) -add_library(${CMAKE_PROJECT_NAME} SHARED ${markdowntextinput_SRC}) +add_library(${CMAKE_PROJECT_NAME} SHARED ${livemarkdown_SRC}) target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/android/src/main/cpp/MarkdownUtils.cpp b/android/src/main/cpp/MarkdownUtils.cpp index 97dc859fb..63c69a726 100644 --- a/android/src/main/cpp/MarkdownUtils.cpp +++ b/android/src/main/cpp/MarkdownUtils.cpp @@ -5,7 +5,8 @@ using namespace facebook; -namespace markdowntextinput { +namespace expensify { +namespace livemarkdown { std::shared_ptr MarkdownUtils::runtime_; void MarkdownUtils::nativeInitializeRuntime( @@ -21,9 +22,15 @@ namespace markdowntextinput { jni::alias_ref jThis, jni::alias_ref input) { jsi::Runtime &rt = *runtime_; - auto func = rt.global().getPropertyAsFunction(rt, "parseMarkdownToTextAndRanges"); - auto output = func.call(rt, input->toStdString()); - auto json = rt.global().getPropertyAsObject(rt, "JSON").getPropertyAsFunction(rt, "stringify").call(rt, output).asString(rt).utf8(rt); + auto func = rt.global().getPropertyAsFunction(rt, "parseExpensiMarkToRanges"); + auto arg = input->toStdString(); + jsi::Value result; + try { + result = func.call(rt, arg); + } catch (jsi::JSError e) { + result = jsi::Array(rt, 0); + } + auto json = rt.global().getPropertyAsObject(rt, "JSON").getPropertyAsFunction(rt, "stringify").call(rt, result).asString(rt).utf8(rt); return jni::make_jstring(json); } @@ -33,4 +40,5 @@ namespace markdowntextinput { makeNativeMethod("nativeParseMarkdown", MarkdownUtils::nativeParseMarkdown)}); } -} // namespace markdowntextinput +} // namespace livemarkdown +} // namespace expensify diff --git a/android/src/main/cpp/MarkdownUtils.h b/android/src/main/cpp/MarkdownUtils.h index ae3047348..eb951bae6 100644 --- a/android/src/main/cpp/MarkdownUtils.h +++ b/android/src/main/cpp/MarkdownUtils.h @@ -12,13 +12,14 @@ using namespace facebook; -namespace markdowntextinput { +namespace expensify { +namespace livemarkdown { class MarkdownUtils : public jni::HybridClass, public jsi::HostObject { public: static constexpr auto kJavaDescriptor = - "Lcom/markdowntextinput/MarkdownUtils;"; + "Lcom/expensify/livemarkdown/MarkdownUtils;"; static void nativeInitializeRuntime( jni::alias_ref jThis, @@ -36,4 +37,5 @@ namespace markdowntextinput { friend HybridBase; }; -} // namespace markdowntextinput +} // namespace livemarkdown +} // namespace expensify diff --git a/android/src/main/cpp/OnLoad.cpp b/android/src/main/cpp/OnLoad.cpp index a607b4ea1..deddae9b0 100644 --- a/android/src/main/cpp/OnLoad.cpp +++ b/android/src/main/cpp/OnLoad.cpp @@ -4,5 +4,5 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { return facebook::jni::initialize( - vm, [] { markdowntextinput::MarkdownUtils::registerNatives(); }); + vm, [] { expensify::livemarkdown::MarkdownUtils::registerNatives(); }); } diff --git a/android/src/main/java/com/markdowntextinput/MarkdownTextInputViewPackage.java b/android/src/main/java/com/expensify/livemarkdown/LiveMarkdownPackage.java similarity index 78% rename from android/src/main/java/com/markdowntextinput/MarkdownTextInputViewPackage.java rename to android/src/main/java/com/expensify/livemarkdown/LiveMarkdownPackage.java index 7bd8c7546..c1c8fece8 100644 --- a/android/src/main/java/com/markdowntextinput/MarkdownTextInputViewPackage.java +++ b/android/src/main/java/com/expensify/livemarkdown/LiveMarkdownPackage.java @@ -1,5 +1,4 @@ - -package com.markdowntextinput; +package com.expensify.livemarkdown; import com.facebook.react.ReactPackage; import com.facebook.react.bridge.NativeModule; @@ -10,11 +9,11 @@ import java.util.Collections; import java.util.List; -public class MarkdownTextInputViewPackage implements ReactPackage { +public class LiveMarkdownPackage implements ReactPackage { @Override public List createViewManagers(ReactApplicationContext reactContext) { List viewManagers = new ArrayList<>(); - viewManagers.add(new MarkdownTextInputViewManager()); + viewManagers.add(new MarkdownTextInputDecoratorViewManager()); return viewManagers; } diff --git a/android/src/main/java/com/expensify/livemarkdown/MarkdownBackgroundColorSpan.java b/android/src/main/java/com/expensify/livemarkdown/MarkdownBackgroundColorSpan.java new file mode 100644 index 000000000..4a4ce1d1f --- /dev/null +++ b/android/src/main/java/com/expensify/livemarkdown/MarkdownBackgroundColorSpan.java @@ -0,0 +1,11 @@ +package com.expensify.livemarkdown; + +import android.text.style.BackgroundColorSpan; + +import androidx.annotation.ColorInt; + +public class MarkdownBackgroundColorSpan extends BackgroundColorSpan implements MarkdownSpan { + public MarkdownBackgroundColorSpan(@ColorInt int color) { + super(color); + } +} diff --git a/android/src/main/java/com/markdowntextinput/QuoteSpan.java b/android/src/main/java/com/expensify/livemarkdown/MarkdownBlockquoteSpan.java similarity index 84% rename from android/src/main/java/com/markdowntextinput/QuoteSpan.java rename to android/src/main/java/com/expensify/livemarkdown/MarkdownBlockquoteSpan.java index f083fb85d..9c86dd7ec 100644 --- a/android/src/main/java/com/markdowntextinput/QuoteSpan.java +++ b/android/src/main/java/com/expensify/livemarkdown/MarkdownBlockquoteSpan.java @@ -1,19 +1,23 @@ -package com.markdowntextinput; +package com.expensify.livemarkdown; import android.graphics.Canvas; import android.graphics.Paint; import android.text.Layout; import android.text.style.LeadingMarginSpan; + +import androidx.annotation.ColorInt; + import com.facebook.react.uimanager.PixelUtil; -public class QuoteSpan implements LeadingMarginSpan { +public class MarkdownBlockquoteSpan implements MarkdownSpan, LeadingMarginSpan { + @ColorInt private final int borderColor; private final float borderWidth; private final float marginLeft; private final float paddingLeft; private int nestingLevel = 0; - public QuoteSpan(int borderColor, float borderWidth, float marginLeft, float paddingLeft) { + public MarkdownBlockquoteSpan(@ColorInt int borderColor, float borderWidth, float marginLeft, float paddingLeft) { this.borderColor = borderColor; this.borderWidth = PixelUtil.toPixelFromDIP(borderWidth); this.marginLeft = PixelUtil.toPixelFromDIP(marginLeft); diff --git a/android/src/main/java/com/expensify/livemarkdown/MarkdownBoldSpan.java b/android/src/main/java/com/expensify/livemarkdown/MarkdownBoldSpan.java new file mode 100644 index 000000000..cd2b07fca --- /dev/null +++ b/android/src/main/java/com/expensify/livemarkdown/MarkdownBoldSpan.java @@ -0,0 +1,10 @@ +package com.expensify.livemarkdown; + +import android.graphics.Typeface; +import android.text.style.StyleSpan; + +public class MarkdownBoldSpan extends StyleSpan implements MarkdownSpan { + public MarkdownBoldSpan() { + super(Typeface.BOLD); + } +} diff --git a/android/src/main/java/com/expensify/livemarkdown/MarkdownFontFamilySpan.java b/android/src/main/java/com/expensify/livemarkdown/MarkdownFontFamilySpan.java new file mode 100644 index 000000000..facecb82b --- /dev/null +++ b/android/src/main/java/com/expensify/livemarkdown/MarkdownFontFamilySpan.java @@ -0,0 +1,39 @@ +package com.expensify.livemarkdown; + +import android.content.res.AssetManager; +import android.graphics.Paint; +import android.graphics.Typeface; +import android.text.TextPaint; +import android.text.style.MetricAffectingSpan; + +import androidx.annotation.NonNull; + +import com.facebook.react.views.text.ReactFontManager; + +public class MarkdownFontFamilySpan extends MetricAffectingSpan implements MarkdownSpan { + + private final @NonNull String mFontFamily; + private final @NonNull AssetManager mAssetManager; + + public MarkdownFontFamilySpan(@NonNull String fontFamily, @NonNull AssetManager assetManager) { + mFontFamily = fontFamily; + mAssetManager = assetManager; + } + + @Override + public void updateMeasureState(@NonNull TextPaint textPaint) { + apply(textPaint); + } + + @Override + public void updateDrawState(TextPaint tp) { + apply(tp); + } + + private void apply(@NonNull TextPaint textPaint) { + int style = textPaint.getTypeface().getStyle(); + Typeface typeface = ReactFontManager.getInstance().getTypeface(mFontFamily, style, mAssetManager); + textPaint.setTypeface(typeface); + textPaint.setFlags(textPaint.getFlags() | Paint.SUBPIXEL_TEXT_FLAG); + } +} diff --git a/android/src/main/java/com/expensify/livemarkdown/MarkdownFontSizeSpan.java b/android/src/main/java/com/expensify/livemarkdown/MarkdownFontSizeSpan.java new file mode 100644 index 000000000..6e3c1b93f --- /dev/null +++ b/android/src/main/java/com/expensify/livemarkdown/MarkdownFontSizeSpan.java @@ -0,0 +1,9 @@ +package com.expensify.livemarkdown; + +import android.text.style.AbsoluteSizeSpan; + +public class MarkdownFontSizeSpan extends AbsoluteSizeSpan implements MarkdownSpan { + public MarkdownFontSizeSpan(float fontSize) { + super((int) fontSize, true); + } +} diff --git a/android/src/main/java/com/expensify/livemarkdown/MarkdownForegroundColorSpan.java b/android/src/main/java/com/expensify/livemarkdown/MarkdownForegroundColorSpan.java new file mode 100644 index 000000000..352282225 --- /dev/null +++ b/android/src/main/java/com/expensify/livemarkdown/MarkdownForegroundColorSpan.java @@ -0,0 +1,11 @@ +package com.expensify.livemarkdown; + +import android.text.style.ForegroundColorSpan; + +import androidx.annotation.ColorInt; + +public class MarkdownForegroundColorSpan extends ForegroundColorSpan implements MarkdownSpan { + public MarkdownForegroundColorSpan(@ColorInt int color) { + super(color); + } +} diff --git a/android/src/main/java/com/expensify/livemarkdown/MarkdownItalicSpan.java b/android/src/main/java/com/expensify/livemarkdown/MarkdownItalicSpan.java new file mode 100644 index 000000000..7e1ce0586 --- /dev/null +++ b/android/src/main/java/com/expensify/livemarkdown/MarkdownItalicSpan.java @@ -0,0 +1,10 @@ +package com.expensify.livemarkdown; + +import android.graphics.Typeface; +import android.text.style.StyleSpan; + +public class MarkdownItalicSpan extends StyleSpan implements MarkdownSpan { + public MarkdownItalicSpan() { + super(Typeface.ITALIC); + } +} diff --git a/android/src/main/java/com/expensify/livemarkdown/MarkdownLineHeightSpan.java b/android/src/main/java/com/expensify/livemarkdown/MarkdownLineHeightSpan.java new file mode 100644 index 000000000..ca660f379 --- /dev/null +++ b/android/src/main/java/com/expensify/livemarkdown/MarkdownLineHeightSpan.java @@ -0,0 +1,18 @@ +package com.expensify.livemarkdown; + +import android.graphics.Paint; +import android.text.style.LineHeightSpan; + +public class MarkdownLineHeightSpan implements MarkdownSpan, LineHeightSpan { + private final float mLineHeight; + + public MarkdownLineHeightSpan(float lineHeight) { + mLineHeight = lineHeight; + } + + @Override + public void chooseHeight(CharSequence text, int start, int end, int spanstartv, int lineHeight, Paint.FontMetricsInt fm) { + fm.top -= mLineHeight / 4; + fm.ascent -= mLineHeight / 4; + } +} diff --git a/android/src/main/java/com/expensify/livemarkdown/MarkdownSpan.java b/android/src/main/java/com/expensify/livemarkdown/MarkdownSpan.java new file mode 100644 index 000000000..d6cea3e50 --- /dev/null +++ b/android/src/main/java/com/expensify/livemarkdown/MarkdownSpan.java @@ -0,0 +1,7 @@ +package com.expensify.livemarkdown; + +/* + * Enables us to distinguish between spans that were added by Live Markdown and spans that were + * added by something else. All spans that Live Markdown adds should implement this interface. + */ +public interface MarkdownSpan {} diff --git a/android/src/main/java/com/expensify/livemarkdown/MarkdownStrikethroughSpan.java b/android/src/main/java/com/expensify/livemarkdown/MarkdownStrikethroughSpan.java new file mode 100644 index 000000000..63a07a387 --- /dev/null +++ b/android/src/main/java/com/expensify/livemarkdown/MarkdownStrikethroughSpan.java @@ -0,0 +1,5 @@ +package com.expensify.livemarkdown; + +import android.text.style.StrikethroughSpan; + +public class MarkdownStrikethroughSpan extends StrikethroughSpan implements MarkdownSpan {} diff --git a/android/src/main/java/com/markdowntextinput/MarkdownStyle.java b/android/src/main/java/com/expensify/livemarkdown/MarkdownStyle.java similarity index 63% rename from android/src/main/java/com/markdowntextinput/MarkdownStyle.java rename to android/src/main/java/com/expensify/livemarkdown/MarkdownStyle.java index 491c89630..31c1280ee 100644 --- a/android/src/main/java/com/markdowntextinput/MarkdownStyle.java +++ b/android/src/main/java/com/expensify/livemarkdown/MarkdownStyle.java @@ -1,7 +1,8 @@ -package com.markdowntextinput; +package com.expensify.livemarkdown; import android.content.Context; +import androidx.annotation.ColorInt; import androidx.annotation.NonNull; import com.facebook.react.bridge.ColorPropConverter; @@ -12,30 +13,57 @@ import java.util.Objects; public class MarkdownStyle { + @ColorInt private final int mSyntaxColor; + + @ColorInt private final int mLinkColor; + private final float mH1FontSize; - private final int mQuoteBorderColor; - private final float mQuoteBorderWidth; - private final float mQuoteMarginLeft; - private final float mQuotePaddingLeft; + + @ColorInt + private final int mBlockquoteBorderColor; + + private final float mBlockquoteBorderWidth; + + private final float mBlockquoteMarginLeft; + + private final float mBlockquotePaddingLeft; + + private final String mCodeFontFamily; + + @ColorInt private final int mCodeColor; + + @ColorInt private final int mCodeBackgroundColor; + + private final String mPreFontFamily; + + @ColorInt private final int mPreColor; + + @ColorInt private final int mPreBackgroundColor; + + @ColorInt private final int mMentionHereBackgroundColor; + + @ColorInt private final int mMentionUserBackgroundColor; public MarkdownStyle(@NonNull ReadableMap map, @NonNull Context context) { mSyntaxColor = parseColor(map, "syntax", "color", context); mLinkColor = parseColor(map, "link", "color", context); mH1FontSize = parseFloat(map, "h1", "fontSize"); - mQuoteBorderColor = parseColor(map, "quote", "borderColor", context); - mQuoteBorderWidth = parseFloat(map, "quote", "borderWidth"); - mQuoteMarginLeft = parseFloat(map, "quote", "marginLeft"); - mQuotePaddingLeft = parseFloat(map, "quote", "paddingLeft"); + mBlockquoteBorderColor = parseColor(map, "blockquote", "borderColor", context); + mBlockquoteBorderWidth = parseFloat(map, "blockquote", "borderWidth"); + mBlockquoteMarginLeft = parseFloat(map, "blockquote", "marginLeft"); + mBlockquotePaddingLeft = parseFloat(map, "blockquote", "paddingLeft"); + mCodeFontFamily = parseString(map, "code", "fontFamily"); mCodeColor = parseColor(map, "code", "color", context); mCodeBackgroundColor = parseColor(map, "code", "backgroundColor", context); + mPreFontFamily = parseString(map, "pre", "fontFamily"); mPreColor = parseColor(map, "pre", "color", context); mPreBackgroundColor = parseColor(map, "pre", "backgroundColor", context); mMentionHereBackgroundColor = parseColor(map, "mentionHere", "backgroundColor", context); @@ -63,10 +91,18 @@ private static float parseFloat(@NonNull ReadableMap map, @NonNull String key, @ return (float) value; } + private static String parseString(@NonNull ReadableMap map, @NonNull String key, @NonNull String prop) { + ReadableMap style = map.getMap(key); + Objects.requireNonNull(style); + return style.getString(prop); + } + + @ColorInt public int getSyntaxColor() { return mSyntaxColor; } + @ColorInt public int getLinkColor() { return mLinkColor; } @@ -75,42 +111,57 @@ public float getH1FontSize() { return mH1FontSize; } - public int getQuoteBorderColor() { - return mQuoteBorderColor; + @ColorInt + public int getBlockquoteBorderColor() { + return mBlockquoteBorderColor; + } + + public float getBlockquoteBorderWidth() { + return mBlockquoteBorderWidth; } - public float getQuoteBorderWidth() { - return mQuoteBorderWidth; + public float getBlockquoteMarginLeft() { + return mBlockquoteMarginLeft; } - public float getQuoteMarginLeft() { - return mQuoteMarginLeft; + public float getBlockquotePaddingLeft() { + return mBlockquotePaddingLeft; } - public float getQuotePaddingLeft() { - return mQuotePaddingLeft; + public String getCodeFontFamily() { + return mCodeFontFamily; } + @ColorInt public int getCodeColor() { return mCodeColor; } + @ColorInt public int getCodeBackgroundColor() { return mCodeBackgroundColor; } + public String getPreFontFamily() { + return mPreFontFamily; + } + + @ColorInt public int getPreColor() { return mPreColor; } + @ColorInt public int getPreBackgroundColor() { return mPreBackgroundColor; } + @ColorInt public int getMentionHereBackgroundColor() { return mMentionHereBackgroundColor; } + @ColorInt public int getMentionUserBackgroundColor() { return mMentionUserBackgroundColor; } diff --git a/android/src/main/java/com/markdowntextinput/MarkdownTextInputView.java b/android/src/main/java/com/expensify/livemarkdown/MarkdownTextInputDecoratorView.java similarity index 77% rename from android/src/main/java/com/markdowntextinput/MarkdownTextInputView.java rename to android/src/main/java/com/expensify/livemarkdown/MarkdownTextInputDecoratorView.java index b0750a677..9ea574571 100644 --- a/android/src/main/java/com/markdowntextinput/MarkdownTextInputView.java +++ b/android/src/main/java/com/expensify/livemarkdown/MarkdownTextInputDecoratorView.java @@ -1,8 +1,9 @@ -package com.markdowntextinput; +package com.expensify.livemarkdown; import androidx.annotation.Nullable; import android.content.Context; +import android.content.res.AssetManager; import android.text.TextWatcher; import android.util.AttributeSet; @@ -12,17 +13,17 @@ import com.facebook.react.views.textinput.ReactEditText; -public class MarkdownTextInputView extends View { +public class MarkdownTextInputDecoratorView extends View { - public MarkdownTextInputView(Context context) { + public MarkdownTextInputDecoratorView(Context context) { super(context); } - public MarkdownTextInputView(Context context, @Nullable AttributeSet attrs) { + public MarkdownTextInputDecoratorView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } - public MarkdownTextInputView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + public MarkdownTextInputDecoratorView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @@ -51,8 +52,9 @@ protected void onAttachedToWindow() { } if (previousSibling instanceof ReactEditText) { - MarkdownUtils.maybeInitializeRuntime(getContext().getAssets()); - mMarkdownUtils = new MarkdownUtils(); + AssetManager assetManager = getContext().getAssets(); + MarkdownUtils.maybeInitializeRuntime(assetManager); + mMarkdownUtils = new MarkdownUtils(assetManager); mMarkdownUtils.setMarkdownStyle(mMarkdownStyle); mReactEditText = (ReactEditText) previousSibling; mTextWatcher = new MarkdownTextWatcher(mMarkdownUtils); diff --git a/android/src/main/java/com/expensify/livemarkdown/MarkdownTextInputDecoratorViewManager.java b/android/src/main/java/com/expensify/livemarkdown/MarkdownTextInputDecoratorViewManager.java new file mode 100644 index 000000000..c86ccd5d4 --- /dev/null +++ b/android/src/main/java/com/expensify/livemarkdown/MarkdownTextInputDecoratorViewManager.java @@ -0,0 +1,31 @@ +package com.expensify.livemarkdown; + +import androidx.annotation.NonNull; + +import com.facebook.react.bridge.ReadableMap; +import com.facebook.react.module.annotations.ReactModule; +import com.facebook.react.uimanager.ThemedReactContext; +import com.facebook.react.uimanager.annotations.ReactProp; + +@ReactModule(name = MarkdownTextInputDecoratorViewManager.NAME) +public class MarkdownTextInputDecoratorViewManager extends MarkdownTextInputDecoratorViewManagerSpec { + + public static final String NAME = "MarkdownTextInputDecoratorView"; + + @Override + public String getName() { + return NAME; + } + + @Override + public MarkdownTextInputDecoratorView createViewInstance(ThemedReactContext context) { + return new MarkdownTextInputDecoratorView(context); + } + + @Override + @ReactProp(name = "markdownStyle") + public void setMarkdownStyle(@NonNull MarkdownTextInputDecoratorView view, @NonNull ReadableMap value) { + MarkdownStyle markdownStyle = new MarkdownStyle(value, view.getContext()); + view.setMarkdownStyle(markdownStyle); + } +} diff --git a/android/src/main/java/com/markdowntextinput/MarkdownTextWatcher.java b/android/src/main/java/com/expensify/livemarkdown/MarkdownTextWatcher.java similarity index 79% rename from android/src/main/java/com/markdowntextinput/MarkdownTextWatcher.java rename to android/src/main/java/com/expensify/livemarkdown/MarkdownTextWatcher.java index 2591063f8..9391d334f 100644 --- a/android/src/main/java/com/markdowntextinput/MarkdownTextWatcher.java +++ b/android/src/main/java/com/expensify/livemarkdown/MarkdownTextWatcher.java @@ -1,4 +1,4 @@ -package com.markdowntextinput; +package com.expensify.livemarkdown; import android.text.Editable; import android.text.SpannableStringBuilder; @@ -9,6 +9,8 @@ public class MarkdownTextWatcher implements TextWatcher { private final MarkdownUtils mMarkdownUtils; + private boolean mShouldSkip = false; + public MarkdownTextWatcher(@NonNull MarkdownUtils markdownUtils) { mMarkdownUtils = markdownUtils; } @@ -19,15 +21,18 @@ public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { + public void onTextChanged(CharSequence s, int start, int before, int count) { + if (mShouldSkip) { + return; + } if (s instanceof SpannableStringBuilder) { mMarkdownUtils.applyMarkdownFormatting((SpannableStringBuilder) s); + mShouldSkip = true; } } @Override public void afterTextChanged(Editable editable) { - // ensures proper styling after wrapping for the next line - mMarkdownUtils.reinitializeSpans((SpannableStringBuilder) editable); + mShouldSkip = false; } } diff --git a/android/src/main/java/com/expensify/livemarkdown/MarkdownUnderlineSpan.java b/android/src/main/java/com/expensify/livemarkdown/MarkdownUnderlineSpan.java new file mode 100644 index 000000000..08fcbe4fa --- /dev/null +++ b/android/src/main/java/com/expensify/livemarkdown/MarkdownUnderlineSpan.java @@ -0,0 +1,5 @@ +package com.expensify.livemarkdown; + +import android.text.style.UnderlineSpan; + +public class MarkdownUnderlineSpan extends UnderlineSpan implements MarkdownSpan {} diff --git a/android/src/main/java/com/expensify/livemarkdown/MarkdownUtils.java b/android/src/main/java/com/expensify/livemarkdown/MarkdownUtils.java new file mode 100644 index 000000000..079baa6a6 --- /dev/null +++ b/android/src/main/java/com/expensify/livemarkdown/MarkdownUtils.java @@ -0,0 +1,191 @@ +package com.expensify.livemarkdown; + +import static com.facebook.infer.annotation.ThreadConfined.UI; + +import android.content.res.AssetManager; +import android.text.SpannableStringBuilder; +import android.text.Spanned; + +import androidx.annotation.NonNull; + +import com.facebook.infer.annotation.Assertions; +import com.facebook.infer.annotation.ThreadConfined; +import com.facebook.react.bridge.UiThreadUtil; +import com.facebook.react.views.text.CustomLineHeightSpan; +import com.facebook.soloader.SoLoader; + +import org.json.JSONArray; +import org.json.JSONException; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Objects; + +public class MarkdownUtils { + static { + SoLoader.loadLibrary("livemarkdown"); + } + + private static boolean IS_RUNTIME_INITIALIZED = false; + + @ThreadConfined(UI) + public static void maybeInitializeRuntime(AssetManager assetManager) { + UiThreadUtil.assertOnUiThread(); + if (IS_RUNTIME_INITIALIZED) { + return; + } + try { + InputStream inputStream = assetManager.open("react-native-live-markdown-parser.js"); + byte[] buffer = new byte[inputStream.available()]; + inputStream.read(buffer); + inputStream.close(); + String code = new String(buffer); + nativeInitializeRuntime(code); + IS_RUNTIME_INITIALIZED = true; + } catch (IOException e) { + throw new RuntimeException("Failed to initialize Markdown runtime"); + } + } + + private static native void nativeInitializeRuntime(String code); + + @ThreadConfined(UI) + private static String parseMarkdown(String input) { + UiThreadUtil.assertOnUiThread(); + return nativeParseMarkdown(input); + } + + private static native String nativeParseMarkdown(String input); + + public MarkdownUtils(@NonNull AssetManager assetManager) { + mAssetManager = assetManager; + } + + private final @NonNull AssetManager mAssetManager; + + private String mPrevInput; + + private String mPrevOutput; + + private MarkdownStyle mMarkdownStyle; + + public void setMarkdownStyle(@NonNull MarkdownStyle markdownStyle) { + mMarkdownStyle = markdownStyle; + } + + public void applyMarkdownFormatting(SpannableStringBuilder ssb) { + Objects.requireNonNull(mMarkdownStyle, "mMarkdownStyle is null"); + + removeSpans(ssb); + + String input = ssb.toString(); + String output; + if (input.equals(mPrevInput)) { + output = mPrevOutput; + } else { + output = parseMarkdown(input); + mPrevInput = input; + mPrevOutput = output; + } + + try { + JSONArray ranges = new JSONArray(output); + for (int i = 0; i < ranges.length(); i++) { + JSONArray range = ranges.getJSONArray(i); + String type = range.getString(0); + int start = range.getInt(1); + int end = start + range.getInt(2); + applyRange(ssb, type, start, end); + } + } catch (JSONException e) { + // Do nothing + } + } + + private void applyRange(SpannableStringBuilder ssb, String type, int start, int end) { + switch (type) { + case "bold": + setSpan(ssb, new MarkdownBoldSpan(), start, end); + break; + case "italic": + setSpan(ssb, new MarkdownItalicSpan(), start, end); + break; + case "strikethrough": + setSpan(ssb, new MarkdownStrikethroughSpan(), start, end); + break; + case "mention-here": + setSpan(ssb, new MarkdownBoldSpan(), start, end); + setSpan(ssb, new MarkdownBackgroundColorSpan(mMarkdownStyle.getMentionHereBackgroundColor()), start, end); + break; + case "mention-user": + setSpan(ssb, new MarkdownBoldSpan(), start, end); + // TODO: change mention color when it mentions current user + setSpan(ssb, new MarkdownBackgroundColorSpan(mMarkdownStyle.getMentionUserBackgroundColor()), start, end); + break; + case "syntax": + setSpan(ssb, new MarkdownBoldSpan(), start, end); + setSpan(ssb, new MarkdownForegroundColorSpan(mMarkdownStyle.getSyntaxColor()), start, end); + break; + case "link": + setSpan(ssb, new MarkdownUnderlineSpan(), start, end); + setSpan(ssb, new MarkdownForegroundColorSpan(mMarkdownStyle.getLinkColor()), start, end); + break; + case "code": + setSpan(ssb, new MarkdownFontFamilySpan(mMarkdownStyle.getCodeFontFamily(), mAssetManager), start, end); + setSpan(ssb, new MarkdownForegroundColorSpan(mMarkdownStyle.getCodeColor()), start, end); + setSpan(ssb, new MarkdownBackgroundColorSpan(mMarkdownStyle.getCodeBackgroundColor()), start, end); + break; + case "pre": + setSpan(ssb, new MarkdownFontFamilySpan(mMarkdownStyle.getPreFontFamily(), mAssetManager), start, end); + setSpan(ssb, new MarkdownForegroundColorSpan(mMarkdownStyle.getPreColor()), start, end); + setSpan(ssb, new MarkdownBackgroundColorSpan(mMarkdownStyle.getPreBackgroundColor()), start, end); + break; + case "h1": + setSpan(ssb, new MarkdownBoldSpan(), start, end); + CustomLineHeightSpan[] spans = ssb.getSpans(0, ssb.length(), CustomLineHeightSpan.class); + if (spans.length >= 1) { + int lineHeight = spans[0].getLineHeight(); + setSpan(ssb, new MarkdownLineHeightSpan(lineHeight * 1.5f), start, end); + } + // NOTE: size span must be set after line height span to avoid height jumps + setSpan(ssb, new MarkdownFontSizeSpan(mMarkdownStyle.getH1FontSize()), start, end); + break; + case "blockquote": + Object containSpan = checkIfInsideSpanType(ssb, MarkdownBlockquoteSpan.class, start, end); + if (containSpan != null) { + MarkdownBlockquoteSpan blockquoteSpan = (MarkdownBlockquoteSpan) containSpan; + blockquoteSpan.increaseNestingLevel(); + break; + } + MarkdownBlockquoteSpan span = new MarkdownBlockquoteSpan( + mMarkdownStyle.getBlockquoteBorderColor(), + mMarkdownStyle.getBlockquoteBorderWidth(), + mMarkdownStyle.getBlockquoteMarginLeft(), + mMarkdownStyle.getBlockquotePaddingLeft()); + setSpan(ssb, span, start, end); + break; + default: + throw new IllegalStateException("Unsupported type: " + type); + } + } + + private Object checkIfInsideSpanType(SpannableStringBuilder ssb, Class spanClass, int start, int end) { + Object[] spans = ssb.getSpans(start, end, spanClass); + if(spans.length == 0) { + return null; + } + return spans[0]; + } + + private void setSpan(SpannableStringBuilder ssb, MarkdownSpan span, int start, int end) { + ssb.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + } + + private void removeSpans(SpannableStringBuilder ssb) { + // We shouldn't use `removeSpans()` because it also removes SpellcheckSpan, SuggestionSpan etc. + MarkdownSpan[] spans = ssb.getSpans(0, ssb.length(), MarkdownSpan.class); + for (MarkdownSpan span : spans) { + ssb.removeSpan(span); + } + } +} diff --git a/android/src/main/java/com/markdowntextinput/MarkdownTextInputViewManager.java b/android/src/main/java/com/markdowntextinput/MarkdownTextInputViewManager.java deleted file mode 100644 index eb57c6d98..000000000 --- a/android/src/main/java/com/markdowntextinput/MarkdownTextInputViewManager.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.markdowntextinput; - -import androidx.annotation.NonNull; - -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.module.annotations.ReactModule; -import com.facebook.react.uimanager.ThemedReactContext; -import com.facebook.react.uimanager.annotations.ReactProp; - -@ReactModule(name = MarkdownTextInputViewManager.NAME) -public class MarkdownTextInputViewManager extends MarkdownTextInputViewManagerSpec { - - public static final String NAME = "MarkdownTextInputView"; - - @Override - public String getName() { - return NAME; - } - - @Override - public MarkdownTextInputView createViewInstance(ThemedReactContext context) { - return new MarkdownTextInputView(context); - } - - @Override - @ReactProp(name = "markdownStyle") - public void setMarkdownStyle(@NonNull MarkdownTextInputView view, @NonNull ReadableMap value) { - MarkdownStyle markdownStyle = new MarkdownStyle(value, view.getContext()); - view.setMarkdownStyle(markdownStyle); - } -} diff --git a/android/src/main/java/com/markdowntextinput/MarkdownUtils.java b/android/src/main/java/com/markdowntextinput/MarkdownUtils.java deleted file mode 100644 index 220b8bfea..000000000 --- a/android/src/main/java/com/markdowntextinput/MarkdownUtils.java +++ /dev/null @@ -1,270 +0,0 @@ -package com.markdowntextinput; - -import static com.facebook.infer.annotation.ThreadConfined.UI; - -import android.content.res.AssetManager; -import android.graphics.Typeface; -import android.text.SpannableStringBuilder; -import android.text.Spanned; -import android.text.style.AbsoluteSizeSpan; -import android.text.style.BackgroundColorSpan; -import android.text.style.ForegroundColorSpan; -import android.text.style.LineHeightSpan; -import android.text.style.StrikethroughSpan; -import android.text.style.StyleSpan; -import android.text.style.TypefaceSpan; -import android.text.style.UnderlineSpan; - -import androidx.annotation.NonNull; - -import com.facebook.infer.annotation.ThreadConfined; -import com.facebook.react.bridge.UiThreadUtil; -import com.facebook.react.views.text.CustomLineHeightSpan; -import com.facebook.soloader.SoLoader; - -import org.json.JSONArray; -import org.json.JSONException; - -import java.io.IOException; -import java.io.InputStream; -import java.util.LinkedList; -import java.util.List; -import java.util.Objects; - -public class MarkdownUtils { - static { - SoLoader.loadLibrary("markdowntextinput"); - } - - private static boolean IS_RUNTIME_INITIALIZED = false; - - @ThreadConfined(UI) - public static void maybeInitializeRuntime(AssetManager assetManager) { - UiThreadUtil.assertOnUiThread(); - if (IS_RUNTIME_INITIALIZED) { - return; - } - try { - InputStream inputStream = assetManager.open("out.js"); - byte[] buffer = new byte[inputStream.available()]; - inputStream.read(buffer); - inputStream.close(); - String code = new String(buffer); - nativeInitializeRuntime(code); - IS_RUNTIME_INITIALIZED = true; - } catch (IOException e) { - throw new RuntimeException("Failed to initialize Markdown runtime"); - } - } - - private static native void nativeInitializeRuntime(String code); - - @ThreadConfined(UI) - private static String parseMarkdown(String input) { - UiThreadUtil.assertOnUiThread(); - return nativeParseMarkdown(input); - } - - private static native String nativeParseMarkdown(String input); - - private final List mSpans = new LinkedList<>(); - - private MarkdownStyle mMarkdownStyle; - - public void setMarkdownStyle(@NonNull MarkdownStyle markdownStyle) { - mMarkdownStyle = markdownStyle; - } - - // Spans - private static Object makeBoldSpan() { - return new StyleSpan(Typeface.BOLD); - } - - private static Object makeItalicSpan() { - return new StyleSpan(Typeface.ITALIC); - } - - private static Object makeUnderlineSpan() { - return new UnderlineSpan(); - } - - private static Object makeStrikethroughSpan() { - return new StrikethroughSpan(); - } - - private static Object makeMonospaceSpan() { - return new TypefaceSpan("monospace"); - } - - private Object makeSyntaxColorSpan() { - return new ForegroundColorSpan(mMarkdownStyle.getSyntaxColor()); - } - - private Object makeLinkColorSpan() { - return new ForegroundColorSpan(mMarkdownStyle.getLinkColor()); - } - - private Object makeCodeColorSpan() { - return new ForegroundColorSpan(mMarkdownStyle.getCodeColor()); - } - - private Object makePreColorSpan() { - return new ForegroundColorSpan(mMarkdownStyle.getPreColor()); - } - - private Object makeMentionHereBackgroundSpan() { - return new BackgroundColorSpan(mMarkdownStyle.getMentionHereBackgroundColor()); - } - - private Object makeMentionUserBackgroundSpan() { - return new BackgroundColorSpan(mMarkdownStyle.getMentionUserBackgroundColor()); - } - - private Object makeCodeBackgroundSpan() { - return new BackgroundColorSpan(mMarkdownStyle.getCodeBackgroundColor()); - } - - private Object makePreBackgroundSpan() { - return new BackgroundColorSpan(mMarkdownStyle.getPreBackgroundColor()); - } - - private Object makeH1FontSizeSpan() { - return new AbsoluteSizeSpan((int) mMarkdownStyle.getH1FontSize(), true); - } - - private static Object makeHeadingLineHeightSpan(float lineHeight) { - return (LineHeightSpan) (text, start, end, spanstartv, lh, fm) -> { - fm.top -= lineHeight / 4; - fm.ascent -= lineHeight / 4; - }; - } - - private Object makeBlockquoteMarginSpan() { - return new QuoteSpan( - mMarkdownStyle.getQuoteBorderColor(), - mMarkdownStyle.getQuoteBorderWidth(), - mMarkdownStyle.getQuoteMarginLeft(), - mMarkdownStyle.getQuotePaddingLeft()); - } - - public void applyMarkdownFormatting(SpannableStringBuilder ssb) { - Objects.requireNonNull(mMarkdownStyle, "mMarkdownStyle is null"); - - removeSpans(ssb); - - String input = ssb.toString(); - String output = parseMarkdown(input); - try { - JSONArray array = new JSONArray(output); - String text = array.getString(0); - - if (!ssb.toString().equals(text)) { - return; - } - - JSONArray ranges = array.getJSONArray(1); - for (int i = 0; i < ranges.length(); i++) { - JSONArray range = ranges.getJSONArray(i); - String type = range.getString(0); - int start = range.getInt(1); - int end = start + range.getInt(2); - applyRange(ssb, type, start, end); - } - } catch (JSONException e) { - // Do nothing - } - } - - private void applyRange(SpannableStringBuilder ssb, String type, int start, int end) { - switch (type) { - case "bold": - setSpan(ssb, makeBoldSpan(), start, end); - break; - case "italic": - setSpan(ssb, makeItalicSpan(), start, end); - break; - case "strikethrough": - setSpan(ssb, makeStrikethroughSpan(), start, end); - break; - case "mention": - setSpan(ssb, makeBoldSpan(), start, end); - setSpan(ssb, makeMentionHereBackgroundSpan(), start, end); - break; - case "mention-user": - setSpan(ssb, makeBoldSpan(), start, end); - // TODO: change mention color when it mentions current user - setSpan(ssb, makeMentionUserBackgroundSpan(), start, end); - break; - case "syntax": - setSpan(ssb, makeBoldSpan(), start, end); - setSpan(ssb, makeSyntaxColorSpan(), start, end); - break; - case "link": - setSpan(ssb, makeUnderlineSpan(), start, end); - setSpan(ssb, makeLinkColorSpan(), start, end); - break; - case "code": - setSpan(ssb, makeMonospaceSpan(), start, end); - setSpan(ssb, makeCodeColorSpan(), start, end); - setSpan(ssb, makeCodeBackgroundSpan(), start, end); - break; - case "pre": - setSpan(ssb, makeMonospaceSpan(), start, end); - setSpan(ssb, makePreColorSpan(), start, end); - setSpan(ssb, makePreBackgroundSpan(), start, end); - break; - case "h1": - setSpan(ssb, makeBoldSpan(), start, end); - CustomLineHeightSpan[] spans = ssb.getSpans(0, ssb.length(), CustomLineHeightSpan.class); - if (spans.length >= 1) { - int lineHeight = spans[0].getLineHeight(); - setSpan(ssb, makeHeadingLineHeightSpan(lineHeight * 1.5f), start, end); - } - // NOTE: size span must be set after line height span to avoid height jumps - setSpan(ssb, makeH1FontSizeSpan(), start, end); - break; - case "blockquote": - Object containSpan = checkIfInsideSpanType(ssb, QuoteSpan.class, start, end); - if (containSpan != null) { - QuoteSpan blockquoteSpan = (QuoteSpan) containSpan; - blockquoteSpan.increaseNestingLevel(); - } else { - setSpan(ssb, makeBlockquoteMarginSpan(), start, end); - } - break; - default: - throw new IllegalStateException("Unsupported type: " + type); - } - } - - private Object checkIfInsideSpanType(SpannableStringBuilder ssb, Class spanClass, int start, int end) { - Object[] spans = ssb.getSpans(start, end, spanClass); - if(spans.length == 0) { - return null; - } - return spans[0]; - } - - private void setSpan(SpannableStringBuilder ssb, Object span, int start, int end) { - mSpans.add(span); - ssb.setSpan(span, start, end, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); - } - - private void removeSpans(SpannableStringBuilder ssb) { - // We shouldn't use `removeSpans()` because it also removes SpellcheckSpan, SuggestionSpan etc. - for (Object span : mSpans) { - ssb.removeSpan(span); - } - mSpans.clear(); - } - - void reinitializeSpans(SpannableStringBuilder ssb) { - for (Object span : mSpans) { - int start = ssb.getSpanStart(span); - int end = ssb.getSpanEnd(span); - int flags = ssb.getSpanFlags(span); - ssb.removeSpan(span); - ssb.setSpan(span, start, end, flags); - } - } -} diff --git a/android/src/newarch/MarkdownTextInputDecoratorViewManagerSpec.java b/android/src/newarch/MarkdownTextInputDecoratorViewManagerSpec.java new file mode 100644 index 000000000..c6d6b4cb3 --- /dev/null +++ b/android/src/newarch/MarkdownTextInputDecoratorViewManagerSpec.java @@ -0,0 +1,24 @@ +package com.expensify.livemarkdown; + +import android.view.View; + +import androidx.annotation.Nullable; + +import com.facebook.react.uimanager.SimpleViewManager; +import com.facebook.react.uimanager.ViewManagerDelegate; +import com.facebook.react.viewmanagers.MarkdownTextInputDecoratorViewManagerDelegate; +import com.facebook.react.viewmanagers.MarkdownTextInputDecoratorViewManagerInterface; + +public abstract class MarkdownTextInputDecoratorViewManagerSpec extends SimpleViewManager implements MarkdownTextInputDecoratorViewManagerInterface { + private final ViewManagerDelegate mDelegate; + + public MarkdownTextInputDecoratorViewManagerSpec() { + mDelegate = new MarkdownTextInputDecoratorViewManagerDelegate(this); + } + + @Nullable + @Override + protected ViewManagerDelegate getDelegate() { + return mDelegate; + } +} diff --git a/android/src/newarch/MarkdownTextInputViewManagerSpec.java b/android/src/newarch/MarkdownTextInputViewManagerSpec.java deleted file mode 100644 index 281bd3cb1..000000000 --- a/android/src/newarch/MarkdownTextInputViewManagerSpec.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.markdowntextinput; - -import android.view.View; - -import androidx.annotation.Nullable; - -import com.facebook.react.uimanager.SimpleViewManager; -import com.facebook.react.uimanager.ViewManagerDelegate; -import com.facebook.react.viewmanagers.MarkdownTextInputViewManagerDelegate; -import com.facebook.react.viewmanagers.MarkdownTextInputViewManagerInterface; - -public abstract class MarkdownTextInputViewManagerSpec extends SimpleViewManager implements MarkdownTextInputViewManagerInterface { - private final ViewManagerDelegate mDelegate; - - public MarkdownTextInputViewManagerSpec() { - mDelegate = new MarkdownTextInputViewManagerDelegate(this); - } - - @Nullable - @Override - protected ViewManagerDelegate getDelegate() { - return mDelegate; - } -} diff --git a/android/src/oldarch/MarkdownTextInputViewManagerSpec.java b/android/src/oldarch/MarkdownTextInputDecoratorViewManagerSpec.java similarity index 57% rename from android/src/oldarch/MarkdownTextInputViewManagerSpec.java rename to android/src/oldarch/MarkdownTextInputDecoratorViewManagerSpec.java index c4c1af924..48306ffae 100644 --- a/android/src/oldarch/MarkdownTextInputViewManagerSpec.java +++ b/android/src/oldarch/MarkdownTextInputDecoratorViewManagerSpec.java @@ -1,10 +1,10 @@ -package com.markdowntextinput; +package com.expensify.livemarkdown; import android.view.View; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.uimanager.SimpleViewManager; -public abstract class MarkdownTextInputViewManagerSpec extends SimpleViewManager { +public abstract class MarkdownTextInputDecoratorViewManagerSpec extends SimpleViewManager { public abstract void setMarkdownStyle(T view, ReadableMap value); } diff --git a/babel.config.js b/babel.config.js index f842b77fc..108519000 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,3 +1,15 @@ -module.exports = { - presets: ['module:metro-react-native-babel-preset'], +module.exports = (api) => { + const isWeb = api.caller((caller) => caller && caller.target === 'web'); + if (isWeb) { + return { + // Default browser list is a reasonable preset covering a wide list of non-dead browsers + // https://github.com/browserslist/browserslist#best-practices + targets: 'defaults', + presets: ['@babel/preset-env', '@babel/preset-react'], + }; + } + + return { + presets: ['module:metro-react-native-babel-preset'], + }; }; diff --git a/example/README.md b/example/README.md index 12470c30e..8bd066df0 100644 --- a/example/README.md +++ b/example/README.md @@ -2,7 +2,7 @@ This is a new [**React Native**](https://reactnative.dev) project, bootstrapped # Getting Started ->**Note**: Make sure you have completed the [React Native - Environment Setup](https://reactnative.dev/docs/environment-setup) instructions till "Creating a new application" step, before proceeding. +> **Note**: Make sure you have completed the [React Native - Environment Setup](https://reactnative.dev/docs/environment-setup) instructions till "Creating a new application" step, before proceeding. ## Step 1: Start the Metro Server diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index ccbe89a8a..8c9f4be17 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -73,9 +73,9 @@ android { compileSdkVersion rootProject.ext.compileSdkVersion - namespace "com.markdowntextinputexample" + namespace "com.expensify.livemarkdownexample" defaultConfig { - applicationId "com.markdowntextinputexample" + applicationId "com.expensify.livemarkdownexample" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionCode 1 diff --git a/example/android/app/src/debug/java/com/markdowntextinputexample/ReactNativeFlipper.java b/example/android/app/src/debug/java/com/livemarkdownexample/ReactNativeFlipper.java similarity index 98% rename from example/android/app/src/debug/java/com/markdowntextinputexample/ReactNativeFlipper.java rename to example/android/app/src/debug/java/com/livemarkdownexample/ReactNativeFlipper.java index b8a8d1aba..89dc1fb11 100644 --- a/example/android/app/src/debug/java/com/markdowntextinputexample/ReactNativeFlipper.java +++ b/example/android/app/src/debug/java/com/livemarkdownexample/ReactNativeFlipper.java @@ -4,7 +4,7 @@ *

This source code is licensed under the MIT license found in the LICENSE file in the root * directory of this source tree. */ -package com.markdowntextinputexample; +package com.expensify.livemarkdownexample; import android.content.Context; import com.facebook.flipper.android.AndroidFlipperClient; diff --git a/example/android/app/src/main/java/com/markdowntextinputexample/MainActivity.java b/example/android/app/src/main/java/com/livemarkdownexample/MainActivity.java similarity index 93% rename from example/android/app/src/main/java/com/markdowntextinputexample/MainActivity.java rename to example/android/app/src/main/java/com/livemarkdownexample/MainActivity.java index bc79aa1f9..c60781cad 100644 --- a/example/android/app/src/main/java/com/markdowntextinputexample/MainActivity.java +++ b/example/android/app/src/main/java/com/livemarkdownexample/MainActivity.java @@ -1,4 +1,4 @@ -package com.markdowntextinputexample; +package com.expensify.livemarkdownexample; import com.facebook.react.ReactActivity; import com.facebook.react.ReactActivityDelegate; @@ -13,7 +13,7 @@ public class MainActivity extends ReactActivity { */ @Override protected String getMainComponentName() { - return "MarkdownTextInputExample"; + return "LiveMarkdownExample"; } /** diff --git a/example/android/app/src/main/java/com/markdowntextinputexample/MainApplication.java b/example/android/app/src/main/java/com/livemarkdownexample/MainApplication.java similarity index 97% rename from example/android/app/src/main/java/com/markdowntextinputexample/MainApplication.java rename to example/android/app/src/main/java/com/livemarkdownexample/MainApplication.java index 2082ac47d..58a729cd1 100644 --- a/example/android/app/src/main/java/com/markdowntextinputexample/MainApplication.java +++ b/example/android/app/src/main/java/com/livemarkdownexample/MainApplication.java @@ -1,4 +1,4 @@ -package com.markdowntextinputexample; +package com.expensify.livemarkdownexample; import android.app.Application; import com.facebook.react.PackageList; diff --git a/example/android/app/src/main/res/values/strings.xml b/example/android/app/src/main/res/values/strings.xml index bde383505..eafd5276c 100644 --- a/example/android/app/src/main/res/values/strings.xml +++ b/example/android/app/src/main/res/values/strings.xml @@ -1,3 +1,3 @@ - MarkdownTextInputExample + LiveMarkdownExample diff --git a/example/android/app/src/release/java/com/markdowntextinputexample/ReactNativeFlipper.java b/example/android/app/src/release/java/com/livemarkdownexample/ReactNativeFlipper.java similarity index 93% rename from example/android/app/src/release/java/com/markdowntextinputexample/ReactNativeFlipper.java rename to example/android/app/src/release/java/com/livemarkdownexample/ReactNativeFlipper.java index 92f0b141f..5dac1fc60 100644 --- a/example/android/app/src/release/java/com/markdowntextinputexample/ReactNativeFlipper.java +++ b/example/android/app/src/release/java/com/livemarkdownexample/ReactNativeFlipper.java @@ -4,7 +4,7 @@ *

This source code is licensed under the MIT license found in the LICENSE file in the root * directory of this source tree. */ -package com.markdowntextinputexample; +package com.expensify.livemarkdownexample; import android.content.Context; import com.facebook.react.ReactInstanceManager; diff --git a/example/android/settings.gradle b/example/android/settings.gradle index a500e2b70..48643a6f2 100644 --- a/example/android/settings.gradle +++ b/example/android/settings.gradle @@ -1,4 +1,4 @@ -rootProject.name = 'MarkdownTextInputExample' +rootProject.name = 'LiveMarkdownExample' apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) include ':app' includeBuild('../node_modules/@react-native/gradle-plugin') diff --git a/example/app.json b/example/app.json index 723e08cab..9dacced4f 100644 --- a/example/app.json +++ b/example/app.json @@ -1,4 +1,4 @@ { - "name": "MarkdownTextInputExample", - "displayName": "MarkdownTextInputExample" + "name": "LiveMarkdownExample", + "displayName": "LiveMarkdownExample" } diff --git a/example/index.js b/example/index.js deleted file mode 100644 index 117ddcae4..000000000 --- a/example/index.js +++ /dev/null @@ -1,5 +0,0 @@ -import { AppRegistry } from 'react-native'; -import App from './src/App'; -import { name as appName } from './app.json'; - -AppRegistry.registerComponent(appName, () => App); diff --git a/example/index.ts b/example/index.ts new file mode 100644 index 000000000..ef707c254 --- /dev/null +++ b/example/index.ts @@ -0,0 +1,5 @@ +import {AppRegistry} from 'react-native'; +import App from './src/App'; +import {name as appName} from './app.json'; + +AppRegistry.registerComponent(appName, () => App); diff --git a/example/ios/File.swift b/example/ios/File.swift index 80a228ebc..56f52a634 100644 --- a/example/ios/File.swift +++ b/example/ios/File.swift @@ -1,6 +1,6 @@ // // File.swift -// MarkdownTextInputExample +// LiveMarkdownExample // import Foundation diff --git a/example/ios/MarkdownTextInputExample-Bridging-Header.h b/example/ios/LiveMarkdownExample-Bridging-Header.h similarity index 100% rename from example/ios/MarkdownTextInputExample-Bridging-Header.h rename to example/ios/LiveMarkdownExample-Bridging-Header.h diff --git a/example/ios/MarkdownTextInputExample.xcodeproj/project.pbxproj b/example/ios/LiveMarkdownExample.xcodeproj/project.pbxproj similarity index 68% rename from example/ios/MarkdownTextInputExample.xcodeproj/project.pbxproj rename to example/ios/LiveMarkdownExample.xcodeproj/project.pbxproj index a642d88c4..228c722f4 100644 --- a/example/ios/MarkdownTextInputExample.xcodeproj/project.pbxproj +++ b/example/ios/LiveMarkdownExample.xcodeproj/project.pbxproj @@ -7,12 +7,12 @@ objects = { /* Begin PBXBuildFile section */ - 00E356F31AD99517003FC87E /* MarkdownTextInputExampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* MarkdownTextInputExampleTests.m */; }; - 0C80B921A6F3F58F76C31292 /* libPods-MarkdownTextInputExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DCACB8F33CDC322A6C60F78 /* libPods-MarkdownTextInputExample.a */; }; + 00E356F31AD99517003FC87E /* LiveMarkdownExampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* LiveMarkdownExampleTests.m */; }; + 0C80B921A6F3F58F76C31292 /* libPods-LiveMarkdownExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DCACB8F33CDC322A6C60F78 /* libPods-LiveMarkdownExample.a */; }; 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; }; 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; - 7699B88040F8A987B510C191 /* libPods-MarkdownTextInputExample-MarkdownTextInputExampleTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 19F6CBCC0A4E27FBF8BF4A61 /* libPods-MarkdownTextInputExample-MarkdownTextInputExampleTests.a */; }; + 7699B88040F8A987B510C191 /* libPods-LiveMarkdownExample-LiveMarkdownExampleTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 19F6CBCC0A4E27FBF8BF4A61 /* libPods-LiveMarkdownExample-LiveMarkdownExampleTests.a */; }; 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; /* End PBXBuildFile section */ @@ -22,27 +22,27 @@ containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */; proxyType = 1; remoteGlobalIDString = 13B07F861A680F5B00A75B9A; - remoteInfo = MarkdownTextInputExample; + remoteInfo = LiveMarkdownExample; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - 00E356EE1AD99517003FC87E /* MarkdownTextInputExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MarkdownTextInputExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 00E356EE1AD99517003FC87E /* LiveMarkdownExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = LiveMarkdownExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 00E356F21AD99517003FC87E /* MarkdownTextInputExampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MarkdownTextInputExampleTests.m; sourceTree = ""; }; - 13B07F961A680F5B00A75B9A /* MarkdownTextInputExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MarkdownTextInputExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = MarkdownTextInputExample/AppDelegate.h; sourceTree = ""; }; - 13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = MarkdownTextInputExample/AppDelegate.mm; sourceTree = ""; }; - 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = MarkdownTextInputExample/Images.xcassets; sourceTree = ""; }; - 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = MarkdownTextInputExample/Info.plist; sourceTree = ""; }; - 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = MarkdownTextInputExample/main.m; sourceTree = ""; }; - 19F6CBCC0A4E27FBF8BF4A61 /* libPods-MarkdownTextInputExample-MarkdownTextInputExampleTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-MarkdownTextInputExample-MarkdownTextInputExampleTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 3B4392A12AC88292D35C810B /* Pods-MarkdownTextInputExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MarkdownTextInputExample.debug.xcconfig"; path = "Target Support Files/Pods-MarkdownTextInputExample/Pods-MarkdownTextInputExample.debug.xcconfig"; sourceTree = ""; }; - 5709B34CF0A7D63546082F79 /* Pods-MarkdownTextInputExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MarkdownTextInputExample.release.xcconfig"; path = "Target Support Files/Pods-MarkdownTextInputExample/Pods-MarkdownTextInputExample.release.xcconfig"; sourceTree = ""; }; - 5B7EB9410499542E8C5724F5 /* Pods-MarkdownTextInputExample-MarkdownTextInputExampleTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MarkdownTextInputExample-MarkdownTextInputExampleTests.debug.xcconfig"; path = "Target Support Files/Pods-MarkdownTextInputExample-MarkdownTextInputExampleTests/Pods-MarkdownTextInputExample-MarkdownTextInputExampleTests.debug.xcconfig"; sourceTree = ""; }; - 5DCACB8F33CDC322A6C60F78 /* libPods-MarkdownTextInputExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-MarkdownTextInputExample.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = MarkdownTextInputExample/LaunchScreen.storyboard; sourceTree = ""; }; - 89C6BE57DB24E9ADA2F236DE /* Pods-MarkdownTextInputExample-MarkdownTextInputExampleTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MarkdownTextInputExample-MarkdownTextInputExampleTests.release.xcconfig"; path = "Target Support Files/Pods-MarkdownTextInputExample-MarkdownTextInputExampleTests/Pods-MarkdownTextInputExample-MarkdownTextInputExampleTests.release.xcconfig"; sourceTree = ""; }; + 00E356F21AD99517003FC87E /* LiveMarkdownExampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LiveMarkdownExampleTests.m; sourceTree = ""; }; + 13B07F961A680F5B00A75B9A /* LiveMarkdownExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LiveMarkdownExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = LiveMarkdownExample/AppDelegate.h; sourceTree = ""; }; + 13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = LiveMarkdownExample/AppDelegate.mm; sourceTree = ""; }; + 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = LiveMarkdownExample/Images.xcassets; sourceTree = ""; }; + 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = LiveMarkdownExample/Info.plist; sourceTree = ""; }; + 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = LiveMarkdownExample/main.m; sourceTree = ""; }; + 19F6CBCC0A4E27FBF8BF4A61 /* libPods-LiveMarkdownExample-LiveMarkdownExampleTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-LiveMarkdownExample-LiveMarkdownExampleTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 3B4392A12AC88292D35C810B /* Pods-LiveMarkdownExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LiveMarkdownExample.debug.xcconfig"; path = "Target Support Files/Pods-LiveMarkdownExample/Pods-LiveMarkdownExample.debug.xcconfig"; sourceTree = ""; }; + 5709B34CF0A7D63546082F79 /* Pods-LiveMarkdownExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LiveMarkdownExample.release.xcconfig"; path = "Target Support Files/Pods-LiveMarkdownExample/Pods-LiveMarkdownExample.release.xcconfig"; sourceTree = ""; }; + 5B7EB9410499542E8C5724F5 /* Pods-LiveMarkdownExample-LiveMarkdownExampleTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LiveMarkdownExample-LiveMarkdownExampleTests.debug.xcconfig"; path = "Target Support Files/Pods-LiveMarkdownExample-LiveMarkdownExampleTests/Pods-LiveMarkdownExample-LiveMarkdownExampleTests.debug.xcconfig"; sourceTree = ""; }; + 5DCACB8F33CDC322A6C60F78 /* libPods-LiveMarkdownExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-LiveMarkdownExample.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = LiveMarkdownExample/LaunchScreen.storyboard; sourceTree = ""; }; + 89C6BE57DB24E9ADA2F236DE /* Pods-LiveMarkdownExample-LiveMarkdownExampleTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LiveMarkdownExample-LiveMarkdownExampleTests.release.xcconfig"; path = "Target Support Files/Pods-LiveMarkdownExample-LiveMarkdownExampleTests/Pods-LiveMarkdownExample-LiveMarkdownExampleTests.release.xcconfig"; sourceTree = ""; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; /* End PBXFileReference section */ @@ -51,7 +51,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 7699B88040F8A987B510C191 /* libPods-MarkdownTextInputExample-MarkdownTextInputExampleTests.a in Frameworks */, + 7699B88040F8A987B510C191 /* libPods-LiveMarkdownExample-LiveMarkdownExampleTests.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -59,20 +59,20 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 0C80B921A6F3F58F76C31292 /* libPods-MarkdownTextInputExample.a in Frameworks */, + 0C80B921A6F3F58F76C31292 /* libPods-LiveMarkdownExample.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 00E356EF1AD99517003FC87E /* MarkdownTextInputExampleTests */ = { + 00E356EF1AD99517003FC87E /* LiveMarkdownExampleTests */ = { isa = PBXGroup; children = ( - 00E356F21AD99517003FC87E /* MarkdownTextInputExampleTests.m */, + 00E356F21AD99517003FC87E /* LiveMarkdownExampleTests.m */, 00E356F01AD99517003FC87E /* Supporting Files */, ); - path = MarkdownTextInputExampleTests; + path = LiveMarkdownExampleTests; sourceTree = ""; }; 00E356F01AD99517003FC87E /* Supporting Files */ = { @@ -83,7 +83,7 @@ name = "Supporting Files"; sourceTree = ""; }; - 13B07FAE1A68108700A75B9A /* MarkdownTextInputExample */ = { + 13B07FAE1A68108700A75B9A /* LiveMarkdownExample */ = { isa = PBXGroup; children = ( 13B07FAF1A68108700A75B9A /* AppDelegate.h */, @@ -93,15 +93,15 @@ 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */, 13B07FB71A68108700A75B9A /* main.m */, ); - name = MarkdownTextInputExample; + name = LiveMarkdownExample; sourceTree = ""; }; 2D16E6871FA4F8E400B85C8A /* Frameworks */ = { isa = PBXGroup; children = ( ED297162215061F000B7C4FE /* JavaScriptCore.framework */, - 5DCACB8F33CDC322A6C60F78 /* libPods-MarkdownTextInputExample.a */, - 19F6CBCC0A4E27FBF8BF4A61 /* libPods-MarkdownTextInputExample-MarkdownTextInputExampleTests.a */, + 5DCACB8F33CDC322A6C60F78 /* libPods-LiveMarkdownExample.a */, + 19F6CBCC0A4E27FBF8BF4A61 /* libPods-LiveMarkdownExample-LiveMarkdownExampleTests.a */, ); name = Frameworks; sourceTree = ""; @@ -116,9 +116,9 @@ 83CBB9F61A601CBA00E9B192 = { isa = PBXGroup; children = ( - 13B07FAE1A68108700A75B9A /* MarkdownTextInputExample */, + 13B07FAE1A68108700A75B9A /* LiveMarkdownExample */, 832341AE1AAA6A7D00B99B32 /* Libraries */, - 00E356EF1AD99517003FC87E /* MarkdownTextInputExampleTests */, + 00E356EF1AD99517003FC87E /* LiveMarkdownExampleTests */, 83CBBA001A601CBA00E9B192 /* Products */, 2D16E6871FA4F8E400B85C8A /* Frameworks */, BBD78D7AC51CEA395F1C20DB /* Pods */, @@ -131,8 +131,8 @@ 83CBBA001A601CBA00E9B192 /* Products */ = { isa = PBXGroup; children = ( - 13B07F961A680F5B00A75B9A /* MarkdownTextInputExample.app */, - 00E356EE1AD99517003FC87E /* MarkdownTextInputExampleTests.xctest */, + 13B07F961A680F5B00A75B9A /* LiveMarkdownExample.app */, + 00E356EE1AD99517003FC87E /* LiveMarkdownExampleTests.xctest */, ); name = Products; sourceTree = ""; @@ -140,10 +140,10 @@ BBD78D7AC51CEA395F1C20DB /* Pods */ = { isa = PBXGroup; children = ( - 3B4392A12AC88292D35C810B /* Pods-MarkdownTextInputExample.debug.xcconfig */, - 5709B34CF0A7D63546082F79 /* Pods-MarkdownTextInputExample.release.xcconfig */, - 5B7EB9410499542E8C5724F5 /* Pods-MarkdownTextInputExample-MarkdownTextInputExampleTests.debug.xcconfig */, - 89C6BE57DB24E9ADA2F236DE /* Pods-MarkdownTextInputExample-MarkdownTextInputExampleTests.release.xcconfig */, + 3B4392A12AC88292D35C810B /* Pods-LiveMarkdownExample.debug.xcconfig */, + 5709B34CF0A7D63546082F79 /* Pods-LiveMarkdownExample.release.xcconfig */, + 5B7EB9410499542E8C5724F5 /* Pods-LiveMarkdownExample-LiveMarkdownExampleTests.debug.xcconfig */, + 89C6BE57DB24E9ADA2F236DE /* Pods-LiveMarkdownExample-LiveMarkdownExampleTests.release.xcconfig */, ); path = Pods; sourceTree = ""; @@ -151,9 +151,9 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - 00E356ED1AD99517003FC87E /* MarkdownTextInputExampleTests */ = { + 00E356ED1AD99517003FC87E /* LiveMarkdownExampleTests */ = { isa = PBXNativeTarget; - buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "MarkdownTextInputExampleTests" */; + buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "LiveMarkdownExampleTests" */; buildPhases = ( A55EABD7B0C7F3A422A6CC61 /* [CP] Check Pods Manifest.lock */, 00E356EA1AD99517003FC87E /* Sources */, @@ -167,14 +167,14 @@ dependencies = ( 00E356F51AD99517003FC87E /* PBXTargetDependency */, ); - name = MarkdownTextInputExampleTests; - productName = MarkdownTextInputExampleTests; - productReference = 00E356EE1AD99517003FC87E /* MarkdownTextInputExampleTests.xctest */; + name = LiveMarkdownExampleTests; + productName = LiveMarkdownExampleTests; + productReference = 00E356EE1AD99517003FC87E /* LiveMarkdownExampleTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; - 13B07F861A680F5B00A75B9A /* MarkdownTextInputExample */ = { + 13B07F861A680F5B00A75B9A /* LiveMarkdownExample */ = { isa = PBXNativeTarget; - buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "MarkdownTextInputExample" */; + buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "LiveMarkdownExample" */; buildPhases = ( C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */, FD10A7F022414F080027D42C /* Start Packager */, @@ -189,9 +189,9 @@ ); dependencies = ( ); - name = MarkdownTextInputExample; - productName = MarkdownTextInputExample; - productReference = 13B07F961A680F5B00A75B9A /* MarkdownTextInputExample.app */; + name = LiveMarkdownExample; + productName = LiveMarkdownExample; + productReference = 13B07F961A680F5B00A75B9A /* LiveMarkdownExample.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ @@ -211,7 +211,7 @@ }; }; }; - buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "MarkdownTextInputExample" */; + buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "LiveMarkdownExample" */; compatibilityVersion = "Xcode 12.0"; developmentRegion = en; hasScannedForEncodings = 0; @@ -224,8 +224,8 @@ projectDirPath = ""; projectRoot = ""; targets = ( - 13B07F861A680F5B00A75B9A /* MarkdownTextInputExample */, - 00E356ED1AD99517003FC87E /* MarkdownTextInputExampleTests */, + 13B07F861A680F5B00A75B9A /* LiveMarkdownExample */, + 00E356ED1AD99517003FC87E /* LiveMarkdownExampleTests */, ); }; /* End PBXProject section */ @@ -272,15 +272,15 @@ files = ( ); inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-MarkdownTextInputExample/Pods-MarkdownTextInputExample-frameworks-${CONFIGURATION}-input-files.xcfilelist", + "${PODS_ROOT}/Target Support Files/Pods-LiveMarkdownExample/Pods-LiveMarkdownExample-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-MarkdownTextInputExample/Pods-MarkdownTextInputExample-frameworks-${CONFIGURATION}-output-files.xcfilelist", + "${PODS_ROOT}/Target Support Files/Pods-LiveMarkdownExample/Pods-LiveMarkdownExample-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-MarkdownTextInputExample/Pods-MarkdownTextInputExample-frameworks.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-LiveMarkdownExample/Pods-LiveMarkdownExample-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; A55EABD7B0C7F3A422A6CC61 /* [CP] Check Pods Manifest.lock */ = { @@ -298,7 +298,7 @@ outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-MarkdownTextInputExample-MarkdownTextInputExampleTests-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-LiveMarkdownExample-LiveMarkdownExampleTests-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -320,7 +320,7 @@ outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-MarkdownTextInputExample-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-LiveMarkdownExample-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -333,15 +333,15 @@ files = ( ); inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-MarkdownTextInputExample-MarkdownTextInputExampleTests/Pods-MarkdownTextInputExample-MarkdownTextInputExampleTests-frameworks-${CONFIGURATION}-input-files.xcfilelist", + "${PODS_ROOT}/Target Support Files/Pods-LiveMarkdownExample-LiveMarkdownExampleTests/Pods-LiveMarkdownExample-LiveMarkdownExampleTests-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-MarkdownTextInputExample-MarkdownTextInputExampleTests/Pods-MarkdownTextInputExample-MarkdownTextInputExampleTests-frameworks-${CONFIGURATION}-output-files.xcfilelist", + "${PODS_ROOT}/Target Support Files/Pods-LiveMarkdownExample-LiveMarkdownExampleTests/Pods-LiveMarkdownExample-LiveMarkdownExampleTests-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-MarkdownTextInputExample-MarkdownTextInputExampleTests/Pods-MarkdownTextInputExample-MarkdownTextInputExampleTests-frameworks.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-LiveMarkdownExample-LiveMarkdownExampleTests/Pods-LiveMarkdownExample-LiveMarkdownExampleTests-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; E235C05ADACE081382539298 /* [CP] Copy Pods Resources */ = { @@ -350,15 +350,15 @@ files = ( ); inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-MarkdownTextInputExample/Pods-MarkdownTextInputExample-resources-${CONFIGURATION}-input-files.xcfilelist", + "${PODS_ROOT}/Target Support Files/Pods-LiveMarkdownExample/Pods-LiveMarkdownExample-resources-${CONFIGURATION}-input-files.xcfilelist", ); name = "[CP] Copy Pods Resources"; outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-MarkdownTextInputExample/Pods-MarkdownTextInputExample-resources-${CONFIGURATION}-output-files.xcfilelist", + "${PODS_ROOT}/Target Support Files/Pods-LiveMarkdownExample/Pods-LiveMarkdownExample-resources-${CONFIGURATION}-output-files.xcfilelist", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-MarkdownTextInputExample/Pods-MarkdownTextInputExample-resources.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-LiveMarkdownExample/Pods-LiveMarkdownExample-resources.sh\"\n"; showEnvVarsInLog = 0; }; F6A41C54EA430FDDC6A6ED99 /* [CP] Copy Pods Resources */ = { @@ -367,15 +367,15 @@ files = ( ); inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-MarkdownTextInputExample-MarkdownTextInputExampleTests/Pods-MarkdownTextInputExample-MarkdownTextInputExampleTests-resources-${CONFIGURATION}-input-files.xcfilelist", + "${PODS_ROOT}/Target Support Files/Pods-LiveMarkdownExample-LiveMarkdownExampleTests/Pods-LiveMarkdownExample-LiveMarkdownExampleTests-resources-${CONFIGURATION}-input-files.xcfilelist", ); name = "[CP] Copy Pods Resources"; outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-MarkdownTextInputExample-MarkdownTextInputExampleTests/Pods-MarkdownTextInputExample-MarkdownTextInputExampleTests-resources-${CONFIGURATION}-output-files.xcfilelist", + "${PODS_ROOT}/Target Support Files/Pods-LiveMarkdownExample-LiveMarkdownExampleTests/Pods-LiveMarkdownExample-LiveMarkdownExampleTests-resources-${CONFIGURATION}-output-files.xcfilelist", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-MarkdownTextInputExample-MarkdownTextInputExampleTests/Pods-MarkdownTextInputExample-MarkdownTextInputExampleTests-resources.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-LiveMarkdownExample-LiveMarkdownExampleTests/Pods-LiveMarkdownExample-LiveMarkdownExampleTests-resources.sh\"\n"; showEnvVarsInLog = 0; }; FD10A7F022414F080027D42C /* Start Packager */ = { @@ -404,7 +404,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 00E356F31AD99517003FC87E /* MarkdownTextInputExampleTests.m in Sources */, + 00E356F31AD99517003FC87E /* LiveMarkdownExampleTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -422,7 +422,7 @@ /* Begin PBXTargetDependency section */ 00E356F51AD99517003FC87E /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 13B07F861A680F5B00A75B9A /* MarkdownTextInputExample */; + target = 13B07F861A680F5B00A75B9A /* LiveMarkdownExample */; targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ @@ -430,14 +430,14 @@ /* Begin XCBuildConfiguration section */ 00E356F61AD99517003FC87E /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 5B7EB9410499542E8C5724F5 /* Pods-MarkdownTextInputExample-MarkdownTextInputExampleTests.debug.xcconfig */; + baseConfigurationReference = 5B7EB9410499542E8C5724F5 /* Pods-LiveMarkdownExample-LiveMarkdownExampleTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); - INFOPLIST_FILE = MarkdownTextInputExampleTests/Info.plist; + INFOPLIST_FILE = LiveMarkdownExampleTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 12.4; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -449,19 +449,19 @@ "-lc++", "$(inherited)", ); - PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_BUNDLE_IDENTIFIER = "com.expensify.livemarkdown.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MarkdownTextInputExample.app/MarkdownTextInputExample"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/LiveMarkdownExample.app/LiveMarkdownExample"; }; name = Debug; }; 00E356F71AD99517003FC87E /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 89C6BE57DB24E9ADA2F236DE /* Pods-MarkdownTextInputExample-MarkdownTextInputExampleTests.release.xcconfig */; + baseConfigurationReference = 89C6BE57DB24E9ADA2F236DE /* Pods-LiveMarkdownExample-LiveMarkdownExampleTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; COPY_PHASE_STRIP = NO; - INFOPLIST_FILE = MarkdownTextInputExampleTests/Info.plist; + INFOPLIST_FILE = LiveMarkdownExampleTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 12.4; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -473,21 +473,21 @@ "-lc++", "$(inherited)", ); - PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_BUNDLE_IDENTIFIER = "com.expensify.livemarkdown.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MarkdownTextInputExample.app/MarkdownTextInputExample"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/LiveMarkdownExample.app/LiveMarkdownExample"; }; name = Release; }; 13B07F941A680F5B00A75B9A /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 3B4392A12AC88292D35C810B /* Pods-MarkdownTextInputExample.debug.xcconfig */; + baseConfigurationReference = 3B4392A12AC88292D35C810B /* Pods-LiveMarkdownExample.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = 1; ENABLE_BITCODE = NO; - INFOPLIST_FILE = MarkdownTextInputExample/Info.plist; + INFOPLIST_FILE = LiveMarkdownExample/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -498,8 +498,8 @@ "-ObjC", "-lc++", ); - PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = MarkdownTextInputExample; + PRODUCT_BUNDLE_IDENTIFIER = "com.expensify.livemarkdown.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = LiveMarkdownExample; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; @@ -508,12 +508,12 @@ }; 13B07F951A680F5B00A75B9A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 5709B34CF0A7D63546082F79 /* Pods-MarkdownTextInputExample.release.xcconfig */; + baseConfigurationReference = 5709B34CF0A7D63546082F79 /* Pods-LiveMarkdownExample.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CURRENT_PROJECT_VERSION = 1; - INFOPLIST_FILE = MarkdownTextInputExample/Info.plist; + INFOPLIST_FILE = LiveMarkdownExample/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -524,8 +524,8 @@ "-ObjC", "-lc++", ); - PRODUCT_BUNDLE_IDENTIFIER = "org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = MarkdownTextInputExample; + PRODUCT_BUNDLE_IDENTIFIER = "com.expensify.livemarkdown.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = LiveMarkdownExample; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; }; @@ -593,16 +593,12 @@ ); MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; - OTHER_CFLAGS = ( - "$(inherited)", - " ", - ); + OTHER_CFLAGS = "$(inherited)"; OTHER_CPLUSPLUSFLAGS = ( "$(OTHER_CFLAGS)", "-DFOLLY_NO_CONFIG", "-DFOLLY_MOBILE=1", "-DFOLLY_USE_LIBCPP=1", - " ", ); OTHER_LDFLAGS = ( "$(inherited)", @@ -671,16 +667,12 @@ "\"$(inherited)\"", ); MTL_ENABLE_DEBUG_INFO = NO; - OTHER_CFLAGS = ( - "$(inherited)", - " ", - ); + OTHER_CFLAGS = "$(inherited)"; OTHER_CPLUSPLUSFLAGS = ( "$(OTHER_CFLAGS)", "-DFOLLY_NO_CONFIG", "-DFOLLY_MOBILE=1", "-DFOLLY_USE_LIBCPP=1", - " ", ); OTHER_LDFLAGS = ( "$(inherited)", @@ -696,7 +688,7 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "MarkdownTextInputExampleTests" */ = { + 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "LiveMarkdownExampleTests" */ = { isa = XCConfigurationList; buildConfigurations = ( 00E356F61AD99517003FC87E /* Debug */, @@ -705,7 +697,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "MarkdownTextInputExample" */ = { + 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "LiveMarkdownExample" */ = { isa = XCConfigurationList; buildConfigurations = ( 13B07F941A680F5B00A75B9A /* Debug */, @@ -714,7 +706,7 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "MarkdownTextInputExample" */ = { + 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "LiveMarkdownExample" */ = { isa = XCConfigurationList; buildConfigurations = ( 83CBBA201A601CBA00E9B192 /* Debug */, diff --git a/example/ios/MarkdownTextInputExample.xcodeproj/xcshareddata/xcschemes/MarkdownTextInputExample.xcscheme b/example/ios/LiveMarkdownExample.xcodeproj/xcshareddata/xcschemes/LiveMarkdownExample.xcscheme similarity index 76% rename from example/ios/MarkdownTextInputExample.xcodeproj/xcshareddata/xcschemes/MarkdownTextInputExample.xcscheme rename to example/ios/LiveMarkdownExample.xcodeproj/xcshareddata/xcschemes/LiveMarkdownExample.xcscheme index 732f3f64c..10c3c6abb 100644 --- a/example/ios/MarkdownTextInputExample.xcodeproj/xcshareddata/xcschemes/MarkdownTextInputExample.xcscheme +++ b/example/ios/LiveMarkdownExample.xcodeproj/xcshareddata/xcschemes/LiveMarkdownExample.xcscheme @@ -15,9 +15,9 @@ + BuildableName = "LiveMarkdownExample.app" + BlueprintName = "LiveMarkdownExample" + ReferencedContainer = "container:LiveMarkdownExample.xcodeproj"> @@ -33,9 +33,9 @@ + BuildableName = "LiveMarkdownExampleTests.xctest" + BlueprintName = "LiveMarkdownExampleTests" + ReferencedContainer = "container:LiveMarkdownExample.xcodeproj"> @@ -55,9 +55,9 @@ + BuildableName = "LiveMarkdownExample.app" + BlueprintName = "LiveMarkdownExample" + ReferencedContainer = "container:LiveMarkdownExample.xcodeproj"> @@ -72,9 +72,9 @@ + BuildableName = "LiveMarkdownExample.app" + BlueprintName = "LiveMarkdownExample" + ReferencedContainer = "container:LiveMarkdownExample.xcodeproj"> diff --git a/example/ios/MarkdownTextInputExample.xcworkspace/contents.xcworkspacedata b/example/ios/LiveMarkdownExample.xcworkspace/contents.xcworkspacedata similarity index 74% rename from example/ios/MarkdownTextInputExample.xcworkspace/contents.xcworkspacedata rename to example/ios/LiveMarkdownExample.xcworkspace/contents.xcworkspacedata index 3639464bc..298568e50 100644 --- a/example/ios/MarkdownTextInputExample.xcworkspace/contents.xcworkspacedata +++ b/example/ios/LiveMarkdownExample.xcworkspace/contents.xcworkspacedata @@ -2,7 +2,7 @@ + location = "group:LiveMarkdownExample.xcodeproj"> diff --git a/example/ios/MarkdownTextInputExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/example/ios/LiveMarkdownExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist similarity index 100% rename from example/ios/MarkdownTextInputExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to example/ios/LiveMarkdownExample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/example/ios/MarkdownTextInputExample/AppDelegate.h b/example/ios/LiveMarkdownExample/AppDelegate.h similarity index 100% rename from example/ios/MarkdownTextInputExample/AppDelegate.h rename to example/ios/LiveMarkdownExample/AppDelegate.h diff --git a/example/ios/MarkdownTextInputExample/AppDelegate.mm b/example/ios/LiveMarkdownExample/AppDelegate.mm similarity index 93% rename from example/ios/MarkdownTextInputExample/AppDelegate.mm rename to example/ios/LiveMarkdownExample/AppDelegate.mm index e2bef3c12..d5473fc8c 100644 --- a/example/ios/MarkdownTextInputExample/AppDelegate.mm +++ b/example/ios/LiveMarkdownExample/AppDelegate.mm @@ -6,7 +6,7 @@ @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - self.moduleName = @"MarkdownTextInputExample"; + self.moduleName = @"LiveMarkdownExample"; // You can add your custom initial props in the dictionary below. // They will be passed down to the ViewController used by React Native. self.initialProps = @{}; diff --git a/example/ios/MarkdownTextInputExample/Images.xcassets/AppIcon.appiconset/Contents.json b/example/ios/LiveMarkdownExample/Images.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from example/ios/MarkdownTextInputExample/Images.xcassets/AppIcon.appiconset/Contents.json rename to example/ios/LiveMarkdownExample/Images.xcassets/AppIcon.appiconset/Contents.json diff --git a/example/ios/MarkdownTextInputExample/Images.xcassets/Contents.json b/example/ios/LiveMarkdownExample/Images.xcassets/Contents.json similarity index 100% rename from example/ios/MarkdownTextInputExample/Images.xcassets/Contents.json rename to example/ios/LiveMarkdownExample/Images.xcassets/Contents.json diff --git a/example/ios/MarkdownTextInputExample/Info.plist b/example/ios/LiveMarkdownExample/Info.plist similarity index 97% rename from example/ios/MarkdownTextInputExample/Info.plist rename to example/ios/LiveMarkdownExample/Info.plist index c99abc5a4..d9fe4d24c 100644 --- a/example/ios/MarkdownTextInputExample/Info.plist +++ b/example/ios/LiveMarkdownExample/Info.plist @@ -5,7 +5,7 @@ CFBundleDevelopmentRegion en CFBundleDisplayName - MarkdownTextInputExample + LiveMarkdownExample CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier diff --git a/example/ios/MarkdownTextInputExample/LaunchScreen.storyboard b/example/ios/LiveMarkdownExample/LaunchScreen.storyboard similarity index 93% rename from example/ios/MarkdownTextInputExample/LaunchScreen.storyboard rename to example/ios/LiveMarkdownExample/LaunchScreen.storyboard index e84fe190b..e7f0f4732 100644 --- a/example/ios/MarkdownTextInputExample/LaunchScreen.storyboard +++ b/example/ios/LiveMarkdownExample/LaunchScreen.storyboard @@ -16,7 +16,7 @@ -