Add support for syntax highlighting for languages other than JS

Summary:
The current website defaults to using JavaScript for any code block, regardless of language tag. This PR adds syntax highlighting support by passing the necessary language prop and by adding any missing languages to Marked.js.

Depends on #14212, #14065
Closes https://github.com/facebook/react-native/pull/14215

Differential Revision: D5149897

Pulled By: hramos

fbshipit-source-id: 95a817af2168d5743c75dd1ac030d399a68fb93c
This commit is contained in:
Hector Ramos 2017-05-30 14:30:38 -07:00 committed by Facebook Github Bot
parent b1ecb84c97
commit 0a6935618c
8 changed files with 880 additions and 417 deletions

View File

@ -240,7 +240,7 @@ React Native also requires a recent version of the [Java SE Development Kit (JDK
Open an Administrator Command Prompt (right click Command Prompt and select "Run as Administrator"), then run the following commands:
```
```powershell
choco install nodejs.install
choco install python2
choco install jdk8
@ -272,7 +272,7 @@ Node comes with npm, which lets you install the React Native command line interf
Run the following command in a Command Prompt or shell:
```
```powershell
npm install -g react-native-cli
```
@ -430,7 +430,7 @@ Open the System pane under **System and Security** in the Control Panel, then cl
The SDK is installed, by default, at the following location:
```
```powershell
c:\Users\YOUR_USERNAME\AppData\Local\Android\Sdk
```
@ -646,7 +646,6 @@ function displayTab(type, value) {
var container = document.getElementsByTagName('block')[0].parentNode;
container.className = 'display-' + type + '-' + value + ' ' +
container.className.replace(RegExp('display-' + type + '-[a-z]+ ?'), '');
console.log(container.className);
event && event.preventDefault();
}
</script>

View File

@ -143,7 +143,7 @@ To ensure a smooth experience, create a new folder for your integrated React Nat
Go to the root directory for your project and create a new `package.json` file with the following contents:
```bash
```
{
"name": "MyReactNativeApp",
"version": "0.0.1",
@ -156,7 +156,7 @@ Go to the root directory for your project and create a new `package.json` file w
Next, you will install the `react` and `react-native` packages. Open a terminal or command prompt, then navigate to the root directory for your project and type the following commands:
```bash
```
$ npm install --save react react-native
```
@ -170,7 +170,7 @@ This will create a new `/node_modules` folder in your project's root directory.
We recommend installing CocoaPods using [Homebrew](http://brew.sh/).
```bash
```
$ brew install cocoapods
```
@ -200,7 +200,7 @@ The list of supported `subspec`s is available in [`/node_modules/react-native/Re
You can specify which `subspec`s your app will depend on in a `Podfile` file. The easiest way to create a `Podfile` is by running the CocoaPods `init` command in the `/ios` subfolder of your project:
```bash
```
$ pod init
```
@ -258,13 +258,13 @@ end
After you have created your `Podfile`, you are ready to install the React Native pod.
```bash
```
$ pod install
```
You should see output such as:
```bash
```
Analyzing dependencies
Fetching podspec for `React` from `../node_modules/react-native`
Downloading dependencies
@ -299,7 +299,7 @@ First, create an empty `index.ios.js` file in the root of your React Native proj
In your `index.ios.js`, create your component. In our sample here, we will add simple `<Text>` component within a styled `<View>`
```js
```javascript
'use strict';
import React from 'react';
@ -377,21 +377,21 @@ We will, for debugging purposes, log that the event handler was invoked. Then, w
First `import` the `RCTRootView` header.
```
```objectivec
#import <React/RCTRootView.h>
```
> The `initialProperties` are here for illustration purposes so we have some data for our high score screen. In our React Native component, we will use `this.props` to get access to that data.
```
```objectivec
- (IBAction)highScoreButtonPressed:(id)sender {
NSLog(@"High Score Button Pressed");
NSURL *jsCodeLocation = [NSURL
URLWithString:@"http://localhost:8081/index.ios.bundle?platform=ios"];
NSURL *jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle?platform=ios"];
RCTRootView *rootView =
[[RCTRootView alloc] initWithBundleURL : jsCodeLocation
moduleName : @"RNHighScores"
initialProperties :
[[RCTRootView alloc] initWithBundleURL: jsCodeLocation
moduleName: @"RNHighScores"
initialProperties:
@{
@"scores" : @[
@{
@ -404,7 +404,7 @@ First `import` the `RCTRootView` header.
}
]
}
launchOptions : nil];
launchOptions: nil];
UIViewController *vc = [[UIViewController alloc] init];
vc.view = rootView;
[self presentViewController:vc animated:YES completion:nil];
@ -417,13 +417,13 @@ First `import` the `RCTRootView` header.
First `import` the `React` library.
```
```javascript
import React
```
> The `initialProperties` are here for illustration purposes so we have some data for our high score screen. In our React Native component, we will use `this.props` to get access to that data.
```
```swift
@IBAction func highScoreButtonTapped(sender : UIButton) {
NSLog("Hello")
let jsCodeLocation = URL(string: "http://localhost:8081/index.ios.bundle?platform=ios")
@ -494,7 +494,7 @@ Apple has blocked implicit cleartext HTTP resource loading. So we need to add th
To run your app, you need to first start the development server. To do this, simply run the following command in the root directory of your React Native project:
```bash
```
$ npm start
```
@ -502,7 +502,7 @@ $ npm start
If you are using Xcode or your favorite editor, build and run your native iOS application as normal. Alternatively, you can run the app from the command line using:
```bash
```
# From the root of your project
$ react-native run-ios
```
@ -593,7 +593,7 @@ First, create an empty `index.android.js` file in the root of your React Native
In your `index.android.js`, create your component. In our sample here, we will add simple `<Text>` component within a styled `<View>`:
```js
```javascript
'use strict';
import React from 'react';
@ -692,11 +692,13 @@ public class MyReactActivity extends Activity implements DefaultHardwareBackBtnH
}
}
```
> If you are using a starter kit for React Native, replace the "HelloWorld" string with the one in your index.android.js file (its the first argument to the `AppRegistry.registerComponent()` method).
If you are using Android Studio, use `Alt + Enter` to add all missing imports in your MyReactActivity class. Be careful to use your packages `BuildConfig` and not the one from the `...facebook...` package.
We need set the theme of `MyReactActivity` to `Theme.AppCompat.Light.NoActionBar` because some components rely on this theme.
```xml
<activity
android:name=".MyReactActivity"
@ -776,7 +778,7 @@ You have now done all the basic steps to integrate React Native with your curren
To run your app, you need to first start the development server. To do this, simply run the following command in the root directory of your React Native project:
```bash
```
$ npm start
```
@ -790,11 +792,13 @@ Once you reach your React-powered activity inside the app, it should load the Ja
### Creating a release build in Android Studio
You can use Android Studio to create your release builds too! Its as easy as creating release builds of your previously-existing native Android app. Theres just one additional step, which youll have to do before every release build. You need to execute the following to create a React Native bundle, whichll be included with your native Android app:
You can use Android Studio to create your release builds too! Its as easy as creating release builds of your previously-existing native Android app. Theres just one additional step, which youll have to do before every release build. You need to execute the following to create a React Native bundle, which will be included with your native Android app:
$ react-native bundle --platform android --dev false --entry-file index.android.js --bundle-output android/com/your-company-name/app-package-name/src/main/assets/index.android.bundle --assets-dest android/com/your-company-name/app-package-name/src/main/res/
```
$ react-native bundle --platform android --dev false --entry-file index.android.js --bundle-output android/com/your-company-name/app-package-name/src/main/assets/index.android.bundle --assets-dest android/com/your-company-name/app-package-name/src/main/res/
```
Dont forget to replace the paths with correct ones and create the assets folder if it doesnt exist!
> Dont forget to replace the paths with correct ones and create the assets folder if it doesnt exist.
Now just create a release build of your native app from within Android Studio as usual and you should be good to go!
@ -809,7 +813,6 @@ function displayTab(type, value) {
var container = document.getElementsByTagName('block')[0].parentNode;
container.className = 'display-' + type + '-' + value + ' ' +
container.className.replace(RegExp('display-' + type + '-[a-z]+ ?'), '');
console.log(container.className);
event && event.preventDefault();
}
</script>

View File

@ -25,7 +25,7 @@ Vending a view is simple:
- Add the `RCT_EXPORT_MODULE()` marker macro.
- Implement the `-(UIView *)view` method.
```objective-c
```objectivec
// RNTMapManager.m
#import <MapKit/MapKit.h>
@ -66,7 +66,7 @@ This is now a fully-functioning native map view component in JavaScript, complet
The first thing we can do to make this component more usable is to bridge over some native properties. Let's say we want to be able to disable pitch control and specify the visible region. Disabling pitch is a simple boolean, so we add this one line:
```objective-c
```objectivec
// RNTMapManager.m
RCT_EXPORT_VIEW_PROPERTY(pitchEnabled, BOOL)
```
@ -113,7 +113,7 @@ Now we have a nicely documented wrapper component that is easy to work with. No
Next, let's add the more complex `region` prop. We start by adding the native code:
```objective-c
```objectivec
// RNTMapManager.m
RCT_CUSTOM_VIEW_PROPERTY(region, MKCoordinateRegion, RNTMap)
{
@ -125,7 +125,7 @@ Ok, this is more complicated than the simple `BOOL` case we had before. Now we
You could write any conversion function you want for your view - here is the implementation for `MKCoordinateRegion` via two categories on `RCTConvert`:
```objective-c
```objectivec
@implementation RCTConvert(CoreLocation)
RCT_CONVERTER(CLLocationDegrees, CLLocationDegrees, doubleValue);
@ -229,7 +229,7 @@ var RCTSwitch = requireNativeComponent('RCTSwitch', Switch, {
So now we have a native map component that we can control easily from JS, but how do we deal with events from the user, like pinch-zooms or panning to change the visible region? The key is to declare an event handler property on `RNTMapManager`, make it a delegate for all the views it vends, and forward events to JS by calling the event handler block from the native view. This looks like so (simplified from the full implementation):
```objective-c
```objectivec
// RNTMap.h
#import <MapKit/MapKit.h>
@ -243,7 +243,7 @@ So now we have a native map component that we can control easily from JS, but ho
@end
```
```objective-c
```objectivec
// RNTMap.m
#import "RNTMap.h"
@ -253,7 +253,7 @@ So now we have a native map component that we can control easily from JS, but ho
@end
```
```objective-c
```objectivec
// RNTMapManager.m
#import "RNTMapManager.h"
@ -383,7 +383,7 @@ var styles = StyleSheet.create({
The `RCTDatePickerIOSConsts` constants are exported from native by grabbing the actual frame of the native component like so:
```objective-c
```objectivec
// RCTDatePickerManager.m
- (NSDictionary *)constantsToExport

View File

@ -21,7 +21,7 @@ This guide will use the [iOS Calendar API](https://developer.apple.com/library/m
A native module is just an Objective-C class that implements the `RCTBridgeModule` protocol. If you are wondering, RCT is an abbreviation of ReaCT.
```objective-c
```objectivec
// CalendarManager.h
#import <React/RCTBridgeModule.h>
@ -31,7 +31,7 @@ A native module is just an Objective-C class that implements the `RCTBridgeModul
In addition to implementing the `RCTBridgeModule` protocol, your class must also include the `RCT_EXPORT_MODULE()` macro. This takes an optional argument that specifies the name that the module will be accessible as in your JavaScript code (more on this later). If you do not specify a name, the JavaScript module name will match the Objective-C class name.
```objective-c
```objectivec
// CalendarManager.m
@implementation CalendarManager
@ -46,7 +46,7 @@ RCT_EXPORT_MODULE();
React Native will not expose any methods of `CalendarManager` to JavaScript unless explicitly told to. This is done using the `RCT_EXPORT_METHOD()` macro:
```objective-c
```objectivec
#import "CalendarManager.h"
#import <React/RCTLog.h>
@ -89,7 +89,7 @@ But it also works with any type that is supported by the `RCTConvert` class (see
In our `CalendarManager` example, we need to pass the event date to the native method. We can't send JavaScript Date objects over the bridge, so we need to convert the date to a string or number. We could write our native function like this:
```objective-c
```objectivec
RCT_EXPORT_METHOD(addEvent:(NSString *)name location:(NSString *)location date:(nonnull NSNumber *)secondsSinceUnixEpoch)
{
NSDate *date = [RCTConvert NSDate:secondsSinceUnixEpoch];
@ -98,7 +98,7 @@ RCT_EXPORT_METHOD(addEvent:(NSString *)name location:(NSString *)location date:(
or like this:
```objective-c
```objectivec
RCT_EXPORT_METHOD(addEvent:(NSString *)name location:(NSString *)location date:(NSString *)ISO8601DateString)
{
NSDate *date = [RCTConvert NSDate:ISO8601DateString];
@ -107,7 +107,7 @@ RCT_EXPORT_METHOD(addEvent:(NSString *)name location:(NSString *)location date:(
But by using the automatic type conversion feature, we can skip the manual conversion step completely, and just write:
```objective-c
```objectivec
RCT_EXPORT_METHOD(addEvent:(NSString *)name location:(NSString *)location date:(NSDate *)date)
{
// Date is ready to use!
@ -130,7 +130,7 @@ And both values would get converted correctly to the native `NSDate`. A bad val
As `CalendarManager.addEvent` method gets more and more complex, the number of arguments will grow. Some of them might be optional. In this case it's worth considering changing the API a little bit to accept a dictionary of event attributes, like this:
```objective-c
```objectivec
#import <React/RCTConvert.h>
RCT_EXPORT_METHOD(addEvent:(NSString *)name details:(NSDictionary *)details)
@ -163,7 +163,7 @@ CalendarManager.addEvent('Birthday Party', {
Native modules also supports a special kind of argument- a callback. In most cases it is used to provide the function call result to JavaScript.
```objective-c
```objectivec
RCT_EXPORT_METHOD(findEvents:(RCTResponseSenderBlock)callback)
{
NSArray *events = ...
@ -193,7 +193,7 @@ Native modules can also fulfill a promise, which can simplify your code, especia
Refactoring the above code to use a promise instead of callbacks looks like this:
```objective-c
```objectivec
RCT_REMAP_METHOD(findEvents,
findEventsWithResolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
@ -228,7 +228,7 @@ updateEvents();
The native module should not have any assumptions about what thread it is being called on. React Native invokes native modules methods on a separate serial GCD queue, but this is an implementation detail and might change. The `- (dispatch_queue_t)methodQueue` method allows the native module to specify which queue its methods should be run on. For example, if it needs to use a main-thread-only iOS API, it should specify this via:
```objective-c
```objectivec
- (dispatch_queue_t)methodQueue
{
return dispatch_get_main_queue();
@ -237,7 +237,7 @@ The native module should not have any assumptions about what thread it is being
Similarly, if an operation may take a long time to complete, the native module should not block and can specify it's own queue to run operations on. For example, the `RCTAsyncLocalStorage` module creates it's own queue so the React queue isn't blocked waiting on potentially slow disk access:
```objective-c
```objectivec
- (dispatch_queue_t)methodQueue
{
return dispatch_queue_create("com.facebook.React.AsyncLocalStorageQueue", DISPATCH_QUEUE_SERIAL);
@ -246,7 +246,7 @@ Similarly, if an operation may take a long time to complete, the native module s
The specified `methodQueue` will be shared by all of the methods in your module. If *just one* of your methods is long-running (or needs to be run on a different queue than the others for some reason), you can use `dispatch_async` inside the method to perform that particular method's code on another queue, without affecting the others:
```objective-c
```objectivec
RCT_EXPORT_METHOD(doSomethingExpensive:(NSString *)param callback:(RCTResponseSenderBlock)callback)
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@ -267,7 +267,7 @@ The bridge initializes any registered RCTBridgeModules automatically, however yo
You can do this by creating a class that implements the RCTBridgeDelegate Protocol, initializing an RCTBridge with the delegate as an argument and initialising a RCTRootView with the initialized bridge.
```objective-c
```objectivec
id<RCTBridgeDelegate> moduleInitialiser = [[classThatImplementsRCTBridgeDelegate alloc] init];
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:moduleInitialiser launchOptions:nil];
@ -282,7 +282,7 @@ RCTRootView *rootView = [[RCTRootView alloc]
A native module can export constants that are immediately available to JavaScript at runtime. This is useful for communicating static data that would otherwise require a round-trip through the bridge.
```objective-c
```objectivec
- (NSDictionary *)constantsToExport
{
return @{ @"firstDayOfTheWeek": @"Monday" };
@ -303,7 +303,7 @@ Enums that are defined via `NS_ENUM` cannot be used as method arguments without
In order to export the following `NS_ENUM` definition:
```objc
```objectivec
typedef NS_ENUM(NSInteger, UIStatusBarAnimation) {
UIStatusBarAnimationNone,
UIStatusBarAnimationFade,
@ -313,7 +313,7 @@ typedef NS_ENUM(NSInteger, UIStatusBarAnimation) {
You must create a class extension of RCTConvert like so:
```objc
```objectivec
@implementation RCTConvert (StatusBarAnimation)
RCT_ENUM_CONVERTER(UIStatusBarAnimation, (@{ @"statusBarAnimationNone" : @(UIStatusBarAnimationNone),
@"statusBarAnimationFade" : @(UIStatusBarAnimationFade),
@ -324,7 +324,7 @@ You must create a class extension of RCTConvert like so:
You can then define methods and export your enum constants like this:
```objc
```objectivec
- (NSDictionary *)constantsToExport
{
return @{ @"statusBarAnimationNone" : @(UIStatusBarAnimationNone),
@ -343,7 +343,7 @@ Your enum will then be automatically unwrapped using the selector provided (`int
The native module can signal events to JavaScript without being invoked directly. The preferred way to do this is to subclass `RCTEventEmitter`, implement `suppportEvents` and call `self sendEventWithName`:
```objective-c
```objectivec
// CalendarManager.h
#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>
@ -353,7 +353,7 @@ The native module can signal events to JavaScript without being invoked directly
@end
```
```objective-c
```objectivec
// CalendarManager.m
#import "CalendarManager.h"
@ -396,7 +396,7 @@ For more examples of sending events to JavaScript, see [`RCTLocationObserver`](h
### Optimizing for zero listeners
You will receive a warning if you expend resources unnecessarily by emitting an event while there are no listeners. To avoid this, and to optimize your module's workload (e.g. by unsubscribing from upstream notifications or pausing background tasks), you can override `startObserving` and `stopObserving` in your `RCTEventEmitter` subclass.
```objective-c
```objectivec
@implementation CalendarManager
{
bool hasListeners;
@ -446,7 +446,7 @@ class CalendarManager: NSObject {
Then create a private implementation file that will register the required information with the React Native bridge:
```objc
```objectivec
// CalendarManagerBridge.m
#import <React/RCTBridgeModule.h>
@ -459,7 +459,7 @@ RCT_EXTERN_METHOD(addEvent:(NSString *)name location:(NSString *)location date:(
For those of you new to Swift and Objective-C, whenever you [mix the two languages in an iOS project](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html), you will also need an additional bridging file, known as a bridging header, to expose the Objective-C files to Swift. Xcode will offer to create this header file for you if you add your Swift file to your app through the Xcode `File>New File` menu option. You will need to import `RCTBridgeModule.h` in this header file.
```objc
```objectivec
// CalendarManager-Bridging-Header.h
#import <React/RCTBridgeModule.h>
```

View File

@ -35,40 +35,41 @@ var block = {
def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
table: noop,
paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
text: /^[^\n]+/
text: /^[^\n]+/,
};
block.bullet = /(?:[*+-]|\d+\.)/;
block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
block.item = replace(block.item, 'gm')
(/bull/g, block.bullet)
();
block.item = replace(block.item, 'gm')(
/bull/g,
block.bullet
)();
block.list = replace(block.list)
(/bull/g, block.bullet)
('hr', /\n+(?=(?: *[-*_]){3,} *(?:\n+|$))/)
();
block.list = replace(block.list)(/bull/g, block.bullet)(
'hr',
/\n+(?=(?: *[-*_]){3,} *(?:\n+|$))/
)();
block._tag = '(?!(?:'
+ 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
+ '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
+ '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|@)\\b';
block._tag = '(?!(?:' +
'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code' +
'|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo' +
'|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|@)\\b';
block.html = replace(block.html)
('comment', /<!--[\s\S]*?-->/)
('closed', /<(tag)[\s\S]+?<\/\1>/)
('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
(/tag/g, block._tag)
();
block.html = replace(block.html)(
'comment',
/<!--[\s\S]*?-->/
)('closed', /<(tag)[\s\S]+?<\/\1>/)(
'closing',
/<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/
)(/tag/g, block._tag)();
block.paragraph = replace(block.paragraph)
('hr', block.hr)
('heading', block.heading)
('lheading', block.lheading)
('blockquote', block.blockquote)
('tag', '<' + block._tag)
('def', block.def)
();
block.paragraph = replace(block.paragraph)('hr', block.hr)(
'heading',
block.heading
)('lheading', block.lheading)(
'blockquote',
block.blockquote
)('tag', '<' + block._tag)('def', block.def)();
/**
* Normal Block Grammar
@ -82,12 +83,15 @@ block.normal = merge({}, block);
block.gfm = merge({}, block.normal, {
fences: /^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/,
paragraph: /^/
paragraph: /^/,
});
block.gfm.paragraph = replace(block.paragraph)
('(?!', '(?!' + block.gfm.fences.source.replace('\\1', '\\2') + '|')
();
block.gfm.paragraph = replace(block.paragraph)(
'(?!',
'(?!' +
block.gfm.fences.source.replace('\\1', '\\2') +
'|'
)();
/**
* GFM + Tables Block Grammar
@ -95,7 +99,7 @@ block.gfm.paragraph = replace(block.paragraph)
block.tables = merge({}, block.gfm, {
nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/,
});
/**
@ -151,59 +155,59 @@ Lexer.prototype.lex = function(src) {
*/
Lexer.prototype.token = function(src, top) {
var src = src.replace(/^ +$/gm, '')
, next
, loose
, cap
, bull
, b
, item
, space
, i
, l;
var src = src.replace(/^ +$/gm, ''),
next,
loose,
cap,
bull,
b,
item,
space,
i,
l;
while (src) {
// newline
if (cap = this.rules.newline.exec(src)) {
if ((cap = this.rules.newline.exec(src))) {
src = src.substring(cap[0].length);
if (cap[0].length > 1) {
this.tokens.push({
type: 'space'
type: 'space',
});
}
}
// code
if (cap = this.rules.code.exec(src)) {
if ((cap = this.rules.code.exec(src))) {
src = src.substring(cap[0].length);
cap = cap[0].replace(/^ {4}/gm, '');
this.tokens.push({
type: 'code',
text: !this.options.pedantic
? cap.replace(/\n+$/, '')
: cap
: cap,
});
continue;
}
// fences (gfm)
if (cap = this.rules.fences.exec(src)) {
if ((cap = this.rules.fences.exec(src))) {
src = src.substring(cap[0].length);
this.tokens.push({
type: 'code',
lang: cap[2],
text: cap[3]
text: cap[3],
});
continue;
}
// heading
if (cap = this.rules.heading.exec(src)) {
if ((cap = this.rules.heading.exec(src))) {
src = src.substring(cap[0].length);
this.tokens.push({
type: 'heading',
depth: cap[1].length,
text: cap[2]
text: cap[2],
});
continue;
}
@ -214,9 +218,13 @@ Lexer.prototype.token = function(src, top) {
item = {
type: 'table',
header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
cells: cap[3].replace(/\n$/, '').split('\n')
header: cap[1]
.replace(/^ *| *\| *$/g, '')
.split(/ *\| */),
align: cap[2]
.replace(/^ *|\| *$/g, '')
.split(/ *\| */),
cells: cap[3].replace(/\n$/, '').split('\n'),
};
for (i = 0; i < item.align.length; i++) {
@ -241,31 +249,31 @@ Lexer.prototype.token = function(src, top) {
}
// lheading
if (cap = this.rules.lheading.exec(src)) {
if ((cap = this.rules.lheading.exec(src))) {
src = src.substring(cap[0].length);
this.tokens.push({
type: 'heading',
depth: cap[2] === '=' ? 1 : 2,
text: cap[1]
text: cap[1],
});
continue;
}
// hr
if (cap = this.rules.hr.exec(src)) {
if ((cap = this.rules.hr.exec(src))) {
src = src.substring(cap[0].length);
this.tokens.push({
type: 'hr'
type: 'hr',
});
continue;
}
// blockquote
if (cap = this.rules.blockquote.exec(src)) {
if ((cap = this.rules.blockquote.exec(src))) {
src = src.substring(cap[0].length);
this.tokens.push({
type: 'blockquote_start'
type: 'blockquote_start',
});
cap = cap[0].replace(/^ *> ?/gm, '');
@ -276,20 +284,20 @@ Lexer.prototype.token = function(src, top) {
this.token(cap, top);
this.tokens.push({
type: 'blockquote_end'
type: 'blockquote_end',
});
continue;
}
// list
if (cap = this.rules.list.exec(src)) {
if ((cap = this.rules.list.exec(src))) {
src = src.substring(cap[0].length);
bull = cap[2];
this.tokens.push({
type: 'list_start',
ordered: bull.length > 1
ordered: bull.length > 1,
});
// Get each top-level item.
@ -312,15 +320,20 @@ Lexer.prototype.token = function(src, top) {
if (~item.indexOf('\n ')) {
space -= item.length;
item = !this.options.pedantic
? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
? item.replace(
new RegExp('^ {1,' + space + '}', 'gm'),
''
)
: item.replace(/^ {1,4}/gm, '');
}
// Determine whether the next list item belongs here.
// Backpedal if it does not belong in this list.
if (this.options.smartLists && i !== l - 1) {
b = block.bullet.exec(cap[i+1])[0];
if (bull !== b && !(bull.length > 1 && b.length > 1)) {
b = block.bullet.exec(cap[i + 1])[0];
if (
bull !== b && !(bull.length > 1 && b.length > 1)
) {
src = cap.slice(i + 1).join('\n') + src;
i = l - 1;
}
@ -331,40 +344,38 @@ Lexer.prototype.token = function(src, top) {
// for discount behavior.
loose = next || /\n\n(?!\s*$)/.test(item);
if (i !== l - 1) {
next = item[item.length-1] === '\n';
next = item[item.length - 1] === '\n';
if (!loose) loose = next;
}
this.tokens.push({
type: loose
? 'loose_item_start'
: 'list_item_start'
: 'list_item_start',
});
// Recurse.
this.token(item, false);
this.tokens.push({
type: 'list_item_end'
type: 'list_item_end',
});
}
this.tokens.push({
type: 'list_end'
type: 'list_end',
});
continue;
}
// html
if (cap = this.rules.html.exec(src)) {
if ((cap = this.rules.html.exec(src))) {
src = src.substring(cap[0].length);
this.tokens.push({
type: this.options.sanitize
? 'paragraph'
: 'html',
type: this.options.sanitize ? 'paragraph' : 'html',
pre: cap[1] === 'pre',
text: cap[0]
text: cap[0],
});
continue;
}
@ -374,7 +385,7 @@ Lexer.prototype.token = function(src, top) {
src = src.substring(cap[0].length);
this.tokens.links[cap[1].toLowerCase()] = {
href: cap[2],
title: cap[3]
title: cap[3],
};
continue;
}
@ -385,9 +396,15 @@ Lexer.prototype.token = function(src, top) {
item = {
type: 'table',
header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
header: cap[1]
.replace(/^ *| *\| *$/g, '')
.split(/ *\| */),
align: cap[2]
.replace(/^ *|\| *$/g, '')
.split(/ *\| */),
cells: cap[3]
.replace(/(?: *\| *)?\n$/, '')
.split('\n'),
};
for (i = 0; i < item.align.length; i++) {
@ -418,27 +435,28 @@ Lexer.prototype.token = function(src, top) {
src = src.substring(cap[0].length);
this.tokens.push({
type: 'paragraph',
text: cap[1][cap[1].length-1] === '\n'
text: cap[1][cap[1].length - 1] === '\n'
? cap[1].slice(0, -1)
: cap[1]
: cap[1],
});
continue;
}
// text
if (cap = this.rules.text.exec(src)) {
if ((cap = this.rules.text.exec(src))) {
// Top-level should never reach here.
src = src.substring(cap[0].length);
this.tokens.push({
type: 'text',
text: cap[0]
text: cap[0],
});
continue;
}
if (src) {
throw new
Error('Infinite loop on byte: ' + src.charCodeAt(0));
throw new Error(
'Infinite loop on byte: ' + src.charCodeAt(0)
);
}
}
@ -462,20 +480,21 @@ var inline = {
code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
br: /^ {2,}\n(?!\s*$)/,
del: noop,
text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/,
};
inline._inside = /(?:\[[^\]]*\]|[^\]]|\](?=[^\[]*\]))*/;
inline._href = /\s*<?([^\s]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
inline.link = replace(inline.link)
('inside', inline._inside)
('href', inline._href)
();
inline.link = replace(inline.link)(
'inside',
inline._inside
)('href', inline._href)();
inline.reflink = replace(inline.reflink)
('inside', inline._inside)
();
inline.reflink = replace(inline.reflink)(
'inside',
inline._inside
)();
/**
* Normal Inline Grammar
@ -489,7 +508,7 @@ inline.normal = merge({}, inline);
inline.pedantic = merge({}, inline.normal, {
strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/,
});
/**
@ -500,10 +519,10 @@ inline.gfm = merge({}, inline.normal, {
escape: replace(inline.escape)('])', '~|])')(),
url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
del: /^~~(?=\S)([\s\S]*?\S)~~/,
text: replace(inline.text)
(']|', '~]|')
('|', '|https?://|')
()
text: replace(inline.text)(']|', '~]|')(
'|',
'|https?://|'
)(),
});
/**
@ -512,7 +531,7 @@ inline.gfm = merge({}, inline.normal, {
inline.breaks = merge({}, inline.gfm, {
br: replace(inline.br)('{2,}', '*')(),
text: replace(inline.gfm.text)('{2,}', '*')()
text: replace(inline.gfm.text)('{2,}', '*')(),
});
/**
@ -525,8 +544,9 @@ function InlineLexer(links, options) {
this.rules = inline.normal;
if (!this.links) {
throw new
Error('Tokens array requires a `links` property.');
throw new Error(
'Tokens array requires a `links` property.'
);
}
if (this.options.gfm) {
@ -560,22 +580,18 @@ InlineLexer.output = function(src, links, options) {
*/
InlineLexer.prototype.output = function(src) {
var out = []
, link
, text
, href
, cap;
var out = [], link, text, href, cap;
while (src) {
// escape
if (cap = this.rules.escape.exec(src)) {
if ((cap = this.rules.escape.exec(src))) {
src = src.substring(cap[0].length);
out.push(cap[1]);
continue;
}
// autolink
if (cap = this.rules.autolink.exec(src)) {
if ((cap = this.rules.autolink.exec(src))) {
src = src.substring(cap[0].length);
if (cap[2] === '@') {
text = cap[1][6] === ':'
@ -586,26 +602,35 @@ InlineLexer.prototype.output = function(src) {
text = cap[1];
href = text;
}
out.push(React.DOM.a({href: this.sanitizeUrl(href)}, text));
out.push(
React.DOM.a({ href: this.sanitizeUrl(href) }, text)
);
continue;
}
// url (gfm)
if (cap = this.rules.url.exec(src)) {
if ((cap = this.rules.url.exec(src))) {
src = src.substring(cap[0].length);
text = cap[1];
href = text;
out.push(React.DOM.a({href: this.sanitizeUrl(href)}, text));
out.push(
React.DOM.a({ href: this.sanitizeUrl(href) }, text)
);
continue;
}
// tag
if (cap = this.rules.tag.exec(src)) {
if ((cap = this.rules.tag.exec(src))) {
src = src.substring(cap[0].length);
var color = cap[0].match('<color ([^ ]+) />');
if (color) {
out.push(React.DOM.span({className: 'color', style: {backgroundColor: color[1]}}));
out.push(
React.DOM.span({
className: 'color',
style: { backgroundColor: color[1] },
})
);
continue;
}
@ -615,18 +640,22 @@ InlineLexer.prototype.output = function(src) {
}
// link
if (cap = this.rules.link.exec(src)) {
if ((cap = this.rules.link.exec(src))) {
src = src.substring(cap[0].length);
out.push(this.outputLink(cap, {
href: cap[2],
title: cap[3]
}));
out.push(
this.outputLink(cap, {
href: cap[2],
title: cap[3],
})
);
continue;
}
// reflink, nolink
if ((cap = this.rules.reflink.exec(src))
|| (cap = this.rules.nolink.exec(src))) {
if (
(cap = this.rules.reflink.exec(src)) ||
(cap = this.rules.nolink.exec(src))
) {
src = src.substring(cap[0].length);
link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
link = this.links[link.toLowerCase()];
@ -640,50 +669,58 @@ InlineLexer.prototype.output = function(src) {
}
// strong
if (cap = this.rules.strong.exec(src)) {
if ((cap = this.rules.strong.exec(src))) {
src = src.substring(cap[0].length);
out.push(React.DOM.strong(null, this.output(cap[2] || cap[1])));
out.push(
React.DOM.strong(
null,
this.output(cap[2] || cap[1])
)
);
continue;
}
// em
if (cap = this.rules.em.exec(src)) {
if ((cap = this.rules.em.exec(src))) {
src = src.substring(cap[0].length);
out.push(React.DOM.em(null, this.output(cap[2] || cap[1])));
out.push(
React.DOM.em(null, this.output(cap[2] || cap[1]))
);
continue;
}
// code
if (cap = this.rules.code.exec(src)) {
if ((cap = this.rules.code.exec(src))) {
src = src.substring(cap[0].length);
out.push(React.DOM.code(null, cap[2]));
continue;
}
// br
if (cap = this.rules.br.exec(src)) {
if ((cap = this.rules.br.exec(src))) {
src = src.substring(cap[0].length);
out.push(React.DOM.br(null, null));
continue;
}
// del (gfm)
if (cap = this.rules.del.exec(src)) {
if ((cap = this.rules.del.exec(src))) {
src = src.substring(cap[0].length);
out.push(React.DOM.del(null, this.output(cap[1])));
continue;
}
// text
if (cap = this.rules.text.exec(src)) {
if ((cap = this.rules.text.exec(src))) {
src = src.substring(cap[0].length);
out.push(this.smartypants(cap[0]));
continue;
}
if (src) {
throw new
Error('Infinite loop on byte: ' + src.charCodeAt(0));
throw new Error(
'Infinite loop on byte: ' + src.charCodeAt(0)
);
}
}
@ -698,8 +735,8 @@ InlineLexer.prototype.sanitizeUrl = function(url) {
if (this.options.sanitize) {
try {
var prot = decodeURIComponent(url)
.replace(/[^A-Za-z0-9:]/g, '')
.toLowerCase();
.replace(/[^A-Za-z0-9:]/g, '')
.toLowerCase();
if (prot.indexOf('javascript:') === 0) {
return '#';
}
@ -716,21 +753,26 @@ InlineLexer.prototype.sanitizeUrl = function(url) {
InlineLexer.prototype.outputLink = function(cap, link) {
if (cap[0][0] !== '!') {
var shouldOpenInNewWindow =
link.href.charAt(0) !== '/'
&& link.href.charAt(0) !== '#';
var shouldOpenInNewWindow = link.href.charAt(0) !==
'/' && link.href.charAt(0) !== '#';
return React.DOM.a({
href: this.sanitizeUrl(link.href),
title: link.title,
target: shouldOpenInNewWindow ? '_blank' : ''
}, this.output(cap[1]));
return React.DOM.a(
{
href: this.sanitizeUrl(link.href),
title: link.title,
target: shouldOpenInNewWindow ? '_blank' : '',
},
this.output(cap[1])
);
} else {
return React.DOM.img({
src: this.sanitizeUrl(link.href),
alt: cap[1],
title: link.title
}, null);
return React.DOM.img(
{
src: this.sanitizeUrl(link.href),
alt: cap[1],
title: link.title,
},
null
);
}
};
@ -787,7 +829,7 @@ Parser.prototype.parse = function(src) {
*/
Parser.prototype.next = function() {
return this.token = this.tokens.pop();
return (this.token = this.tokens.pop());
};
/**
@ -795,7 +837,7 @@ Parser.prototype.next = function() {
*/
Parser.prototype.peek = function() {
return this.tokens[this.tokens.length-1] || 0;
return this.tokens[this.tokens.length - 1] || 0;
};
/**
@ -828,61 +870,83 @@ Parser.prototype.tok = function() {
return (
<Header
level={this.token.depth}
toSlug={this.token.text}>
toSlug={this.token.text}
>
{this.inline.output(this.token.text)}
</Header>
);
}
case 'code': {
var lang = this.token.lang
, text = this.token.text;
var lang = this.token.lang, text = this.token.text;
if (lang && lang.indexOf('ReactNativeWebPlayer') === 0) {
if (
lang && lang.indexOf('ReactNativeWebPlayer') === 0
) {
return (
<WebPlayer params={lang.split('?')[1]}>{text}</WebPlayer>
<WebPlayer params={lang.split('?')[1]}>
{text}
</WebPlayer>
);
}
if (lang && lang.indexOf('SnackPlayer') === 0) {
return (
<SnackPlayer params={lang.split('?')[1]}>{text}</SnackPlayer>
<SnackPlayer params={lang.split('?')[1]}>
{text}
</SnackPlayer>
);
}
if (lang) {
return <Prism language={lang}>{text}</Prism>;
}
return <Prism>{text}</Prism>;
}
case 'table': {
var table = []
, body = []
, row = []
, heading
, i
, cells
, j;
var table = [],
body = [],
row = [],
heading,
i,
cells,
j;
// header
for (i = 0; i < this.token.header.length; i++) {
heading = this.inline.output(this.token.header[i]);
row.push(React.DOM.th(
this.token.align[i]
? {style: {textAlign: this.token.align[i]}}
: null,
heading
));
row.push(
React.DOM.th(
this.token.align[i]
? {
style: { textAlign: this.token.align[i] },
}
: null,
heading
)
);
}
table.push(React.DOM.thead(null, React.DOM.tr(null, row)));
table.push(
React.DOM.thead(null, React.DOM.tr(null, row))
);
// body
for (i = 0; i < this.token.cells.length; i++) {
row = [];
cells = this.token.cells[i];
for (j = 0; j < cells.length; j++) {
row.push(React.DOM.td(
this.token.align[j]
? {style: {textAlign: this.token.align[j]}}
: null,
this.inline.output(cells[j])
));
row.push(
React.DOM.td(
this.token.align[j]
? {
style: {
textAlign: this.token.align[j],
},
}
: null,
this.inline.output(cells[j])
)
);
}
body.push(React.DOM.tr(null, row));
}
@ -900,8 +964,8 @@ Parser.prototype.tok = function() {
return React.DOM.blockquote(null, body);
}
case 'list_start': {
var type = this.token.ordered ? 'ol' : 'ul'
, body = [];
var type = this.token.ordered ? 'ol' : 'ul',
body = [];
while (this.next().type !== 'list_end') {
body.push(this.tok());
@ -913,9 +977,11 @@ Parser.prototype.tok = function() {
var body = [];
while (this.next().type !== 'list_item_end') {
body.push(this.token.type === 'text'
? this.parseText()
: this.tok());
body.push(
this.token.type === 'text'
? this.parseText()
: this.tok()
);
}
return React.DOM.li(null, body);
@ -931,17 +997,30 @@ Parser.prototype.tok = function() {
}
case 'html': {
return !this.token.pre && !this.options.pedantic
? React.DOM.span({dangerouslySetInnerHTML: {__html: this.token.text}})
? React.DOM.span({
dangerouslySetInnerHTML: {
__html: this.token.text,
},
})
: this.token.text;
}
case 'paragraph': {
return this.options.paragraphFn
? this.options.paragraphFn.call(null, this.inline.output(this.token.text))
: React.DOM.p(null, this.inline.output(this.token.text));
? this.options.paragraphFn.call(
null,
this.inline.output(this.token.text)
)
: React.DOM.p(
null,
this.inline.output(this.token.text)
);
}
case 'text': {
return this.options.paragraphFn
? this.options.paragraphFn.call(null, this.parseText())
? this.options.paragraphFn.call(
null,
this.parseText()
)
: React.DOM.p(null, this.parseText());
}
}
@ -976,14 +1055,14 @@ function noop() {}
noop.exec = noop;
function merge(obj) {
var i = 1
, target
, key;
var i = 1, target, key;
for (; i < arguments.length; i++) {
target = arguments[i];
for (key in target) {
if (Object.prototype.hasOwnProperty.call(target, key)) {
if (
Object.prototype.hasOwnProperty.call(target, key)
) {
obj[key] = target[key];
}
}
@ -1005,13 +1084,10 @@ function marked(src, opt, callback) {
if (opt) opt = merge({}, marked.defaults, opt);
var highlight = opt.highlight
, tokens
, pending
, i = 0;
var highlight = opt.highlight, tokens, pending, i = 0;
try {
tokens = Lexer.lex(src, opt)
tokens = Lexer.lex(src, opt);
} catch (e) {
return callback(e);
}
@ -1033,9 +1109,7 @@ function marked(src, opt, callback) {
opt.highlight = highlight;
return err
? callback(err)
: callback(null, out);
return err ? callback(err) : callback(null, out);
};
if (!highlight || highlight.length < 3) {
@ -1049,14 +1123,18 @@ function marked(src, opt, callback) {
if (token.type !== 'code') {
return --pending || done();
}
return highlight(token.text, token.lang, function(err, code) {
if (code == null || code === token.text) {
return --pending || done();
return highlight(
token.text,
token.lang,
function(err, code) {
if (code == null || code === token.text) {
return --pending || done();
}
token.text = code;
token.escaped = true;
--pending || done();
}
token.text = code;
token.escaped = true;
--pending || done();
});
);
})(tokens[i]);
}
@ -1068,8 +1146,10 @@ function marked(src, opt, callback) {
} catch (e) {
e.message += '\nPlease report this to https://github.com/chjj/marked.';
if ((opt || marked.defaults).silent) {
return [React.DOM.p(null, "An error occurred:"),
React.DOM.pre(null, e.message)];
return [
React.DOM.p(null, 'An error occurred:'),
React.DOM.pre(null, e.message),
];
}
throw e;
}
@ -1079,11 +1159,10 @@ function marked(src, opt, callback) {
* Options
*/
marked.options =
marked.setOptions = function(opt) {
marked.options = (marked.setOptions = function(opt) {
merge(marked.defaults, opt);
return marked;
};
});
marked.defaults = {
gfm: true,
@ -1096,7 +1175,7 @@ marked.defaults = {
highlight: null,
langPrefix: 'lang-',
smartypants: false,
paragraphFn: null
paragraphFn: null,
};
/**
@ -1116,10 +1195,13 @@ marked.parse = marked;
var Marked = React.createClass({
render: function() {
return this.props.children ?
React.DOM.div(null, marked(this.props.children, this.props)) :
null;
}
return this.props.children
? React.DOM.div(
null,
marked(this.props.children, this.props)
)
: null;
},
});
module.exports = Marked;

View File

@ -14,12 +14,14 @@ var React = require('React');
var _ = {
util: {
type: function (o) {
return Object.prototype.toString.call(o).match(/\[object (\w+)\]/)[1];
type: function(o) {
return Object.prototype.toString
.call(o)
.match(/\[object (\w+)\]/)[1];
},
// Deep clone a language definition (e.g. to extend it)
clone: function (o) {
clone: function(o) {
var type = _.util.type(o);
switch (type) {
@ -39,11 +41,11 @@ var _ = {
}
return o;
}
},
},
languages: {
extend: function (id, redef) {
extend: function(id, redef) {
var lang = _.util.clone(_.languages[id]);
for (var key in redef) {
@ -54,19 +56,15 @@ var _ = {
},
// Insert a token before another token in a language literal
insertBefore: function (inside, before, insert, root) {
insertBefore: function(inside, before, insert, root) {
root = root || _.languages;
var grammar = root[inside];
var ret = {};
for (var token in grammar) {
if (grammar.hasOwnProperty(token)) {
if (token == before) {
for (var newToken in insert) {
if (insert.hasOwnProperty(newToken)) {
ret[newToken] = insert[newToken];
}
@ -77,7 +75,7 @@ var _ = {
}
}
return root[inside] = ret;
return (root[inside] = ret);
},
// Traverse a language definition with Depth First Search
@ -89,7 +87,7 @@ var _ = {
_.languages.DFS(o[i], callback);
}
}
}
},
},
tokenize: function(text, grammar) {
@ -108,7 +106,9 @@ var _ = {
}
tokenloop: for (var token in grammar) {
if(!grammar.hasOwnProperty(token) || !grammar[token]) {
if (
!grammar.hasOwnProperty(token) || !grammar[token]
) {
continue;
}
@ -119,7 +119,8 @@ var _ = {
pattern = pattern.pattern || pattern;
for (var i=0; i<strarr.length; i++) { // Dont cache length as it changes during the loop
for (var i = 0; i < strarr.length; i++) {
// Dont cache length as it changes during the loop
var str = strarr[i];
@ -134,35 +135,40 @@ var _ = {
pattern.lastIndex = 0;
var match = pattern.exec(str);
if (pattern.exec) {
var match = pattern.exec(str);
if (match) {
if(lookbehind) {
lookbehindLength = match[1].length;
}
if (match) {
if (lookbehind) {
lookbehindLength = match[1].length;
}
var from = match.index - 1 + lookbehindLength,
var from = match.index - 1 + lookbehindLength,
match = match[0].slice(lookbehindLength),
len = match.length,
to = from + len,
before = str.slice(0, from + 1),
after = str.slice(to + 1);
before = str.slice(0, from + 1),
after = str.slice(to + 1);
var args = [i, 1];
var args = [i, 1];
if (before) {
args.push(before);
if (before) {
args.push(before);
}
var wrapped = new Token(
token,
inside ? _.tokenize(match, inside) : match
);
args.push(wrapped);
if (after) {
args.push(after);
}
Array.prototype.splice.apply(strarr, args);
}
var wrapped = new Token(token, inside? _.tokenize(match, inside) : match);
args.push(wrapped);
if (after) {
args.push(after);
}
Array.prototype.splice.apply(strarr, args);
}
}
}
@ -173,7 +179,7 @@ var _ = {
hooks: {
all: {},
add: function (name, callback) {
add: function(name, callback) {
var hooks = _.hooks.all;
hooks[name] = hooks[name] || [];
@ -181,24 +187,28 @@ var _ = {
hooks[name].push(callback);
},
run: function (name, env) {
run: function(name, env) {
var callbacks = _.hooks.all[name];
if (!callbacks || !callbacks.length) {
return;
}
for (var i=0, callback; callback = callbacks[i++];) {
for (
var i = 0, callback;
(callback = callbacks[i++]);
) {
callback(env);
}
}
}
},
},
};
var Token = _.Token = function(type, content) {
var Token = (_.Token = function(type, content) {
this.type = type;
this.content = content;
};
});
Token.reactify = function(o, key) {
if (typeof o == 'string') {
@ -213,120 +223,124 @@ Token.reactify = function(o, key) {
var attributes = {
className: 'token ' + o.type,
key: key
key: key,
};
if (o.type == 'comment') {
attributes.spellCheck = true;
}
return React.DOM.span(attributes, Token.reactify(o.content));
return React.DOM.span(
attributes,
Token.reactify(o.content)
);
};
_.languages.markup = {
'comment': /&lt;!--[\w\W]*?-->/g,
'prolog': /&lt;\?.+?\?>/,
'doctype': /&lt;!DOCTYPE.+?>/,
'cdata': /&lt;!\[CDATA\[[\w\W]*?]]>/i,
'tag': {
comment: /&lt;!--[\w\W]*?-->/g,
prolog: /&lt;\?.+?\?>/,
doctype: /&lt;!DOCTYPE.+?>/,
cdata: /&lt;!\[CDATA\[[\w\W]*?]]>/i,
tag: {
pattern: /&lt;\/?[\w:-]+\s*(?:\s+[\w:-]+(?:=(?:("|')(\\?[\w\W])*?\1|[^\s'">=]+))?\s*)*\/?>/gi,
inside: {
'tag': {
tag: {
pattern: /^&lt;\/?[\w:-]+/i,
inside: {
'punctuation': /^&lt;\/?/,
'namespace': /^[\w-]+?:/
}
punctuation: /^&lt;\/?/,
namespace: /^[\w-]+?:/,
},
},
'attr-value': {
pattern: /=(?:('|")[\w\W]*?(\1)|[^\s>]+)/gi,
inside: {
'punctuation': /=|>|"/g
}
punctuation: /=|>|"/g,
},
},
'punctuation': /\/?>/g,
punctuation: /\/?>/g,
'attr-name': {
pattern: /[\w:-]+/g,
inside: {
'namespace': /^[\w-]+?:/
}
}
}
namespace: /^[\w-]+?:/,
},
},
},
},
'entity': /&amp;#?[\da-z]{1,8};/gi
entity: /&amp;#?[\da-z]{1,8};/gi,
};
_.languages.xml = _.languages.markup;
_.languages.css = {
'comment': /\/\*[\w\W]*?\*\//g,
'atrule': {
comment: /\/\*[\w\W]*?\*\//g,
atrule: {
pattern: /@[\w-]+?.*?(;|(?=\s*{))/gi,
inside: {
'punctuation': /[;:]/g
}
punctuation: /[;:]/g,
},
},
'url': /url\((["']?).*?\1\)/gi,
'selector': /[^\{\}\s][^\{\};]*(?=\s*\{)/g,
'property': /(\b|\B)[\w-]+(?=\s*:)/ig,
'string': /("|')(\\?.)*?\1/g,
'important': /\B!important\b/gi,
'ignore': /&(lt|gt|amp);/gi,
'punctuation': /[\{\};:]/g
url: /url\((["']?).*?\1\)/gi,
selector: /[^\{\}\s][^\{\};]*(?=\s*\{)/g,
property: /(\b|\B)[\w-]+(?=\s*:)/ig,
string: /("|')(\\?.)*?\1/g,
important: /\B!important\b/gi,
ignore: /&(lt|gt|amp);/gi,
punctuation: /[\{\};:]/g,
};
_.languages.insertBefore('markup', 'tag', {
'style': {
style: {
pattern: /(&lt;|<)style[\w\W]*?(>|&gt;)[\w\W]*?(&lt;|<)\/style(>|&gt;)/ig,
inside: {
'tag': {
tag: {
pattern: /(&lt;|<)style[\w\W]*?(>|&gt;)|(&lt;|<)\/style(>|&gt;)/ig,
inside: _.languages.markup.tag.inside
inside: _.languages.markup.tag.inside,
},
rest: _.languages.css
}
}
rest: _.languages.css,
},
},
});
_.languages.clike = {
'comment': {
comment: {
pattern: /(^|[^\\])(\/\*[\w\W]*?\*\/|(^|[^:])\/\/.*?(\r?\n|$))/g,
lookbehind: true
lookbehind: true,
},
'string': /("|')(\\?.)*?\1/g,
string: /("|')(\\?.)*?\1/g,
'class-name': {
pattern: /((?:(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/ig,
lookbehind: true,
inside: {
punctuation: /(\.|\\)/
}
punctuation: /(\.|\\)/,
},
},
'keyword': /\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/g,
'boolean': /\b(true|false)\b/g,
'function': {
keyword: /\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/g,
boolean: /\b(true|false)\b/g,
function: {
pattern: /[a-z0-9_]+\(/ig,
inside: {
punctuation: /\(/
}
punctuation: /\(/,
},
},
'number': /\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/g,
'operator': /[-+]{1,2}|!|&lt;=?|>=?|={1,3}|(&amp;){1,2}|\|?\||\?|\*|\/|\~|\^|\%/g,
'ignore': /&(lt|gt|amp);/gi,
'punctuation': /[{}[\];(),.:]/g
number: /\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee]-?\d+)?)\b/g,
operator: /[-+]{1,2}|!|&lt;=?|>=?|={1,3}|(&amp;){1,2}|\|?\||\?|\*|\/|\~|\^|\%/g,
ignore: /&(lt|gt|amp);/gi,
punctuation: /[{}[\];(),.:]/g,
};
_.languages.javascript = _.languages.extend('clike', {
'keyword': /\b(as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield)\b/,
'number': /\b-?(0x[\dA-Fa-f]+|0b[01]+|0o[0-7]+|\d*\.?\d+([Ee][+-]?\d+)?|NaN|Infinity)\b/,
keyword: /\b(as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield)\b/,
number: /\b-?(0x[\dA-Fa-f]+|0b[01]+|0o[0-7]+|\d*\.?\d+([Ee][+-]?\d+)?|NaN|Infinity)\b/,
// Allow for all non-ASCII characters (See http://stackoverflow.com/a/2008444)
'function': /[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*(?=\()/i,
'operator': /-[-=]?|\+[+=]?|!=?=?|<<?=?|>>?>?=?|=(?:==?|>)?|&[&=]?|\|[|=]?|\*\*?=?|\/=?|~|\^=?|%=?|\?|\.{3}/
function: /[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*(?=\()/i,
operator: /-[-=]?|\+[+=]?|!=?=?|<<?=?|>>?>?=?|=(?:==?|>)?|&[&=]?|\|[|=]?|\*\*?=?|\/=?|~|\^=?|%=?|\?|\.{3}/,
});
_.languages.insertBefore('javascript', 'keyword', {
'regex': {
regex: {
pattern: /(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\\\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})]))/,
lookbehind: true,
greedy: true
}
greedy: true,
},
});
_.languages.insertBefore('javascript', 'string', {
@ -334,51 +348,208 @@ _.languages.insertBefore('javascript', 'string', {
pattern: /`(?:\\\\|\\?[^\\])*?`/,
greedy: true,
inside: {
'interpolation': {
interpolation: {
pattern: /\$\{[^}]+\}/,
inside: {
'interpolation-punctuation': {
pattern: /^\$\{|\}$/,
alias: 'punctuation'
alias: 'punctuation',
},
rest: _.languages.javascript
}
rest: _.languages.javascript,
},
},
'string': /[\s\S]+/
}
}
string: /[\s\S]+/,
},
},
});
_.languages.insertBefore('markup', 'tag', {
'script': {
script: {
pattern: /(&lt;|<)script[\w\W]*?(>|&gt;)[\w\W]*?(&lt;|<)\/script(>|&gt;)/ig,
inside: {
'tag': {
tag: {
pattern: /(&lt;|<)script[\w\W]*?(>|&gt;)|(&lt;|<)\/script(>|&gt;)/ig,
inside: _.languages.markup.tag.inside
inside: _.languages.markup.tag.inside,
},
rest: _.languages.javascript
}
}
rest: _.languages.javascript,
},
},
});
_.languages.swift = _.languages.extend('clike', {
string: {
pattern: /("|')(\\(?:\((?:[^()]|\([^)]+\))+\)|\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,
greedy: true,
inside: {
interpolation: {
pattern: /\\\((?:[^()]|\([^)]+\))+\)/,
inside: {
delimiter: {
pattern: /^\\\(|\)$/,
alias: 'variable',
},
// See rest below
},
},
},
},
keyword: /\b(as|associativity|break|case|catch|class|continue|convenience|default|defer|deinit|didSet|do|dynamic(?:Type)?|else|enum|extension|fallthrough|final|for|func|get|guard|if|import|in|infix|init|inout|internal|is|lazy|left|let|mutating|new|none|nonmutating|operator|optional|override|postfix|precedence|prefix|private|Protocol|public|repeat|required|rethrows|return|right|safe|self|Self|set|static|struct|subscript|super|switch|throws?|try|Type|typealias|unowned|unsafe|var|weak|where|while|willSet|__(?:COLUMN__|FILE__|FUNCTION__|LINE__))\b/,
number: /\b([\d_]+(\.[\de_]+)?|0x[a-f0-9_]+(\.[a-f0-9p_]+)?|0b[01_]+|0o[0-7_]+)\b/i,
constant: /\b(nil|[A-Z_]{2,}|k[A-Z][A-Za-z_]+)\b/,
atrule: /@\b(IB(?:Outlet|Designable|Action|Inspectable)|class_protocol|exported|noreturn|NS(?:Copying|Managed)|objc|UIApplicationMain|auto_closure)\b/,
builtin: /\b([A-Z]\S+|abs|advance|alignof(?:Value)?|assert|contains|count(?:Elements)?|debugPrint(?:ln)?|distance|drop(?:First|Last)|dump|enumerate|equal|filter|find|first|getVaList|indices|isEmpty|join|last|lexicographicalCompare|map|max(?:Element)?|min(?:Element)?|numericCast|overlaps|partition|print(?:ln)?|reduce|reflect|reverse|sizeof(?:Value)?|sort(?:ed)?|split|startsWith|stride(?:of(?:Value)?)?|suffix|swap|toDebugString|toString|transcode|underestimateCount|unsafeBitCast|with(?:ExtendedLifetime|Unsafe(?:MutablePointers?|Pointers?)|VaList))\b/,
});
_.languages.swift['string'].inside[
'interpolation'
].inside.rest = _.util.clone(_.languages.swift);
_.languages.c = _.languages.extend('clike', {
keyword: /\b(asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)\b/,
operator: /\-[>-]?|\+\+?|!=?|<<?=?|>>?=?|==?|&&?|\|?\||[~^%?*\/]/,
number: /\b-?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)[ful]*\b/i,
});
_.languages.insertBefore('c', 'string', {
macro: {
// allow for multiline macro definitions
// spaces after the # character compile fine with gcc
pattern: /(^\s*)#\s*[a-z]+([^\r\n\\]|\\.|\\(?:\r\n?|\n))*/im,
lookbehind: true,
alias: 'property',
inside: {
// highlight the path of the include statement as a string
string: {
pattern: /(#\s*include\s*)(<.+?>|("|')(\\?.)+?\3)/,
lookbehind: true,
},
// highlight macro directives as keywords
directive: {
pattern: /(#\s*)\b(define|elif|else|endif|error|ifdef|ifndef|if|import|include|line|pragma|undef|using)\b/,
lookbehind: true,
alias: 'keyword',
},
},
},
// highlight predefined macros as constants
constant: /\b(__FILE__|__LINE__|__DATE__|__TIME__|__TIMESTAMP__|__func__|EOF|NULL|stdin|stdout|stderr)\b/,
});
_.languages.objectivec = _.languages.extend('c', {
keyword: /\b(asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while|in|self|super)\b|(@interface|@end|@implementation|@protocol|@class|@public|@protected|@private|@property|@try|@catch|@finally|@throw|@synthesize|@dynamic|@selector)\b/,
string: /("|')(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1|@"(\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,
operator: /-[->]?|\+\+?|!=?|<<?=?|>>?=?|==?|&&?|\|\|?|[~^%?*\/@]/,
});
_.languages.java = _.languages.extend('clike', {
keyword: /\b(abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|const|float|native|super|while)\b/,
number: /\b0b[01]+\b|\b0x[\da-f]*\.?[\da-fp\-]+\b|\b\d*\.?\d+(?:e[+-]?\d+)?[df]?\b/i,
operator: {
pattern: /(^|[^.])(?:\+[+=]?|-[-=]?|!=?|<<?=?|>>?>?=?|==?|&[&=]?|\|[|=]?|\*=?|\/=?|%=?|\^=?|[?:~])/m,
lookbehind: true,
},
});
_.languages.insertBefore('java', 'function', {
annotation: {
alias: 'punctuation',
pattern: /(^|[^.])@\w+/,
lookbehind: true,
},
});
_.languages.powershell = {
comment: [
{
pattern: /(^|[^`])<#[\s\S]*?#>/,
lookbehind: true,
},
{
pattern: /(^|[^`])#.*/,
lookbehind: true,
},
],
string: [
{
pattern: /"(`?[\s\S])*?"/,
greedy: true,
inside: {
function: {
pattern: /[^`]\$\(.*?\)/,
// Populated at end of file
inside: {},
},
},
},
{
pattern: /'([^']|'')*'/,
greedy: true,
},
],
// Matches name spaces as well as casts, attribute decorators. Force starting with letter to avoid matching array indices
namespace: /\[[a-z][\s\S]*?\]/i,
boolean: /\$(true|false)\b/i,
variable: /\$\w+\b/i,
// Cmdlets and aliases. Aliases should come last, otherwise "write" gets preferred over "write-host" for example
// Get-Command | ?{ $_.ModuleName -match "Microsoft.PowerShell.(Util|Core|Management)" }
// Get-Alias | ?{ $_.ReferencedCommand.Module.Name -match "Microsoft.PowerShell.(Util|Core|Management)" }
function: [
/\b(Add-(Computer|Content|History|Member|PSSnapin|Type)|Checkpoint-Computer|Clear-(Content|EventLog|History|Item|ItemProperty|Variable)|Compare-Object|Complete-Transaction|Connect-PSSession|ConvertFrom-(Csv|Json|StringData)|Convert-Path|ConvertTo-(Csv|Html|Json|Xml)|Copy-(Item|ItemProperty)|Debug-Process|Disable-(ComputerRestore|PSBreakpoint|PSRemoting|PSSessionConfiguration)|Disconnect-PSSession|Enable-(ComputerRestore|PSBreakpoint|PSRemoting|PSSessionConfiguration)|Enter-PSSession|Exit-PSSession|Export-(Alias|Clixml|Console|Csv|FormatData|ModuleMember|PSSession)|ForEach-Object|Format-(Custom|List|Table|Wide)|Get-(Alias|ChildItem|Command|ComputerRestorePoint|Content|ControlPanelItem|Culture|Date|Event|EventLog|EventSubscriber|FormatData|Help|History|Host|HotFix|Item|ItemProperty|Job|Location|Member|Module|Process|PSBreakpoint|PSCallStack|PSDrive|PSProvider|PSSession|PSSessionConfiguration|PSSnapin|Random|Service|TraceSource|Transaction|TypeData|UICulture|Unique|Variable|WmiObject)|Group-Object|Import-(Alias|Clixml|Csv|LocalizedData|Module|PSSession)|Invoke-(Command|Expression|History|Item|RestMethod|WebRequest|WmiMethod)|Join-Path|Limit-EventLog|Measure-(Command|Object)|Move-(Item|ItemProperty)|New-(Alias|Event|EventLog|Item|ItemProperty|Module|ModuleManifest|Object|PSDrive|PSSession|PSSessionConfigurationFile|PSSessionOption|PSTransportOption|Service|TimeSpan|Variable|WebServiceProxy)|Out-(Default|File|GridView|Host|Null|Printer|String)|Pop-Location|Push-Location|Read-Host|Receive-(Job|PSSession)|Register-(EngineEvent|ObjectEvent|PSSessionConfiguration|WmiEvent)|Remove-(Computer|Event|EventLog|Item|ItemProperty|Job|Module|PSBreakpoint|PSDrive|PSSession|PSSnapin|TypeData|Variable|WmiObject)|Rename-(Computer|Item|ItemProperty)|Reset-ComputerMachinePassword|Resolve-Path|Restart-(Computer|Service)|Restore-Computer|Resume-(Job|Service)|Save-Help|Select-(Object|String|Xml)|Send-MailMessage|Set-(Alias|Content|Date|Item|ItemProperty|Location|PSBreakpoint|PSDebug|PSSessionConfiguration|Service|StrictMode|TraceSource|Variable|WmiInstance)|Show-(Command|ControlPanelItem|EventLog)|Sort-Object|Split-Path|Start-(Job|Process|Service|Sleep|Transaction)|Stop-(Computer|Job|Process|Service)|Suspend-(Job|Service)|Tee-Object|Test-(ComputerSecureChannel|Connection|ModuleManifest|Path|PSSessionConfigurationFile)|Trace-Command|Unblock-File|Undo-Transaction|Unregister-(Event|PSSessionConfiguration)|Update-(FormatData|Help|List|TypeData)|Use-Transaction|Wait-(Event|Job|Process)|Where-Object|Write-(Debug|Error|EventLog|Host|Output|Progress|Verbose|Warning))\b/i,
/\b(ac|cat|chdir|clc|cli|clp|clv|compare|copy|cp|cpi|cpp|cvpa|dbp|del|diff|dir|ebp|echo|epal|epcsv|epsn|erase|fc|fl|ft|fw|gal|gbp|gc|gci|gcs|gdr|gi|gl|gm|gp|gps|group|gsv|gu|gv|gwmi|iex|ii|ipal|ipcsv|ipsn|irm|iwmi|iwr|kill|lp|ls|measure|mi|mount|move|mp|mv|nal|ndr|ni|nv|ogv|popd|ps|pushd|pwd|rbp|rd|rdr|ren|ri|rm|rmdir|rni|rnp|rp|rv|rvpa|rwmi|sal|saps|sasv|sbp|sc|select|set|shcm|si|sl|sleep|sls|sort|sp|spps|spsv|start|sv|swmi|tee|trcm|type|write)\b/i,
],
// per http://technet.microsoft.com/en-us/library/hh847744.aspx
keyword: /\b(Begin|Break|Catch|Class|Continue|Data|Define|Do|DynamicParam|Else|ElseIf|End|Exit|Filter|Finally|For|ForEach|From|Function|If|InlineScript|Parallel|Param|Process|Return|Sequence|Switch|Throw|Trap|Try|Until|Using|Var|While|Workflow)\b/i,
operator: {
pattern: /(\W?)(!|-(eq|ne|gt|ge|lt|le|sh[lr]|not|b?(and|x?or)|(Not)?(Like|Match|Contains|In)|Replace|Join|is(Not)?|as)\b|-[-=]?|\+[+=]?|[*\/%]=?)/i,
lookbehind: true,
},
punctuation: /[|{}[\];(),.]/,
};
// Variable interpolation inside strings, and nested expressions
_.languages.powershell.string[
0
].inside.boolean = _.languages.powershell.boolean;
_.languages.powershell.string[
0
].inside.variable = _.languages.powershell.variable;
_.languages.powershell.string[
0
].inside.function.inside = _.util.clone(
_.languages.powershell
);
_.languages.java = _.languages.extend('clike', {
keyword: /\b(abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|const|float|native|super|while)\b/,
number: /\b0b[01]+\b|\b0x[\da-f]*\.?[\da-fp\-]+\b|\b\d*\.?\d+(?:e[+-]?\d+)?[df]?\b/i,
operator: {
pattern: /(^|[^.])(?:\+[+=]?|-[-=]?|!=?|<<?=?|>>?>?=?|==?|&[&=]?|\|[|=]?|\*=?|\/=?|%=?|\^=?|[?:~])/m,
lookbehind: true,
},
});
var Prism = React.createClass({
statics: {
_: _
_: _,
},
getDefaultProps: function() {
return {
language: 'javascript'
language: 'javascript',
};
},
render: function() {
var grammar = _.languages[this.props.language];
if (!grammar) {
grammar = _.languages.javascript;
}
return (
<div className={'prism language-' + this.props.language}>
{Token.reactify(_.tokenize(this.props.children, grammar))}
<div
className={'prism language-' + this.props.language}
>
{Token.reactify(
_.tokenize(this.props.children, grammar)
)}
</div>
);
}
},
});
module.exports = Prism;

View File

@ -18,8 +18,11 @@ var Site = React.createClass({
render: function() {
const path = Metadata.config.RN_DEPLOYMENT_PATH;
const version = Metadata.config.RN_VERSION;
const algoliaVersion = version === 'next' ? 'master' : version;
var basePath = '/react-native/' + (path ? path + '/' : '');
const algoliaVersion = version === 'next'
? 'master'
: version;
var basePath = '/react-native/' +
(path ? path + '/' : '');
var currentYear = new Date().getFullYear();
var title = this.props.title
@ -37,7 +40,10 @@ var Site = React.createClass({
content: 'width=device-width',
},
// Facebook
{ property: 'fb:app_id', content: '1677033832619985' },
{
property: 'fb:app_id',
content: '1677033832619985',
},
{ property: 'fb:admins', content: '121800083' },
// Open Graph
{
@ -51,7 +57,9 @@ var Site = React.createClass({
{
property: 'og:url',
content: 'https://facebook.github.io/react-native/' +
(this.props.path ? this.props.path : 'index.html'),
(this.props.path
? this.props.path
: 'index.html'),
},
{
property: 'og:image',
@ -107,7 +115,9 @@ var Site = React.createClass({
<html>
<head>
<title>{title}</title>
{metaTags.map((tag, index) => <meta key={index} {...tag} />)}
{metaTags.map((tag, index) => (
<meta key={index} {...tag} />
))}
<base href={basePath} />
@ -116,8 +126,15 @@ var Site = React.createClass({
href="https://cdn.jsdelivr.net/docsearch.js/1/docsearch.min.css"
/>
<link rel="shortcut icon" href="img/favicon.png?2" />
<link rel="stylesheet" href="css/react-native.css" />
<link
rel="shortcut icon"
href="img/favicon.png?2"
/>
<link
rel="stylesheet"
href="css/react-native.css"
/>
<link rel="stylesheet" href="css/prism.css" />
<link
rel="alternate"
@ -131,7 +148,10 @@ var Site = React.createClass({
type="text/css"
/>
<script type="text/javascript" src="//use.typekit.net/vqa1hcx.js" />
<script
type="text/javascript"
src="//use.typekit.net/vqa1hcx.js"
/>
<script type="text/javascript">
{'try{Typekit.load();}catch(e){}'}
</script>
@ -154,7 +174,10 @@ var Site = React.createClass({
<img src="img/header_logo.png" />
React Native
</a>
<a className="nav-version" href="/react-native/versions.html">
<a
className="nav-version"
href="/react-native/versions.html"
>
{version}
</a>
<HeaderLinks section={this.props.section} />
@ -165,7 +188,10 @@ var Site = React.createClass({
<footer className="nav-footer">
<section className="sitemap">
<a href="/react-native" className="nav-home">
<a
href="/react-native"
className="nav-home"
>
<img
src="img/header_logo.png"
alt="React Native"
@ -175,46 +201,74 @@ var Site = React.createClass({
</a>
<div>
<h5><a href="docs/">Docs</a></h5>
<a href="docs/getting-started.html">Getting Started</a>
<a href="docs/getting-started.html">
Getting Started
</a>
<a href="docs/tutorial.html">Tutorial</a>
<a href="docs/integration-with-existing-apps.html">
<a
href="docs/integration-with-existing-apps.html"
>
Integration With Existing Apps
</a>
<a href="docs/more-resources.html">More Resources</a>
<a href="docs/more-resources.html">
More Resources
</a>
</div>
<div>
<h5><a href="/react-native/support.html">Community</a></h5>
<a href="/react-native/showcase.html">Showcase</a>
<h5>
<a href="/react-native/support.html">
Community
</a>
</h5>
<a href="/react-native/showcase.html">
Showcase
</a>
<a
href="http://www.meetup.com/topics/react-native/"
target="_blank">
target="_blank"
>
Upcoming Events
</a>
<a
href="https://www.facebook.com/groups/react.native.community"
target="_blank">
target="_blank"
>
Facebook Group
</a>
<a href="https://twitter.com/reactnative" target="_blank">
<a
href="https://twitter.com/reactnative"
target="_blank"
>
Twitter
</a>
</div>
<div>
<h5><a href="/react-native/support.html">Help</a></h5>
<h5>
<a href="/react-native/support.html">
Help
</a>
</h5>
<a
href="http://stackoverflow.com/questions/tagged/react-native"
target="_blank">
target="_blank"
>
Stack Overflow
</a>
<a href="https://discord.gg/0ZcbPKXt5bZjGY5n">
<a
href="https://discord.gg/0ZcbPKXt5bZjGY5n"
>
Reactiflux Chat
</a>
<a href="/react-native/versions.html" target="_blank">
<a
href="/react-native/versions.html"
target="_blank"
>
Latest Releases
</a>
<a
href="https://react-native.canny.io/feature-requests"
target="_blank">
target="_blank"
>
Feature Requests
</a>
</div>
@ -223,10 +277,14 @@ var Site = React.createClass({
<a href="/react-native/blog">Blog</a>
<a
href="https://github.com/facebook/react-native"
target="_blank">
target="_blank"
>
GitHub
</a>
<a href="http://facebook.github.io/react/" target="_blank">
<a
href="http://facebook.github.io/react/"
target="_blank"
>
React
</a>
</div>
@ -240,10 +298,13 @@ var Site = React.createClass({
name="mc-embedded-subscribe-form"
className="validate"
target="_blank"
noValidate>
noValidate
>
<div id="mc_embed_signup_scroll">
<label htmlFor="mce-EMAIL">
<h5>Get the React Native Newsletter</h5>
<h5>
Get the React Native Newsletter
</h5>
</label>
<input
type="email"
@ -255,8 +316,12 @@ var Site = React.createClass({
required
/>
<div
style={{ position: 'absolute', left: '-5000px' }}
aria-hidden="true">
style={{
position: 'absolute',
left: '-5000px',
}}
aria-hidden="true"
>
<input
type="text"
name="b_db0dd948e2b729ee62625b1a8_47cd41008f"
@ -281,7 +346,8 @@ var Site = React.createClass({
<a
href="https://code.facebook.com/projects/"
target="_blank"
className="fbOpenSource">
className="fbOpenSource"
>
<img
src="img/oss_logo.png"
alt="Facebook Open Source"
@ -335,7 +401,10 @@ var Site = React.createClass({
__html: "(function($) {window.fnames = new Array(); window.ftypes = new Array();fnames[0]='EMAIL';ftypes[0]='email';fnames[1]='FNAME';ftypes[1]='text';fnames[2]='LNAME';ftypes[2]='text';}(jQuery));var $mcj = jQuery.noConflict(true);",
}}
/>
<script type="text/javascript" src="https://snack.expo.io/embed.js" />
<script
type="text/javascript"
src="https://snack.expo.io/embed.js"
/>
</body>
</html>
);

View File

@ -0,0 +1,139 @@
/* http://prismjs.com/download.html?themes=prism&languages=markup+css+clike+javascript+bash+c+git+java+json+objectivec+powershell+jsx+swift */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
code[class*="language-"]::selection, code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre) > code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
/* Inline code */
:not(pre) > code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #a67f59;
background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function {
color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}