[New Feature] Add web folder to support web documentation

This commit is contained in:
Rudy Haryanto
2022-10-04 20:17:17 +07:00
parent c27f624ca8
commit a54aa04c9b
251 changed files with 11079 additions and 0 deletions

View File

@@ -0,0 +1,47 @@
<h1 align="center">Remark SnackPlayer</h1>
<p align="center">Remark plugin to embed <a href="https://snack.expo.dev/">Expo Snack's</a> using Code Blocks</p>
## Usage
This plugin parses codeblocks with language set as `SnackPlayer` and replaces them with embedded Expo's SnackPlayers, you can also provide parameters along with the codeblock to set some basic details.
### Example Code Block
````
```SnackPlayer name=Hello%20World description=This%20is%20a%20description
import React from 'react';
import { Text, View } from 'react-native';
const YourApp = () => {
return (
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<Text>Try editing me! 🎉</Text>
</View>
);
}
export default YourApp;
```
````
The above code snippet would look like this:
<img width="783" alt="Screenshot 2020-10-03 at 1 11 19 AM" src="https://user-images.githubusercontent.com/11258286/94963203-67de3500-0515-11eb-974a-a2289c0bfdc8.png">
### Parameters
| Name | Description | Default |
| ------------------ | --------------------------------------------------------- | ------------------- |
| name | SnackPlayer name | `"Example"` |
| description | Description of the example | `"Example usage"` |
| dependencies | Additional dependencies, eg. `"expo-constant"` | `""` |
| platform | Example platform | `"web"` |
| supportedPlatforms | Supported platforms | `"ios,android,web"` |
| theme | SnackPlayer theme, `"light"` or `"dark"` | `"light"` |
| preview | Preview visible, `"true"` or `"false"` | `"true"` |
| loading | iFrame loading attribute, `"auto"`, `"lazy"` or `"eager"` | `"lazy"` |
## Styling
To style the Snack Player wrapper you can use `.snack-player` class.

View File

@@ -0,0 +1,31 @@
{
"name": "@react-native-website/remark-snackplayer",
"version": "0.0.7",
"private": true,
"description": "Remark Expo Snack Plugin",
"main": "src/index.js",
"keywords": [
"remark",
"react-native",
"expo",
"snackplayer",
"preview"
],
"files": [
"src"
],
"scripts": {
"prettier": "prettier --write \"{src/**/*.js,tests/**/*.js,*.md}\"",
"test": "yarn tape tests/index.js"
},
"dependencies": {
"dedent": "^0.7.0",
"object.fromentries": "^2.0.3",
"unist-builder": "^2.0.3",
"unist-util-visit-parents": "^3.1.1"
},
"devDependencies": {
"remark": "^12.0.1",
"tape": "^5.0.1"
}
}

View File

@@ -0,0 +1,82 @@
'use strict';
const visit = require('unist-util-visit-parents');
const u = require('unist-builder');
const dedent = require('dedent');
const fromEntries = require('object.fromentries');
const parseParams = (paramString = '') => {
const params = fromEntries(new URLSearchParams(paramString));
if (!params.platform) {
params.platform = 'web';
}
return params;
};
const processNode = (node, parent) => {
return new Promise(async (resolve, reject) => {
try {
const params = parseParams(node.meta);
// Gather necessary Params
const name = params.name ? decodeURIComponent(params.name) : 'Example';
const description = params.description
? decodeURIComponent(params.description)
: 'Example usage';
const sampleCode = node.value;
const encodedSampleCode = encodeURIComponent(sampleCode);
const dependencies = params.dependencies || '';
const platform = params.platform || 'web';
const supportedPlatforms = params.supportedPlatforms || 'ios,android,web';
const theme = params.theme || 'light';
const preview = params.preview || 'true';
const loading = params.loading || 'lazy';
// Generate Node for SnackPlayer
// See https://github.com/expo/snack/blob/main/docs/embedding-snacks.md
const snackPlayerDiv = u('html', {
value: dedent`
<div
class="snack-player"
data-snack-name="${name}"
data-snack-description="${description}"
data-snack-code="${encodedSampleCode}"
data-snack-dependencies="${dependencies}"
data-snack-platform="${platform}"
data-snack-supported-platforms="${supportedPlatforms}"
data-snack-theme="${theme}"
data-snack-preview="${preview}"
data-snack-loading="${loading}"
></div>
`,
});
// Replace code block with SnackPlayer Node
const index = parent[0].children.indexOf(node);
parent[0].children.splice(index, 1, snackPlayerDiv);
} catch (e) {
return reject(e);
}
resolve();
});
};
const SnackPlayer = () => {
return tree =>
new Promise(async (resolve, reject) => {
const nodesToProcess = [];
// Parse all CodeBlocks
visit(tree, 'code', (node, parent) => {
// Add SnackPlayer CodeBlocks to processing queue
if (node.lang == 'SnackPlayer') {
nodesToProcess.push(processNode(node, parent));
}
});
// Wait for all promises to be resolved
Promise.all(nodesToProcess).then(resolve()).catch(reject());
});
};
module.exports = SnackPlayer;

View File

@@ -0,0 +1,30 @@
const path = require('path');
const fs = require('fs');
const test = require('tape');
const remark = require('remark');
const snackplayer = require('../');
const read = name => fs.readFileSync(path.join(__dirname, name), 'utf8');
const normalizeLineEndings = str => str.replace(/\r\n/g, '\n');
test('remark-snackplayer', async t => {
const processor = remark().use(snackplayer);
processor.process(read('markdown/test1.md'), (err, file) => {
if (err) t.fail('Failed to process markdown/test1.md');
t.equal(
normalizeLineEndings(String(file)),
normalizeLineEndings(read('output/output1.html')),
'With 1 Code Block'
);
});
processor.process(read('markdown/test2.md'), (err, file) => {
if (err) t.fail('Failed to process markdown/test2.md');
t.equal(
normalizeLineEndings(String(file)),
normalizeLineEndings(read('output/output2.html')),
'With 2 Code Blocks'
);
});
});

