From 0a6935618cfc11f9c97ffe4dbbf28550847c7b80 Mon Sep 17 00:00:00 2001 From: Hector Ramos Date: Tue, 30 May 2017 14:30:38 -0700 Subject: [PATCH] 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 --- docs/GettingStarted.md | 7 +- docs/IntegrationWithExistingApps.md | 53 +-- docs/NativeComponentsIOS.md | 16 +- docs/NativeModulesIOS.md | 44 +-- website/core/Marked.js | 500 ++++++++++++++----------- website/core/Prism.js | 407 ++++++++++++++------ website/core/Site.js | 131 +++++-- website/src/react-native/css/prism.css | 139 +++++++ 8 files changed, 880 insertions(+), 417 deletions(-) create mode 100644 website/src/react-native/css/prism.css diff --git a/docs/GettingStarted.md b/docs/GettingStarted.md index cddb28600..3234ef56b 100644 --- a/docs/GettingStarted.md +++ b/docs/GettingStarted.md @@ -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(); } diff --git a/docs/IntegrationWithExistingApps.md b/docs/IntegrationWithExistingApps.md index 76b5a9093..ee730f9ea 100644 --- a/docs/IntegrationWithExistingApps.md +++ b/docs/IntegrationWithExistingApps.md @@ -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 `` component within a styled `` -```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 ``` > 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 `` component within a styled ``: -```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 (it’s 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 package’s `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 Don’t forget to replace the paths with correct ones and create the assets folder if it doesn’t 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(); } diff --git a/docs/NativeComponentsIOS.md b/docs/NativeComponentsIOS.md index 91a8e6eb1..b66fb324c 100644 --- a/docs/NativeComponentsIOS.md +++ b/docs/NativeComponentsIOS.md @@ -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 @@ -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 @@ -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 diff --git a/docs/NativeModulesIOS.md b/docs/NativeModulesIOS.md index 31cf2ff7d..d6b48e6bf 100644 --- a/docs/NativeModulesIOS.md +++ b/docs/NativeModulesIOS.md @@ -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 @@ -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 @@ -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 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 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 #import @@ -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 @@ -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 ``` diff --git a/website/core/Marked.js b/website/core/Marked.js index 64bc26feb..d105e1f30 100644 --- a/website/core/Marked.js +++ b/website/core/Marked.js @@ -35,40 +35,41 @@ var block = { def: /^ *\[([^\]]+)\]: *]+)>?(?: +["(]([^\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', //) - ('closed', /<(tag)[\s\S]+?<\/\1>/) - ('closing', /])*?>/) - (/tag/g, block._tag) - (); +block.html = replace(block.html)( + 'comment', + // +)('closed', /<(tag)[\s\S]+?<\/\1>/)( + 'closing', + /])*?>/ +)(/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]+?(?=[\\?(?:\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(''); 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 (
+ toSlug={this.token.text} + > {this.inline.output(this.token.text)}
); } 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 ( - {text} + + {text} + ); } if (lang && lang.indexOf('SnackPlayer') === 0) { return ( - {text} + + {text} + ); } + if (lang) { + return {text}; + } + return {text}; } 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; diff --git a/website/core/Prism.js b/website/core/Prism.js index 5ae3cd17e..6662ecaa3 100644 --- a/website/core/Prism.js +++ b/website/core/Prism.js @@ -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/g, - 'prolog': /<\?.+?\?>/, - 'doctype': /<!DOCTYPE.+?>/, - 'cdata': /<!\[CDATA\[[\w\W]*?]]>/i, - 'tag': { + comment: /<!--[\w\W]*?-->/g, + prolog: /<\?.+?\?>/, + doctype: /<!DOCTYPE.+?>/, + cdata: /<!\[CDATA\[[\w\W]*?]]>/i, + tag: { pattern: /<\/?[\w:-]+\s*(?:\s+[\w:-]+(?:=(?:("|')(\\?[\w\W])*?\1|[^\s'">=]+))?\s*)*\/?>/gi, inside: { - 'tag': { + tag: { pattern: /^<\/?[\w:-]+/i, inside: { - 'punctuation': /^<\/?/, - 'namespace': /^[\w-]+?:/ - } + punctuation: /^<\/?/, + 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': /&#?[\da-z]{1,8};/gi + entity: /&#?[\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: /(<|<)style[\w\W]*?(>|>)[\w\W]*?(<|<)\/style(>|>)/ig, inside: { - 'tag': { + tag: { pattern: /(<|<)style[\w\W]*?(>|>)|(<|<)\/style(>|>)/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}|!|<=?|>=?|={1,3}|(&){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}|!|<=?|>=?|={1,3}|(&){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: /(<|<)script[\w\W]*?(>|>)[\w\W]*?(<|<)\/script(>|>)/ig, inside: { - 'tag': { + tag: { pattern: /(<|<)script[\w\W]*?(>|>)|(<|<)\/script(>|>)/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 ( -
- {Token.reactify(_.tokenize(this.props.children, grammar))} +
+ {Token.reactify( + _.tokenize(this.props.children, grammar) + )}
); - } + }, }); module.exports = Prism; diff --git a/website/core/Site.js b/website/core/Site.js index 286aa06b0..383ae7383 100644 --- a/website/core/Site.js +++ b/website/core/Site.js @@ -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({ {title} - {metaTags.map((tag, index) => )} + {metaTags.map((tag, index) => ( + + ))} @@ -116,8 +126,15 @@ var Site = React.createClass({ href="https://cdn.jsdelivr.net/docsearch.js/1/docsearch.min.css" /> - - + + + - @@ -154,7 +174,10 @@ var Site = React.createClass({ React Native - + {version} @@ -165,7 +188,10 @@ var Site = React.createClass({
@@ -240,10 +298,13 @@ var Site = React.createClass({ name="mc-embedded-subscribe-form" className="validate" target="_blank" - noValidate> + noValidate + >