├── .gitignore
├── LICENSE
├── Markdown.js
├── README.md
├── example
├── .babelrc
├── .buckconfig
├── .flowconfig
├── .gitignore
├── .watchmanconfig
├── __tests__
│ ├── index.android.js
│ └── index.ios.js
├── android
│ ├── app
│ │ ├── BUCK
│ │ ├── build.gradle
│ │ ├── proguard-rules.pro
│ │ └── src
│ │ │ └── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ ├── MainActivity.java
│ │ │ │ └── MainApplication.java
│ │ │ └── res
│ │ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.png
│ │ │ └── values
│ │ │ ├── strings.xml
│ │ │ └── styles.xml
│ ├── build.gradle
│ ├── gradle.properties
│ ├── gradle
│ │ └── wrapper
│ │ │ ├── gradle-wrapper.jar
│ │ │ └── gradle-wrapper.properties
│ ├── gradlew
│ ├── gradlew.bat
│ ├── keystores
│ │ ├── BUCK
│ │ └── debug.keystore.properties
│ └── settings.gradle
├── index.android.js
├── index.ios.js
├── ios
│ ├── example.xcodeproj
│ │ ├── project.pbxproj
│ │ └── xcshareddata
│ │ │ └── xcschemes
│ │ │ └── example.xcscheme
│ ├── example
│ │ ├── AppDelegate.h
│ │ ├── AppDelegate.m
│ │ ├── Base.lproj
│ │ │ └── LaunchScreen.xib
│ │ ├── Images.xcassets
│ │ │ └── AppIcon.appiconset
│ │ │ │ └── Contents.json
│ │ ├── Info.plist
│ │ └── main.m
│ └── exampleTests
│ │ ├── Info.plist
│ │ └── exampleTests.m
├── package.json
└── yarn.lock
├── lib
├── index.js
├── md.js
└── react_helpers.js
└── package.json
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 |
6 | # Runtime data
7 | pids
8 | *.pid
9 | *.seed
10 |
11 | # Directory for instrumented libs generated by jscoverage/JSCover
12 | lib-cov
13 |
14 | # Coverage directory used by tools like istanbul
15 | coverage
16 |
17 | # nyc test coverage
18 | .nyc_output
19 |
20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
21 | .grunt
22 |
23 | # node-waf configuration
24 | .lock-wscript
25 |
26 | # Compiled binary addons (http://nodejs.org/api/addons.html)
27 | build/Release
28 |
29 | # Dependency directories
30 | node_modules
31 | jspm_packages
32 |
33 | # Optional npm cache directory
34 | .npm
35 |
36 | # IDE
37 | .idea
38 |
39 | .DS_Store
40 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 Pierre Monge
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Markdown.js:
--------------------------------------------------------------------------------
1 | import React, { Component, PropTypes } from 'react';
2 | import {
3 | View,
4 | } from 'react-native';
5 | import { markdown } from './lib/index';
6 |
7 | type Props = {
8 | style: any;
9 | mdStyle: any,
10 | childre?: any;
11 | };
12 |
13 | export default class Markdown extends Component {
14 | props: Props;
15 |
16 | static propTypes = {
17 | style: View.propTypes.style,
18 | mdStyle: PropTypes.any,
19 | };
20 |
21 | componentDidMount() {
22 | if (this.props.mdStyle) {
23 | mdStyle = _.merge({}, this.props.mdStyle, mdStyle);
24 | }
25 | }
26 |
27 | render() {
28 | let text;
29 | if (typeof this.props.children === 'string') {
30 | text = this.props.children;
31 | } else if (typeof this.props.children === 'object') {
32 | text = this.props.children.join('');
33 | } else {
34 | throw 'Not supported type of text: ' + typeof this.props.children;
35 | }
36 | return (
37 |
38 | {markdown.toReact(text)}
39 |
40 | )
41 | }
42 | }
43 |
44 | // Here is the default style for markdown
45 | let mdStyle = {
46 | h: {
47 | fontWeight: '200',
48 | },
49 | h1: {
50 | fontSize: 32,
51 | },
52 | h2: {
53 | fontSize: 24,
54 | },
55 | h3: {
56 | fontSize: 18,
57 | },
58 | h4: {
59 | fontSize: 16,
60 | },
61 | h5: {
62 | fontSize: 13,
63 | },
64 | h6: {
65 | fontSize: 11,
66 | },
67 | code: {
68 | backgroundColor: '#f7f7f7',
69 | },
70 | boxPre: {
71 | backgroundColor: '#f7f7f7',
72 | },
73 | pre: {
74 | },
75 | a: {
76 | color: 'blue',
77 | },
78 | blockquote: {
79 | fontFamily: 'Courier',
80 | fontWeight: '500',
81 | color: 'grey',
82 | },
83 | blockQuotePipe: {
84 | height: 25,
85 | width: 3,
86 | marginHorizontal: 10,
87 | backgroundColor: '#dddddd',
88 | },
89 | del: {
90 | containerBackgroundColor: '#222222',
91 | },
92 | em: {
93 | fontStyle: 'italic',
94 | },
95 | strong: {
96 | fontWeight: 'bold',
97 | },
98 | li: {
99 |
100 | },
101 | liPoint: {
102 | height: 5,
103 | width: 5,
104 | borderRadius: 50,
105 | margin: 5,
106 | backgroundColor: 'black',
107 | },
108 | liOrder: {
109 | fontWeight: 'bold',
110 | paddingLeft: 5,
111 | },
112 | p: {
113 | marginTop: 10,
114 | marginBottom: 10,
115 | flexWrap: 'wrap',
116 | flexDirection: 'row',
117 | alignItems: 'flex-start',
118 | justifyContent: 'flex-start',
119 | },
120 | };
121 | export { mdStyle };
122 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-native-markdown-syntax
2 | ***
3 | This component is based on the parser [markdown-js](https://github.com/evilstreak/markdown-js).
4 |
5 | ### Installation
6 |
7 | `npm install react-native-markdown-syntax`
8 |
9 | ### Usage
10 |
11 | ```
12 | import React, { Component } from 'react';
13 | import {
14 | AppRegistry,
15 | } from 'react-native';
16 | import Markdown from 'react-native-markdown-syntax';
17 |
18 | export default class example extends Component {
19 | render() {
20 | return (
21 |
22 | {'\n\n'}
23 | Emphasis, aka italics, with *asterisks* or _underscores_.{'\n'}
24 | Strong emphasis, aka bold, with **asterisks** or __underscores__.{'\n'}
25 | Combined emphasis with **asterisks and _underscores_**.{'\n'}
26 | Inline code uses one `. `Scratch this.`{'\n'}
27 |
28 | Here comes codeblock{'\n'}
29 | > Hello
30 | __em__
31 | `inline Code` az{'\n'}{'\n'}
32 | - ul{'\n\n\n\n'}
33 | 1. ol1{'\n'}
34 | 2. ol2{'\n'}
35 | 3. ol3{'\n\n\nHere a new list\n\n'}
36 | - ulnew{'\n'}
37 | - [ ] checkbox not supported yet :/{'\n'}
38 |
39 | );
40 | }
41 | }
42 | AppRegistry.registerComponent('example', () => example);
43 | ```
44 |
45 | Based on a html parser, `react-native-markdown-syntax` support many markdown syntax, but not fully feature is implemented in react-native, here is the supported tag from web to react-native:
46 |
47 | | HTML Tag | Desc | Markdown syntax example |
48 | |------------ |---------------- |------------------------- |
49 | | h {1-6} | Header | # Hello |
50 | | strong | Bold | **Hello** |
51 | | em | Italics | _Hello_ |
52 | | p | Paragraph | Hello |
53 | | code | Code | `Hello` |
54 | | pre | Inline Code | `Hello` |
55 | | blockquote | Quote | > Hello |
56 | | ul | Unordered List | - Hello {'\n'} - Hello |
57 | | ol | Ordered List | 1. Hello {'\n'} - Hello |
58 | | li | List Item | |
59 | | br | Line Break | \n |
60 |
61 | You can pass style for each tag as mdStyle props:
62 |
63 | ```
64 | /website/.*
14 |
15 | # Ignore BUCK generated dirs
16 | /\.buckd/
17 |
18 | # Ignore unexpected extra @providesModule
19 | .*/node_modules/commoner/test/source/widget/share.js
20 |
21 | # Ignore duplicate module providers
22 | # For RN Apps installed via npm, "Libraries" folder is inside node_modules/react-native but in the source repo it is in the root
23 | .*/Libraries/react-native/React.js
24 | .*/Libraries/react-native/ReactNative.js
25 | .*/node_modules/jest-runtime/build/__tests__/.*
26 |
27 | [include]
28 |
29 | [libs]
30 | node_modules/react-native/Libraries/react-native/react-native-interface.js
31 | node_modules/react-native/flow
32 | flow/
33 |
34 | [options]
35 | module.system=haste
36 |
37 | esproposal.class_static_fields=enable
38 | esproposal.class_instance_fields=enable
39 |
40 | experimental.strict_type_args=true
41 |
42 | munge_underscores=true
43 |
44 | module.name_mapper='^image![a-zA-Z0-9$_-]+$' -> 'GlobalImageStub'
45 | module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub'
46 |
47 | suppress_type=$FlowIssue
48 | suppress_type=$FlowFixMe
49 | suppress_type=$FixMe
50 |
51 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(3[0-3]\\|[1-2][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)
52 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(3[0-3]\\|1[0-9]\\|[1-2][0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+
53 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
54 |
55 | unsafe.enable_getters_and_setters=true
56 |
57 | [version]
58 | ^0.33.0
59 |
--------------------------------------------------------------------------------
/example/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # Xcode
6 | #
7 | build/
8 | *.pbxuser
9 | !default.pbxuser
10 | *.mode1v3
11 | !default.mode1v3
12 | *.mode2v3
13 | !default.mode2v3
14 | *.perspectivev3
15 | !default.perspectivev3
16 | xcuserdata
17 | *.xccheckout
18 | *.moved-aside
19 | DerivedData
20 | *.hmap
21 | *.ipa
22 | *.xcuserstate
23 | project.xcworkspace
24 |
25 | # Android/IJ
26 | #
27 | *.iml
28 | .idea
29 | .gradle
30 | local.properties
31 |
32 | # node.js
33 | #
34 | node_modules/
35 | npm-debug.log
36 |
37 | # BUCK
38 | buck-out/
39 | \.buckd/
40 | android/app/libs
41 | android/keystores/debug.keystore
42 |
--------------------------------------------------------------------------------
/example/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/example/__tests__/index.android.js:
--------------------------------------------------------------------------------
1 | import 'react-native';
2 | import React from 'react';
3 | import Index from '../index.android.js';
4 |
5 | // Note: test renderer must be required after react-native.
6 | import renderer from 'react-test-renderer';
7 |
8 | it('renders correctly', () => {
9 | const tree = renderer.create(
10 |
11 | );
12 | });
13 |
--------------------------------------------------------------------------------
/example/__tests__/index.ios.js:
--------------------------------------------------------------------------------
1 | import 'react-native';
2 | import React from 'react';
3 | import Index from '../index.ios.js';
4 |
5 | // Note: test renderer must be required after react-native.
6 | import renderer from 'react-test-renderer';
7 |
8 | it('renders correctly', () => {
9 | const tree = renderer.create(
10 |
11 | );
12 | });
13 |
--------------------------------------------------------------------------------
/example/android/app/BUCK:
--------------------------------------------------------------------------------
1 | import re
2 |
3 | # To learn about Buck see [Docs](https://buckbuild.com/).
4 | # To run your application with Buck:
5 | # - install Buck
6 | # - `npm start` - to start the packager
7 | # - `cd android`
8 | # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"`
9 | # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck
10 | # - `buck install -r android/app` - compile, install and run application
11 | #
12 |
13 | lib_deps = []
14 | for jarfile in glob(['libs/*.jar']):
15 | name = 'jars__' + re.sub(r'^.*/([^/]+)\.jar$', r'\1', jarfile)
16 | lib_deps.append(':' + name)
17 | prebuilt_jar(
18 | name = name,
19 | binary_jar = jarfile,
20 | )
21 |
22 | for aarfile in glob(['libs/*.aar']):
23 | name = 'aars__' + re.sub(r'^.*/([^/]+)\.aar$', r'\1', aarfile)
24 | lib_deps.append(':' + name)
25 | android_prebuilt_aar(
26 | name = name,
27 | aar = aarfile,
28 | )
29 |
30 | android_library(
31 | name = 'all-libs',
32 | exported_deps = lib_deps
33 | )
34 |
35 | android_library(
36 | name = 'app-code',
37 | srcs = glob([
38 | 'src/main/java/**/*.java',
39 | ]),
40 | deps = [
41 | ':all-libs',
42 | ':build_config',
43 | ':res',
44 | ],
45 | )
46 |
47 | android_build_config(
48 | name = 'build_config',
49 | package = 'com.example',
50 | )
51 |
52 | android_resource(
53 | name = 'res',
54 | res = 'src/main/res',
55 | package = 'com.example',
56 | )
57 |
58 | android_binary(
59 | name = 'app',
60 | package_type = 'debug',
61 | manifest = 'src/main/AndroidManifest.xml',
62 | keystore = '//android/keystores:debug',
63 | deps = [
64 | ':app-code',
65 | ],
66 | )
67 |
--------------------------------------------------------------------------------
/example/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: "com.android.application"
2 |
3 | import com.android.build.OutputFile
4 |
5 | /**
6 | * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets
7 | * and bundleReleaseJsAndAssets).
8 | * These basically call `react-native bundle` with the correct arguments during the Android build
9 | * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the
10 | * bundle directly from the development server. Below you can see all the possible configurations
11 | * and their defaults. If you decide to add a configuration block, make sure to add it before the
12 | * `apply from: "../../node_modules/react-native/react.gradle"` line.
13 | *
14 | * project.ext.react = [
15 | * // the name of the generated asset file containing your JS bundle
16 | * bundleAssetName: "index.android.bundle",
17 | *
18 | * // the entry file for bundle generation
19 | * entryFile: "index.android.js",
20 | *
21 | * // whether to bundle JS and assets in debug mode
22 | * bundleInDebug: false,
23 | *
24 | * // whether to bundle JS and assets in release mode
25 | * bundleInRelease: true,
26 | *
27 | * // whether to bundle JS and assets in another build variant (if configured).
28 | * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
29 | * // The configuration property can be in the following formats
30 | * // 'bundleIn${productFlavor}${buildType}'
31 | * // 'bundleIn${buildType}'
32 | * // bundleInFreeDebug: true,
33 | * // bundleInPaidRelease: true,
34 | * // bundleInBeta: true,
35 | *
36 | * // the root of your project, i.e. where "package.json" lives
37 | * root: "../../",
38 | *
39 | * // where to put the JS bundle asset in debug mode
40 | * jsBundleDirDebug: "$buildDir/intermediates/assets/debug",
41 | *
42 | * // where to put the JS bundle asset in release mode
43 | * jsBundleDirRelease: "$buildDir/intermediates/assets/release",
44 | *
45 | * // where to put drawable resources / React Native assets, e.g. the ones you use via
46 | * // require('./image.png')), in debug mode
47 | * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug",
48 | *
49 | * // where to put drawable resources / React Native assets, e.g. the ones you use via
50 | * // require('./image.png')), in release mode
51 | * resourcesDirRelease: "$buildDir/intermediates/res/merged/release",
52 | *
53 | * // by default the gradle tasks are skipped if none of the JS files or assets change; this means
54 | * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to
55 | * // date; if you have any other folders that you want to ignore for performance reasons (gradle
56 | * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/
57 | * // for example, you might want to remove it from here.
58 | * inputExcludes: ["android/**", "ios/**"],
59 | *
60 | * // override which node gets called and with what additional arguments
61 | * nodeExecutableAndArgs: ["node"]
62 | *
63 | * // supply additional arguments to the packager
64 | * extraPackagerArgs: []
65 | * ]
66 | */
67 |
68 | apply from: "../../node_modules/react-native/react.gradle"
69 |
70 | /**
71 | * Set this to true to create two separate APKs instead of one:
72 | * - An APK that only works on ARM devices
73 | * - An APK that only works on x86 devices
74 | * The advantage is the size of the APK is reduced by about 4MB.
75 | * Upload all the APKs to the Play Store and people will download
76 | * the correct one based on the CPU architecture of their device.
77 | */
78 | def enableSeparateBuildPerCPUArchitecture = false
79 |
80 | /**
81 | * Run Proguard to shrink the Java bytecode in release builds.
82 | */
83 | def enableProguardInReleaseBuilds = false
84 |
85 | android {
86 | compileSdkVersion 23
87 | buildToolsVersion "23.0.1"
88 |
89 | defaultConfig {
90 | applicationId "com.example"
91 | minSdkVersion 16
92 | targetSdkVersion 22
93 | versionCode 1
94 | versionName "1.0"
95 | ndk {
96 | abiFilters "armeabi-v7a", "x86"
97 | }
98 | }
99 | splits {
100 | abi {
101 | reset()
102 | enable enableSeparateBuildPerCPUArchitecture
103 | universalApk false // If true, also generate a universal APK
104 | include "armeabi-v7a", "x86"
105 | }
106 | }
107 | buildTypes {
108 | release {
109 | minifyEnabled enableProguardInReleaseBuilds
110 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
111 | }
112 | }
113 | // applicationVariants are e.g. debug, release
114 | applicationVariants.all { variant ->
115 | variant.outputs.each { output ->
116 | // For each separate APK per architecture, set a unique version code as described here:
117 | // http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits
118 | def versionCodes = ["armeabi-v7a":1, "x86":2]
119 | def abi = output.getFilter(OutputFile.ABI)
120 | if (abi != null) { // null for the universal-debug, universal-release variants
121 | output.versionCodeOverride =
122 | versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
123 | }
124 | }
125 | }
126 | }
127 |
128 | dependencies {
129 | compile fileTree(dir: "libs", include: ["*.jar"])
130 | compile "com.android.support:appcompat-v7:23.0.1"
131 | compile "com.facebook.react:react-native:+" // From node_modules
132 | }
133 |
134 | // Run this once to be able to run the application with BUCK
135 | // puts all compile dependencies into folder libs for BUCK to use
136 | task copyDownloadableDepsToLibs(type: Copy) {
137 | from configurations.compile
138 | into 'libs'
139 | }
140 |
--------------------------------------------------------------------------------
/example/android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Disabling obfuscation is useful if you collect stack traces from production crashes
20 | # (unless you are using a system that supports de-obfuscate the stack traces).
21 | -dontobfuscate
22 |
23 | # React Native
24 |
25 | # Keep our interfaces so they can be used by other ProGuard rules.
26 | # See http://sourceforge.net/p/proguard/bugs/466/
27 | -keep,allowobfuscation @interface com.facebook.proguard.annotations.DoNotStrip
28 | -keep,allowobfuscation @interface com.facebook.proguard.annotations.KeepGettersAndSetters
29 | -keep,allowobfuscation @interface com.facebook.common.internal.DoNotStrip
30 |
31 | # Do not strip any method/class that is annotated with @DoNotStrip
32 | -keep @com.facebook.proguard.annotations.DoNotStrip class *
33 | -keep @com.facebook.common.internal.DoNotStrip class *
34 | -keepclassmembers class * {
35 | @com.facebook.proguard.annotations.DoNotStrip *;
36 | @com.facebook.common.internal.DoNotStrip *;
37 | }
38 |
39 | -keepclassmembers @com.facebook.proguard.annotations.KeepGettersAndSetters class * {
40 | void set*(***);
41 | *** get*();
42 | }
43 |
44 | -keep class * extends com.facebook.react.bridge.JavaScriptModule { *; }
45 | -keep class * extends com.facebook.react.bridge.NativeModule { *; }
46 | -keepclassmembers,includedescriptorclasses class * { native ; }
47 | -keepclassmembers class * { @com.facebook.react.uimanager.UIProp ; }
48 | -keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactProp ; }
49 | -keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactPropGroup ; }
50 |
51 | -dontwarn com.facebook.react.**
52 |
53 | # okhttp
54 |
55 | -keepattributes Signature
56 | -keepattributes *Annotation*
57 | -keep class okhttp3.** { *; }
58 | -keep interface okhttp3.** { *; }
59 | -dontwarn okhttp3.**
60 |
61 | # okio
62 |
63 | -keep class sun.misc.Unsafe { *; }
64 | -dontwarn java.nio.file.*
65 | -dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
66 | -dontwarn okio.**
67 |
--------------------------------------------------------------------------------
/example/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
12 |
13 |
19 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/example/android/app/src/main/java/com/example/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.example;
2 |
3 | import com.facebook.react.ReactActivity;
4 |
5 | public class MainActivity extends ReactActivity {
6 |
7 | /**
8 | * Returns the name of the main component registered from JavaScript.
9 | * This is used to schedule rendering of the component.
10 | */
11 | @Override
12 | protected String getMainComponentName() {
13 | return "example";
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/example/android/app/src/main/java/com/example/MainApplication.java:
--------------------------------------------------------------------------------
1 | package com.example;
2 |
3 | import android.app.Application;
4 | import android.util.Log;
5 |
6 | import com.facebook.react.ReactApplication;
7 | import com.facebook.react.ReactInstanceManager;
8 | import com.facebook.react.ReactNativeHost;
9 | import com.facebook.react.ReactPackage;
10 | import com.facebook.react.shell.MainReactPackage;
11 |
12 | import java.util.Arrays;
13 | import java.util.List;
14 |
15 | public class MainApplication extends Application implements ReactApplication {
16 |
17 | private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
18 | @Override
19 | protected boolean getUseDeveloperSupport() {
20 | return BuildConfig.DEBUG;
21 | }
22 |
23 | @Override
24 | protected List getPackages() {
25 | return Arrays.asList(
26 | new MainReactPackage()
27 | );
28 | }
29 | };
30 |
31 | @Override
32 | public ReactNativeHost getReactNativeHost() {
33 | return mReactNativeHost;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Liroo/react-native-markdown-syntax/7f8788c90ec3ad82ee17377b65e8a3d8f9b6a437/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Liroo/react-native-markdown-syntax/7f8788c90ec3ad82ee17377b65e8a3d8f9b6a437/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Liroo/react-native-markdown-syntax/7f8788c90ec3ad82ee17377b65e8a3d8f9b6a437/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Liroo/react-native-markdown-syntax/7f8788c90ec3ad82ee17377b65e8a3d8f9b6a437/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | example
3 |
4 |
--------------------------------------------------------------------------------
/example/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/android/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.3.1'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | mavenLocal()
18 | jcenter()
19 | maven {
20 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
21 | url "$rootDir/../node_modules/react-native/android"
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/example/android/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 |
20 | android.useDeprecatedNdk=true
21 |
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Liroo/react-native-markdown-syntax/7f8788c90ec3ad82ee17377b65e8a3d8f9b6a437/example/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/example/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | zipStoreBase=GRADLE_USER_HOME
4 | zipStorePath=wrapper/dists
5 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip
6 |
--------------------------------------------------------------------------------
/example/android/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/example/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/example/android/keystores/BUCK:
--------------------------------------------------------------------------------
1 | keystore(
2 | name = 'debug',
3 | store = 'debug.keystore',
4 | properties = 'debug.keystore.properties',
5 | visibility = [
6 | 'PUBLIC',
7 | ],
8 | )
9 |
--------------------------------------------------------------------------------
/example/android/keystores/debug.keystore.properties:
--------------------------------------------------------------------------------
1 | key.store=debug.keystore
2 | key.alias=androiddebugkey
3 | key.store.password=android
4 | key.alias.password=android
5 |
--------------------------------------------------------------------------------
/example/android/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'example'
2 |
3 | include ':app'
4 |
--------------------------------------------------------------------------------
/example/index.android.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Sample React Native App
3 | * https://github.com/facebook/react-native
4 | * @flow
5 | */
6 |
7 | import React, { Component } from 'react';
8 | import {
9 | AppRegistry,
10 | StyleSheet,
11 | Text,
12 | View
13 | } from 'react-native';
14 |
15 | export default class example extends Component {
16 | render() {
17 | return (
18 |
19 |
20 | Welcome to React Native!
21 |
22 |
23 | To get started, edit index.android.js
24 |
25 |
26 | Double tap R on your keyboard to reload,{'\n'}
27 | Shake or press menu button for dev menu
28 |
29 |
30 | );
31 | }
32 | }
33 |
34 | const styles = StyleSheet.create({
35 | container: {
36 | flex: 1,
37 | justifyContent: 'center',
38 | alignItems: 'center',
39 | backgroundColor: '#F5FCFF',
40 | },
41 | welcome: {
42 | fontSize: 20,
43 | textAlign: 'center',
44 | margin: 10,
45 | },
46 | instructions: {
47 | textAlign: 'center',
48 | color: '#333333',
49 | marginBottom: 5,
50 | },
51 | });
52 |
53 | AppRegistry.registerComponent('example', () => example);
54 |
--------------------------------------------------------------------------------
/example/index.ios.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Sample React Native App
3 | * https://github.com/facebook/react-native
4 | * @flow
5 | */
6 |
7 | import React, { Component } from 'react';
8 | import {
9 | AppRegistry,
10 | } from 'react-native';
11 | import Markdown from 'react-native-markdown-syntax';
12 |
13 | export default class example extends Component {
14 | render() {
15 | return (
16 |
17 | {'\n\n'}
18 | Emphasis, aka italics, with *asterisks* or _underscores_.{'\n'}
19 | Strong emphasis, aka bold, with **asterisks** or __underscores__.{'\n'}
20 | Combined emphasis with **asterisks and _underscores_**.{'\n'}
21 | Strikethrough uses two tildes. `Scratch this.`{'\n'}
22 | {' '}Hello World{'\n'}
23 | {'\n'}
24 | > Hello
25 | __yoloeza__
26 | `e az` az
27 | e
28 | az{'\n'}{'\n'}
29 | - ul{'\n\n\n\n'}1. ol1{'\n'}2. ol2{'\n'}3. ol3{'\n\n\nHellloooo\n\n'}- ulnew{'\n'}- [ ] checkbox{'\n'}
30 |
31 | );
32 | }
33 | }
34 | AppRegistry.registerComponent('example', () => example);
35 |
--------------------------------------------------------------------------------
/example/ios/example.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; };
11 | 00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */; };
12 | 00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */; };
13 | 00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; };
14 | 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; };
15 | 00E356F31AD99517003FC87E /* exampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* exampleTests.m */; };
16 | 133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; };
17 | 139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */; };
18 | 139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */; };
19 | 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
20 | 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
21 | 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
22 | 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
23 | 140ED2AC1D01E1AD002B40FF /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; };
24 | 146834051AC3E58100842450 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; };
25 | 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; };
26 | /* End PBXBuildFile section */
27 |
28 | /* Begin PBXContainerItemProxy section */
29 | 00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */ = {
30 | isa = PBXContainerItemProxy;
31 | containerPortal = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */;
32 | proxyType = 2;
33 | remoteGlobalIDString = 134814201AA4EA6300B7C361;
34 | remoteInfo = RCTActionSheet;
35 | };
36 | 00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */ = {
37 | isa = PBXContainerItemProxy;
38 | containerPortal = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */;
39 | proxyType = 2;
40 | remoteGlobalIDString = 134814201AA4EA6300B7C361;
41 | remoteInfo = RCTGeolocation;
42 | };
43 | 00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */ = {
44 | isa = PBXContainerItemProxy;
45 | containerPortal = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */;
46 | proxyType = 2;
47 | remoteGlobalIDString = 58B5115D1A9E6B3D00147676;
48 | remoteInfo = RCTImage;
49 | };
50 | 00C302DB1ABCB9D200DB3ED1 /* PBXContainerItemProxy */ = {
51 | isa = PBXContainerItemProxy;
52 | containerPortal = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */;
53 | proxyType = 2;
54 | remoteGlobalIDString = 58B511DB1A9E6C8500147676;
55 | remoteInfo = RCTNetwork;
56 | };
57 | 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */ = {
58 | isa = PBXContainerItemProxy;
59 | containerPortal = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */;
60 | proxyType = 2;
61 | remoteGlobalIDString = 832C81801AAF6DEF007FA2F7;
62 | remoteInfo = RCTVibration;
63 | };
64 | 00E356F41AD99517003FC87E /* PBXContainerItemProxy */ = {
65 | isa = PBXContainerItemProxy;
66 | containerPortal = 83CBB9F71A601CBA00E9B192 /* Project object */;
67 | proxyType = 1;
68 | remoteGlobalIDString = 13B07F861A680F5B00A75B9A;
69 | remoteInfo = example;
70 | };
71 | 139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */ = {
72 | isa = PBXContainerItemProxy;
73 | containerPortal = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */;
74 | proxyType = 2;
75 | remoteGlobalIDString = 134814201AA4EA6300B7C361;
76 | remoteInfo = RCTSettings;
77 | };
78 | 139FDEF31B06529B00C62182 /* PBXContainerItemProxy */ = {
79 | isa = PBXContainerItemProxy;
80 | containerPortal = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */;
81 | proxyType = 2;
82 | remoteGlobalIDString = 3C86DF461ADF2C930047B81A;
83 | remoteInfo = RCTWebSocket;
84 | };
85 | 146834031AC3E56700842450 /* PBXContainerItemProxy */ = {
86 | isa = PBXContainerItemProxy;
87 | containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
88 | proxyType = 2;
89 | remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192;
90 | remoteInfo = React;
91 | };
92 | 78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */ = {
93 | isa = PBXContainerItemProxy;
94 | containerPortal = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */;
95 | proxyType = 2;
96 | remoteGlobalIDString = 134814201AA4EA6300B7C361;
97 | remoteInfo = RCTLinking;
98 | };
99 | 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */ = {
100 | isa = PBXContainerItemProxy;
101 | containerPortal = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */;
102 | proxyType = 2;
103 | remoteGlobalIDString = 58B5119B1A9E6C1200147676;
104 | remoteInfo = RCTText;
105 | };
106 | /* End PBXContainerItemProxy section */
107 |
108 | /* Begin PBXFileReference section */
109 | 008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = main.jsbundle; path = main.jsbundle; sourceTree = ""; };
110 | 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = ../node_modules/react-native/Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj; sourceTree = ""; };
111 | 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTGeolocation.xcodeproj; path = ../node_modules/react-native/Libraries/Geolocation/RCTGeolocation.xcodeproj; sourceTree = ""; };
112 | 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = ../node_modules/react-native/Libraries/Image/RCTImage.xcodeproj; sourceTree = ""; };
113 | 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = ../node_modules/react-native/Libraries/Network/RCTNetwork.xcodeproj; sourceTree = ""; };
114 | 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = ../node_modules/react-native/Libraries/Vibration/RCTVibration.xcodeproj; sourceTree = ""; };
115 | 00E356EE1AD99517003FC87E /* exampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = exampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
116 | 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
117 | 00E356F21AD99517003FC87E /* exampleTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = exampleTests.m; sourceTree = ""; };
118 | 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTSettings.xcodeproj; path = ../node_modules/react-native/Libraries/Settings/RCTSettings.xcodeproj; sourceTree = ""; };
119 | 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocket.xcodeproj; path = ../node_modules/react-native/Libraries/WebSocket/RCTWebSocket.xcodeproj; sourceTree = ""; };
120 | 13B07F961A680F5B00A75B9A /* example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = example.app; sourceTree = BUILT_PRODUCTS_DIR; };
121 | 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = example/AppDelegate.h; sourceTree = ""; };
122 | 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = example/AppDelegate.m; sourceTree = ""; };
123 | 13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; };
124 | 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = example/Images.xcassets; sourceTree = ""; };
125 | 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = example/Info.plist; sourceTree = ""; };
126 | 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = example/main.m; sourceTree = ""; };
127 | 146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = ../node_modules/react-native/React/React.xcodeproj; sourceTree = ""; };
128 | 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTLinking.xcodeproj; path = ../node_modules/react-native/Libraries/LinkingIOS/RCTLinking.xcodeproj; sourceTree = ""; };
129 | 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = ../node_modules/react-native/Libraries/Text/RCTText.xcodeproj; sourceTree = ""; };
130 | /* End PBXFileReference section */
131 |
132 | /* Begin PBXFrameworksBuildPhase section */
133 | 00E356EB1AD99517003FC87E /* Frameworks */ = {
134 | isa = PBXFrameworksBuildPhase;
135 | buildActionMask = 2147483647;
136 | files = (
137 | 140ED2AC1D01E1AD002B40FF /* libReact.a in Frameworks */,
138 | );
139 | runOnlyForDeploymentPostprocessing = 0;
140 | };
141 | 13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
142 | isa = PBXFrameworksBuildPhase;
143 | buildActionMask = 2147483647;
144 | files = (
145 | 146834051AC3E58100842450 /* libReact.a in Frameworks */,
146 | 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */,
147 | 00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */,
148 | 00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */,
149 | 133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */,
150 | 00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */,
151 | 139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */,
152 | 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */,
153 | 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */,
154 | 139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */,
155 | );
156 | runOnlyForDeploymentPostprocessing = 0;
157 | };
158 | /* End PBXFrameworksBuildPhase section */
159 |
160 | /* Begin PBXGroup section */
161 | 00C302A81ABCB8CE00DB3ED1 /* Products */ = {
162 | isa = PBXGroup;
163 | children = (
164 | 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */,
165 | );
166 | name = Products;
167 | sourceTree = "";
168 | };
169 | 00C302B61ABCB90400DB3ED1 /* Products */ = {
170 | isa = PBXGroup;
171 | children = (
172 | 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */,
173 | );
174 | name = Products;
175 | sourceTree = "";
176 | };
177 | 00C302BC1ABCB91800DB3ED1 /* Products */ = {
178 | isa = PBXGroup;
179 | children = (
180 | 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */,
181 | );
182 | name = Products;
183 | sourceTree = "";
184 | };
185 | 00C302D41ABCB9D200DB3ED1 /* Products */ = {
186 | isa = PBXGroup;
187 | children = (
188 | 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */,
189 | );
190 | name = Products;
191 | sourceTree = "";
192 | };
193 | 00C302E01ABCB9EE00DB3ED1 /* Products */ = {
194 | isa = PBXGroup;
195 | children = (
196 | 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */,
197 | );
198 | name = Products;
199 | sourceTree = "";
200 | };
201 | 00E356EF1AD99517003FC87E /* exampleTests */ = {
202 | isa = PBXGroup;
203 | children = (
204 | 00E356F21AD99517003FC87E /* exampleTests.m */,
205 | 00E356F01AD99517003FC87E /* Supporting Files */,
206 | );
207 | path = exampleTests;
208 | sourceTree = "";
209 | };
210 | 00E356F01AD99517003FC87E /* Supporting Files */ = {
211 | isa = PBXGroup;
212 | children = (
213 | 00E356F11AD99517003FC87E /* Info.plist */,
214 | );
215 | name = "Supporting Files";
216 | sourceTree = "";
217 | };
218 | 139105B71AF99BAD00B5F7CC /* Products */ = {
219 | isa = PBXGroup;
220 | children = (
221 | 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */,
222 | );
223 | name = Products;
224 | sourceTree = "";
225 | };
226 | 139FDEE71B06529A00C62182 /* Products */ = {
227 | isa = PBXGroup;
228 | children = (
229 | 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */,
230 | );
231 | name = Products;
232 | sourceTree = "";
233 | };
234 | 13B07FAE1A68108700A75B9A /* example */ = {
235 | isa = PBXGroup;
236 | children = (
237 | 008F07F21AC5B25A0029DE68 /* main.jsbundle */,
238 | 13B07FAF1A68108700A75B9A /* AppDelegate.h */,
239 | 13B07FB01A68108700A75B9A /* AppDelegate.m */,
240 | 13B07FB51A68108700A75B9A /* Images.xcassets */,
241 | 13B07FB61A68108700A75B9A /* Info.plist */,
242 | 13B07FB11A68108700A75B9A /* LaunchScreen.xib */,
243 | 13B07FB71A68108700A75B9A /* main.m */,
244 | );
245 | name = example;
246 | sourceTree = "";
247 | };
248 | 146834001AC3E56700842450 /* Products */ = {
249 | isa = PBXGroup;
250 | children = (
251 | 146834041AC3E56700842450 /* libReact.a */,
252 | );
253 | name = Products;
254 | sourceTree = "";
255 | };
256 | 78C398B11ACF4ADC00677621 /* Products */ = {
257 | isa = PBXGroup;
258 | children = (
259 | 78C398B91ACF4ADC00677621 /* libRCTLinking.a */,
260 | );
261 | name = Products;
262 | sourceTree = "";
263 | };
264 | 832341AE1AAA6A7D00B99B32 /* Libraries */ = {
265 | isa = PBXGroup;
266 | children = (
267 | 146833FF1AC3E56700842450 /* React.xcodeproj */,
268 | 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */,
269 | 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */,
270 | 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */,
271 | 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */,
272 | 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */,
273 | 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */,
274 | 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */,
275 | 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */,
276 | 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */,
277 | );
278 | name = Libraries;
279 | sourceTree = "";
280 | };
281 | 832341B11AAA6A8300B99B32 /* Products */ = {
282 | isa = PBXGroup;
283 | children = (
284 | 832341B51AAA6A8300B99B32 /* libRCTText.a */,
285 | );
286 | name = Products;
287 | sourceTree = "";
288 | };
289 | 83CBB9F61A601CBA00E9B192 = {
290 | isa = PBXGroup;
291 | children = (
292 | 13B07FAE1A68108700A75B9A /* example */,
293 | 832341AE1AAA6A7D00B99B32 /* Libraries */,
294 | 00E356EF1AD99517003FC87E /* exampleTests */,
295 | 83CBBA001A601CBA00E9B192 /* Products */,
296 | );
297 | indentWidth = 2;
298 | sourceTree = "";
299 | tabWidth = 2;
300 | };
301 | 83CBBA001A601CBA00E9B192 /* Products */ = {
302 | isa = PBXGroup;
303 | children = (
304 | 13B07F961A680F5B00A75B9A /* example.app */,
305 | 00E356EE1AD99517003FC87E /* exampleTests.xctest */,
306 | );
307 | name = Products;
308 | sourceTree = "";
309 | };
310 | /* End PBXGroup section */
311 |
312 | /* Begin PBXNativeTarget section */
313 | 00E356ED1AD99517003FC87E /* exampleTests */ = {
314 | isa = PBXNativeTarget;
315 | buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "exampleTests" */;
316 | buildPhases = (
317 | 00E356EA1AD99517003FC87E /* Sources */,
318 | 00E356EB1AD99517003FC87E /* Frameworks */,
319 | 00E356EC1AD99517003FC87E /* Resources */,
320 | );
321 | buildRules = (
322 | );
323 | dependencies = (
324 | 00E356F51AD99517003FC87E /* PBXTargetDependency */,
325 | );
326 | name = exampleTests;
327 | productName = exampleTests;
328 | productReference = 00E356EE1AD99517003FC87E /* exampleTests.xctest */;
329 | productType = "com.apple.product-type.bundle.unit-test";
330 | };
331 | 13B07F861A680F5B00A75B9A /* example */ = {
332 | isa = PBXNativeTarget;
333 | buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "example" */;
334 | buildPhases = (
335 | 13B07F871A680F5B00A75B9A /* Sources */,
336 | 13B07F8C1A680F5B00A75B9A /* Frameworks */,
337 | 13B07F8E1A680F5B00A75B9A /* Resources */,
338 | 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
339 | );
340 | buildRules = (
341 | );
342 | dependencies = (
343 | );
344 | name = example;
345 | productName = "Hello World";
346 | productReference = 13B07F961A680F5B00A75B9A /* example.app */;
347 | productType = "com.apple.product-type.application";
348 | };
349 | /* End PBXNativeTarget section */
350 |
351 | /* Begin PBXProject section */
352 | 83CBB9F71A601CBA00E9B192 /* Project object */ = {
353 | isa = PBXProject;
354 | attributes = {
355 | LastUpgradeCheck = 0610;
356 | ORGANIZATIONNAME = Facebook;
357 | TargetAttributes = {
358 | 00E356ED1AD99517003FC87E = {
359 | CreatedOnToolsVersion = 6.2;
360 | TestTargetID = 13B07F861A680F5B00A75B9A;
361 | };
362 | };
363 | };
364 | buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "example" */;
365 | compatibilityVersion = "Xcode 3.2";
366 | developmentRegion = English;
367 | hasScannedForEncodings = 0;
368 | knownRegions = (
369 | en,
370 | Base,
371 | );
372 | mainGroup = 83CBB9F61A601CBA00E9B192;
373 | productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
374 | projectDirPath = "";
375 | projectReferences = (
376 | {
377 | ProductGroup = 00C302A81ABCB8CE00DB3ED1 /* Products */;
378 | ProjectRef = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */;
379 | },
380 | {
381 | ProductGroup = 00C302B61ABCB90400DB3ED1 /* Products */;
382 | ProjectRef = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */;
383 | },
384 | {
385 | ProductGroup = 00C302BC1ABCB91800DB3ED1 /* Products */;
386 | ProjectRef = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */;
387 | },
388 | {
389 | ProductGroup = 78C398B11ACF4ADC00677621 /* Products */;
390 | ProjectRef = 78C398B01ACF4ADC00677621 /* RCTLinking.xcodeproj */;
391 | },
392 | {
393 | ProductGroup = 00C302D41ABCB9D200DB3ED1 /* Products */;
394 | ProjectRef = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */;
395 | },
396 | {
397 | ProductGroup = 139105B71AF99BAD00B5F7CC /* Products */;
398 | ProjectRef = 139105B61AF99BAD00B5F7CC /* RCTSettings.xcodeproj */;
399 | },
400 | {
401 | ProductGroup = 832341B11AAA6A8300B99B32 /* Products */;
402 | ProjectRef = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */;
403 | },
404 | {
405 | ProductGroup = 00C302E01ABCB9EE00DB3ED1 /* Products */;
406 | ProjectRef = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */;
407 | },
408 | {
409 | ProductGroup = 139FDEE71B06529A00C62182 /* Products */;
410 | ProjectRef = 139FDEE61B06529A00C62182 /* RCTWebSocket.xcodeproj */;
411 | },
412 | {
413 | ProductGroup = 146834001AC3E56700842450 /* Products */;
414 | ProjectRef = 146833FF1AC3E56700842450 /* React.xcodeproj */;
415 | },
416 | );
417 | projectRoot = "";
418 | targets = (
419 | 13B07F861A680F5B00A75B9A /* example */,
420 | 00E356ED1AD99517003FC87E /* exampleTests */,
421 | );
422 | };
423 | /* End PBXProject section */
424 |
425 | /* Begin PBXReferenceProxy section */
426 | 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */ = {
427 | isa = PBXReferenceProxy;
428 | fileType = archive.ar;
429 | path = libRCTActionSheet.a;
430 | remoteRef = 00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */;
431 | sourceTree = BUILT_PRODUCTS_DIR;
432 | };
433 | 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */ = {
434 | isa = PBXReferenceProxy;
435 | fileType = archive.ar;
436 | path = libRCTGeolocation.a;
437 | remoteRef = 00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */;
438 | sourceTree = BUILT_PRODUCTS_DIR;
439 | };
440 | 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */ = {
441 | isa = PBXReferenceProxy;
442 | fileType = archive.ar;
443 | path = libRCTImage.a;
444 | remoteRef = 00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */;
445 | sourceTree = BUILT_PRODUCTS_DIR;
446 | };
447 | 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */ = {
448 | isa = PBXReferenceProxy;
449 | fileType = archive.ar;
450 | path = libRCTNetwork.a;
451 | remoteRef = 00C302DB1ABCB9D200DB3ED1 /* PBXContainerItemProxy */;
452 | sourceTree = BUILT_PRODUCTS_DIR;
453 | };
454 | 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */ = {
455 | isa = PBXReferenceProxy;
456 | fileType = archive.ar;
457 | path = libRCTVibration.a;
458 | remoteRef = 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */;
459 | sourceTree = BUILT_PRODUCTS_DIR;
460 | };
461 | 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */ = {
462 | isa = PBXReferenceProxy;
463 | fileType = archive.ar;
464 | path = libRCTSettings.a;
465 | remoteRef = 139105C01AF99BAD00B5F7CC /* PBXContainerItemProxy */;
466 | sourceTree = BUILT_PRODUCTS_DIR;
467 | };
468 | 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */ = {
469 | isa = PBXReferenceProxy;
470 | fileType = archive.ar;
471 | path = libRCTWebSocket.a;
472 | remoteRef = 139FDEF31B06529B00C62182 /* PBXContainerItemProxy */;
473 | sourceTree = BUILT_PRODUCTS_DIR;
474 | };
475 | 146834041AC3E56700842450 /* libReact.a */ = {
476 | isa = PBXReferenceProxy;
477 | fileType = archive.ar;
478 | path = libReact.a;
479 | remoteRef = 146834031AC3E56700842450 /* PBXContainerItemProxy */;
480 | sourceTree = BUILT_PRODUCTS_DIR;
481 | };
482 | 78C398B91ACF4ADC00677621 /* libRCTLinking.a */ = {
483 | isa = PBXReferenceProxy;
484 | fileType = archive.ar;
485 | path = libRCTLinking.a;
486 | remoteRef = 78C398B81ACF4ADC00677621 /* PBXContainerItemProxy */;
487 | sourceTree = BUILT_PRODUCTS_DIR;
488 | };
489 | 832341B51AAA6A8300B99B32 /* libRCTText.a */ = {
490 | isa = PBXReferenceProxy;
491 | fileType = archive.ar;
492 | path = libRCTText.a;
493 | remoteRef = 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */;
494 | sourceTree = BUILT_PRODUCTS_DIR;
495 | };
496 | /* End PBXReferenceProxy section */
497 |
498 | /* Begin PBXResourcesBuildPhase section */
499 | 00E356EC1AD99517003FC87E /* Resources */ = {
500 | isa = PBXResourcesBuildPhase;
501 | buildActionMask = 2147483647;
502 | files = (
503 | );
504 | runOnlyForDeploymentPostprocessing = 0;
505 | };
506 | 13B07F8E1A680F5B00A75B9A /* Resources */ = {
507 | isa = PBXResourcesBuildPhase;
508 | buildActionMask = 2147483647;
509 | files = (
510 | 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
511 | 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */,
512 | );
513 | runOnlyForDeploymentPostprocessing = 0;
514 | };
515 | /* End PBXResourcesBuildPhase section */
516 |
517 | /* Begin PBXShellScriptBuildPhase section */
518 | 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = {
519 | isa = PBXShellScriptBuildPhase;
520 | buildActionMask = 2147483647;
521 | files = (
522 | );
523 | inputPaths = (
524 | );
525 | name = "Bundle React Native code and images";
526 | outputPaths = (
527 | );
528 | runOnlyForDeploymentPostprocessing = 0;
529 | shellPath = /bin/sh;
530 | shellScript = "export NODE_BINARY=node\n../node_modules/react-native/packager/react-native-xcode.sh";
531 | showEnvVarsInLog = 1;
532 | };
533 | /* End PBXShellScriptBuildPhase section */
534 |
535 | /* Begin PBXSourcesBuildPhase section */
536 | 00E356EA1AD99517003FC87E /* Sources */ = {
537 | isa = PBXSourcesBuildPhase;
538 | buildActionMask = 2147483647;
539 | files = (
540 | 00E356F31AD99517003FC87E /* exampleTests.m in Sources */,
541 | );
542 | runOnlyForDeploymentPostprocessing = 0;
543 | };
544 | 13B07F871A680F5B00A75B9A /* Sources */ = {
545 | isa = PBXSourcesBuildPhase;
546 | buildActionMask = 2147483647;
547 | files = (
548 | 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */,
549 | 13B07FC11A68108700A75B9A /* main.m in Sources */,
550 | );
551 | runOnlyForDeploymentPostprocessing = 0;
552 | };
553 | /* End PBXSourcesBuildPhase section */
554 |
555 | /* Begin PBXTargetDependency section */
556 | 00E356F51AD99517003FC87E /* PBXTargetDependency */ = {
557 | isa = PBXTargetDependency;
558 | target = 13B07F861A680F5B00A75B9A /* example */;
559 | targetProxy = 00E356F41AD99517003FC87E /* PBXContainerItemProxy */;
560 | };
561 | /* End PBXTargetDependency section */
562 |
563 | /* Begin PBXVariantGroup section */
564 | 13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = {
565 | isa = PBXVariantGroup;
566 | children = (
567 | 13B07FB21A68108700A75B9A /* Base */,
568 | );
569 | name = LaunchScreen.xib;
570 | path = example;
571 | sourceTree = "";
572 | };
573 | /* End PBXVariantGroup section */
574 |
575 | /* Begin XCBuildConfiguration section */
576 | 00E356F61AD99517003FC87E /* Debug */ = {
577 | isa = XCBuildConfiguration;
578 | buildSettings = {
579 | BUNDLE_LOADER = "$(TEST_HOST)";
580 | GCC_PREPROCESSOR_DEFINITIONS = (
581 | "DEBUG=1",
582 | "$(inherited)",
583 | );
584 | INFOPLIST_FILE = exampleTests/Info.plist;
585 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
586 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
587 | PRODUCT_NAME = "$(TARGET_NAME)";
588 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/example.app/example";
589 | };
590 | name = Debug;
591 | };
592 | 00E356F71AD99517003FC87E /* Release */ = {
593 | isa = XCBuildConfiguration;
594 | buildSettings = {
595 | BUNDLE_LOADER = "$(TEST_HOST)";
596 | COPY_PHASE_STRIP = NO;
597 | INFOPLIST_FILE = exampleTests/Info.plist;
598 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
599 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
600 | PRODUCT_NAME = "$(TARGET_NAME)";
601 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/example.app/example";
602 | };
603 | name = Release;
604 | };
605 | 13B07F941A680F5B00A75B9A /* Debug */ = {
606 | isa = XCBuildConfiguration;
607 | buildSettings = {
608 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
609 | CURRENT_PROJECT_VERSION = 1;
610 | DEAD_CODE_STRIPPING = NO;
611 | HEADER_SEARCH_PATHS = (
612 | "$(inherited)",
613 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
614 | "$(SRCROOT)/../node_modules/react-native/React/**",
615 | );
616 | INFOPLIST_FILE = "example/Info.plist";
617 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
618 | OTHER_LDFLAGS = (
619 | "$(inherited)",
620 | "-ObjC",
621 | "-lc++",
622 | );
623 | PRODUCT_NAME = example;
624 | VERSIONING_SYSTEM = "apple-generic";
625 | };
626 | name = Debug;
627 | };
628 | 13B07F951A680F5B00A75B9A /* Release */ = {
629 | isa = XCBuildConfiguration;
630 | buildSettings = {
631 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
632 | CURRENT_PROJECT_VERSION = 1;
633 | HEADER_SEARCH_PATHS = (
634 | "$(inherited)",
635 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
636 | "$(SRCROOT)/../node_modules/react-native/React/**",
637 | );
638 | INFOPLIST_FILE = "example/Info.plist";
639 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
640 | OTHER_LDFLAGS = (
641 | "$(inherited)",
642 | "-ObjC",
643 | "-lc++",
644 | );
645 | PRODUCT_NAME = example;
646 | VERSIONING_SYSTEM = "apple-generic";
647 | };
648 | name = Release;
649 | };
650 | 83CBBA201A601CBA00E9B192 /* Debug */ = {
651 | isa = XCBuildConfiguration;
652 | buildSettings = {
653 | ALWAYS_SEARCH_USER_PATHS = NO;
654 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
655 | CLANG_CXX_LIBRARY = "libc++";
656 | CLANG_ENABLE_MODULES = YES;
657 | CLANG_ENABLE_OBJC_ARC = YES;
658 | CLANG_WARN_BOOL_CONVERSION = YES;
659 | CLANG_WARN_CONSTANT_CONVERSION = YES;
660 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
661 | CLANG_WARN_EMPTY_BODY = YES;
662 | CLANG_WARN_ENUM_CONVERSION = YES;
663 | CLANG_WARN_INT_CONVERSION = YES;
664 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
665 | CLANG_WARN_UNREACHABLE_CODE = YES;
666 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
667 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
668 | COPY_PHASE_STRIP = NO;
669 | ENABLE_STRICT_OBJC_MSGSEND = YES;
670 | GCC_C_LANGUAGE_STANDARD = gnu99;
671 | GCC_DYNAMIC_NO_PIC = NO;
672 | GCC_OPTIMIZATION_LEVEL = 0;
673 | GCC_PREPROCESSOR_DEFINITIONS = (
674 | "DEBUG=1",
675 | "$(inherited)",
676 | );
677 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
678 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
679 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
680 | GCC_WARN_UNDECLARED_SELECTOR = YES;
681 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
682 | GCC_WARN_UNUSED_FUNCTION = YES;
683 | GCC_WARN_UNUSED_VARIABLE = YES;
684 | HEADER_SEARCH_PATHS = (
685 | "$(inherited)",
686 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
687 | "$(SRCROOT)/../node_modules/react-native/React/**",
688 | );
689 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
690 | MTL_ENABLE_DEBUG_INFO = YES;
691 | ONLY_ACTIVE_ARCH = YES;
692 | SDKROOT = iphoneos;
693 | };
694 | name = Debug;
695 | };
696 | 83CBBA211A601CBA00E9B192 /* Release */ = {
697 | isa = XCBuildConfiguration;
698 | buildSettings = {
699 | ALWAYS_SEARCH_USER_PATHS = NO;
700 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
701 | CLANG_CXX_LIBRARY = "libc++";
702 | CLANG_ENABLE_MODULES = YES;
703 | CLANG_ENABLE_OBJC_ARC = YES;
704 | CLANG_WARN_BOOL_CONVERSION = YES;
705 | CLANG_WARN_CONSTANT_CONVERSION = YES;
706 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
707 | CLANG_WARN_EMPTY_BODY = YES;
708 | CLANG_WARN_ENUM_CONVERSION = YES;
709 | CLANG_WARN_INT_CONVERSION = YES;
710 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
711 | CLANG_WARN_UNREACHABLE_CODE = YES;
712 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
713 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
714 | COPY_PHASE_STRIP = YES;
715 | ENABLE_NS_ASSERTIONS = NO;
716 | ENABLE_STRICT_OBJC_MSGSEND = YES;
717 | GCC_C_LANGUAGE_STANDARD = gnu99;
718 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
719 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
720 | GCC_WARN_UNDECLARED_SELECTOR = YES;
721 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
722 | GCC_WARN_UNUSED_FUNCTION = YES;
723 | GCC_WARN_UNUSED_VARIABLE = YES;
724 | HEADER_SEARCH_PATHS = (
725 | "$(inherited)",
726 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
727 | "$(SRCROOT)/../node_modules/react-native/React/**",
728 | );
729 | IPHONEOS_DEPLOYMENT_TARGET = 8.0;
730 | MTL_ENABLE_DEBUG_INFO = NO;
731 | SDKROOT = iphoneos;
732 | VALIDATE_PRODUCT = YES;
733 | };
734 | name = Release;
735 | };
736 | /* End XCBuildConfiguration section */
737 |
738 | /* Begin XCConfigurationList section */
739 | 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "exampleTests" */ = {
740 | isa = XCConfigurationList;
741 | buildConfigurations = (
742 | 00E356F61AD99517003FC87E /* Debug */,
743 | 00E356F71AD99517003FC87E /* Release */,
744 | );
745 | defaultConfigurationIsVisible = 0;
746 | defaultConfigurationName = Release;
747 | };
748 | 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "example" */ = {
749 | isa = XCConfigurationList;
750 | buildConfigurations = (
751 | 13B07F941A680F5B00A75B9A /* Debug */,
752 | 13B07F951A680F5B00A75B9A /* Release */,
753 | );
754 | defaultConfigurationIsVisible = 0;
755 | defaultConfigurationName = Release;
756 | };
757 | 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "example" */ = {
758 | isa = XCConfigurationList;
759 | buildConfigurations = (
760 | 83CBBA201A601CBA00E9B192 /* Debug */,
761 | 83CBBA211A601CBA00E9B192 /* Release */,
762 | );
763 | defaultConfigurationIsVisible = 0;
764 | defaultConfigurationName = Release;
765 | };
766 | /* End XCConfigurationList section */
767 | };
768 | rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;
769 | }
770 |
--------------------------------------------------------------------------------
/example/ios/example.xcodeproj/xcshareddata/xcschemes/example.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
29 |
35 |
36 |
37 |
38 |
39 |
44 |
45 |
47 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
65 |
66 |
75 |
77 |
83 |
84 |
85 |
86 |
87 |
88 |
94 |
96 |
102 |
103 |
104 |
105 |
107 |
108 |
111 |
112 |
113 |
--------------------------------------------------------------------------------
/example/ios/example/AppDelegate.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2015-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | #import
11 |
12 | @interface AppDelegate : UIResponder
13 |
14 | @property (nonatomic, strong) UIWindow *window;
15 |
16 | @end
17 |
--------------------------------------------------------------------------------
/example/ios/example/AppDelegate.m:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2015-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | #import "AppDelegate.h"
11 |
12 | #import "RCTBundleURLProvider.h"
13 | #import "RCTRootView.h"
14 |
15 | @implementation AppDelegate
16 |
17 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
18 | {
19 | NSURL *jsCodeLocation;
20 |
21 | jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
22 |
23 | RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
24 | moduleName:@"example"
25 | initialProperties:nil
26 | launchOptions:launchOptions];
27 | rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
28 |
29 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
30 | UIViewController *rootViewController = [UIViewController new];
31 | rootViewController.view = rootView;
32 | self.window.rootViewController = rootViewController;
33 | [self.window makeKeyAndVisible];
34 | return YES;
35 | }
36 |
37 | @end
38 |
--------------------------------------------------------------------------------
/example/ios/example/Base.lproj/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
21 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/example/ios/example/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | }
33 | ],
34 | "info" : {
35 | "version" : 1,
36 | "author" : "xcode"
37 | }
38 | }
--------------------------------------------------------------------------------
/example/ios/example/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIRequiredDeviceCapabilities
28 |
29 | armv7
30 |
31 | UISupportedInterfaceOrientations
32 |
33 | UIInterfaceOrientationPortrait
34 | UIInterfaceOrientationLandscapeLeft
35 | UIInterfaceOrientationLandscapeRight
36 |
37 | UIViewControllerBasedStatusBarAppearance
38 |
39 | NSLocationWhenInUseUsageDescription
40 |
41 | NSAppTransportSecurity
42 |
43 |
44 | NSExceptionDomains
45 |
46 | localhost
47 |
48 | NSExceptionAllowsInsecureHTTPLoads
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/example/ios/example/main.m:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2015-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | #import
11 |
12 | #import "AppDelegate.h"
13 |
14 | int main(int argc, char * argv[]) {
15 | @autoreleasepool {
16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/example/ios/exampleTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/example/ios/exampleTests/exampleTests.m:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2015-present, Facebook, Inc.
3 | * All rights reserved.
4 | *
5 | * This source code is licensed under the BSD-style license found in the
6 | * LICENSE file in the root directory of this source tree. An additional grant
7 | * of patent rights can be found in the PATENTS file in the same directory.
8 | */
9 |
10 | #import
11 | #import
12 |
13 | #import "RCTLog.h"
14 | #import "RCTRootView.h"
15 |
16 | #define TIMEOUT_SECONDS 600
17 | #define TEXT_TO_LOOK_FOR @"Welcome to React Native!"
18 |
19 | @interface exampleTests : XCTestCase
20 |
21 | @end
22 |
23 | @implementation exampleTests
24 |
25 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test
26 | {
27 | if (test(view)) {
28 | return YES;
29 | }
30 | for (UIView *subview in [view subviews]) {
31 | if ([self findSubviewInView:subview matching:test]) {
32 | return YES;
33 | }
34 | }
35 | return NO;
36 | }
37 |
38 | - (void)testRendersWelcomeScreen
39 | {
40 | UIViewController *vc = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
41 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];
42 | BOOL foundElement = NO;
43 |
44 | __block NSString *redboxError = nil;
45 | RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {
46 | if (level >= RCTLogLevelError) {
47 | redboxError = message;
48 | }
49 | });
50 |
51 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {
52 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
53 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
54 |
55 | foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) {
56 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) {
57 | return YES;
58 | }
59 | return NO;
60 | }];
61 | }
62 |
63 | RCTSetLogFunction(RCTDefaultLogFunction);
64 |
65 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError);
66 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS);
67 | }
68 |
69 |
70 | @end
71 |
--------------------------------------------------------------------------------
/example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "example",
3 | "version": "0.0.1",
4 | "private": true,
5 | "scripts": {
6 | "start": "node node_modules/react-native/local-cli/cli.js start",
7 | "test": "jest"
8 | },
9 | "dependencies": {
10 | "react": "15.3.2",
11 | "react-native": "0.36.0",
12 | "react-native-markdown-syntax": "Liroo/react-native-markdown-syntax"
13 | },
14 | "jest": {
15 | "preset": "jest-react-native"
16 | },
17 | "devDependencies": {
18 | "babel-jest": "16.0.0",
19 | "babel-preset-react-native": "1.9.0",
20 | "jest": "16.0.2",
21 | "jest-react-native": "16.0.0",
22 | "react-test-renderer": "15.3.2"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | // super simple module for the most common nodejs use case.
2 | exports.markdown = require("./md");
3 | exports.parse = exports.markdown.toHTML;
4 |
--------------------------------------------------------------------------------
/lib/md.js:
--------------------------------------------------------------------------------
1 | // Released under MIT license
2 | // Copyright (c) 2009-2010 Dominic Baggott
3 | // Copyright (c) 2009-2010 Ash Berlin
4 | // Copyright (c) 2011 Christoph Dorn (http://www.christophdorn.com)
5 | // Copyright (c) 2016 Pierre Monge
6 | /*jshint browser:true, devel:true */
7 |
8 | const ReactHelpers = require('./react_helpers');
9 | (function( expose ) {
10 |
11 | /**
12 | * class Markdown
13 | *
14 | * Markdown processing in Javascript done right. We have very particular views
15 | * on what constitutes 'right' which include:
16 | *
17 | * - produces well-formed HTML (this means that em and strong nesting is
18 | * important)
19 | *
20 | * - has an intermediate representation to allow processing of parsed data (We
21 | * in fact have two, both as [JsonML]: a markdown tree and an HTML tree).
22 | *
23 | * - is easily extensible to add new dialects without having to rewrite the
24 | * entire parsing mechanics
25 | *
26 | * - has a good test suite
27 | *
28 | * This implementation fulfills all of these (except that the test suite could
29 | * do with expanding to automatically run all the fixtures from other Markdown
30 | * implementations.)
31 | *
32 | * ##### Intermediate Representation
33 | *
34 | * *TODO* Talk about this :) Its JsonML, but document the node names we use.
35 | *
36 | * [JsonML]: http://jsonml.org/ "JSON Markup Language"
37 | **/
38 | var Markdown = expose.Markdown = function(dialect) {
39 | switch (typeof dialect) {
40 | case "undefined":
41 | this.dialect = Markdown.dialects.Gruber;
42 | break;
43 | case "object":
44 | this.dialect = dialect;
45 | break;
46 | default:
47 | if ( dialect in Markdown.dialects ) {
48 | this.dialect = Markdown.dialects[dialect];
49 | }
50 | else {
51 | throw new Error("Unknown Markdown dialect '" + String(dialect) + "'");
52 | }
53 | break;
54 | }
55 | this.em_state = [];
56 | this.strong_state = [];
57 | this.debug_indent = "";
58 | };
59 |
60 | /**
61 | * parse( markdown, [dialect] ) -> JsonML
62 | * - markdown (String): markdown string to parse
63 | * - dialect (String | Dialect): the dialect to use, defaults to gruber
64 | *
65 | * Parse `markdown` and return a markdown document as a Markdown.JsonML tree.
66 | **/
67 | expose.parse = function( source, dialect ) {
68 | // dialect will default if undefined
69 | var md = new Markdown( dialect );
70 | return md.toTree( source );
71 | };
72 |
73 | /**
74 | * toReact( markdown, [dialect] ) -> String
75 | * toReact( md_tree ) -> String
76 | * - markdown (String): markdown string to parse
77 | * - md_tree (Markdown.JsonML): parsed markdown tree
78 | *
79 | * Take markdown (either as a string or as a JsonML tree) and run it through
80 | * [[toHTMLTree]] then turn it into a well-formated HTML fragment.
81 | **/
82 | expose.toReact = function toReact( source , dialect , options ) {
83 | var input = expose.toHTMLTree( source , dialect , options );
84 |
85 | return expose.renderJsonML( input );
86 | };
87 |
88 | /**
89 | * toHTMLTree( markdown, [dialect] ) -> JsonML
90 | * toHTMLTree( md_tree ) -> JsonML
91 | * - markdown (String): markdown string to parse
92 | * - dialect (String | Dialect): the dialect to use, defaults to gruber
93 | * - md_tree (Markdown.JsonML): parsed markdown tree
94 | *
95 | * Turn markdown into HTML, represented as a JsonML tree. If a string is given
96 | * to this function, it is first parsed into a markdown tree by calling
97 | * [[parse]].
98 | **/
99 | expose.toHTMLTree = function toHTMLTree( input, dialect , options ) {
100 | // convert string input to an MD tree
101 | if ( typeof input ==="string" ) input = this.parse( input, dialect );
102 |
103 | // Now convert the MD tree to an HTML tree
104 |
105 | // remove references from the tree
106 | var attrs = extract_attr( input ),
107 | refs = {};
108 |
109 | if ( attrs && attrs.references ) {
110 | refs = attrs.references;
111 | }
112 |
113 | var html = convert_tree_to_html( input, refs , options );
114 | merge_text_nodes( html );
115 | return html;
116 | };
117 |
118 | // For Spidermonkey based engines
119 | function mk_block_toSource() {
120 | return "Markdown.mk_block( " +
121 | uneval(this.toString()) +
122 | ", " +
123 | uneval(this.trailing) +
124 | ", " +
125 | uneval(this.lineNumber) +
126 | " )";
127 | }
128 |
129 | // node
130 | function mk_block_inspect() {
131 | var util = require("util");
132 | return "Markdown.mk_block( " +
133 | util.inspect(this.toString()) +
134 | ", " +
135 | util.inspect(this.trailing) +
136 | ", " +
137 | util.inspect(this.lineNumber) +
138 | " )";
139 |
140 | }
141 |
142 | var mk_block = Markdown.mk_block = function(block, trail, line) {
143 | // Be helpful for default case in tests.
144 | if ( arguments.length == 1 ) trail = "\n\n";
145 |
146 | var s = new String(block);
147 | s.trailing = trail;
148 | // To make it clear its not just a string
149 | s.inspect = mk_block_inspect;
150 | s.toSource = mk_block_toSource;
151 |
152 | if ( line != undefined )
153 | s.lineNumber = line;
154 |
155 | return s;
156 | };
157 |
158 | function count_lines( str ) {
159 | var n = 0, i = -1;
160 | while ( ( i = str.indexOf("\n", i + 1) ) !== -1 ) n++;
161 | return n;
162 | }
163 |
164 | // Internal - split source into rough blocks
165 | Markdown.prototype.split_blocks = function splitBlocks( input, startLine ) {
166 | input = input.replace(/(\r\n|\n|\r)/g, "\n");
167 | // [\s\S] matches _anything_ (newline or space)
168 | // [^] is equivalent but doesn't work in IEs.
169 | var re = /([\s\S]+?)($|\n#|\n(?:\s*\n|$)+)/g,
170 | blocks = [],
171 | m;
172 |
173 | var line_no = 1;
174 |
175 | if ( ( m = /^(\s*\n)/.exec(input) ) != null ) {
176 | // skip (but count) leading blank lines
177 | line_no += count_lines( m[0] );
178 | re.lastIndex = m[0].length;
179 | }
180 |
181 | while ( ( m = re.exec(input) ) !== null ) {
182 | if (m[2] == "\n#") {
183 | m[2] = "\n";
184 | re.lastIndex--;
185 | }
186 | blocks.push( mk_block( m[1], m[2], line_no ) );
187 | line_no += count_lines( m[0] );
188 | }
189 |
190 | return blocks;
191 | };
192 |
193 | /**
194 | * Markdown#processBlock( block, next ) -> undefined | [ JsonML, ... ]
195 | * - block (String): the block to process
196 | * - next (Array): the following blocks
197 | *
198 | * Process `block` and return an array of JsonML nodes representing `block`.
199 | *
200 | * It does this by asking each block level function in the dialect to process
201 | * the block until one can. Succesful handling is indicated by returning an
202 | * array (with zero or more JsonML nodes), failure by a false value.
203 | *
204 | * Blocks handlers are responsible for calling [[Markdown#processInline]]
205 | * themselves as appropriate.
206 | *
207 | * If the blocks were split incorrectly or adjacent blocks need collapsing you
208 | * can adjust `next` in place using shift/splice etc.
209 | *
210 | * If any of this default behaviour is not right for the dialect, you can
211 | * define a `__call__` method on the dialect that will get invoked to handle
212 | * the block processing.
213 | */
214 | Markdown.prototype.processBlock = function processBlock( block, next ) {
215 | var cbs = this.dialect.block,
216 | ord = cbs.__order__;
217 |
218 | if ( "__call__" in cbs ) {
219 | return cbs.__call__.call(this, block, next);
220 | }
221 |
222 | for ( var i = 0; i < ord.length; i++ ) {
223 | //D:this.debug( "Testing", ord[i] );
224 | var res = cbs[ ord[i] ].call( this, block, next );
225 | if ( res ) {
226 | //D:this.debug(" matched");
227 | if ( !isArray(res) || ( res.length > 0 && !( isArray(res[0]) ) ) )
228 | this.debug(ord[i], "didn't return a proper array");
229 | //D:this.debug( "" );
230 | return res;
231 | }
232 | }
233 |
234 | // Uhoh! no match! Should we throw an error?
235 | return [];
236 | };
237 |
238 | Markdown.prototype.processInline = function processInline( block ) {
239 | return this.dialect.inline.__call__.call( this, String( block ) );
240 | };
241 |
242 | /**
243 | * Markdown#toTree( source ) -> JsonML
244 | * - source (String): markdown source to parse
245 | *
246 | * Parse `source` into a JsonML tree representing the markdown document.
247 | **/
248 | // custom_tree means set this.tree to `custom_tree` and restore old value on return
249 | Markdown.prototype.toTree = function toTree( source, custom_root ) {
250 | var blocks = source instanceof Array ? source : this.split_blocks( source );
251 |
252 | // Make tree a member variable so its easier to mess with in extensions
253 | var old_tree = this.tree;
254 | try {
255 | this.tree = custom_root || this.tree || [ "markdown" ];
256 |
257 | blocks:
258 | while ( blocks.length ) {
259 | var b = this.processBlock( blocks.shift(), blocks );
260 |
261 | // Reference blocks and the like won't return any content
262 | if ( !b.length ) continue blocks;
263 |
264 | this.tree.push.apply( this.tree, b );
265 | }
266 | return this.tree;
267 | }
268 | finally {
269 | if ( custom_root ) {
270 | this.tree = old_tree;
271 | }
272 | }
273 | };
274 |
275 | // Noop by default
276 | Markdown.prototype.debug = function () {
277 | var args = Array.prototype.slice.call( arguments);
278 | args.unshift(this.debug_indent);
279 | if ( typeof print !== "undefined" )
280 | print.apply( print, args );
281 | if ( typeof console !== "undefined" && typeof console.log !== "undefined" )
282 | console.log.apply( null, args );
283 | }
284 |
285 | Markdown.prototype.loop_re_over_block = function( re, block, cb ) {
286 | // Dont use /g regexps with this
287 | var m,
288 | b = block.valueOf();
289 |
290 | while ( b.length && (m = re.exec(b) ) != null ) {
291 | b = b.substr( m[0].length );
292 | cb.call(this, m);
293 | }
294 | return b;
295 | };
296 |
297 | /**
298 | * Markdown.dialects
299 | *
300 | * Namespace of built-in dialects.
301 | **/
302 | Markdown.dialects = {};
303 |
304 | /**
305 | * Markdown.dialects.Gruber
306 | *
307 | * The default dialect that follows the rules set out by John Gruber's
308 | * markdown.pl as closely as possible. Well actually we follow the behaviour of
309 | * that script which in some places is not exactly what the syntax web page
310 | * says.
311 | **/
312 | Markdown.dialects.Gruber = {
313 | block: {
314 | atxHeader: function atxHeader( block, next ) {
315 | var m = block.match( /^(#{1,6})\s*(.*?)\s*#*\s*(?:\n|$)/ );
316 |
317 | if ( !m ) return undefined;
318 |
319 | var header = [ "header", { level: m[ 1 ].length } ];
320 | Array.prototype.push.apply(header, this.processInline(m[ 2 ]));
321 |
322 | if ( m[0].length < block.length )
323 | next.unshift( mk_block( block.substr( m[0].length ), block.trailing, block.lineNumber + 2 ) );
324 |
325 | return [ header ];
326 | },
327 |
328 | setextHeader: function setextHeader( block, next ) {
329 | var m = block.match( /^(.*)\n([-=])\2\2+(?:\n|$)/ );
330 |
331 | if ( !m ) return undefined;
332 |
333 | var level = ( m[ 2 ] === "=" ) ? 1 : 2;
334 | var header = [ "header", { level : level }, m[ 1 ] ];
335 |
336 | if ( m[0].length < block.length )
337 | next.unshift( mk_block( block.substr( m[0].length ), block.trailing, block.lineNumber + 2 ) );
338 |
339 | return [ header ];
340 | },
341 |
342 | code: function code( block, next ) {
343 | // | Foo
344 | // |bar
345 | // should be a code block followed by a paragraph. Fun
346 | //
347 | // There might also be adjacent code block to merge.
348 |
349 | var ret = [],
350 | re = /^(?: {0,3}\t| {4})(.*)\n?/,
351 | lines;
352 |
353 | // 4 spaces + content
354 | if ( !block.match( re ) ) return undefined;
355 |
356 | block_search:
357 | do {
358 | // Now pull out the rest of the lines
359 | var b = this.loop_re_over_block(
360 | re, block.valueOf(), function( m ) { ret.push( m[1] ); } );
361 |
362 | if ( b.length ) {
363 | // Case alluded to in first comment. push it back on as a new block
364 | next.unshift( mk_block(b, block.trailing) );
365 | break block_search;
366 | }
367 | else if ( next.length ) {
368 | // Check the next block - it might be code too
369 | if ( !next[0].match( re ) ) break block_search;
370 |
371 | // Pull how how many blanks lines follow - minus two to account for .join
372 | ret.push ( block.trailing.replace(/[^\n]/g, "").substring(2) );
373 |
374 | block = next.shift();
375 | }
376 | else {
377 | break block_search;
378 | }
379 | } while ( true );
380 |
381 | return [ [ "code_block", ret.join("\n") ] ];
382 | },
383 |
384 | horizRule: function horizRule( block, next ) {
385 | // this needs to find any hr in the block to handle abutting blocks
386 | var m = block.match( /^(?:([\s\S]*?)\n)?[ \t]*([-_*])(?:[ \t]*\2){2,}[ \t]*(?:\n([\s\S]*))?$/ );
387 |
388 | if ( !m ) {
389 | return undefined;
390 | }
391 |
392 | var jsonml = [ [ "hr" ] ];
393 |
394 | // if there's a leading abutting block, process it
395 | if ( m[ 1 ] ) {
396 | jsonml.unshift.apply( jsonml, this.processBlock( m[ 1 ], [] ) );
397 | }
398 |
399 | // if there's a trailing abutting block, stick it into next
400 | if ( m[ 3 ] ) {
401 | next.unshift( mk_block( m[ 3 ] ) );
402 | }
403 |
404 | return jsonml;
405 | },
406 |
407 | // There are two types of lists. Tight and loose. Tight lists have no whitespace
408 | // between the items (and result in text just in the ) and loose lists,
409 | // which have an empty line between list items, resulting in (one or more)
410 | // paragraphs inside the .
411 | //
412 | // There are all sorts weird edge cases about the original markdown.pl's
413 | // handling of lists:
414 | //
415 | // * Nested lists are supposed to be indented by four chars per level. But
416 | // if they aren't, you can get a nested list by indenting by less than
417 | // four so long as the indent doesn't match an indent of an existing list
418 | // item in the 'nest stack'.
419 | //
420 | // * The type of the list (bullet or number) is controlled just by the
421 | // first item at the indent. Subsequent changes are ignored unless they
422 | // are for nested lists
423 | //
424 | lists: (function( ) {
425 | // Use a closure to hide a few variables.
426 | var any_list = "[*+-]|\\d+\\.",
427 | bullet_list = /[*+-]/,
428 | number_list = /\d+\./,
429 | // Capture leading indent as it matters for determining nested lists.
430 | is_list_re = new RegExp( "^( {0,3})(" + any_list + ")[ \t]+" ),
431 | indent_re = "(?: {0,3}\t| {4})";
432 |
433 | // TODO: Cache this regexp for certain depths.
434 | // Create a regexp suitable for matching an li for a given stack depth
435 | function regex_for_depth( depth ) {
436 |
437 | return new RegExp(
438 | // m[1] = indent, m[2] = list_type
439 | "(?:^(" + indent_re + "{0," + depth + "} {0,3})(" + any_list + ")\\s+)|" +
440 | // m[3] = cont
441 | "(^" + indent_re + "{0," + (depth-1) + "}[ ]{0,4})"
442 | );
443 | }
444 | function expand_tab( input ) {
445 | return input.replace( / {0,3}\t/g, " " );
446 | }
447 |
448 | // Add inline content `inline` to `li`. inline comes from processInline
449 | // so is an array of content
450 | function add(li, loose, inline, nl) {
451 | if ( loose ) {
452 | li.push( [ "para" ].concat(inline) );
453 | return;
454 | }
455 | // Hmmm, should this be any block level element or just paras?
456 | var add_to = li[li.length -1] instanceof Array && li[li.length - 1][0] == "para"
457 | ? li[li.length -1]
458 | : li;
459 |
460 | // If there is already some content in this list, add the new line in
461 | if ( nl && li.length > 1 ) inline.unshift(nl);
462 |
463 | for ( var i = 0; i < inline.length; i++ ) {
464 | var what = inline[i],
465 | is_str = typeof what == "string";
466 | if ( is_str && add_to.length > 1 && typeof add_to[add_to.length-1] == "string" ) {
467 | add_to[ add_to.length-1 ] += what;
468 | }
469 | else {
470 | add_to.push( what );
471 | }
472 | }
473 | }
474 |
475 | // contained means have an indent greater than the current one. On
476 | // *every* line in the block
477 | function get_contained_blocks( depth, blocks ) {
478 |
479 | var re = new RegExp( "^(" + indent_re + "{" + depth + "}.*?\\n?)*$" ),
480 | replace = new RegExp("^" + indent_re + "{" + depth + "}", "gm"),
481 | ret = [];
482 |
483 | while ( blocks.length > 0 ) {
484 | if ( re.exec( blocks[0] ) ) {
485 | var b = blocks.shift(),
486 | // Now remove that indent
487 | x = b.replace( replace, "");
488 |
489 | ret.push( mk_block( x, b.trailing, b.lineNumber ) );
490 | }
491 | else {
492 | break;
493 | }
494 | }
495 | return ret;
496 | }
497 |
498 | // passed to stack.forEach to turn list items up the stack into paras
499 | function paragraphify(s, i, stack) {
500 | var list = s.list;
501 | var last_li = list[list.length-1];
502 |
503 | if ( last_li[1] instanceof Array && last_li[1][0] == "para" ) {
504 | return;
505 | }
506 | if ( i + 1 == stack.length ) {
507 | // Last stack frame
508 | // Keep the same array, but replace the contents
509 | last_li.push( ["para"].concat( last_li.splice(1, last_li.length - 1) ) );
510 | }
511 | else {
512 | var sublist = last_li.pop();
513 | last_li.push( ["para"].concat( last_li.splice(1, last_li.length - 1) ), sublist );
514 | }
515 | }
516 |
517 | // The matcher function
518 | return function( block, next ) {
519 | var m = block.match( is_list_re );
520 | if ( !m ) return undefined;
521 |
522 | function make_list( m ) {
523 | var list = bullet_list.exec( m[2] )
524 | ? ["bulletlist"]
525 | : ["numberlist"];
526 |
527 | stack.push( { list: list, indent: m[1] } );
528 | return list;
529 | }
530 |
531 |
532 | var stack = [], // Stack of lists for nesting.
533 | list = make_list( m ),
534 | last_li,
535 | loose = false,
536 | ret = [ stack[0].list ],
537 | i;
538 |
539 | // Loop to search over block looking for inner block elements and loose lists
540 | loose_search:
541 | while ( true ) {
542 | // Split into lines preserving new lines at end of line
543 | var lines = block.split( /(?=\n)/ );
544 |
545 | // We have to grab all lines for a li and call processInline on them
546 | // once as there are some inline things that can span lines.
547 | var li_accumulate = "";
548 |
549 | // Loop over the lines in this block looking for tight lists.
550 | tight_search:
551 | for ( var line_no = 0; line_no < lines.length; line_no++ ) {
552 | var nl = "",
553 | l = lines[line_no].replace(/^\n/, function(n) { nl = n; return ""; });
554 |
555 | // TODO: really should cache this
556 | var line_re = regex_for_depth( stack.length );
557 |
558 | m = l.match( line_re );
559 | //print( "line:", uneval(l), "\nline match:", uneval(m) );
560 |
561 | // We have a list item
562 | if ( m[1] !== undefined ) {
563 | // Process the previous list item, if any
564 | if ( li_accumulate.length ) {
565 | add( last_li, loose, this.processInline( li_accumulate ), nl );
566 | // Loose mode will have been dealt with. Reset it
567 | loose = false;
568 | li_accumulate = "";
569 | }
570 |
571 | m[1] = expand_tab( m[1] );
572 | var wanted_depth = Math.floor(m[1].length/4)+1;
573 | //print( "want:", wanted_depth, "stack:", stack.length);
574 | if ( wanted_depth > stack.length ) {
575 | // Deep enough for a nested list outright
576 | //print ( "new nested list" );
577 | list = make_list( m );
578 | last_li.push( list );
579 | last_li = list[1] = [ "listitem" ];
580 | }
581 | else {
582 | // We aren't deep enough to be strictly a new level. This is
583 | // where Md.pl goes nuts. If the indent matches a level in the
584 | // stack, put it there, else put it one deeper then the
585 | // wanted_depth deserves.
586 | var found = false;
587 | for ( i = 0; i < stack.length; i++ ) {
588 | if ( stack[ i ].indent != m[1] ) continue;
589 | list = stack[ i ].list;
590 | stack.splice( i+1, stack.length - (i+1) );
591 | found = true;
592 | break;
593 | }
594 |
595 | if (!found) {
596 | //print("not found. l:", uneval(l));
597 | wanted_depth++;
598 | if ( wanted_depth <= stack.length ) {
599 | stack.splice(wanted_depth, stack.length - wanted_depth);
600 | //print("Desired depth now", wanted_depth, "stack:", stack.length);
601 | list = stack[wanted_depth-1].list;
602 | //print("list:", uneval(list) );
603 | }
604 | else {
605 | //print ("made new stack for messy indent");
606 | list = make_list(m);
607 | last_li.push(list);
608 | }
609 | }
610 |
611 | //print( uneval(list), "last", list === stack[stack.length-1].list );
612 | last_li = [ "listitem" ];
613 | list.push(last_li);
614 | } // end depth of shenegains
615 | nl = "";
616 | }
617 |
618 | // Add content
619 | if ( l.length > m[0].length ) {
620 | li_accumulate += nl + l.substr( m[0].length );
621 | }
622 | } // tight_search
623 |
624 | if ( li_accumulate.length ) {
625 | add( last_li, loose, this.processInline( li_accumulate ), nl );
626 | // Loose mode will have been dealt with. Reset it
627 | loose = false;
628 | li_accumulate = "";
629 | }
630 |
631 | // Look at the next block - we might have a loose list. Or an extra
632 | // paragraph for the current li
633 | var contained = get_contained_blocks( stack.length, next );
634 |
635 | // Deal with code blocks or properly nested lists
636 | if ( contained.length > 0 ) {
637 | // Make sure all listitems up the stack are paragraphs
638 | forEach( stack, paragraphify, this);
639 |
640 | last_li.push.apply( last_li, this.toTree( contained, [] ) );
641 | }
642 |
643 | var next_block = next[0] && next[0].valueOf() || "";
644 |
645 | if ( next_block.match(is_list_re) || next_block.match( /^ / ) ) {
646 | block = next.shift();
647 |
648 | // Check for an HR following a list: features/lists/hr_abutting
649 | var hr = this.dialect.block.horizRule( block, next );
650 |
651 | if ( hr ) {
652 | ret.push.apply(ret, hr);
653 | break;
654 | }
655 |
656 | // Make sure all listitems up the stack are paragraphs
657 | forEach( stack, paragraphify, this);
658 |
659 | loose = true;
660 | continue loose_search;
661 | }
662 | break;
663 | } // loose_search
664 |
665 | return ret;
666 | };
667 | })(),
668 |
669 | blockquote: function blockquote( block, next ) {
670 | if ( !block.match( /^>/m ) )
671 | return undefined;
672 |
673 | var jsonml = [];
674 |
675 | // separate out the leading abutting block, if any. I.e. in this case:
676 | //
677 | // a
678 | // > b
679 | //
680 | if ( block[ 0 ] != ">" ) {
681 | var lines = block.split( /\n/ ),
682 | prev = [],
683 | line_no = block.lineNumber;
684 |
685 | // keep shifting lines until you find a crotchet
686 | while ( lines.length && lines[ 0 ][ 0 ] != ">" ) {
687 | prev.push( lines.shift() );
688 | line_no++;
689 | }
690 |
691 | var abutting = mk_block( prev.join( "\n" ), "\n", block.lineNumber );
692 | jsonml.push.apply( jsonml, this.processBlock( abutting, [] ) );
693 | // reassemble new block of just block quotes!
694 | block = mk_block( lines.join( "\n" ), block.trailing, line_no );
695 | }
696 |
697 |
698 | // if the next block is also a blockquote merge it in
699 | while ( next.length && next[ 0 ][ 0 ] == ">" ) {
700 | var b = next.shift();
701 | block = mk_block( block + block.trailing + b, b.trailing, block.lineNumber );
702 | }
703 |
704 | // Strip off the leading "> " and re-process as a block.
705 | var input = block.replace( /^> ?/gm, "" ),
706 | old_tree = this.tree,
707 | processedBlock = this.toTree( input, [ "blockquote" ] ),
708 | attr = extract_attr( processedBlock );
709 |
710 | // If any link references were found get rid of them
711 | if ( attr && attr.references ) {
712 | delete attr.references;
713 | // And then remove the attribute object if it's empty
714 | if ( isEmpty( attr ) ) {
715 | processedBlock.splice( 1, 1 );
716 | }
717 | }
718 |
719 | jsonml.push( processedBlock );
720 | return jsonml;
721 | },
722 |
723 | referenceDefn: function referenceDefn( block, next) {
724 | var re = /^\s*\[(.*?)\]:\s*(\S+)(?:\s+(?:(['"])(.*?)\3|\((.*?)\)))?\n?/;
725 | // interesting matches are [ , ref_id, url, , title, title ]
726 |
727 | if ( !block.match(re) )
728 | return undefined;
729 |
730 | // make an attribute node if it doesn't exist
731 | if ( !extract_attr( this.tree ) ) {
732 | this.tree.splice( 1, 0, {} );
733 | }
734 |
735 | var attrs = extract_attr( this.tree );
736 |
737 | // make a references hash if it doesn't exist
738 | if ( attrs.references === undefined ) {
739 | attrs.references = {};
740 | }
741 |
742 | var b = this.loop_re_over_block(re, block, function( m ) {
743 |
744 | if ( m[2] && m[2][0] == "<" && m[2][m[2].length-1] == ">" )
745 | m[2] = m[2].substring( 1, m[2].length - 1 );
746 |
747 | var ref = attrs.references[ m[1].toLowerCase() ] = {
748 | href: m[2]
749 | };
750 |
751 | if ( m[4] !== undefined )
752 | ref.title = m[4];
753 | else if ( m[5] !== undefined )
754 | ref.title = m[5];
755 |
756 | } );
757 |
758 | if ( b.length )
759 | next.unshift( mk_block( b, block.trailing ) );
760 |
761 | return [];
762 | },
763 |
764 | para: function para( block, next ) {
765 | // everything's a para!
766 | return [ ["para"].concat( this.processInline( block ) ) ];
767 | }
768 | }
769 | };
770 |
771 | Markdown.dialects.Gruber.inline = {
772 |
773 | __oneElement__: function oneElement( text, patterns_or_re, previous_nodes ) {
774 | var m,
775 | res,
776 | lastIndex = 0;
777 |
778 | patterns_or_re = patterns_or_re || this.dialect.inline.__patterns__;
779 | var re = new RegExp( "([\\s\\S]*?)(" + (patterns_or_re.source || patterns_or_re) + ")" );
780 |
781 | m = re.exec( text );
782 | if (!m) {
783 | // Just boring text
784 | return [ text.length, text ];
785 | }
786 | else if ( m[1] ) {
787 | // Some un-interesting text matched. Return that first
788 | return [ m[1].length, m[1] ];
789 | }
790 |
791 | var res;
792 | if ( m[2] in this.dialect.inline ) {
793 | res = this.dialect.inline[ m[2] ].call(
794 | this,
795 | text.substr( m.index ), m, previous_nodes || [] );
796 | }
797 | // Default for now to make dev easier. just slurp special and output it.
798 | res = res || [ m[2].length, m[2] ];
799 | return res;
800 | },
801 |
802 | __call__: function inline( text, patterns ) {
803 |
804 | var out = [],
805 | res;
806 |
807 | function add(x) {
808 | //D:self.debug(" adding output", uneval(x));
809 | if ( typeof x == "string" && typeof out[out.length-1] == "string" )
810 | out[ out.length-1 ] += x;
811 | else
812 | out.push(x);
813 | }
814 |
815 | while ( text.length > 0 ) {
816 | res = this.dialect.inline.__oneElement__.call(this, text, patterns, out );
817 | text = text.substr( res.shift() );
818 | forEach(res, add )
819 | }
820 |
821 | return out;
822 | },
823 |
824 | // These characters are intersting elsewhere, so have rules for them so that
825 | // chunks of plain text blocks don't include them
826 | "]": function () {},
827 | "}": function () {},
828 |
829 | __escape__ : /^\\[\\`\*_{}\[\]()#\+.!\-]/,
830 |
831 | "\\": function escaped( text ) {
832 | // [ length of input processed, node/children to add... ]
833 | // Only esacape: \ ` * _ { } [ ] ( ) # * + - . !
834 | if ( this.dialect.inline.__escape__.exec( text ) )
835 | return [ 2, text.charAt( 1 ) ];
836 | else
837 | // Not an esacpe
838 | return [ 1, "\\" ];
839 | },
840 |
841 | "
847 | // 1 2 3 4 <--- captures
848 | var m = text.match( /^!\[(.*?)\][ \t]*\([ \t]*([^")]*?)(?:[ \t]+(["'])(.*?)\3)?[ \t]*\)/ );
849 |
850 | if ( m ) {
851 | if ( m[2] && m[2][0] == "<" && m[2][m[2].length-1] == ">" )
852 | m[2] = m[2].substring( 1, m[2].length - 1 );
853 |
854 | m[2] = this.dialect.inline.__call__.call( this, m[2], /\\/ )[0];
855 |
856 | var attrs = { alt: m[1], href: m[2] || "" };
857 | if ( m[4] !== undefined)
858 | attrs.title = m[4];
859 |
860 | return [ m[0].length, [ "img", attrs ] ];
861 | }
862 |
863 | // ![Alt text][id]
864 | m = text.match( /^!\[(.*?)\][ \t]*\[(.*?)\]/ );
865 |
866 | if ( m ) {
867 | // We can't check if the reference is known here as it likely wont be
868 | // found till after. Check it in md tree->hmtl tree conversion
869 | return [ m[0].length, [ "img_ref", { alt: m[1], ref: m[2].toLowerCase(), original: m[0] } ] ];
870 | }
871 |
872 | // Just consume the '!['
873 | return [ 2, "![" ];
874 | },
875 |
876 | "[": function link( text ) {
877 |
878 | var orig = String(text);
879 | // Inline content is possible inside `link text`
880 | var res = Markdown.DialectHelpers.inline_until_char.call( this, text.substr(1), "]" );
881 |
882 | // No closing ']' found. Just consume the [
883 | if ( !res ) return [ 1, "[" ];
884 |
885 | var consumed = 1 + res[ 0 ],
886 | children = res[ 1 ],
887 | link,
888 | attrs;
889 |
890 | // At this point the first [...] has been parsed. See what follows to find
891 | // out which kind of link we are (reference or direct url)
892 | text = text.substr( consumed );
893 |
894 | // [link text](/path/to/img.jpg "Optional title")
895 | // 1 2 3 <--- captures
896 | // This will capture up to the last paren in the block. We then pull
897 | // back based on if there a matching ones in the url
898 | // ([here](/url/(test))
899 | // The parens have to be balanced
900 | var m = text.match( /^\s*\([ \t]*([^"']*)(?:[ \t]+(["'])(.*?)\2)?[ \t]*\)/ );
901 | if ( m ) {
902 | var url = m[1];
903 | consumed += m[0].length;
904 |
905 | if ( url && url[0] == "<" && url[url.length-1] == ">" )
906 | url = url.substring( 1, url.length - 1 );
907 |
908 | // If there is a title we don't have to worry about parens in the url
909 | if ( !m[3] ) {
910 | var open_parens = 1; // One open that isn't in the capture
911 | for ( var len = 0; len < url.length; len++ ) {
912 | switch ( url[len] ) {
913 | case "(":
914 | open_parens++;
915 | break;
916 | case ")":
917 | if ( --open_parens == 0) {
918 | consumed -= url.length - len;
919 | url = url.substring(0, len);
920 | }
921 | break;
922 | }
923 | }
924 | }
925 |
926 | // Process escapes only
927 | url = this.dialect.inline.__call__.call( this, url, /\\/ )[0];
928 |
929 | attrs = { href: url || "" };
930 | if ( m[3] !== undefined)
931 | attrs.title = m[3];
932 |
933 | link = [ "link", attrs ].concat( children );
934 | return [ consumed, link ];
935 | }
936 |
937 | // [Alt text][id]
938 | // [Alt text] [id]
939 | m = text.match( /^\s*\[(.*?)\]/ );
940 |
941 | if ( m ) {
942 |
943 | consumed += m[ 0 ].length;
944 |
945 | // [links][] uses links as its reference
946 | attrs = { ref: ( m[ 1 ] || String(children) ).toLowerCase(), original: orig.substr( 0, consumed ) };
947 |
948 | link = [ "link_ref", attrs ].concat( children );
949 |
950 | // We can't check if the reference is known here as it likely wont be
951 | // found till after. Check it in md tree->hmtl tree conversion.
952 | // Store the original so that conversion can revert if the ref isn't found.
953 | return [ consumed, link ];
954 | }
955 |
956 | // [id]
957 | // Only if id is plain (no formatting.)
958 | if ( children.length == 1 && typeof children[0] == "string" ) {
959 |
960 | attrs = { ref: children[0].toLowerCase(), original: orig.substr( 0, consumed ) };
961 | link = [ "link_ref", attrs, children[0] ];
962 | return [ consumed, link ];
963 | }
964 |
965 | // Just consume the "["
966 | return [ 1, "[" ];
967 | },
968 |
969 |
970 | "<": function autoLink( text ) {
971 | var m;
972 |
973 | if ( ( m = text.match( /^<(?:((https?|ftp|mailto):[^>]+)|(.*?@.*?\.[a-zA-Z]+))>/ ) ) != null ) {
974 | if ( m[3] ) {
975 | return [ m[0].length, [ "link", { href: "mailto:" + m[3] }, m[3] ] ];
976 |
977 | }
978 | else if ( m[2] == "mailto" ) {
979 | return [ m[0].length, [ "link", { href: m[1] }, m[1].substr("mailto:".length ) ] ];
980 | }
981 | else
982 | return [ m[0].length, [ "link", { href: m[1] }, m[1] ] ];
983 | }
984 |
985 | return [ 1, "<" ];
986 | },
987 |
988 | "`": function inlineCode( text ) {
989 | // Inline code block. as many backticks as you like to start it
990 | // Always skip over the opening ticks.
991 | var m = text.match( /(`+)(([\s\S]*?)\1)/ );
992 |
993 | if ( m && m[2] )
994 | return [ m[1].length + m[2].length, [ "inlinecode", m[3] ] ];
995 | else {
996 | // TODO: No matching end code found - warn!
997 | return [ 1, "`" ];
998 | }
999 | },
1000 |
1001 | " \n": function lineBreak( text ) {
1002 | return [ 3, [ "linebreak" ] ];
1003 | }
1004 |
1005 | };
1006 |
1007 | // Meta Helper/generator method for em and strong handling
1008 | function strong_em( tag, md ) {
1009 |
1010 | var state_slot = tag + "_state",
1011 | other_slot = tag == "strong" ? "em_state" : "strong_state";
1012 |
1013 | function CloseTag(len) {
1014 | this.len_after = len;
1015 | this.name = "close_" + md;
1016 | }
1017 |
1018 | return function ( text, orig_match ) {
1019 |
1020 | if ( this[state_slot][0] == md ) {
1021 | // Most recent em is of this type
1022 | //D:this.debug("closing", md);
1023 | this[state_slot].shift();
1024 |
1025 | // "Consume" everything to go back to the recrusion in the else-block below
1026 | return[ text.length, new CloseTag(text.length-md.length) ];
1027 | }
1028 | else {
1029 | // Store a clone of the em/strong states
1030 | var other = this[other_slot].slice(),
1031 | state = this[state_slot].slice();
1032 |
1033 | this[state_slot].unshift(md);
1034 |
1035 | //D:this.debug_indent += " ";
1036 |
1037 | // Recurse
1038 | var res = this.processInline( text.substr( md.length ) );
1039 | //D:this.debug_indent = this.debug_indent.substr(2);
1040 |
1041 | var last = res[res.length - 1];
1042 |
1043 | //D:this.debug("processInline from", tag + ": ", uneval( res ) );
1044 |
1045 | var check = this[state_slot].shift();
1046 | if ( last instanceof CloseTag ) {
1047 | res.pop();
1048 | // We matched! Huzzah.
1049 | var consumed = text.length - last.len_after;
1050 | return [ consumed, [ tag ].concat(res) ];
1051 | }
1052 | else {
1053 | // Restore the state of the other kind. We might have mistakenly closed it.
1054 | this[other_slot] = other;
1055 | this[state_slot] = state;
1056 |
1057 | // We can't reuse the processed result as it could have wrong parsing contexts in it.
1058 | return [ md.length, md ];
1059 | }
1060 | }
1061 | }; // End returned function
1062 | }
1063 |
1064 | Markdown.dialects.Gruber.inline["**"] = strong_em("strong", "**");
1065 | Markdown.dialects.Gruber.inline["__"] = strong_em("strong", "__");
1066 | Markdown.dialects.Gruber.inline["*"] = strong_em("em", "*");
1067 | Markdown.dialects.Gruber.inline["_"] = strong_em("em", "_");
1068 |
1069 |
1070 | // Build default order from insertion order.
1071 | Markdown.buildBlockOrder = function(d) {
1072 | var ord = [];
1073 | for ( var i in d ) {
1074 | if ( i == "__order__" || i == "__call__" ) continue;
1075 | ord.push( i );
1076 | }
1077 | d.__order__ = ord;
1078 | };
1079 |
1080 | // Build patterns for inline matcher
1081 | Markdown.buildInlinePatterns = function(d) {
1082 | var patterns = [];
1083 |
1084 | for ( var i in d ) {
1085 | // __foo__ is reserved and not a pattern
1086 | if ( i.match( /^__.*__$/) ) continue;
1087 | var l = i.replace( /([\\.*+?|()\[\]{}])/g, "\\$1" )
1088 | .replace( /\n/, "\\n" );
1089 | patterns.push( i.length == 1 ? l : "(?:" + l + ")" );
1090 | }
1091 |
1092 | patterns = patterns.join("|");
1093 | d.__patterns__ = patterns;
1094 | //print("patterns:", uneval( patterns ) );
1095 |
1096 | var fn = d.__call__;
1097 | d.__call__ = function(text, pattern) {
1098 | if ( pattern != undefined ) {
1099 | return fn.call(this, text, pattern);
1100 | }
1101 | else
1102 | {
1103 | return fn.call(this, text, patterns);
1104 | }
1105 | };
1106 | };
1107 |
1108 | Markdown.DialectHelpers = {};
1109 | Markdown.DialectHelpers.inline_until_char = function( text, want ) {
1110 | var consumed = 0,
1111 | nodes = [];
1112 |
1113 | while ( true ) {
1114 | if ( text.charAt( consumed ) == want ) {
1115 | // Found the character we were looking for
1116 | consumed++;
1117 | return [ consumed, nodes ];
1118 | }
1119 |
1120 | if ( consumed >= text.length ) {
1121 | // No closing char found. Abort.
1122 | return null;
1123 | }
1124 |
1125 | var res = this.dialect.inline.__oneElement__.call(this, text.substr( consumed ) );
1126 | consumed += res[ 0 ];
1127 | // Add any returned nodes.
1128 | nodes.push.apply( nodes, res.slice( 1 ) );
1129 | }
1130 | }
1131 |
1132 | // Helper function to make sub-classing a dialect easier
1133 | Markdown.subclassDialect = function( d ) {
1134 | function Block() {}
1135 | Block.prototype = d.block;
1136 | function Inline() {}
1137 | Inline.prototype = d.inline;
1138 |
1139 | return { block: new Block(), inline: new Inline() };
1140 | };
1141 |
1142 | Markdown.buildBlockOrder ( Markdown.dialects.Gruber.block );
1143 | Markdown.buildInlinePatterns( Markdown.dialects.Gruber.inline );
1144 |
1145 | Markdown.dialects.Maruku = Markdown.subclassDialect( Markdown.dialects.Gruber );
1146 |
1147 | Markdown.dialects.Maruku.processMetaHash = function processMetaHash( meta_string ) {
1148 | var meta = split_meta_hash( meta_string ),
1149 | attr = {};
1150 |
1151 | for ( var i = 0; i < meta.length; ++i ) {
1152 | // id: #foo
1153 | if ( /^#/.test( meta[ i ] ) ) {
1154 | attr.id = meta[ i ].substring( 1 );
1155 | }
1156 | // class: .foo
1157 | else if ( /^\./.test( meta[ i ] ) ) {
1158 | // if class already exists, append the new one
1159 | if ( attr["class"] ) {
1160 | attr["class"] = attr["class"] + meta[ i ].replace( /./, " " );
1161 | }
1162 | else {
1163 | attr["class"] = meta[ i ].substring( 1 );
1164 | }
1165 | }
1166 | // attribute: foo=bar
1167 | else if ( /\=/.test( meta[ i ] ) ) {
1168 | var s = meta[ i ].split( /\=/ );
1169 | attr[ s[ 0 ] ] = s[ 1 ];
1170 | }
1171 | }
1172 |
1173 | return attr;
1174 | }
1175 |
1176 | function split_meta_hash( meta_string ) {
1177 | var meta = meta_string.split( "" ),
1178 | parts = [ "" ],
1179 | in_quotes = false;
1180 |
1181 | while ( meta.length ) {
1182 | var letter = meta.shift();
1183 | switch ( letter ) {
1184 | case " " :
1185 | // if we're in a quoted section, keep it
1186 | if ( in_quotes ) {
1187 | parts[ parts.length - 1 ] += letter;
1188 | }
1189 | // otherwise make a new part
1190 | else {
1191 | parts.push( "" );
1192 | }
1193 | break;
1194 | case "'" :
1195 | case '"' :
1196 | // reverse the quotes and move straight on
1197 | in_quotes = !in_quotes;
1198 | break;
1199 | case "\\" :
1200 | // shift off the next letter to be used straight away.
1201 | // it was escaped so we'll keep it whatever it is
1202 | letter = meta.shift();
1203 | default :
1204 | parts[ parts.length - 1 ] += letter;
1205 | break;
1206 | }
1207 | }
1208 |
1209 | return parts;
1210 | }
1211 |
1212 | Markdown.dialects.Maruku.block.document_meta = function document_meta( block, next ) {
1213 | // we're only interested in the first block
1214 | if ( block.lineNumber > 1 ) return undefined;
1215 |
1216 | // document_meta blocks consist of one or more lines of `Key: Value\n`
1217 | if ( ! block.match( /^(?:\w+:.*\n)*\w+:.*$/ ) ) return undefined;
1218 |
1219 | // make an attribute node if it doesn't exist
1220 | if ( !extract_attr( this.tree ) ) {
1221 | this.tree.splice( 1, 0, {} );
1222 | }
1223 |
1224 | var pairs = block.split( /\n/ );
1225 | for ( p in pairs ) {
1226 | var m = pairs[ p ].match( /(\w+):\s*(.*)$/ ),
1227 | key = m[ 1 ].toLowerCase(),
1228 | value = m[ 2 ];
1229 |
1230 | this.tree[ 1 ][ key ] = value;
1231 | }
1232 |
1233 | // document_meta produces no content!
1234 | return [];
1235 | };
1236 |
1237 | Markdown.dialects.Maruku.block.block_meta = function block_meta( block, next ) {
1238 | // check if the last line of the block is an meta hash
1239 | var m = block.match( /(^|\n) {0,3}\{:\s*((?:\\\}|[^\}])*)\s*\}$/ );
1240 | if ( !m ) return undefined;
1241 |
1242 | // process the meta hash
1243 | var attr = this.dialect.processMetaHash( m[ 2 ] );
1244 |
1245 | var hash;
1246 |
1247 | // if we matched ^ then we need to apply meta to the previous block
1248 | if ( m[ 1 ] === "" ) {
1249 | var node = this.tree[ this.tree.length - 1 ];
1250 | hash = extract_attr( node );
1251 |
1252 | // if the node is a string (rather than JsonML), bail
1253 | if ( typeof node === "string" ) return undefined;
1254 |
1255 | // create the attribute hash if it doesn't exist
1256 | if ( !hash ) {
1257 | hash = {};
1258 | node.splice( 1, 0, hash );
1259 | }
1260 |
1261 | // add the attributes in
1262 | for ( a in attr ) {
1263 | hash[ a ] = attr[ a ];
1264 | }
1265 |
1266 | // return nothing so the meta hash is removed
1267 | return [];
1268 | }
1269 |
1270 | // pull the meta hash off the block and process what's left
1271 | var b = block.replace( /\n.*$/, "" ),
1272 | result = this.processBlock( b, [] );
1273 |
1274 | // get or make the attributes hash
1275 | hash = extract_attr( result[ 0 ] );
1276 | if ( !hash ) {
1277 | hash = {};
1278 | result[ 0 ].splice( 1, 0, hash );
1279 | }
1280 |
1281 | // attach the attributes to the block
1282 | for ( a in attr ) {
1283 | hash[ a ] = attr[ a ];
1284 | }
1285 |
1286 | return result;
1287 | };
1288 |
1289 | Markdown.dialects.Maruku.block.definition_list = function definition_list( block, next ) {
1290 | // one or more terms followed by one or more definitions, in a single block
1291 | var tight = /^((?:[^\s:].*\n)+):\s+([\s\S]+)$/,
1292 | list = [ "dl" ],
1293 | i, m;
1294 |
1295 | // see if we're dealing with a tight or loose block
1296 | if ( ( m = block.match( tight ) ) ) {
1297 | // pull subsequent tight DL blocks out of `next`
1298 | var blocks = [ block ];
1299 | while ( next.length && tight.exec( next[ 0 ] ) ) {
1300 | blocks.push( next.shift() );
1301 | }
1302 |
1303 | for ( var b = 0; b < blocks.length; ++b ) {
1304 | var m = blocks[ b ].match( tight ),
1305 | terms = m[ 1 ].replace( /\n$/, "" ).split( /\n/ ),
1306 | defns = m[ 2 ].split( /\n:\s+/ );
1307 |
1308 | // print( uneval( m ) );
1309 |
1310 | for ( i = 0; i < terms.length; ++i ) {
1311 | list.push( [ "dt", terms[ i ] ] );
1312 | }
1313 |
1314 | for ( i = 0; i < defns.length; ++i ) {
1315 | // run inline processing over the definition
1316 | list.push( [ "dd" ].concat( this.processInline( defns[ i ].replace( /(\n)\s+/, "$1" ) ) ) );
1317 | }
1318 | }
1319 | }
1320 | else {
1321 | return undefined;
1322 | }
1323 |
1324 | return [ list ];
1325 | };
1326 |
1327 | // splits on unescaped instances of @ch. If @ch is not a character the result
1328 | // can be unpredictable
1329 |
1330 | Markdown.dialects.Maruku.block.table = function table (block, next) {
1331 |
1332 | var _split_on_unescaped = function(s, ch) {
1333 | ch = ch || '\\s';
1334 | if (ch.match(/^[\\|\[\]{}?*.+^$]$/)) { ch = '\\' + ch; }
1335 | var res = [ ],
1336 | r = new RegExp('^((?:\\\\.|[^\\\\' + ch + '])*)' + ch + '(.*)'),
1337 | m;
1338 | while(m = s.match(r)) {
1339 | res.push(m[1]);
1340 | s = m[2];
1341 | }
1342 | res.push(s);
1343 | return res;
1344 | }
1345 |
1346 | var leading_pipe = /^ {0,3}\|(.+)\n {0,3}\|\s*([\-:]+[\-| :]*)\n((?:\s*\|.*(?:\n|$))*)(?=\n|$)/,
1347 | // find at least an unescaped pipe in each line
1348 | no_leading_pipe = /^ {0,3}(\S(?:\\.|[^\\|])*\|.*)\n {0,3}([\-:]+\s*\|[\-| :]*)\n((?:(?:\\.|[^\\|])*\|.*(?:\n|$))*)(?=\n|$)/,
1349 | i, m;
1350 | if (m = block.match(leading_pipe)) {
1351 | // remove leading pipes in contents
1352 | // (header and horizontal rule already have the leading pipe left out)
1353 | m[3] = m[3].replace(/^\s*\|/gm, '');
1354 | } else if (! ( m = block.match(no_leading_pipe))) {
1355 | return undefined;
1356 | }
1357 |
1358 | var table = [ "table", [ "thead", [ "tr" ] ], [ "tbody" ] ];
1359 |
1360 | // remove trailing pipes, then split on pipes
1361 | // (no escaped pipes are allowed in horizontal rule)
1362 | m[2] = m[2].replace(/\|\s*$/, '').split('|');
1363 |
1364 | // process alignment
1365 | var html_attrs = [ ];
1366 | forEach (m[2], function (s) {
1367 | if (s.match(/^\s*-+:\s*$/)) html_attrs.push({align: "right"});
1368 | else if (s.match(/^\s*:-+\s*$/)) html_attrs.push({align: "left"});
1369 | else if (s.match(/^\s*:-+:\s*$/)) html_attrs.push({align: "center"});
1370 | else html_attrs.push({});
1371 | });
1372 |
1373 | // now for the header, avoid escaped pipes
1374 | m[1] = _split_on_unescaped(m[1].replace(/\|\s*$/, ''), '|');
1375 | for (i = 0; i < m[1].length; i++) {
1376 | table[1][1].push(['th', html_attrs[i] || {}].concat(
1377 | this.processInline(m[1][i].trim())));
1378 | }
1379 |
1380 | // now for body contents
1381 | forEach (m[3].replace(/\|\s*$/mg, '').split('\n'), function (row) {
1382 | var html_row = ['tr'];
1383 | row = _split_on_unescaped(row, '|');
1384 | for (i = 0; i < row.length; i++) {
1385 | html_row.push(['td', html_attrs[i] || {}].concat(this.processInline(row[i].trim())));
1386 | }
1387 | table[2].push(html_row);
1388 | }, this);
1389 |
1390 | return [table];
1391 | }
1392 |
1393 | Markdown.dialects.Maruku.inline[ "{:" ] = function inline_meta( text, matches, out ) {
1394 | if ( !out.length ) {
1395 | return [ 2, "{:" ];
1396 | }
1397 |
1398 | // get the preceeding element
1399 | var before = out[ out.length - 1 ];
1400 |
1401 | if ( typeof before === "string" ) {
1402 | return [ 2, "{:" ];
1403 | }
1404 |
1405 | // match a meta hash
1406 | var m = text.match( /^\{:\s*((?:\\\}|[^\}])*)\s*\}/ );
1407 |
1408 | // no match, false alarm
1409 | if ( !m ) {
1410 | return [ 2, "{:" ];
1411 | }
1412 |
1413 | // attach the attributes to the preceeding element
1414 | var meta = this.dialect.processMetaHash( m[ 1 ] ),
1415 | attr = extract_attr( before );
1416 |
1417 | if ( !attr ) {
1418 | attr = {};
1419 | before.splice( 1, 0, attr );
1420 | }
1421 |
1422 | for ( var k in meta ) {
1423 | attr[ k ] = meta[ k ];
1424 | }
1425 |
1426 | // cut out the string and replace it with nothing
1427 | return [ m[ 0 ].length, "" ];
1428 | };
1429 |
1430 | Markdown.dialects.Maruku.inline.__escape__ = /^\\[\\`\*_{}\[\]()#\+.!\-|:]/;
1431 |
1432 | Markdown.buildBlockOrder ( Markdown.dialects.Maruku.block );
1433 | Markdown.buildInlinePatterns( Markdown.dialects.Maruku.inline );
1434 |
1435 | var isArray = Array.isArray || function(obj) {
1436 | return Object.prototype.toString.call(obj) == "[object Array]";
1437 | };
1438 |
1439 | var forEach;
1440 | // Don't mess with Array.prototype. Its not friendly
1441 | if ( Array.prototype.forEach ) {
1442 | forEach = function( arr, cb, thisp ) {
1443 | return arr.forEach( cb, thisp );
1444 | };
1445 | }
1446 | else {
1447 | forEach = function(arr, cb, thisp) {
1448 | for (var i = 0; i < arr.length; i++) {
1449 | cb.call(thisp || arr, arr[i], i, arr);
1450 | }
1451 | }
1452 | }
1453 |
1454 | var isEmpty = function( obj ) {
1455 | for ( var key in obj ) {
1456 | if ( hasOwnProperty.call( obj, key ) ) {
1457 | return false;
1458 | }
1459 | }
1460 |
1461 | return true;
1462 | }
1463 |
1464 | function extract_attr( jsonml ) {
1465 | return isArray(jsonml)
1466 | && jsonml.length > 1
1467 | && typeof jsonml[ 1 ] === "object"
1468 | && !( isArray(jsonml[ 1 ]) )
1469 | ? jsonml[ 1 ]
1470 | : undefined;
1471 | }
1472 |
1473 |
1474 |
1475 | /**
1476 | * renderJsonML( jsonml[, options] ) -> String
1477 | * - jsonml (Array): JsonML array to render to XML
1478 | * - options (Object): options
1479 | *
1480 | * Converts the given JsonML into well-formed XML.
1481 | *
1482 | * The options currently understood are:
1483 | *
1484 | * - root (Boolean): wether or not the root node should be included in the
1485 | * output, or just its children. The default `false` is to not include the
1486 | * root itself.
1487 | */
1488 | expose.renderJsonML = function( jsonml, options ) {
1489 | options = options || {};
1490 | // include the root element in the rendered output?
1491 | options.root = options.root || false;
1492 |
1493 | var content = [];
1494 |
1495 | if ( options.root ) {
1496 | content.push( render_tree( jsonml ) );
1497 | }
1498 | else {
1499 | jsonml.shift(); // get rid of the tag
1500 | if ( jsonml.length && typeof jsonml[ 0 ] === "object" && !( jsonml[ 0 ] instanceof Array ) ) {
1501 | jsonml.shift(); // get rid of the attributes
1502 | }
1503 |
1504 | while ( jsonml.length ) {
1505 | content.push( render_tree( jsonml.shift() ) );
1506 | }
1507 | }
1508 |
1509 | return content;
1510 | };
1511 |
1512 | function escapeHTML( text ) {
1513 | return text.replace( /&/g, "&" )
1514 | .replace( //g, ">" )
1516 | .replace( /"/g, """ )
1517 | .replace( /'/g, "'" );
1518 | }
1519 |
1520 | function render_tree( jsonml ) {
1521 | // basic case
1522 | if ( typeof jsonml === "string" ) {
1523 | return ReactHelpers.htmlReactLinks('text', null, escapeHTML(jsonml)); // Here is the magic
1524 | }
1525 |
1526 | var tag = jsonml.shift(),
1527 | attributes = {},
1528 | content = [];
1529 |
1530 | if ( jsonml.length && typeof jsonml[ 0 ] === "object" && !( jsonml[ 0 ] instanceof Array ) ) {
1531 | attributes = jsonml.shift();
1532 | }
1533 |
1534 | while ( jsonml.length ) {
1535 | content.push( render_tree( jsonml.shift() ) );
1536 | }
1537 |
1538 | var tag_attrs = "";
1539 | for ( var a in attributes ) {
1540 | tag_attrs += " " + a + '="' + escapeHTML( attributes[ a ] ) + '"';
1541 | }
1542 | return ReactHelpers.htmlReactLinks(tag, tag_attrs, content); // Here is the magic
1543 | }
1544 |
1545 | function convert_tree_to_html( tree, references, options ) {
1546 | var i;
1547 | options = options || {};
1548 |
1549 | // shallow clone
1550 | var jsonml = tree.slice( 0 );
1551 |
1552 | if ( typeof options.preprocessTreeNode === "function" ) {
1553 | jsonml = options.preprocessTreeNode(jsonml, references);
1554 | }
1555 |
1556 | // Clone attributes if they exist
1557 | var attrs = extract_attr( jsonml );
1558 | if ( attrs ) {
1559 | jsonml[ 1 ] = {};
1560 | for ( i in attrs ) {
1561 | jsonml[ 1 ][ i ] = attrs[ i ];
1562 | }
1563 | attrs = jsonml[ 1 ];
1564 | }
1565 |
1566 | // basic case
1567 | if ( typeof jsonml === "string" ) {
1568 | return jsonml;
1569 | }
1570 |
1571 | // convert this node
1572 | switch ( jsonml[ 0 ] ) {
1573 | case "header":
1574 | jsonml[ 0 ] = "h" + jsonml[ 1 ].level;
1575 | delete jsonml[ 1 ].level;
1576 | break;
1577 | case "bulletlist":
1578 | jsonml[ 0 ] = "ul";
1579 | break;
1580 | case "numberlist":
1581 | jsonml[ 0 ] = "ol";
1582 | break;
1583 | case "listitem":
1584 | jsonml[ 0 ] = "li";
1585 | break;
1586 | case "para":
1587 | jsonml[ 0 ] = "p";
1588 | break;
1589 | case "markdown":
1590 | jsonml[ 0 ] = "html";
1591 | if ( attrs ) delete attrs.references;
1592 | break;
1593 | case "code_block":
1594 | jsonml[ 0 ] = "pre";
1595 | i = attrs ? 2 : 1;
1596 | var code = [ "code" ];
1597 | code.push.apply( code, jsonml.splice( i, jsonml.length - i ) );
1598 | jsonml[ i ] = code;
1599 | break;
1600 | case "inlinecode":
1601 | jsonml[ 0 ] = "code";
1602 | break;
1603 | case "img":
1604 | jsonml[ 1 ].src = jsonml[ 1 ].href;
1605 | delete jsonml[ 1 ].href;
1606 | break;
1607 | case "linebreak":
1608 | jsonml[ 0 ] = "br";
1609 | break;
1610 | case "link":
1611 | jsonml[ 0 ] = "a";
1612 | break;
1613 | case "link_ref":
1614 | jsonml[ 0 ] = "a";
1615 |
1616 | // grab this ref and clean up the attribute node
1617 | var ref = references[ attrs.ref ];
1618 |
1619 | // if the reference exists, make the link
1620 | if ( ref ) {
1621 | delete attrs.ref;
1622 |
1623 | // add in the href and title, if present
1624 | attrs.href = ref.href;
1625 | if ( ref.title ) {
1626 | attrs.title = ref.title;
1627 | }
1628 |
1629 | // get rid of the unneeded original text
1630 | delete attrs.original;
1631 | }
1632 | // the reference doesn't exist, so revert to plain text
1633 | else {
1634 | return attrs.original;
1635 | }
1636 | break;
1637 | case "img_ref":
1638 | jsonml[ 0 ] = "img";
1639 |
1640 | // grab this ref and clean up the attribute node
1641 | var ref = references[ attrs.ref ];
1642 |
1643 | // if the reference exists, make the link
1644 | if ( ref ) {
1645 | delete attrs.ref;
1646 |
1647 | // add in the href and title, if present
1648 | attrs.src = ref.href;
1649 | if ( ref.title ) {
1650 | attrs.title = ref.title;
1651 | }
1652 |
1653 | // get rid of the unneeded original text
1654 | delete attrs.original;
1655 | }
1656 | // the reference doesn't exist, so revert to plain text
1657 | else {
1658 | return attrs.original;
1659 | }
1660 | break;
1661 | }
1662 |
1663 | // convert all the children
1664 | i = 1;
1665 |
1666 | // deal with the attribute node, if it exists
1667 | if ( attrs ) {
1668 | // if there are keys, skip over it
1669 | for ( var key in jsonml[ 1 ] ) {
1670 | i = 2;
1671 | break;
1672 | }
1673 | // if there aren't, remove it
1674 | if ( i === 1 ) {
1675 | jsonml.splice( i, 1 );
1676 | }
1677 | }
1678 |
1679 | for ( ; i < jsonml.length; ++i ) {
1680 | jsonml[ i ] = convert_tree_to_html( jsonml[ i ], references, options );
1681 | }
1682 |
1683 | return jsonml;
1684 | }
1685 |
1686 |
1687 | // merges adjacent text nodes into a single node
1688 | function merge_text_nodes( jsonml ) {
1689 | // skip the tag name and attribute hash
1690 | var i = extract_attr( jsonml ) ? 2 : 1;
1691 |
1692 | while ( i < jsonml.length ) {
1693 | // if it's a string check the next item too
1694 | if ( typeof jsonml[ i ] === "string" ) {
1695 | if ( i + 1 < jsonml.length && typeof jsonml[ i + 1 ] === "string" ) {
1696 | // merge the second string into the first and remove it
1697 | jsonml[ i ] += jsonml.splice( i + 1, 1 )[ 0 ];
1698 | }
1699 | else {
1700 | ++i;
1701 | }
1702 | }
1703 | // if it's not a string recurse
1704 | else {
1705 | merge_text_nodes( jsonml[ i ] );
1706 | ++i;
1707 | }
1708 | }
1709 | }
1710 |
1711 | } )( (function() {
1712 | return exports;
1713 | } )() );
1714 |
--------------------------------------------------------------------------------
/lib/react_helpers.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {
3 | Linking,
4 | Text,
5 | View,
6 | } from 'react-native';
7 | import _ from 'lodash';
8 | import { mdStyle } from '../Markdown';
9 |
10 | exports.htmlReactLinks = (tag, tag_attrs, content) => {
11 | if (tag === 'text') {
12 | return (
13 |
14 | {content}
15 |
16 | );
17 | }
18 | switch (true) {
19 | case /^h[123456]?$/.test(tag):
20 | case tag === 'strong':
21 | case tag === 'em':
22 | case tag === 'p':
23 | case tag === 'html':
24 | case tag === 'code':
25 | return (
26 |
27 | {content}
28 |
29 | );
30 | case tag === 'a':
31 | console.log(/href="(.*)"/.exec(tag_attrs)[1]);
32 | return (
33 | {
34 | Linking.openURL(/href="(.*)"/.exec(tag_attrs)[1]);
35 | }}>
36 | {content}
37 |
38 | );
39 | case tag === 'pre':
40 | return (
41 |
42 |
43 | {content}
44 |
45 |
46 | );
47 | case tag === 'blockquote':
48 | return (
49 |
50 |
51 |
52 | {content}
53 |
54 |
55 | );
56 | case tag === 'ul':
57 | case tag === 'ol':
58 | return (
59 |
60 | {content}
61 |
62 | );
63 | case /^[0-9]+li$/.test(tag):
64 | return (
65 |
66 |
67 | {/^[0-9]+/.exec(tag)[0]}.{' '}
68 |
69 |
70 | {content}
71 |
72 |
73 | );
74 | case tag === 'li':
75 | return (
76 |
77 |
78 |
79 | {content}
80 |
81 |
82 | );
83 | case tag === 'br':
84 | return (
85 |
86 | {content}
87 | {'\n'}
88 |
89 | );
90 | default:
91 | return (
92 |
93 | {content}
94 |
95 | );
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-markdown-syntax",
3 | "version": "0.1.0",
4 | "description": "A markdown component for react-native",
5 | "keywords": [
6 | "markdown",
7 | "text processing",
8 | "ast",
9 | "react native"
10 | ],
11 | "maintainers": [
12 | "Pierre Monge "
13 | ],
14 | "contributors": [
15 | "Dominic Baggott (http://evilstreak.co.uk)",
16 | "Ash Berlin (http://ashberlin.com)",
17 | "XhmikosR ",
18 | "Robin Ward (http://eviltrout.com)",
19 | "Pierre Monge "
20 | ],
21 | "bugs": {
22 | "url": "https://github.com/Liroo/react-native-markdown-syntax/issues"
23 | },
24 | "license": "MIT",
25 | "repository": {
26 | "type": "git",
27 | "url": "git://github.com/Liroo/react-native-markdown-syntax.git"
28 | },
29 | "main": "./Markdown.js",
30 | "files": [
31 | "lib",
32 | "README.md"
33 | ],
34 | "dependencies": {
35 | "lodash": "^4.16.4"
36 | },
37 | "scripts": {
38 | "test": "echo \"No tests specified\" && exit 1"
39 | }
40 | }
41 |
--------------------------------------------------------------------------------