View File

@@ -0,0 +1,16 @@
```SnackPlayer name=Hello%20World
import React from 'react';
import { Text, View } from 'react-native';
const YourApp = () => {
return (
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<Text>
Try editing me! 🎉
</Text>
</View>
);
}
export default YourApp;
```

View File

@@ -0,0 +1,38 @@
```SnackPlayer name=FirstPlayer
import React from 'react';
import { Text, View } from 'react-native';
const YourApp = () => {
return (
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<Text>
Try editing me! 🎉
</Text>
</View>
);
}
export default YourApp;
```
```SnackPlayer name=SecondPlayer&theme=dark&preview=false&supportedPlatforms=ios&loading=eager&dependencies=@react-native-community/slider
import React from 'react';
import { View } from 'react-native';
import Slider from '@react-native-community/slider';
const YourApp = () => {
return (
<View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
<Slider
style={{width: 200, height: 40}}
minimumValue={0}
maximumValue={1}
minimumTrackTintColor="#FFFFFF"
maximumTrackTintColor="#000000"
/>
</View>
);
}
export default YourApp;
```

View File

@@ -0,0 +1,12 @@
<div
class="snack-player"
data-snack-name="Hello World"
data-snack-description="Example usage"
data-snack-code="import%20React%20from%20'react'%3B%0Aimport%20%7B%20Text%2C%20View%20%7D%20from%20'react-native'%3B%0A%0Aconst%20YourApp%20%3D%20()%20%3D%3E%20%7B%0A%20%20%20%20return%20(%0A%20%20%20%20%3CView%20style%3D%7B%7B%20flex%3A%201%2C%20justifyContent%3A%20%22center%22%2C%20alignItems%3A%20%22center%22%20%7D%7D%3E%0A%20%20%20%20%20%20%20%20%3CText%3E%0A%20%20%20%20%20%20%20%20Try%20editing%20me!%20%F0%9F%8E%89%0A%20%20%20%20%20%20%20%20%3C%2FText%3E%0A%20%20%20%20%3C%2FView%3E%0A%20%20%20%20)%3B%0A%7D%0A%0Aexport%20default%20YourApp%3B"
data-snack-dependencies=""
data-snack-platform="web"
data-snack-supported-platforms="ios,android,web"
data-snack-theme="light"
data-snack-preview="true"
data-snack-loading="lazy"
></div>

View File

@@ -0,0 +1,25 @@
<div
class="snack-player"
data-snack-name="FirstPlayer"
data-snack-description="Example usage"
data-snack-code="import%20React%20from%20'react'%3B%0Aimport%20%7B%20Text%2C%20View%20%7D%20from%20'react-native'%3B%0A%0Aconst%20YourApp%20%3D%20()%20%3D%3E%20%7B%0A%20%20%20%20return%20(%0A%20%20%20%20%3CView%20style%3D%7B%7B%20flex%3A%201%2C%20justifyContent%3A%20%22center%22%2C%20alignItems%3A%20%22center%22%20%7D%7D%3E%0A%20%20%20%20%20%20%20%20%3CText%3E%0A%20%20%20%20%20%20%20%20Try%20editing%20me!%20%F0%9F%8E%89%0A%20%20%20%20%20%20%20%20%3C%2FText%3E%0A%20%20%20%20%3C%2FView%3E%0A%20%20%20%20)%3B%0A%7D%0A%0Aexport%20default%20YourApp%3B"
data-snack-dependencies=""
data-snack-platform="web"
data-snack-supported-platforms="ios,android,web"
data-snack-theme="light"
data-snack-preview="true"
data-snack-loading="lazy"
></div>
<div
class="snack-player"
data-snack-name="SecondPlayer"
data-snack-description="Example usage"
data-snack-code="import%20React%20from%20'react'%3B%0Aimport%20%7B%20View%20%7D%20from%20'react-native'%3B%0Aimport%20Slider%20from%20'%40react-native-community%2Fslider'%3B%0A%0Aconst%20YourApp%20%3D%20()%20%3D%3E%20%7B%0A%20%20%20%20return%20(%0A%20%20%20%20%3CView%20style%3D%7B%7B%20flex%3A%201%2C%20justifyContent%3A%20%22center%22%2C%20alignItems%3A%20%22center%22%20%7D%7D%3E%0A%20%20%20%20%20%20%20%20%3CSlider%0A%20%20%20%20%20%20%20%20%20%20style%3D%7B%7Bwidth%3A%20200%2C%20height%3A%2040%7D%7D%0A%20%20%20%20%20%20%20%20%20%20minimumValue%3D%7B0%7D%0A%20%20%20%20%20%20%20%20%20%20maximumValue%3D%7B1%7D%0A%20%20%20%20%20%20%20%20%20%20minimumTrackTintColor%3D%22%23FFFFFF%22%0A%20%20%20%20%20%20%20%20%20%20maximumTrackTintColor%3D%22%23000000%22%0A%20%20%20%20%20%20%20%20%2F%3E%0A%20%20%20%20%3C%2FView%3E%0A%20%20%20%20)%3B%0A%7D%0A%0Aexport%20default%20YourApp%3B"
data-snack-dependencies="@react-native-community/slider"
data-snack-platform="web"
data-snack-supported-platforms="ios"
data-snack-theme="dark"
data-snack-preview="false"
data-snack-loading="eager"
></div>