livecode代码开发分支
This commit is contained in:
commit
9f96998eb8
34
.bundlewatch.config.js
Normal file
34
.bundlewatch.config.js
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
module.exports = {
|
||||||
|
files: [
|
||||||
|
{
|
||||||
|
path: './build/sdk/*.js',
|
||||||
|
maxSize: '5kB',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: './build/livecodes/!(*lang-)*.js',
|
||||||
|
maxSize: '30kB',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: './build/livecodes/*(app|embed|headless).*.js',
|
||||||
|
maxSize: '120kB',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: './build/livecodes/lang-*.js',
|
||||||
|
maxSize: '20kB',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: './build/livecodes/*.css',
|
||||||
|
maxSize: '25kB',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: './build/livecodes/i18n-*.json',
|
||||||
|
maxSize: '15kB',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
defaultCompression: 'brotli',
|
||||||
|
normalizeFilenames: /^.+?((\.[^.]{8,}}?)|())\.\w+$/,
|
||||||
|
ci: {
|
||||||
|
repoBranchBase: 'develop',
|
||||||
|
trackBranches: ['main', 'develop'],
|
||||||
|
},
|
||||||
|
};
|
||||||
21
.dockerignore
Normal file
21
.dockerignore
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
node_modules
|
||||||
|
*/node_modules
|
||||||
|
docs/.docusaurus
|
||||||
|
package-lock.json
|
||||||
|
build
|
||||||
|
.vscode
|
||||||
|
.jest
|
||||||
|
build
|
||||||
|
dist
|
||||||
|
.cache
|
||||||
|
**/*.log
|
||||||
|
.env
|
||||||
|
docs/docs/api
|
||||||
|
docs/static/**/*.html.md
|
||||||
|
docs/static/llms.txt
|
||||||
|
docs/static/llms-full.txt
|
||||||
|
/test-results/
|
||||||
|
/playwright-report/
|
||||||
|
/playwright/.cache/
|
||||||
|
src/livecodes/i18n/locales/tmp/
|
||||||
|
lokalise_tmp
|
||||||
17
.editorconfig
Normal file
17
.editorconfig
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# http://editorconfig.org
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
insert_final_newline = true
|
||||||
|
max_line_length = 80
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.ts]
|
||||||
|
quote_type = single
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
max_line_length = 0
|
||||||
|
trim_trailing_whitespace = false
|
||||||
117
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
117
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
name: 🐛 Bug report
|
||||||
|
description: Create a bug report to help us improve LiveCodes
|
||||||
|
title: 'Bug: '
|
||||||
|
labels: [👀 needs triage, 🐛 bug]
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Thanks for taking the time to fill out this bug report!
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Describe the bug
|
||||||
|
description: A clear and concise description of what the bug is.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Steps to reproduce
|
||||||
|
description: Describe how to reproduce the behavior.
|
||||||
|
placeholder: |
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '...'
|
||||||
|
3. See error
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Screenshots
|
||||||
|
description: Screenshots showing the issue.
|
||||||
|
- type: dropdown
|
||||||
|
attributes:
|
||||||
|
multiple: true
|
||||||
|
label: Affected services
|
||||||
|
description: Select the platforms where the issue can be reproduced.
|
||||||
|
options:
|
||||||
|
- 'LiveCodes App'
|
||||||
|
- 'LiveCodes Embedded Playgrounds'
|
||||||
|
- 'LiveCodes SDK'
|
||||||
|
- 'LiveCodes Services'
|
||||||
|
- 'LiveCodes Documentations'
|
||||||
|
- 'Repo build/deploy'
|
||||||
|
- 'Other'
|
||||||
|
- type: dropdown
|
||||||
|
attributes:
|
||||||
|
multiple: true
|
||||||
|
label: Platforms
|
||||||
|
description: Select the platforms where the issue can be reproduced.
|
||||||
|
options:
|
||||||
|
- 'Desktop'
|
||||||
|
- 'Mobile'
|
||||||
|
- 'Tablet'
|
||||||
|
- type: dropdown
|
||||||
|
attributes:
|
||||||
|
multiple: true
|
||||||
|
label: Browsers
|
||||||
|
description: Select the browsers where the issue can be reproduced.
|
||||||
|
options:
|
||||||
|
- 'Chrome'
|
||||||
|
- 'Firefox'
|
||||||
|
- 'Safari'
|
||||||
|
- 'Edge'
|
||||||
|
- 'Opera'
|
||||||
|
- 'Other (add additional context)'
|
||||||
|
- type: dropdown
|
||||||
|
attributes:
|
||||||
|
multiple: true
|
||||||
|
label: Environment
|
||||||
|
description: Select the environment where the issue can be reproduced.
|
||||||
|
options:
|
||||||
|
- 'Production'
|
||||||
|
- 'Development'
|
||||||
|
- 'Self-Hosted'
|
||||||
|
- 'Local'
|
||||||
|
- type: textarea
|
||||||
|
id: share
|
||||||
|
attributes:
|
||||||
|
label: Share URL(s)
|
||||||
|
description: Share URL(s) (App menu → Share) where the issue can be reproduced.
|
||||||
|
- type: textarea
|
||||||
|
id: config
|
||||||
|
attributes:
|
||||||
|
label: Configuration
|
||||||
|
description: Project configuration (App menu → Export → Export Project (JSON)) or embed options.
|
||||||
|
- type: textarea
|
||||||
|
id: logs
|
||||||
|
attributes:
|
||||||
|
label: Console logs
|
||||||
|
description: Provide console logs or screenshots for console.
|
||||||
|
- type: textarea
|
||||||
|
id: context
|
||||||
|
attributes:
|
||||||
|
label: Additional context
|
||||||
|
description: Add any other context about the problem or helpful links here.
|
||||||
|
- type: dropdown
|
||||||
|
attributes:
|
||||||
|
multiple: false
|
||||||
|
label: Is it already fixed?
|
||||||
|
description: Is it fixed on latest development build (http://dev.livecodes.io)?
|
||||||
|
options:
|
||||||
|
- 'No'
|
||||||
|
- 'Yes'
|
||||||
|
- type: checkboxes
|
||||||
|
id: terms
|
||||||
|
attributes:
|
||||||
|
label: Code of Conduct
|
||||||
|
description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/live-codes/livecodes/blob/HEAD/CODE_OF_CONDUCT.md)
|
||||||
|
options:
|
||||||
|
- label: I agree to follow this project's Code of Conduct
|
||||||
|
required: true
|
||||||
|
- type: checkboxes
|
||||||
|
id: contribution
|
||||||
|
attributes:
|
||||||
|
label: Contributing Docs
|
||||||
|
description: If you plan on contributing code please read - [Contribution Guide](https://github.com/live-codes/livecodes/blob/HEAD/CONTRIBUTING.md)
|
||||||
|
options:
|
||||||
|
- label: I agree to follow this project's Contribution Docs
|
||||||
|
required: false
|
||||||
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
blank_issues_enabled: true
|
||||||
|
contact_links:
|
||||||
|
- name: ❓ Ask a question
|
||||||
|
url: https://livecodes.io/docs/contact/
|
||||||
|
about: Ask questions about open source onboarding
|
||||||
59
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
59
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
name: 🚀 Feature request
|
||||||
|
description: Suggest an idea for this project 💡
|
||||||
|
title: 'Feature: '
|
||||||
|
labels: [👀 needs triage, 💡 feature]
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Thanks for taking the time to fill out this feature request!
|
||||||
|
- type: dropdown
|
||||||
|
attributes:
|
||||||
|
multiple: false
|
||||||
|
label: Type of feature
|
||||||
|
description: Select the type of feature request, the lowercase should also be the PR prefix.
|
||||||
|
options:
|
||||||
|
- '✨ Feature'
|
||||||
|
- '🐛 Fix'
|
||||||
|
- '📝 Documentation'
|
||||||
|
- '🎨 Style'
|
||||||
|
- '♻️ Refactor'
|
||||||
|
- '🔥 Performance'
|
||||||
|
- '✅ Test'
|
||||||
|
- '🤖 Build'
|
||||||
|
- '🔁 CI'
|
||||||
|
- '📦 Chore'
|
||||||
|
- '⏩ Revert'
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Current behavior
|
||||||
|
description: Is your feature request related to a problem? Please describe.
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Suggested feature
|
||||||
|
description: Describe the feature you'd like.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: context
|
||||||
|
attributes:
|
||||||
|
label: Additional context
|
||||||
|
description: Add any other context about the problem or helpful links here.
|
||||||
|
- type: checkboxes
|
||||||
|
id: terms
|
||||||
|
attributes:
|
||||||
|
label: Code of Conduct
|
||||||
|
description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/live-codes/livecodes/blob/HEAD/CODE_OF_CONDUCT.md)
|
||||||
|
options:
|
||||||
|
- label: I agree to follow this project's Code of Conduct
|
||||||
|
required: true
|
||||||
|
- type: checkboxes
|
||||||
|
id: contribution
|
||||||
|
attributes:
|
||||||
|
label: Contributing Docs
|
||||||
|
description: If you plan on contributing code please read - [Contribution Guide](https://github.com/live-codes/livecodes/blob/HEAD/CONTRIBUTING.md)
|
||||||
|
options:
|
||||||
|
- label: I agree to follow this project's Contribution Docs
|
||||||
|
required: false
|
||||||
44
.github/ISSUE_TEMPLATE/i18n_request.yml
vendored
Normal file
44
.github/ISSUE_TEMPLATE/i18n_request.yml
vendored
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
name: 🌐 I18n Request
|
||||||
|
description: Request for internationalization support for a specific language
|
||||||
|
title: 'I18n: '
|
||||||
|
labels: [👀 needs triage, 🌐 I18n]
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Thanks for taking the time to fill out this i18n request!
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Before submitting your request, please check out [our Lokalise project page](https://app.lokalise.com/public/34958094667a72e9454592.95108106/) to see if the language you are requesting is already supported or being currently worked on.
|
||||||
|
- type: input
|
||||||
|
attributes:
|
||||||
|
label: Requested language
|
||||||
|
description: The UI language you would like to request support for.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Supporting details
|
||||||
|
description: We want to hear why you think this language should be supported (e.g. user base, translation help, etc.). Please provide details regarding your request.
|
||||||
|
- type: textarea
|
||||||
|
id: context
|
||||||
|
attributes:
|
||||||
|
label: Additional context
|
||||||
|
description: Add any other context about the problem or helpful links here.
|
||||||
|
- type: checkboxes
|
||||||
|
id: terms
|
||||||
|
attributes:
|
||||||
|
label: Code of Conduct
|
||||||
|
description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/live-codes/livecodes/blob/HEAD/CODE_OF_CONDUCT.md)
|
||||||
|
options:
|
||||||
|
- label: I agree to follow this project's Code of Conduct
|
||||||
|
required: true
|
||||||
|
- type: checkboxes
|
||||||
|
id: contribution
|
||||||
|
attributes:
|
||||||
|
label: Contributing Docs
|
||||||
|
description: If you plan on contributing i18n please read - [Contribution Guide](https://github.com/live-codes/livecodes/blob/HEAD/CONTRIBUTING.md) and [I18n Guide](https://github.com/live-codes/livecodes/blob/HEAD/docs/docs/contribution/i18n.md)
|
||||||
|
options:
|
||||||
|
- label: I agree to follow this project's Contribution Docs
|
||||||
|
required: false
|
||||||
65
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
65
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
<!--
|
||||||
|
For Work In Progress Pull Requests, please use the Draft PR feature,
|
||||||
|
see https://github.blog/2019-02-14-introducing-draft-pull-requests/ for further details.
|
||||||
|
|
||||||
|
For a timely review/response, please avoid force-pushing additional
|
||||||
|
commits if your PR already received reviews or comments.
|
||||||
|
|
||||||
|
Before submitting a Pull Request, please ensure you've done the following:
|
||||||
|
- 📖 Read the LiveCodes Contributing Guide: https://github.com/live-codes/livecodes/blob/HEAD/CONTRIBUTING.md.
|
||||||
|
- 📖 Read the LiveCodes Code of Conduct: https://github.com/live-codes/livecodes/blob/HEAD/CODE_OF_CONDUCT.md.
|
||||||
|
- 👷♀️ Create small PRs. In most cases, this will be possible.
|
||||||
|
- ✅ Provide tests for your changes.
|
||||||
|
- 📝 Use descriptive commit messages.
|
||||||
|
- 📗 Update any related documentation and include any relevant screenshots.
|
||||||
|
- 🌐 Use `window.deps.translateString` in .ts files and add `data-i18n` attributes in .html files to mark strings that needs to be translated.
|
||||||
|
-->
|
||||||
|
|
||||||
|
## What type of PR is this? (check all applicable)
|
||||||
|
|
||||||
|
- [ ] ✨ Feature
|
||||||
|
- [ ] 🐛 Bug Fix
|
||||||
|
- [ ] 📝 Documentation Update
|
||||||
|
- [ ] 🎨 Style
|
||||||
|
- [ ] ♻️ Code Refactor
|
||||||
|
- [ ] 🔥 Performance Improvements
|
||||||
|
- [ ] ✅ Test
|
||||||
|
- [ ] 🤖 Build
|
||||||
|
- [ ] 🔁 CI
|
||||||
|
- [ ] 📦 Chore (Release)
|
||||||
|
- [ ] ⏩ Revert
|
||||||
|
- [ ] 🌐 Internationalization / Translation
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Please do not leave this blank
|
||||||
|
This PR [adds/removes/fixes/replaces] the [feature/bug/etc].
|
||||||
|
-->
|
||||||
|
|
||||||
|
## Related Tickets & Documents
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Please use this format link issue numbers: Fixes #123
|
||||||
|
-->
|
||||||
|
|
||||||
|
## Mobile & Desktop Screenshots/Recordings
|
||||||
|
|
||||||
|
<!-- Visual changes require screenshots -->
|
||||||
|
|
||||||
|
## Added tests?
|
||||||
|
|
||||||
|
- [ ] 👍 yes
|
||||||
|
- [ ] 🙅 no, because they aren't needed
|
||||||
|
- [ ] 🙋 no, because I need help
|
||||||
|
|
||||||
|
## Added to documentations?
|
||||||
|
|
||||||
|
- [ ] 📓 docs (./docs)
|
||||||
|
- [ ] 📕 storybook (./storybook)
|
||||||
|
- [ ] 📜 README.md
|
||||||
|
- [ ] 🙅 no documentation needed
|
||||||
|
|
||||||
|
## [optional] Are there any post-deployment tasks we need to perform?
|
||||||
|
|
||||||
|
## [optional] What gif best describes this PR or how it makes you feel?
|
||||||
36
.github/workflows/CI-build.yml
vendored
Normal file
36
.github/workflows/CI-build.yml
vendored
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
name: CI-build
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node-version: [18.x]
|
||||||
|
env:
|
||||||
|
NODE_OPTIONS: '--max_old_space_size=4096'
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
cache: 'npm'
|
||||||
|
cache-dependency-path: '**/package-lock.json'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: npm run build
|
||||||
|
env:
|
||||||
|
BUILD_INCLUDE_LOCALES: ${{ startsWith(github.head_ref, 'i18n/') }}
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: npm run test
|
||||||
|
env:
|
||||||
|
CI: true
|
||||||
|
BUNDLEWATCH_GITHUB_TOKEN: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }}
|
||||||
39
.github/workflows/CI-e2e.yml
vendored
Normal file
39
.github/workflows/CI-e2e.yml
vendored
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
name: CI-e2e
|
||||||
|
|
||||||
|
on: [pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
tests:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
node-version: [18.x]
|
||||||
|
test: [1, 2, 3, 4, 5]
|
||||||
|
env:
|
||||||
|
NODE_OPTIONS: '--max_old_space_size=4096'
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
cache: 'npm'
|
||||||
|
cache-dependency-path: '**/package-lock.json'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: npm run build
|
||||||
|
env:
|
||||||
|
BUILD_INCLUDE_LOCALES: ${{ startsWith(github.head_ref, 'i18n/') }}
|
||||||
|
|
||||||
|
- name: Test ${{ matrix.test }}
|
||||||
|
run: npm run ci:e2e
|
||||||
|
env:
|
||||||
|
CI: true
|
||||||
|
CI_SHARD_INDEX: ${{ matrix.test }}
|
||||||
|
CI_SHARD_TOTAL: 5
|
||||||
28
.github/workflows/CI-type-checking.yml
vendored
Normal file
28
.github/workflows/CI-type-checking.yml
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
name: CI-type-checking
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
type-check:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node-version: [18.x]
|
||||||
|
env:
|
||||||
|
NODE_OPTIONS: '--max_old_space_size=4096'
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
cache: 'npm'
|
||||||
|
cache-dependency-path: '**/package-lock.json'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Type Checking
|
||||||
|
run: npm run check-types
|
||||||
16
.github/workflows/CI-typos.yml
vendored
Normal file
16
.github/workflows/CI-typos.yml
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
name: CI-typos
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
spell-check:
|
||||||
|
name: Spell Check
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Check typos on code
|
||||||
|
uses: crate-ci/typos@master
|
||||||
|
with:
|
||||||
|
config: ./typos.toml
|
||||||
17
.github/workflows/bundle-size.yml
vendored
Normal file
17
.github/workflows/bundle-size.yml
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
name: Bundle Size
|
||||||
|
|
||||||
|
on: [pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: preactjs/compressed-size-action@v2
|
||||||
|
with:
|
||||||
|
build-script: 'build:app'
|
||||||
|
pattern: './build/**/*.{js,css,html,json}'
|
||||||
|
strip-hash: "\\b\\w{32}\\."
|
||||||
|
minimum-change-threshold: 200
|
||||||
|
compression: 'brotli'
|
||||||
45
.github/workflows/deploy.yml
vendored
Normal file
45
.github/workflows/deploy.yml
vendored
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
name: Deploy
|
||||||
|
|
||||||
|
# on push to main deploy (as self-hosted build) to github pages
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
env:
|
||||||
|
NODE_VERSION: 18.x
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
NODE_OPTIONS: '--max_old_space_size=4096'
|
||||||
|
steps:
|
||||||
|
- name: Generate Github Token for CI Bot
|
||||||
|
uses: actions/create-github-app-token@v1
|
||||||
|
id: generate-token
|
||||||
|
with:
|
||||||
|
app-id: ${{ secrets.CI_APP_ID }}
|
||||||
|
private-key: ${{ secrets.CI_APP_PRIVATE_KEY }}
|
||||||
|
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
token: ${{ steps.generate-token.outputs.token }}
|
||||||
|
|
||||||
|
- name: Use Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
|
cache: 'npm'
|
||||||
|
cache-dependency-path: '**/package-lock.json'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Deploy
|
||||||
|
run: |
|
||||||
|
git remote set-url origin https://git:${GITHUB_TOKEN}@github.com/${{github.repository}}.git
|
||||||
|
npm run deploy -- -u "github-actions-bot <support+actions@github.com>"
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
|
||||||
38
.github/workflows/i18n-update-notify.yml
vendored
Normal file
38
.github/workflows/i18n-update-notify.yml
vendored
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
name: i18n-update-notify
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request_target:
|
||||||
|
branches: [develop]
|
||||||
|
types: [closed]
|
||||||
|
paths: ['src/livecodes/i18n/locales/**']
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
notify:
|
||||||
|
name: Notify
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.event.pull_request.merged && github.event.sender.login != 'github-actions[bot]' && !startsWith(github.head_ref, 'i18n/')
|
||||||
|
steps:
|
||||||
|
- name: Generate Github Token for CI Bot
|
||||||
|
uses: actions/create-github-app-token@v1
|
||||||
|
id: generate-token
|
||||||
|
with:
|
||||||
|
app-id: ${{ secrets.CI_APP_ID }}
|
||||||
|
private-key: ${{ secrets.CI_APP_PRIVATE_KEY }}
|
||||||
|
|
||||||
|
- name: Create comment on PR
|
||||||
|
uses: actions/github-script@v6
|
||||||
|
with:
|
||||||
|
github-token: ${{ steps.generate-token.outputs.token }}
|
||||||
|
script: |
|
||||||
|
const commentBody = `## i18n Actions
|
||||||
|
Source PR has been merged into the default branch.
|
||||||
|
|
||||||
|
Maintainers can comment \`.i18n-update-push\` to trigger the i18n update workflow and push the changes to Lokalise.
|
||||||
|
`;
|
||||||
|
|
||||||
|
github.rest.issues.createComment({
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
body: commentBody
|
||||||
|
})
|
||||||
235
.github/workflows/i18n-update-pull.yml
vendored
Normal file
235
.github/workflows/i18n-update-pull.yml
vendored
Normal file
@ -0,0 +1,235 @@
|
|||||||
|
name: i18n-update-pull
|
||||||
|
|
||||||
|
on:
|
||||||
|
issue_comment:
|
||||||
|
types: [created]
|
||||||
|
|
||||||
|
env:
|
||||||
|
LOKALISE_PROJECT_ID: ${{ vars.LOKALISE_PROJECT_ID }}
|
||||||
|
LOKALISE_API_TOKEN: ${{ secrets.LOKALISE_API_TOKEN }}
|
||||||
|
NODE_VERSION: 18.x
|
||||||
|
CI: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
precheck:
|
||||||
|
name: Pre-check
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.event.issue.pull_request && github.event.issue.pull_request.merged_at && github.event.issue.state == 'closed' && github.event.comment.body == '.i18n-update-pull' && (github.event.comment.author_association == 'COLLABORATOR' || github.event.comment.author_association == 'MEMBER' || github.event.comment.author_association == 'OWNER')
|
||||||
|
outputs:
|
||||||
|
skip: ${{ steps.fetch-pr.outputs.skip }}
|
||||||
|
skipReason: ${{ steps.fetch-pr.outputs.skipReason }}
|
||||||
|
newBranch: ${{ steps.fetch-pr.outputs.newBranch }}
|
||||||
|
branch: ${{ steps.fetch-pr.outputs.branch }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Generate Github Token for CI Bot
|
||||||
|
uses: actions/create-github-app-token@v1
|
||||||
|
id: generate-token
|
||||||
|
with:
|
||||||
|
app-id: ${{ secrets.CI_APP_ID }}
|
||||||
|
private-key: ${{ secrets.CI_APP_PRIVATE_KEY }}
|
||||||
|
|
||||||
|
- name: Check out repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
token: ${{ steps.generate-token.outputs.token }}
|
||||||
|
|
||||||
|
- name: Fetch PR details
|
||||||
|
id: fetch-pr
|
||||||
|
run: |
|
||||||
|
PR_DETAILS=$(curl -s -H "Authorization: token $GITHUB_TOKEN" "${{ github.event.issue.pull_request.url }}")
|
||||||
|
PR_BRANCH=$(echo "$PR_DETAILS" | jq -r '.head.ref')
|
||||||
|
|
||||||
|
skip () {
|
||||||
|
echo "$1 Exiting..."
|
||||||
|
echo "skip=true" >> $GITHUB_OUTPUT
|
||||||
|
echo "skipReason=$1" >> $GITHUB_OUTPUT
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ $PR_BRANCH == "i18n/"* ]]; then
|
||||||
|
skip "Branch \`$PR_BRANCH\` is a i18n branch."
|
||||||
|
fi
|
||||||
|
|
||||||
|
PR_BRANCH=$(echo "$PR_DETAILS" | jq -r '.head.label' | sed 's/:/\//g')
|
||||||
|
NEW_BRANCH="i18n/$PR_BRANCH"
|
||||||
|
echo "newBranch=$NEW_BRANCH" >> $GITHUB_OUTPUT
|
||||||
|
echo "branch=$PR_BRANCH" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
git config --global user.name "livecodes-ci[bot]"
|
||||||
|
git config --global user.email "186997172+livecodes-ci[bot]@users.noreply.github.com"
|
||||||
|
|
||||||
|
if [[ ! $(git ls-remote --heads origin $NEW_BRANCH) ]]; then
|
||||||
|
skip "Branch \`$NEW_BRANCH\` does not exist."
|
||||||
|
fi
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
|
||||||
|
|
||||||
|
runner:
|
||||||
|
name: Runner
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: precheck
|
||||||
|
if: needs.precheck.outputs.skip != 'true'
|
||||||
|
env:
|
||||||
|
NEW_BRANCH: ${{ needs.precheck.outputs.newBranch }}
|
||||||
|
PR_BRANCH: ${{ needs.precheck.outputs.branch }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Generate Github Token for CI Bot
|
||||||
|
uses: actions/create-github-app-token@v1
|
||||||
|
id: generate-token
|
||||||
|
with:
|
||||||
|
app-id: ${{ secrets.CI_APP_ID }}
|
||||||
|
private-key: ${{ secrets.CI_APP_PRIVATE_KEY }}
|
||||||
|
|
||||||
|
- name: Check out repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
ref: ${{ needs.precheck.outputs.newBranch }}
|
||||||
|
token: ${{ steps.generate-token.outputs.token }}
|
||||||
|
|
||||||
|
- name: Setup Node
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
|
cache: 'npm'
|
||||||
|
cache-dependency-path: '**/package-lock.json'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Import from Lokalise
|
||||||
|
run: |
|
||||||
|
mkdir -p $LOKALISE_TEMP && touch $LOKALISE_TEMP/locales.zip && npm run i18n-update-pull -- $PR_BRANCH && rm -rf $LOKALISE_TEMP
|
||||||
|
env:
|
||||||
|
LOKALISE_TEMP: lokalise_tmp
|
||||||
|
|
||||||
|
- name: Generate Lokalise JSON files
|
||||||
|
run: npm run i18n-lokalise-json all
|
||||||
|
|
||||||
|
- name: Linting and fixing
|
||||||
|
run: npm run fix
|
||||||
|
|
||||||
|
- name: Commit changes
|
||||||
|
run: |
|
||||||
|
git config --global user.name "livecodes-ci[bot]"
|
||||||
|
git config --global user.email "186997172+livecodes-ci[bot]@users.noreply.github.com"
|
||||||
|
git add .
|
||||||
|
|
||||||
|
# Only commit if there are changes
|
||||||
|
git diff-index --quiet HEAD || git commit -m "i18n: pull translation from Lokalise"
|
||||||
|
|
||||||
|
# Save SHA of the latest commit to locale
|
||||||
|
echo "LAST_COMMIT_SHA=$(git log -n 1 --format="%H" -- src/livecodes/i18n/locales)" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Push changes
|
||||||
|
run: git push origin $NEW_BRANCH
|
||||||
|
|
||||||
|
- name: Create a new i18n PR, comment on source PR and reaction
|
||||||
|
uses: actions/github-script@v7
|
||||||
|
with:
|
||||||
|
github-token: ${{ steps.generate-token.outputs.token }}
|
||||||
|
script: |
|
||||||
|
const repoURL = context.payload.repository.html_url;
|
||||||
|
const branchURL = `${repoURL}/tree/${process.env.NEW_BRANCH}`;
|
||||||
|
const prTitle = `i18n: ${{ github.event.issue.title }}`;
|
||||||
|
const prBody = `## What type of PR is this? (check all applicable)
|
||||||
|
|
||||||
|
- [ ] ✨ Feature
|
||||||
|
- [ ] 🐛 Bug Fix
|
||||||
|
- [ ] 📝 Documentation Update
|
||||||
|
- [ ] 🎨 Style
|
||||||
|
- [ ] ♻️ Code Refactor
|
||||||
|
- [ ] 🔥 Performance Improvements
|
||||||
|
- [ ] ✅ Test
|
||||||
|
- [ ] 🤖 Build
|
||||||
|
- [ ] 🔁 CI
|
||||||
|
- [ ] 📦 Chore (Release)
|
||||||
|
- [ ] ⏩ Revert
|
||||||
|
- [x] 🌐 Internationalization / Translation
|
||||||
|
|
||||||
|
## Description
|
||||||
|
### i18n Actions: \`.i18n-update-pull\`
|
||||||
|
Localization pulled from Lokalise.
|
||||||
|
|
||||||
|
| Name | Description |
|
||||||
|
| --- | --- |
|
||||||
|
| **i18n Branch** | [\`${process.env.NEW_BRANCH}\`](${branchURL}) |
|
||||||
|
| **Last Commit SHA** | ${process.env.LAST_COMMIT_SHA} |
|
||||||
|
|
||||||
|
## Related Tickets & Documents
|
||||||
|
- **Source PR**: #${{ github.event.issue.number }}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const prInfo = await github.rest.pulls.create({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
title: prTitle,
|
||||||
|
body: prBody,
|
||||||
|
head: process.env.NEW_BRANCH,
|
||||||
|
base: '${{ github.event.repository.default_branch }}'
|
||||||
|
});
|
||||||
|
|
||||||
|
const commentBody = `## i18n Actions: \`.i18n-update-pull\`
|
||||||
|
Localization pulled from Lokalise.
|
||||||
|
|
||||||
|
| Name | Description |
|
||||||
|
| --- | --- |
|
||||||
|
| **i18n Branch** | [\`${process.env.NEW_BRANCH}\`](${branchURL}) |
|
||||||
|
| **Last Commit SHA** | ${process.env.LAST_COMMIT_SHA} |
|
||||||
|
| **i18n PR** | #${prInfo.data.number} |
|
||||||
|
`;
|
||||||
|
|
||||||
|
github.rest.issues.createComment({
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
body: commentBody
|
||||||
|
})
|
||||||
|
|
||||||
|
github.rest.reactions.createForIssueComment({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
comment_id: ${{ github.event.comment.id }},
|
||||||
|
content: 'rocket'
|
||||||
|
});
|
||||||
|
|
||||||
|
exception:
|
||||||
|
name: Exception
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: precheck
|
||||||
|
if: needs.precheck.outputs.skip == 'true'
|
||||||
|
env:
|
||||||
|
SKIP_REASON: ${{ needs.precheck.outputs.skipReason }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Generate Github Token for CI Bot
|
||||||
|
uses: actions/create-github-app-token@v1
|
||||||
|
id: generate-token
|
||||||
|
with:
|
||||||
|
app-id: ${{ secrets.CI_APP_ID }}
|
||||||
|
private-key: ${{ secrets.CI_APP_PRIVATE_KEY }}
|
||||||
|
|
||||||
|
- name: Create reaction on PR
|
||||||
|
uses: actions/github-script@v7
|
||||||
|
with:
|
||||||
|
github-token: ${{ steps.generate-token.outputs.token }}
|
||||||
|
script: |
|
||||||
|
const runURL = `${context.payload.repository.html_url}/actions/runs/${process.env.GITHUB_RUN_ID}`;
|
||||||
|
const commentBody = `## i18n Actions: \`.i18n-update-pull\`
|
||||||
|
Failed to perform action due to following reason: **${process.env.SKIP_REASON}**
|
||||||
|
|
||||||
|
Please check [action logs](${runURL}) for more details.
|
||||||
|
`;
|
||||||
|
github.rest.issues.createComment({
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
body: commentBody
|
||||||
|
})
|
||||||
|
|
||||||
|
github.rest.reactions.createForIssueComment({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
comment_id: ${{ github.event.comment.id }},
|
||||||
|
content: 'confused'
|
||||||
|
});
|
||||||
195
.github/workflows/i18n-update-push.yml
vendored
Normal file
195
.github/workflows/i18n-update-push.yml
vendored
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
name: i18n-update-push
|
||||||
|
|
||||||
|
on:
|
||||||
|
issue_comment:
|
||||||
|
types: [created]
|
||||||
|
|
||||||
|
env:
|
||||||
|
LOKALISE_PROJECT_ID: ${{ vars.LOKALISE_PROJECT_ID }}
|
||||||
|
LOKALISE_API_TOKEN: ${{ secrets.LOKALISE_API_TOKEN }}
|
||||||
|
NODE_VERSION: 18.x
|
||||||
|
CI: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
precheck:
|
||||||
|
name: Pre-check
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.event.issue.pull_request && github.event.issue.pull_request.merged_at && github.event.issue.state == 'closed' && github.event.comment.body == '.i18n-update-push' && (github.event.comment.author_association == 'COLLABORATOR' || github.event.comment.author_association == 'MEMBER' || github.event.comment.author_association == 'OWNER')
|
||||||
|
outputs:
|
||||||
|
skip: ${{ steps.fetch-pr.outputs.skip }}
|
||||||
|
skipReason: ${{ steps.fetch-pr.outputs.skipReason }}
|
||||||
|
newBranch: ${{ steps.fetch-pr.outputs.newBranch }}
|
||||||
|
branch: ${{ steps.fetch-pr.outputs.branch }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Generate Github Token for CI Bot
|
||||||
|
uses: actions/create-github-app-token@v1
|
||||||
|
id: generate-token
|
||||||
|
with:
|
||||||
|
app-id: ${{ secrets.CI_APP_ID }}
|
||||||
|
private-key: ${{ secrets.CI_APP_PRIVATE_KEY }}
|
||||||
|
|
||||||
|
- name: Check out repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
token: ${{ steps.generate-token.outputs.token }}
|
||||||
|
|
||||||
|
- name: Fetch PR details
|
||||||
|
id: fetch-pr
|
||||||
|
run: |
|
||||||
|
PR_DETAILS=$(curl -s -H "Authorization: token $GITHUB_TOKEN" "${{ github.event.issue.pull_request.url }}")
|
||||||
|
PR_BRANCH=$(echo "$PR_DETAILS" | jq -r '.head.ref')
|
||||||
|
|
||||||
|
if [[ $PR_BRANCH == "i18n/"* ]]; then
|
||||||
|
SKIP_REASON="Branch \`$PR_BRANCH\` is a i18n branch."
|
||||||
|
echo "$SKIP_REASON Exiting..."
|
||||||
|
echo "skip=true" >> $GITHUB_OUTPUT
|
||||||
|
echo "skipReason=$SKIP_REASON" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Use branch name prefixed with owner name
|
||||||
|
PR_BRANCH=$(echo "$PR_DETAILS" | jq -r '.head.label' | sed 's/:/\//g')
|
||||||
|
NEW_BRANCH="i18n/$PR_BRANCH"
|
||||||
|
echo "newBranch=$NEW_BRANCH" >> $GITHUB_OUTPUT
|
||||||
|
echo "branch=$PR_BRANCH" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
git config --global user.name "livecodes-ci[bot]"
|
||||||
|
git config --global user.email "186997172+livecodes-ci[bot]@users.noreply.github.com"
|
||||||
|
|
||||||
|
if [[ $(git ls-remote --heads origin $NEW_BRANCH) ]]; then
|
||||||
|
SKIP_REASON="Branch \`$NEW_BRANCH\` already exists."
|
||||||
|
echo "$SKIP_REASON Exiting..."
|
||||||
|
echo "skip=true" >> $GITHUB_OUTPUT
|
||||||
|
echo "skipReason=$SKIP_REASON" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
|
||||||
|
|
||||||
|
runner:
|
||||||
|
name: Runner
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: precheck
|
||||||
|
if: needs.precheck.outputs.skip != 'true'
|
||||||
|
env:
|
||||||
|
NEW_BRANCH: ${{ needs.precheck.outputs.newBranch }}
|
||||||
|
PR_BRANCH: ${{ needs.precheck.outputs.branch }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Generate Github Token for CI Bot
|
||||||
|
uses: actions/create-github-app-token@v1
|
||||||
|
id: generate-token
|
||||||
|
with:
|
||||||
|
app-id: ${{ secrets.CI_APP_ID }}
|
||||||
|
private-key: ${{ secrets.CI_APP_PRIVATE_KEY }}
|
||||||
|
|
||||||
|
- name: Check out repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
token: ${{ steps.generate-token.outputs.token }}
|
||||||
|
|
||||||
|
- name: Setup Node
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
|
cache: 'npm'
|
||||||
|
cache-dependency-path: '**/package-lock.json'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Create new branch
|
||||||
|
run: git checkout -b $NEW_BRANCH
|
||||||
|
|
||||||
|
- name: Linting and fixing
|
||||||
|
run: npm run fix
|
||||||
|
|
||||||
|
- name: Commit changes
|
||||||
|
run: |
|
||||||
|
git config --global user.name "livecodes-ci[bot]"
|
||||||
|
git config --global user.email "186997172+livecodes-ci[bot]@users.noreply.github.com"
|
||||||
|
git add .
|
||||||
|
|
||||||
|
# Only commit if there are changes
|
||||||
|
git diff-index --quiet HEAD || git commit -m "i18n: update source texts"
|
||||||
|
|
||||||
|
# Save SHA of the latest commit to English locale
|
||||||
|
echo "LAST_COMMIT_SHA=$(git log -n 1 --format="%H" -- src/livecodes/i18n/locales/en)" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Push changes
|
||||||
|
run: git push origin $NEW_BRANCH
|
||||||
|
|
||||||
|
- name: Push source texts to Lokalise
|
||||||
|
run: npm run i18n-update-push -- $PR_BRANCH
|
||||||
|
|
||||||
|
- name: Create comment and reaction on PR
|
||||||
|
uses: actions/github-script@v7
|
||||||
|
with:
|
||||||
|
github-token: ${{ steps.generate-token.outputs.token }}
|
||||||
|
script: |
|
||||||
|
const repoURL = context.payload.repository.html_url;
|
||||||
|
const branchURL = `${repoURL}/tree/${process.env.NEW_BRANCH}`;
|
||||||
|
const commentBody = `## i18n Actions: \`.i18n-update-push\`
|
||||||
|
Localization updated and pushed to [Lokalise](https://app.lokalise.com/project/${process.env.LOKALISE_PROJECT_ID}/?branch=${process.env.PR_BRANCH}).
|
||||||
|
|
||||||
|
| Name | Description |
|
||||||
|
| --- | --- |
|
||||||
|
| **New Branch for i18n** | [\`${process.env.NEW_BRANCH}\`](${branchURL}) |
|
||||||
|
| **Last Commit SHA** | ${process.env.LAST_COMMIT_SHA} |
|
||||||
|
|
||||||
|
Maintainers can comment \`.i18n-update-pull\` after translation is done to trigger the i18n pull workflow and pull the changes back to Github.
|
||||||
|
`;
|
||||||
|
|
||||||
|
github.rest.issues.createComment({
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
body: commentBody
|
||||||
|
})
|
||||||
|
|
||||||
|
github.rest.reactions.createForIssueComment({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
comment_id: ${{ github.event.comment.id }},
|
||||||
|
content: 'rocket'
|
||||||
|
});
|
||||||
|
|
||||||
|
exception:
|
||||||
|
name: Exception
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: precheck
|
||||||
|
if: needs.precheck.outputs.skip == 'true'
|
||||||
|
env:
|
||||||
|
SKIP_REASON: ${{ needs.precheck.outputs.skipReason }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Generate Github Token for CI Bot
|
||||||
|
uses: actions/create-github-app-token@v1
|
||||||
|
id: generate-token
|
||||||
|
with:
|
||||||
|
app-id: ${{ secrets.CI_APP_ID }}
|
||||||
|
private-key: ${{ secrets.CI_APP_PRIVATE_KEY }}
|
||||||
|
|
||||||
|
- name: Create comment and reaction on PR
|
||||||
|
uses: actions/github-script@v7
|
||||||
|
with:
|
||||||
|
github-token: ${{ steps.generate-token.outputs.token }}
|
||||||
|
script: |
|
||||||
|
const runURL = `${context.payload.repository.html_url}/actions/runs/${process.env.GITHUB_RUN_ID}`;
|
||||||
|
const commentBody = `## i18n Actions: \`.i18n-update-push\`
|
||||||
|
Failed to perform action due to following reason: **${process.env.SKIP_REASON}**
|
||||||
|
|
||||||
|
Please check [action logs](${runURL}) for more details.
|
||||||
|
`;
|
||||||
|
github.rest.issues.createComment({
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
body: commentBody
|
||||||
|
})
|
||||||
|
|
||||||
|
github.rest.reactions.createForIssueComment({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
comment_id: ${{ github.event.comment.id }},
|
||||||
|
content: 'confused'
|
||||||
|
});
|
||||||
179
.github/workflows/i18n-update-scheduled.yml
vendored
Normal file
179
.github/workflows/i18n-update-scheduled.yml
vendored
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
name: i18n-update-scheduled
|
||||||
|
|
||||||
|
# Triggered weekly to update source texts and push them to Lokalise, then pull the translations back to Github.
|
||||||
|
# Work on i18n/develop branch.
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: '0 0 * * 0'
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- develop
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
env:
|
||||||
|
LOKALISE_PROJECT_ID: ${{ vars.LOKALISE_PROJECT_ID }}
|
||||||
|
LOKALISE_API_TOKEN: ${{ secrets.LOKALISE_API_TOKEN }}
|
||||||
|
BRANCH: i18n/develop
|
||||||
|
LOKALISE_BRANCH: master
|
||||||
|
NODE_VERSION: 18.x
|
||||||
|
CI: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
update:
|
||||||
|
name: Push and Pull
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Generate Github Token for CI Bot
|
||||||
|
uses: actions/create-github-app-token@v1
|
||||||
|
id: generate-token
|
||||||
|
with:
|
||||||
|
app-id: ${{ secrets.CI_APP_ID }}
|
||||||
|
private-key: ${{ secrets.CI_APP_PRIVATE_KEY }}
|
||||||
|
|
||||||
|
- name: Check out repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
token: ${{ steps.generate-token.outputs.token }}
|
||||||
|
|
||||||
|
- name: Switch to i18n branch
|
||||||
|
run: |
|
||||||
|
git config --global user.name "livecodes-ci[bot]"
|
||||||
|
git config --global user.email "186997172+livecodes-ci[bot]@users.noreply.github.com"
|
||||||
|
|
||||||
|
if [[ $(git ls-remote --heads origin $BRANCH) ]]; then
|
||||||
|
git config pull.rebase false
|
||||||
|
git fetch origin $BRANCH:$BRANCH
|
||||||
|
git checkout $BRANCH
|
||||||
|
else
|
||||||
|
git checkout -b $BRANCH
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Setup Node
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
|
cache: 'npm'
|
||||||
|
cache-dependency-path: '**/package-lock.json'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
# - name: Linting and fixing
|
||||||
|
# run: npm run fix
|
||||||
|
|
||||||
|
# - name: Commit changes
|
||||||
|
# run: |
|
||||||
|
# git add .
|
||||||
|
|
||||||
|
# # Only commit if there are changes
|
||||||
|
# git diff-index --quiet HEAD || git commit -m "i18n: update source texts"
|
||||||
|
|
||||||
|
# # Save SHA of the latest commit to English locale
|
||||||
|
# echo "LAST_COMMIT_SHA_PUSH=$(git log -n 1 --format="%H" -- src/livecodes/i18n/locales/en)" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
# - name: Push changes
|
||||||
|
# run: git push origin $BRANCH
|
||||||
|
|
||||||
|
# - name: Push source texts to Lokalise
|
||||||
|
# run: npm run i18n-update-push -- $LOKALISE_BRANCH
|
||||||
|
|
||||||
|
- name: Import from Lokalise
|
||||||
|
run: |
|
||||||
|
mkdir -p $LOKALISE_TEMP && touch $LOKALISE_TEMP/locales.zip && npm run i18n-update-pull -- $LOKALISE_BRANCH && rm -rf $LOKALISE_TEMP
|
||||||
|
env:
|
||||||
|
LOKALISE_TEMP: lokalise_tmp
|
||||||
|
|
||||||
|
- name: Linting and fixing
|
||||||
|
run: npm run fix
|
||||||
|
|
||||||
|
- name: Commit changes
|
||||||
|
run: |
|
||||||
|
git add .
|
||||||
|
|
||||||
|
# Only commit if there are changes
|
||||||
|
git diff-index --quiet HEAD || git commit -m "i18n: pull translation from Lokalise"
|
||||||
|
|
||||||
|
# Save SHA of the latest commit to locale
|
||||||
|
echo "LAST_COMMIT_SHA_PULL=$(git log -n 1 --format="%H" -- src/livecodes/i18n/locales)" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Push changes
|
||||||
|
run: |
|
||||||
|
|
||||||
|
git pull origin ${{ github.event.repository.default_branch }} || {
|
||||||
|
echo "Failed to pull from ${{ github.event.repository.default_branch }}."
|
||||||
|
echo "Please manually pull the changes, solve potential conflicts, and re-run the workflow."
|
||||||
|
echo "::error title=Pull failed::Failed to pull from ${{ github.event.repository.default_branch }}."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
git push origin $BRANCH
|
||||||
|
|
||||||
|
- name: Check if has differences between ${{ env.BRANCH }} and ${{ github.event.repository.default_branch }}
|
||||||
|
id: check-diff
|
||||||
|
run: |
|
||||||
|
DIFF=$(git diff --name-only $BRANCH origin/${{ github.event.repository.default_branch }})
|
||||||
|
if [[ -z $DIFF ]]; then
|
||||||
|
echo "No difference between $BRANCH and ${{ github.event.repository.default_branch }}."
|
||||||
|
echo "SKIP=true" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "LAST_COMMIT_SHA_PUSH=$(git log -n 1 --format="%H" -- src/livecodes/i18n/locales/en)" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Create a new i18n PR if not exists
|
||||||
|
uses: actions/github-script@v7
|
||||||
|
if: steps.check-diff.outputs.SKIP != 'true'
|
||||||
|
with:
|
||||||
|
github-token: ${{ steps.generate-token.outputs.token }}
|
||||||
|
script: |
|
||||||
|
const prInfo = await github.rest.pulls.list({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
state: 'open',
|
||||||
|
head: process.env.BRANCH
|
||||||
|
});
|
||||||
|
|
||||||
|
if (prInfo.data.length > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Creating a new i18n PR from ${process.env.BRANCH}...`);
|
||||||
|
|
||||||
|
const repoURL = context.payload.repository.html_url;
|
||||||
|
const branchURL = `${repoURL}/tree/${process.env.BRANCH}`;
|
||||||
|
const prTitle = `i18n: scheduled update from ${process.env.BRANCH}`;
|
||||||
|
const prBody = `## What type of PR is this? (check all applicable)
|
||||||
|
|
||||||
|
- [ ] ✨ Feature
|
||||||
|
- [ ] 🐛 Bug Fix
|
||||||
|
- [ ] 📝 Documentation Update
|
||||||
|
- [ ] 🎨 Style
|
||||||
|
- [ ] ♻️ Code Refactor
|
||||||
|
- [ ] 🔥 Performance Improvements
|
||||||
|
- [ ] ✅ Test
|
||||||
|
- [ ] 🤖 Build
|
||||||
|
- [ ] 🔁 CI
|
||||||
|
- [ ] 📦 Chore (Release)
|
||||||
|
- [ ] ⏩ Revert
|
||||||
|
- [x] 🌐 Internationalization / Translation
|
||||||
|
|
||||||
|
## Description
|
||||||
|
### i18n Actions: \`.i18n-update-scheduled\`
|
||||||
|
Scheduled update of source texts and translations.
|
||||||
|
|
||||||
|
| Name | Description |
|
||||||
|
| --- | --- |
|
||||||
|
| **Last Commit SHA (Push)** | ${process.env.LAST_COMMIT_SHA_PUSH} |
|
||||||
|
| **Last Commit SHA (Pull)** | ${process.env.LAST_COMMIT_SHA_PULL} |
|
||||||
|
`;
|
||||||
|
|
||||||
|
github.rest.pulls.create({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
title: prTitle,
|
||||||
|
body: prBody,
|
||||||
|
head: process.env.BRANCH,
|
||||||
|
base: '${{ github.event.repository.default_branch }}'
|
||||||
|
});
|
||||||
29
.github/workflows/release-pr.yml
vendored
Normal file
29
.github/workflows/release-pr.yml
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
name: Release PR
|
||||||
|
|
||||||
|
# on creating a release branch (releases/**) create a PR to develop
|
||||||
|
on: create
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: contains(github.ref, 'refs/heads/releases/')
|
||||||
|
steps:
|
||||||
|
- name: Generate Github Token for CI Bot
|
||||||
|
uses: actions/create-github-app-token@v1
|
||||||
|
id: generate-token
|
||||||
|
with:
|
||||||
|
app-id: ${{ secrets.CI_APP_ID }}
|
||||||
|
private-key: ${{ secrets.CI_APP_PRIVATE_KEY }}
|
||||||
|
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
token: ${{ steps.generate-token.outputs.token }}
|
||||||
|
|
||||||
|
- name: Get version
|
||||||
|
id: vars
|
||||||
|
run: echo ::set-output name=version::$(echo ${{github.ref_name}} | sed 's/^releases\///')
|
||||||
|
|
||||||
|
- name: Create pull request to develop
|
||||||
|
run: gh pr create --title "Prepare release ${{steps.vars.outputs.version}}" --body "Prepare release ${{steps.vars.outputs.version}}" --base develop --head "${{github.ref_name}}"
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
|
||||||
104
.github/workflows/release.yml
vendored
Normal file
104
.github/workflows/release.yml
vendored
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
name: Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- develop
|
||||||
|
types: [closed]
|
||||||
|
|
||||||
|
env:
|
||||||
|
NODE_VERSION: 18.x
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.event.pull_request.merged && startsWith(github.head_ref, 'releases/')
|
||||||
|
env:
|
||||||
|
NODE_OPTIONS: '--max_old_space_size=4096'
|
||||||
|
steps:
|
||||||
|
- name: Generate Github Token for CI Bot
|
||||||
|
uses: actions/create-github-app-token@v1
|
||||||
|
id: generate-token
|
||||||
|
with:
|
||||||
|
app-id: ${{ secrets.CI_APP_ID }}
|
||||||
|
private-key: ${{ secrets.CI_APP_PRIVATE_KEY }}
|
||||||
|
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
token: ${{ steps.generate-token.outputs.token }}
|
||||||
|
|
||||||
|
- name: Get version
|
||||||
|
id: vars
|
||||||
|
run: echo ::set-output name=version::$(echo ${{github.head_ref}} | sed 's/^releases\///')
|
||||||
|
|
||||||
|
- name: Use Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: ${{ env.NODE_VERSION }}
|
||||||
|
cache: 'npm'
|
||||||
|
cache-dependency-path: '**/package-lock.json'
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: npm run build
|
||||||
|
env:
|
||||||
|
BUILD_INCLUDE_LOCALES: true
|
||||||
|
|
||||||
|
- name: Release notes
|
||||||
|
run: node ./scripts/release-notes.js
|
||||||
|
|
||||||
|
- name: Create tag
|
||||||
|
run: git tag ${{steps.vars.outputs.version}} && git push origin --tags
|
||||||
|
|
||||||
|
- name: Compress build directory (tar)
|
||||||
|
run: tar -czf livecodes-${{steps.vars.outputs.version}}.tar.gz build
|
||||||
|
|
||||||
|
- name: Compress build directory (zip)
|
||||||
|
uses: vimtor/action-zip@v1
|
||||||
|
with:
|
||||||
|
files: build/
|
||||||
|
dest: livecodes-${{steps.vars.outputs.version}}.zip
|
||||||
|
|
||||||
|
- name: Create release
|
||||||
|
uses: softprops/action-gh-release@v1
|
||||||
|
with:
|
||||||
|
name: ${{steps.vars.outputs.version}}
|
||||||
|
tag_name: ${{steps.vars.outputs.version}}
|
||||||
|
body_path: CHANGELOG.tmp.md
|
||||||
|
files: |
|
||||||
|
livecodes-${{steps.vars.outputs.version}}.tar.gz
|
||||||
|
livecodes-${{steps.vars.outputs.version}}.zip
|
||||||
|
token: ${{ steps.generate-token.outputs.token }}
|
||||||
|
|
||||||
|
- name: Create permanent URL
|
||||||
|
if: startsWith(github.head_ref, 'releases/v')
|
||||||
|
run: node ./scripts/create-permanent-url.js
|
||||||
|
env:
|
||||||
|
APP_VERSION: ${{steps.vars.outputs.version}}
|
||||||
|
CF_ACCOUNT_ID: ${{ secrets.CF_ACCOUNT_ID }}
|
||||||
|
CF_ZONE: ${{ secrets.CF_ZONE }}
|
||||||
|
CF_TOKEN: ${{ secrets.CF_TOKEN }}
|
||||||
|
|
||||||
|
- name: Publish SDK to NPM
|
||||||
|
if: startsWith(github.head_ref, 'releases/sdk-v')
|
||||||
|
run: |
|
||||||
|
echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc
|
||||||
|
npm publish --access=public
|
||||||
|
working-directory: ./build/sdk
|
||||||
|
env:
|
||||||
|
NPM_TOKEN: ${{secrets.NPM_TOKEN}}
|
||||||
|
|
||||||
|
- name: Create pull request to main (App)
|
||||||
|
if: startsWith(github.head_ref, 'releases/v')
|
||||||
|
run: gh pr create --title "release ${{steps.vars.outputs.version}}" --body "https://${{steps.vars.outputs.version}}.livecodes.io" --base main --head develop
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
|
||||||
|
|
||||||
|
- name: Create pull request to main (SDK)
|
||||||
|
if: startsWith(github.head_ref, 'releases/sdk-v')
|
||||||
|
run: gh pr create --title "release ${{steps.vars.outputs.version}}" --body "https://www.npmjs.com/package/livecodes" --base main --head develop
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
|
||||||
15
.gitignore
vendored
Normal file
15
.gitignore
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
node_modules
|
||||||
|
build
|
||||||
|
dist
|
||||||
|
.cache
|
||||||
|
**/*.log
|
||||||
|
.env
|
||||||
|
docs/docs/api
|
||||||
|
docs/static/**/*.html.md
|
||||||
|
docs/static/llms.txt
|
||||||
|
docs/static/llms-full.txt
|
||||||
|
/test-results/
|
||||||
|
/playwright-report/
|
||||||
|
/playwright/.cache/
|
||||||
|
src/livecodes/i18n/locales/tmp/
|
||||||
|
lokalise_tmp
|
||||||
6
.jest/setup.ts
Normal file
6
.jest/setup.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import pkg from '../package.json';
|
||||||
|
import { languages } from '../src/livecodes/languages/languages';
|
||||||
|
import { processors } from '../src/livecodes/languages/processors';
|
||||||
|
|
||||||
|
process.env.VERSION = pkg.appVersion;
|
||||||
|
(window as any).deps = { languages, processors };
|
||||||
4
.prettierignore
Normal file
4
.prettierignore
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
# package.json is formatted by package managers, so we ignore it here
|
||||||
|
package.json
|
||||||
|
src/modules
|
||||||
|
**/*.mdx
|
||||||
12
.stylelintrc.json
Normal file
12
.stylelintrc.json
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"extends": "stylelint-config-sass-guidelines",
|
||||||
|
"rules": {
|
||||||
|
"color-named": null,
|
||||||
|
"max-nesting-depth": 4,
|
||||||
|
"selector-class-pattern": null,
|
||||||
|
"selector-max-compound-selectors": 5,
|
||||||
|
"selector-max-id": 3,
|
||||||
|
"selector-no-qualifying-type": null
|
||||||
|
},
|
||||||
|
"ignoreFiles": ["**/build/**/*"]
|
||||||
|
}
|
||||||
40
.vscode/html.html-data.json
vendored
Normal file
40
.vscode/html.html-data.json
vendored
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"version": 1.1,
|
||||||
|
"globalAttributes": [
|
||||||
|
{
|
||||||
|
"name": "data-i18n",
|
||||||
|
"description": "The key of the translation for current element."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "data-i18n-prop",
|
||||||
|
"description": "Attributes of the element that should be translated, separated by space.",
|
||||||
|
"valueSet": "i18nProps"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "data-hint",
|
||||||
|
"description": "The tooltip of the element."
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"valueSets": [
|
||||||
|
{
|
||||||
|
"name": "i18nProps",
|
||||||
|
"values": [
|
||||||
|
{
|
||||||
|
"name": "textContent"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "innerHTML"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "title"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "data-hint"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "placeholder"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
30
.vscode/settings.json
vendored
Normal file
30
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"conventionalCommits.scopes": [
|
||||||
|
"Compilers",
|
||||||
|
"SDK",
|
||||||
|
"Config",
|
||||||
|
"UI",
|
||||||
|
"App",
|
||||||
|
"functions",
|
||||||
|
"Share",
|
||||||
|
"Templates",
|
||||||
|
"Types",
|
||||||
|
"Editor",
|
||||||
|
"Code-to-Image",
|
||||||
|
"Result",
|
||||||
|
"Embed",
|
||||||
|
"Modules",
|
||||||
|
"Deploy",
|
||||||
|
"Import",
|
||||||
|
"i18n",
|
||||||
|
"ToolsPane",
|
||||||
|
"Modes",
|
||||||
|
"Import-maps",
|
||||||
|
"Formatter",
|
||||||
|
"Build",
|
||||||
|
"services",
|
||||||
|
"CommandMenu",
|
||||||
|
"Accessibility"
|
||||||
|
],
|
||||||
|
"html.customData": ["./.vscode/html.html-data.json"]
|
||||||
|
}
|
||||||
2513
CHANGELOG.md
Normal file
2513
CHANGELOG.md
Normal file
File diff suppressed because it is too large
Load Diff
132
CODE_OF_CONDUCT.md
Normal file
132
CODE_OF_CONDUCT.md
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
# Contributor Covenant Code of Conduct
|
||||||
|
|
||||||
|
## Our Pledge
|
||||||
|
|
||||||
|
We as members, contributors, and leaders pledge to make participation in our
|
||||||
|
community a harassment-free experience for everyone, regardless of age, body
|
||||||
|
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||||
|
identity and expression, level of experience, education, socio-economic status,
|
||||||
|
nationality, personal appearance, race, caste, color, religion, or sexual
|
||||||
|
identity and orientation.
|
||||||
|
|
||||||
|
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||||
|
diverse, inclusive, and healthy community.
|
||||||
|
|
||||||
|
## Our Standards
|
||||||
|
|
||||||
|
Examples of behavior that contributes to a positive environment for our
|
||||||
|
community include:
|
||||||
|
|
||||||
|
- Demonstrating empathy and kindness toward other people
|
||||||
|
- Being respectful of differing opinions, viewpoints, and experiences
|
||||||
|
- Giving and gracefully accepting constructive feedback
|
||||||
|
- Accepting responsibility and apologizing to those affected by our mistakes,
|
||||||
|
and learning from the experience
|
||||||
|
- Focusing on what is best not just for us as individuals, but for the overall
|
||||||
|
community
|
||||||
|
|
||||||
|
Examples of unacceptable behavior include:
|
||||||
|
|
||||||
|
- The use of sexualized language or imagery, and sexual attention or advances of
|
||||||
|
any kind
|
||||||
|
- Trolling, insulting or derogatory comments, and personal or political attacks
|
||||||
|
- Public or private harassment
|
||||||
|
- Publishing others' private information, such as a physical or email address,
|
||||||
|
without their explicit permission
|
||||||
|
- Other conduct which could reasonably be considered inappropriate in a
|
||||||
|
professional setting
|
||||||
|
|
||||||
|
## Enforcement Responsibilities
|
||||||
|
|
||||||
|
Community leaders are responsible for clarifying and enforcing our standards of
|
||||||
|
acceptable behavior and will take appropriate and fair corrective action in
|
||||||
|
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||||
|
or harmful.
|
||||||
|
|
||||||
|
Community leaders have the right and responsibility to remove, edit, or reject
|
||||||
|
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||||
|
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||||
|
decisions when appropriate.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This Code of Conduct applies within all community spaces, and also applies when
|
||||||
|
an individual is officially representing the community in public spaces.
|
||||||
|
Examples of representing our community include using an official e-mail address,
|
||||||
|
posting via an official social media account, or acting as an appointed
|
||||||
|
representative at an online or offline event.
|
||||||
|
|
||||||
|
## Enforcement
|
||||||
|
|
||||||
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||||
|
reported to the community leaders responsible for enforcement at
|
||||||
|
<a href="mailto:support@livecodes.io">support@livecodes.io</a>.
|
||||||
|
All complaints will be reviewed and investigated promptly and fairly.
|
||||||
|
|
||||||
|
All community leaders are obligated to respect the privacy and security of the
|
||||||
|
reporter of any incident.
|
||||||
|
|
||||||
|
## Enforcement Guidelines
|
||||||
|
|
||||||
|
Community leaders will follow these Community Impact Guidelines in determining
|
||||||
|
the consequences for any action they deem in violation of this Code of Conduct:
|
||||||
|
|
||||||
|
### 1. Correction
|
||||||
|
|
||||||
|
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||||
|
unprofessional or unwelcome in the community.
|
||||||
|
|
||||||
|
**Consequence**: A private, written warning from community leaders, providing
|
||||||
|
clarity around the nature of the violation and an explanation of why the
|
||||||
|
behavior was inappropriate. A public apology may be requested.
|
||||||
|
|
||||||
|
### 2. Warning
|
||||||
|
|
||||||
|
**Community Impact**: A violation through a single incident or series of
|
||||||
|
actions.
|
||||||
|
|
||||||
|
**Consequence**: A warning with consequences for continued behavior. No
|
||||||
|
interaction with the people involved, including unsolicited interaction with
|
||||||
|
those enforcing the Code of Conduct, for a specified period of time. This
|
||||||
|
includes avoiding interactions in community spaces as well as external channels
|
||||||
|
like social media. Violating these terms may lead to a temporary or permanent
|
||||||
|
ban.
|
||||||
|
|
||||||
|
### 3. Temporary Ban
|
||||||
|
|
||||||
|
**Community Impact**: A serious violation of community standards, including
|
||||||
|
sustained inappropriate behavior.
|
||||||
|
|
||||||
|
**Consequence**: A temporary ban from any sort of interaction or public
|
||||||
|
communication with the community for a specified period of time. No public or
|
||||||
|
private interaction with the people involved, including unsolicited interaction
|
||||||
|
with those enforcing the Code of Conduct, is allowed during this period.
|
||||||
|
Violating these terms may lead to a permanent ban.
|
||||||
|
|
||||||
|
### 4. Permanent Ban
|
||||||
|
|
||||||
|
**Community Impact**: Demonstrating a pattern of violation of community
|
||||||
|
standards, including sustained inappropriate behavior, harassment of an
|
||||||
|
individual, or aggression toward or disparagement of classes of individuals.
|
||||||
|
|
||||||
|
**Consequence**: A permanent ban from any sort of public interaction within the
|
||||||
|
community.
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||||
|
version 2.1, available at
|
||||||
|
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
|
||||||
|
|
||||||
|
Community Impact Guidelines were inspired by
|
||||||
|
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
|
||||||
|
|
||||||
|
For answers to common questions about this code of conduct, see the FAQ at
|
||||||
|
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
|
||||||
|
[https://www.contributor-covenant.org/translations][translations].
|
||||||
|
|
||||||
|
[homepage]: https://www.contributor-covenant.org
|
||||||
|
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
|
||||||
|
[Mozilla CoC]: https://github.com/mozilla/diversity
|
||||||
|
[FAQ]: https://www.contributor-covenant.org/faq
|
||||||
|
[translations]: https://www.contributor-covenant.org/translations
|
||||||
136
CONTRIBUTING.md
Normal file
136
CONTRIBUTING.md
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
# Contributing
|
||||||
|
|
||||||
|
Contributions are always welcome, no matter how large or small. Before contributing,
|
||||||
|
please read the [code of conduct](CODE_OF_CONDUCT.md).
|
||||||
|
|
||||||
|
Some thoughts to help you contribute to this project
|
||||||
|
|
||||||
|
## General Recommendations
|
||||||
|
|
||||||
|
1. Always discuss your suggested contribution in an issue, so that we agree on the concept and implementation before the actual work.
|
||||||
|
2. Leave a detailed description in the Pull Request.
|
||||||
|
3. Screenshots are preferable for visuals changes.
|
||||||
|
4. Always communicate. Whether it is in the issue or the pull request, keeping the lines of communication helps everyone around you.
|
||||||
|
5. If you have any questions, [let's discuss](https://github.com/live-codes/livecodes/discussions).
|
||||||
|
|
||||||
|
## Get Started
|
||||||
|
|
||||||
|
1. Fork the repo `https://github.com/live-codes/livecodes`
|
||||||
|
2. Clone
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ git clone https://github.com/<your-name>/livecodes
|
||||||
|
$ cd livecodes
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Install dependencies
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Export all source texts for i18n ([more details](./docs/docs/contribution/i18n.md))
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ npm run i18n-export
|
||||||
|
```
|
||||||
|
|
||||||
|
5. Build
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
6. Serve the app on http://127.0.0.1:8080
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ npm run serve
|
||||||
|
```
|
||||||
|
|
||||||
|
7. Start the app and watch for changes
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ npm run start
|
||||||
|
```
|
||||||
|
|
||||||
|
8. Start the docs and watch for changes: http://localhost:3000/docs
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ npm run docs
|
||||||
|
```
|
||||||
|
|
||||||
|
9. Start storybook and watch for changes: http://localhost:6006
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ npm run storybook
|
||||||
|
```
|
||||||
|
|
||||||
|
10. Run linters, formatters & unit tests
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ npm run test
|
||||||
|
```
|
||||||
|
|
||||||
|
11. Run e2e tests
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ npm run e2e
|
||||||
|
```
|
||||||
|
|
||||||
|
12. Deploy to GitHub Pages (make sure you have built the app first)
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ npm run gh-pages
|
||||||
|
```
|
||||||
|
|
||||||
|
13. Start a release ([more details](./docs/docs/contribution/release.md))
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ npm run start-release
|
||||||
|
```
|
||||||
|
|
||||||
|
## Pull Requests
|
||||||
|
|
||||||
|
### _We actively welcome your pull requests, however linking your work to an existing issue is preferred._
|
||||||
|
|
||||||
|
1. Fork the repo and create your branch from `develop`.
|
||||||
|
2. Name your branch something that is descriptive to the work you are doing. i.e. adds-new-thing or fixes-mobile
|
||||||
|
3. If you've added code that should be tested, add tests.
|
||||||
|
4. If you've changed APIs, update the documentation.
|
||||||
|
5. If you make visual changes, screenshots are required.
|
||||||
|
6. Ensure the test suite passes.
|
||||||
|
7. Make sure you address any lint warnings.
|
||||||
|
8. If you make the existing code better, please let us know in your PR description.
|
||||||
|
9. If your changes are related to i18n, please check the [i18n](./docs/docs/contribution/i18n.md) guide first.
|
||||||
|
10. A PR description and title are required.
|
||||||
|
11. [Link to an issue](https://help.github.com/en/github/writing-on-github/autolinked-references-and-urls) in the project. An issue is required to announce your intentions and discuss decisions.
|
||||||
|
|
||||||
|
### Commit Messages
|
||||||
|
|
||||||
|
This project uses [Conventional Commits](https://www.conventionalcommits.org/) to automatically generate [changelog](CHANGELOG.md).
|
||||||
|
|
||||||
|
### Work in progress
|
||||||
|
|
||||||
|
GitHub has support for draft pull requests, which will disable the merge button until the PR is marked as ready for merge.
|
||||||
|
|
||||||
|
## Issues
|
||||||
|
|
||||||
|
If you plan to contribute a change based on an open issue, please assign yourself by commenting on the following word `.take`. Issues that are not assigned are assumed open, and to avoid conflicts, please assign yourself before beginning work on any issues.
|
||||||
|
|
||||||
|
If you would like to contribute to the project for the first time, please consider checking the [docs](https://github.com/live-codes/livecodes/issues?q=is%3Aissue+is%3Aopen+label%3A%22%F0%9F%90%9B+docs%22), [bug](https://github.com/live-codes/livecodes/issues?q=is%3Aissue+is%3Aopen+label%3A%22%F0%9F%90%9B+bug%22) or [good first issue](https://github.com/live-codes/livecodes/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) labels.
|
||||||
|
|
||||||
|
Also, all questions are [welcomed](https://github.com/live-codes/livecodes/discussions).
|
||||||
|
|
||||||
|
## Specific Topics
|
||||||
|
|
||||||
|
- [Adding Languages](./docs/docs/contribution/adding-languages.mdx)
|
||||||
|
- [Release](./docs/docs/contribution/release.mdx)
|
||||||
|
- [i18n](./docs/docs/contribution/i18n.mdx)
|
||||||
|
|
||||||
|
## Funding
|
||||||
|
|
||||||
|
LiveCodes is a part of GitHub Sponsors. If you would like to contribute, please note the [sponsor page](https://livecodes.io/docs/sponsor) for details.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
By contributing to the LiveCodes project, you agree that your contributions will be licensed under its [MIT license](LICENSE).
|
||||||
18
Dockerfile
Normal file
18
Dockerfile
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
FROM node:24.1.0-alpine3.21 AS build-stage
|
||||||
|
RUN apk update && apk add git
|
||||||
|
|
||||||
|
# set the working directory
|
||||||
|
WORKDIR /app
|
||||||
|
# Copy the working directory in the container
|
||||||
|
COPY . .
|
||||||
|
# Install the project dependencies
|
||||||
|
RUN npm install
|
||||||
|
# Build the application to the production mode to dist folder
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
|
||||||
|
# Use a lightweight web server to serve the built application
|
||||||
|
FROM httpd:2.4 AS production-stage
|
||||||
|
# Copy the build application from the previous stage to the Nginx container
|
||||||
|
COPY --from=build-stage /app/build /usr/local/apache2/htdocs/
|
||||||
|
CMD ["httpd-foreground"]
|
||||||
3
FUNDING.yml
Normal file
3
FUNDING.yml
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
github: [live-codes, hatemhosny]
|
||||||
|
ko_fi: hatemhosny
|
||||||
|
custom: ['https://paypal.me/hatemhosni']
|
||||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2021-PRESENT Hatem Hosny
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
337
README.md
Normal file
337
README.md
Normal file
@ -0,0 +1,337 @@
|
|||||||
|
# LiveCodes
|
||||||
|
|
||||||
|
A Code Playground That Just Works!
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img width="300" src="https://dev.livecodes.io/docs/img/livecodes-logo.svg"></img>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
A [feature-rich](https://livecodes.io/docs/features/), open-source, **client-side** code playground for React, Vue, Svelte, Solid, Typescript, Python, Go, Ruby, PHP and [90+ languages/frameworks](https://livecodes.io/docs/languages/).
|
||||||
|
|
||||||
|
[](https://status.livecodes.io)
|
||||||
|
[](https://livecodes.io)
|
||||||
|
[](https://www.npmjs.com/package/livecodes)
|
||||||
|
[](https://www.npmjs.com/package/livecodes)
|
||||||
|
[](https://www.jsdelivr.com/package/npm/livecodes)
|
||||||
|
[](https://livecodes.io/docs/languages/)
|
||||||
|
[](https://livecodes.io/docs/)
|
||||||
|
[](https://livecodes.io/docs/llms.txt)
|
||||||
|
[](https://livecodes.io/docs/llms-full.txt)
|
||||||
|
[](https://www.codacy.com/gh/live-codes/livecodes/dashboard?utm_source=github.com&utm_medium=referral&utm_content=live-codes/livecodes&utm_campaign=Badge_Grade)
|
||||||
|
[](https://app.lokalise.com/public/34958094667a72e9454592.95108106/)
|
||||||
|
[](https://app.lokalise.com/public/34958094667a72e9454592.95108106/)
|
||||||
|
[](https://github.com/live-codes/livecodes/blob/develop/LICENSE)
|
||||||
|
[](https://github.com/live-codes/livecodes)
|
||||||
|
[](https://github.com/live-codes/livecodes)
|
||||||
|
[](https://x.com/livecodes_io)
|
||||||
|
|
||||||
|
[Try it now on livecodes.io](https://livecodes.io)
|
||||||
|
|
||||||
|
[Documentations](https://livecodes.io/docs)
|
||||||
|
|
||||||
|
[What makes LiveCodes different?](https://livecodes.io/docs/why)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## A Code Playground That Just Works!
|
||||||
|
|
||||||
|
- No servers to configure (or pay for!)
|
||||||
|
- No databases to maintain (or pay for!)
|
||||||
|
- No installs
|
||||||
|
- No configuration files
|
||||||
|
- No build steps
|
||||||
|
- No subscription fees (free and open-source)
|
||||||
|
- No account required \*
|
||||||
|
- No limits for usage (unlimited private projects)
|
||||||
|
- 90+ languages/frameworks/processors
|
||||||
|
- Large set of features and integrations
|
||||||
|
- Import code from a wide variety of sources
|
||||||
|
- Use modules from npm, deno.land/x, jsr, GitHub, and others
|
||||||
|
- Easily embed it in your web pages
|
||||||
|
- It runs in the browser (client-side)
|
||||||
|
|
||||||
|
<sub>\* GitHub account is required only for features that use <a href="https://livecodes.io/docs/features/github-integration" target="_blank" rel="noopener">GitHub Integration</a>.</sub>
|
||||||
|
|
||||||
|
### Quick Start
|
||||||
|
|
||||||
|
#### Standalone App
|
||||||
|
|
||||||
|
1. Go to [livecodes.io](https://livecodes.io)
|
||||||
|
|
||||||
|
... and enjoy all the [features](https://livecodes.io/docs/features/)!
|
||||||
|
|
||||||
|
#### Embedded Playground
|
||||||
|
|
||||||
|
Add this code to your page:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<div id="container"></div>
|
||||||
|
<script type="module">
|
||||||
|
import { createPlayground } from 'https://cdn.jsdelivr.net/npm/livecodes';
|
||||||
|
|
||||||
|
createPlayground('#container', {
|
||||||
|
params: {
|
||||||
|
markdown: '# Hello LiveCodes!',
|
||||||
|
css: 'h1 {color: dodgerblue;}',
|
||||||
|
js: 'console.log("Hello, from JS!");',
|
||||||
|
console: 'open',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
<sup>Check documentations for <a href="https://livecodes.io/docs/features/embeds" target="_blank" rel="noopener">Embedded Playgrounds</a>.</sup>
|
||||||
|
|
||||||
|
#### Self-hosted
|
||||||
|
|
||||||
|
1. Download a [release](https://github.com/live-codes/livecodes/releases)
|
||||||
|
2. Put it on a static file server (for free!) <sup><a href="https://pages.cloudflare.com/" target="_blank" rel="noopener">1</a>, <a href="https://vercel.com/" target="_blank" rel="noopener">2</a>, <a href="https://www.netlify.com/" target="_blank" rel="noopener">3</a>, <a href="https://firebase.google.com/" target="_blank" rel="noopener">4</a>, <a href="https://pages.github.com/" target="_blank" rel="noopener">5</a></sup>
|
||||||
|
|
||||||
|
<sup>Check the guide for <a href="https://livecodes.io/docs/features/self-hosting" target="_blank" rel="noopener">self-hosting</a> (including the built-in setup to deploy to GitHub Pages).</sup>
|
||||||
|
|
||||||
|
... and it just works!
|
||||||
|
|
||||||
|
## Feature Summary
|
||||||
|
|
||||||
|
- A wide range of [language support](https://livecodes.io/docs/languages/) (90+ languages/frameworks/processors)
|
||||||
|
- [Powerful Editor](https://livecodes.io/docs/features/editor-settings)
|
||||||
|
- Mobile-friendly
|
||||||
|
- [External resources/libraries](https://livecodes.io/docs/features/external-resources)
|
||||||
|
- [Import modules](https://livecodes.io/docs/features/module-resolution) from npm, deno.land/x, jsr, GitHub and others
|
||||||
|
- [Code Pre-fill](https://livecodes.io/docs/features/code-prefill)
|
||||||
|
- [Import](https://livecodes.io/docs/features/import)/[Export](https://livecodes.io/docs/features/export) [projects](https://livecodes.io/docs/features/projects)
|
||||||
|
- [Share](https://livecodes.io/docs/features/share)
|
||||||
|
- [Embed the playground](https://livecodes.io/docs/features/embeds) in any web page
|
||||||
|
- [Display modes](https://livecodes.io/docs/features/display-modes)
|
||||||
|
- [Deploy](https://livecodes.io/docs/features/deploy)
|
||||||
|
- [Starter Templates](https://livecodes.io/docs/features/templates)
|
||||||
|
- [Assets](https://livecodes.io/docs/features/assets)
|
||||||
|
- [Themes](https://livecodes.io/docs/features/themes)
|
||||||
|
- [Dev Tools](https://livecodes.io/docs/features/tools-pane) ([console](https://livecodes.io/docs/features/console), [compiled code viewer](https://livecodes.io/docs/features/compiled-code), [test runner](https://livecodes.io/docs/features/tests))
|
||||||
|
- [Code formatting](https://livecodes.io/docs/features/code-format)
|
||||||
|
- [Intellisense](https://livecodes.io/docs/features/intellisense)
|
||||||
|
- [AI Code Assistant 🪄](https://livecodes.io/docs/features/ai)
|
||||||
|
- [Lite mode](https://livecodes.io/docs/features/lite)
|
||||||
|
- [Read-only mode](https://livecodes.io/docs/features/read-only)
|
||||||
|
- [Broadcast](https://livecodes.io/docs/features/broadcast)
|
||||||
|
- [Sync](https://livecodes.io/docs/features/sync)
|
||||||
|
- [Backup/Restore](https://livecodes.io/docs/features/backup-restore)
|
||||||
|
- [Client-side!](https://livecodes.io/docs/why#client-side)
|
||||||
|
- Very [configurable](https://livecodes.io/docs/configuration/)
|
||||||
|
- Developer-friendly build-free environment
|
||||||
|
- Powerful [SDK](https://livecodes.io/docs/sdk/) (available for [vanilla JavaScript, TypeScript](https://livecodes.io/docs/sdk/js-ts), [React](https://livecodes.io/docs/sdk/react), [Vue](https://livecodes.io/docs/sdk/vue) and [Svelte](https://livecodes.io/docs/sdk/svelte))
|
||||||
|
- Comprehensive [Documentations](https://livecodes.io/docs/)
|
||||||
|
- Focused on [privacy and security](https://livecodes.io/docs/features/security)
|
||||||
|
- Free and [Open-Source](https://livecodes.io/docs/license)
|
||||||
|
|
||||||
|
For details check the [full list of features](https://livecodes.io/docs/features/).
|
||||||
|
|
||||||
|
## LiveCodes SDK
|
||||||
|
|
||||||
|
The Software Development Kit (SDK) provides an easy, yet powerful, interface to embed and communicate with LiveCodes playgrounds.
|
||||||
|
|
||||||
|
The SDK is provided as a light-weight ([less than 5kb gzipped](https://bundlephobia.com/package/livecodes)), zero-dependencies [npm package](https://livecodes.io/docs/sdk/#npm-package), that is also available from [CDNs](https://livecodes.io/docs/sdk/#cdn). It can be used to create playgrounds with a wide variety of [configurations](https://livecodes.io/docs/configuration/configuration-object.md) and [embed options](https://livecodes.io/docs/sdk/js-ts.md#embed-options). In addition, [SDK methods](https://livecodes.io/docs/sdk/js-ts.md#sdk-methods) allow programmatic communication and control of the playgrounds during runtime.
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
```
|
||||||
|
npm i livecodes
|
||||||
|
```
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
Example: ([open in LiveCodes](https://livecodes.io/?x=code/N4IgLglmA2CmIC4QBkIDdYGED2ATWAzgAQDKAIgNJH4C22IANCPgQMYBOEADpNgHaIQjEAAtYAQ1yCAPDVhhxRViPHsC8gLwAdEAFUAKgDEAtAA4dRAPQA+LX1nzFfcXO0g0EWAHcu2dmAtWfjBYPjA3LwhcMBENfA9WWGNI6JEGIgg+KAhxaGM2XNgNAEYAOgAGCxthETAaaABBMDA1QWhxPgBzN1DA9oICNx1hBU6CRABtAF0mcVZIDABRXCg-QTZOHmEaVQBrAFcuRFB2rv3xTvgkWvrhILDQsBkVtAzcN3uFTNh2HWtpSwvawgAC+TAIYAAnnBjiBTp1zpdBKwBndgo9BKDwRxuE8ECcOgiLlcQAArcRocQbXFoh5hQQQGi+fxEYBKdgSEIABXakM67Gw+z4uCIIKIADMBTQiAByaDoWBBFgygDcWl+fHVdg4nNgPPEfIFQtwAAoZQBiT7ib7sGXpYBavhEJT8cUQToIVmO53OnbsA5cT0OjU+n3wxGwT0yv27XDYLx8O3e0MuulgKPmogACVg0Gg2CIAHU-NBcABCJMhn1g5M1qsebxRjkEfbQMCVuwggCUao1WJAEOhhDE8nGCGm2M2YDHE5AKIIXOb8kxTC4AsSAz8M5mc-2EOwNBI8kgXTHwDBIEZzOnxwvUK4hFvTBCELPcMJEcE98IOK2TE+GJIP2GBqBA-CCAAzBBIzYNg0BvqE4gAEZwFISC5NAwhzAsJL3AQcHwOCChgHuyL5uoUggiCQA))
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { createPlayground } from 'livecodes';
|
||||||
|
|
||||||
|
createPlayground('#container', {
|
||||||
|
config: {
|
||||||
|
markup: {
|
||||||
|
language: 'markdown',
|
||||||
|
content: '# Hello World!',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
view: 'result',
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
The [JavaScript SDK](https://livecodes.io/docs/sdk/js-ts.md) is framework/library agnostic. However, wrapper components are also provided for popular libraries (currently [React](https://livecodes.io/docs/sdk/react.md) and [Vue](https://livecodes.io/docs/sdk/vue.md)). The SDK can be used in [Svelte](https://livecodes.io/docs/sdk/svelte.md) directly without wrappers. [TypeScript support](https://livecodes.io/docs/sdk/js-ts.md#typescript-types) provides type-safety and a great developer experience.
|
||||||
|
|
||||||
|
React SDK example: ([open in LiveCodes](https://livecodes.io/?x=code/N4IgLglmA2CmIC4QBkIDdYGED2ATWAzgAQBKsAhgMZhEDKAIgNJH4C22IANCPgZQE4QADpGwA7RCC4gAFhVySAPK1hhyRSjPL8CqgLwAdEAFUAKgDEAtAA4jRAPQA+A2OWr1Y8isMg0EWADuQtj8YHaU4mCwYmA+ARC4YDJ6+H6UsJbxiTKcRBBiUBDk0JZ8xbB6AIwAdAAMdk7SMmCs0ACCYGA6ktDkYgDmPtHhvQQEPkbSav0EiADaALrcVJAYAKK4UCGSfIIi0qzaANYArkKIoL0DJ+T98EjNrdIRMdFgkiAAvtwEYACecAuICu-Rud0klDGz0ibw+3xAu2E7wQlz6oNu9xAACsCAAPaGvGKSCCsYKhIioDA4XhEABm-GwrCIAHJoOhYBFePZ+BRqMyANwGfguIUuF6-DTiWkQfpEPREYCisREIiHfinIQIBVKlUqkFg2Ba5lqo64bABMTMzg63UvKIxI0AYiIAAlYNBoNgiAB1ELQXAAQitNu+Ss+guFYnFNAACr0-v0GScxLg5UQABQASjljiIikpWDwhElYmlg2ALzLnyIfkCPh5BBO0DCIAcjgjLlguLJNHwtPITdj8cT2GTuA7EnhvwBhDkqlmCEWPwESIXS5AkIIMYbqg+3CEDPSYxCa6WG5Ov0ZtFUkAGC+A8JJPfv8P+QkIF1fhDA9+BaINkhvoQK77NwdqwkgXzcBgOgQOIkgAMwIVM2DYNAv7ROQABGcAKEgxTQNIKzshC4gEGh8A-GoYAXhCnq6AonyfEAA))
|
||||||
|
|
||||||
|
```jsx
|
||||||
|
import LiveCodes from 'livecodes/react';
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
markup: {
|
||||||
|
language: 'markdown',
|
||||||
|
content: '# Hello World!',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const Playground = () => <LiveCodes config={config} view="result" />;
|
||||||
|
export default Playground;
|
||||||
|
```
|
||||||
|
|
||||||
|
Vue SDK example: ([open in LiveCodes](https://livecodes.io/?x=code/N4IgLglmA2CmIC4QBkIDdYGED2ATWAzgAQBqArrEQMoAiA0kfgLbYgA0I+BAxgE4QAHSNgB2iEOxAALWAENc4gDxNYYWUW5TZvAqoC8AHRABVACoAxALQAOI0QD0APgMjlq9SNkrDINBFgA7gLYvGB23KJgsCJgPgEQuGBSevh+3LCW8YlSbEQQIlAQstCWPMWwegCMAHQADHZOklJgTNAAgmBgOuLQsiIA5j7R4b0EBD5Gkmr9BIgA2gC6HLLckBgAorhQIeI8-EKSTNoA1mQCiKC9A2Sy-fBIza2SETHRYOIgAL4cBGAAnnALiArv0bndxNwxs9Im8Pt8QHtBO8EJc+qDbvdfBRoa8YkpEUIiLowGdnLwXEQ8kxgqEiKgMDguEQAGa8bBMIgAcmg6FgES49jQFE5AG4DOSROKKRpRL8ZSJmRB+kQ9ERgFKRJTKUdeKcBAg1RqtVqQWDYAbOTrjrhsAERJy2EbjfKojELQBiIgACVg0Gg2CIAHUQtBcABCB1OynfJ2fMUSxT2AlgMkuDWKKLU3pRVOaoiKelYPCEIgIF6KwZGctKux+QI+XiEMjQMIgBy5xOZgTZ2C5r4-f5wAgyVSzBCLH58JFjicgSEEAAKjeJHw4AjZ6TGIRnSznZF+7KoqkgAzHwHhEGpITAZ-h-wEhAud8IN6Bpox4nvhCnBw4L1dyISPCGA6BAojiAAzBBUzYNg0BniA0SyAARnAChIMU0CSCsayYi8BBwfAA6yCSY5zv6ugKJ8nxAA))
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script setup>
|
||||||
|
import LiveCodes from 'livecodes/vue';
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
markup: {
|
||||||
|
language: 'markdown',
|
||||||
|
content: '# Hello World!',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<LiveCodes :config="config" view="result" />
|
||||||
|
</template>
|
||||||
|
```
|
||||||
|
|
||||||
|
In addition, the SDK allows creating links to playgrounds:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { getPlaygroundUrl } from 'livecodes';
|
||||||
|
|
||||||
|
const url = getPlaygroundUrl({
|
||||||
|
config: {
|
||||||
|
markup: {
|
||||||
|
language: 'markdown',
|
||||||
|
content: '# Hello World!',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(url);
|
||||||
|
```
|
||||||
|
|
||||||
|
See [SDK docs](https://livecodes.io/docs/sdk/) for more details.
|
||||||
|
|
||||||
|
## Documentations
|
||||||
|
|
||||||
|
Comprehensive documentations for [features](https://livecodes.io/docs/features/), [getting started](https://livecodes.io/docs/getting-started), [configuration](https://livecodes.io/docs/configuration/) and [SDK](https://livecodes.io/docs/sdk/) are available on:
|
||||||
|
|
||||||
|
https://livecodes.io/docs/
|
||||||
|
|
||||||
|
The documentations include demos, code samples, screenshots, [Storybook](https://livecodes.io/stories) and [TypeScript types](https://livecodes.io/docs/sdk/js-ts#typescript-types).
|
||||||
|
|
||||||
|
## Updates
|
||||||
|
|
||||||
|
Keep up with the latest changes:
|
||||||
|
|
||||||
|
- Twitter/X: [@livecodes_io](https://twitter.com/livecodes_io)
|
||||||
|
- Blog: [blog.livecodes.io](https://blog.livecodes.io/)
|
||||||
|
- Development build: [dev.livecodes.io](https://dev.livecodes.io/)
|
||||||
|
|
||||||
|
## Feedback
|
||||||
|
|
||||||
|
We welcome feedback!
|
||||||
|
|
||||||
|
Please start a new [issue](https://github.com/live-codes/livecodes/issues/new/choose) or [discussion](https://github.com/live-codes/livecodes/discussions/new).
|
||||||
|
|
||||||
|
For security reports please refer to [SECURITY.md](https://github.com/live-codes/livecodes/blob/develop/SECURITY.md).
|
||||||
|
|
||||||
|
You may also reach out to us using the [contact form](https://livecodes.io/docs/contact).
|
||||||
|
|
||||||
|
## Contribution
|
||||||
|
|
||||||
|
Contributions are welcome and highly appreciated.
|
||||||
|
|
||||||
|
A huge shout-out to our wonderful [contributors](https://github.com/live-codes/livecodes/graphs/contributors)! Your hard work makes all the difference!
|
||||||
|
|
||||||
|
Please refer to the [contribution guide](https://github.com/live-codes/livecodes/blob/HEAD/CONTRIBUTING.md).
|
||||||
|
|
||||||
|
## Credits
|
||||||
|
|
||||||
|
LiveCodes uses services that are generously provided by:
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<a href="https://pages.cloudflare.com/" target="_blank" title="Cloudflare Pages">
|
||||||
|
<img alt="Cloudflare Pages" width="200" src="https://dev.livecodes.io/docs/img/credits/cloudflare-pages.svg">
|
||||||
|
</img></a><br /><br />
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://www.jsdelivr.com/" target="_blank" title="jsDelivr">
|
||||||
|
<img alt="jsDelivr" width="200" src="https://dev.livecodes.io/docs/img/credits/jsdelivr.svg">
|
||||||
|
</img></a><br /><br />
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://esm.sh/" target="_blank" title="esm.sh">
|
||||||
|
<img alt="esm.sh" width="200" src="https://dev.livecodes.io/docs/img/credits/esm.sh.png">
|
||||||
|
</img></a><br /><br />
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://unpkg.com/" target="_blank" title="unpkg">
|
||||||
|
<img alt="unpkg" width="200" src="https://dev.livecodes.io/docs/img/credits/unpkg.png">
|
||||||
|
</img></a><br /><br />
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://codeium.com/" target="_blank" title="Codeium">
|
||||||
|
<img alt="Codeium" width="200" src="https://dev.livecodes.io/docs/img/credits/codeium.svg">
|
||||||
|
</img></a><br /><br />
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://bundlejs.com/" target="_blank" title="bundlejs">
|
||||||
|
<img alt="bundlejs" width="200" src="https://dev.livecodes.io/docs/img/credits/bundlejs.jpg">
|
||||||
|
</img></a><br /><br />
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://dpaste.com/" target="_blank" title="dpaste">
|
||||||
|
<img alt="dpaste" width="200" src="https://dev.livecodes.io/docs/img/credits/dpaste.png">
|
||||||
|
</img></a><br /><br />
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://github.com/" target="_blank" title="GitHub">
|
||||||
|
<img alt="GitHub" width="200" src="https://dev.livecodes.io/docs/img/credits/github.png">
|
||||||
|
</img></a><br /><br />
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://netlify.com/" target="_blank" title="Netlify">
|
||||||
|
<img alt="Netlify" width="200" src="https://dev.livecodes.io/docs/img/credits/netlify.svg">
|
||||||
|
</img></a><br /><br />
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://www.sonarsource.com/products/sonarcloud/" target="_blank" title="SonarCloud">
|
||||||
|
<img alt="SonarCloud" width="200" src="https://dev.livecodes.io/docs/img/credits/sonarcloud.svg">
|
||||||
|
</img></a><br /><br />
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://www.codacy.com/" target="_blank" title="Codacy">
|
||||||
|
<img alt="Codacy" width="200" src="https://dev.livecodes.io/docs/img/credits/codacy.svg">
|
||||||
|
</img></a><br /><br />
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://bundlewatch.io/" target="_blank" title="BundleWatch">
|
||||||
|
<img alt="BundleWatch" width="200" src="https://dev.livecodes.io/docs/img/credits/bundlewatch.svg">
|
||||||
|
</img></a><br /><br />
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://www.browserstack.com/" target="_blank" title="BrowserStack">
|
||||||
|
<img alt="BrowserStack" width="200" src="https://dev.livecodes.io/docs/img/credits/browserstack.svg">
|
||||||
|
</img></a><br /><br />
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://lokalise.com/" target="_blank" title="Lokalise">
|
||||||
|
<img alt="Lokalise" width="200" src="https://dev.livecodes.io/docs/img/credits/lokalise.png">
|
||||||
|
</img></a><br /><br />
|
||||||
|
</p>
|
||||||
|
|
||||||
|
## Third Party Packages
|
||||||
|
|
||||||
|
Packages used by LiveCodes and their licenses are [listed here](https://github.com/live-codes/livecodes/blob/develop/vendor-licenses.md).
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
[MIT](https://github.com/live-codes/livecodes/blob/HEAD/LICENSE) License © [Hatem Hosny](https://github.com/hatemhosny)
|
||||||
|
|
||||||
|
## Sponsor
|
||||||
|
|
||||||
|
LiveCodes is free and open-source. The app does not contain ads or require subscription. It allows unlimited usage without any restrictions.
|
||||||
|
|
||||||
|
By sponsoring LiveCodes, you will be supporting the ongoing development and maintenance of the project, as well as helping to ensure that it remains a valuable resource for the developer community.
|
||||||
|
|
||||||
|
Please consider [becoming a sponsor](https://livecodes.io/docs/sponsor).
|
||||||
66
SECURITY.md
Normal file
66
SECURITY.md
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
# LiveCodes Security and Responsible Disclosure Policy <!-- omit in toc -->
|
||||||
|
|
||||||
|
This document outlines security procedures and general policies for
|
||||||
|
LiveCodes projects as found on https://github.com/live-codes.
|
||||||
|
|
||||||
|
- [Reporting a Vulnerability](#reporting-a-vulnerability)
|
||||||
|
- [Disclosure Policy](#disclosure-policy)
|
||||||
|
|
||||||
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
**Please do not report security vulnerabilities through public GitHub issues.**
|
||||||
|
|
||||||
|
All security vulnerabilities are taken seriously. Thank you for
|
||||||
|
improving the security of our open source software. We appreciate
|
||||||
|
your efforts and responsible disclosure and will make every effort
|
||||||
|
to acknowledge your contributions.
|
||||||
|
|
||||||
|
Please report security vulnerabilities by email at: security@livecodes.io
|
||||||
|
|
||||||
|
- Type of issue (e.g. cross-site scripting, authentication or authorization flaws etc.)
|
||||||
|
- Version(s) of the App/SDK affected.
|
||||||
|
- Full paths of source file(s) related to the manifestation of the issue
|
||||||
|
- The location of the affected source code (tag/branch/commit or direct URL)
|
||||||
|
- Any special configuration required to reproduce the issue
|
||||||
|
- Step-by-step instructions to reproduce the issue
|
||||||
|
- Proof-of-concept or exploit code (if possible)
|
||||||
|
- Impact of the issue, including how an attacker might exploit the issue
|
||||||
|
|
||||||
|
This information will help us triage your report more quickly.
|
||||||
|
|
||||||
|
We will acknowledge your email, and will send a response indicating
|
||||||
|
the next steps in handling your report. After the initial reply to
|
||||||
|
your report, we will endeavor to keep you informed of the progress towards
|
||||||
|
a fix and full announcement, and may ask for additional information or guidance.
|
||||||
|
|
||||||
|
To show our appreciation for your effort and cooperation during the report,
|
||||||
|
we will list your name and a link to a personal website/social network profile
|
||||||
|
on the page below so that the public can know you've helped keep LiveCodes secure.
|
||||||
|
|
||||||
|
Please report security vulnerabilities in third-party modules to the person or
|
||||||
|
team maintaining the module.
|
||||||
|
|
||||||
|
## Disclosure Policy
|
||||||
|
|
||||||
|
Please follow these rules when testing/reporting vulnerabilities:
|
||||||
|
|
||||||
|
- Do not take advantage of the vulnerability you have discovered.
|
||||||
|
- Do not read, modify or delete data that isn't you own.
|
||||||
|
- We ask that you do not to disclose the problem to third parties
|
||||||
|
until it has been resolved and only after consultation with LiveCodes team.
|
||||||
|
|
||||||
|
When a security bug report is received, the following steps are followed:
|
||||||
|
|
||||||
|
- Confirm the problem and determine the affected versions.
|
||||||
|
- Audit code to find any potential similar problems.
|
||||||
|
- Prepare fixes for all releases still under maintenance. These fixes
|
||||||
|
will be released as fast as possible.
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
|
## Acknowledgement
|
||||||
|
|
||||||
|
We sincerely appreciate the efforts of security researchers in keeping our community safe. The following people have responsibly disclosed vulnerabilities to us in the past:
|
||||||
|
|
||||||
|
- Name (with link to website)
|
||||||
|
-->
|
||||||
9
docker-compose.yml
Normal file
9
docker-compose.yml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
services:
|
||||||
|
live-codes:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
image: result/latest
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- 8080:80
|
||||||
20
docs/.gitignore
vendored
Normal file
20
docs/.gitignore
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# Dependencies
|
||||||
|
/node_modules
|
||||||
|
|
||||||
|
# Production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
.docusaurus
|
||||||
|
.cache-loader
|
||||||
|
|
||||||
|
# Misc
|
||||||
|
.DS_Store
|
||||||
|
.env.local
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
3
docs/README.md
Normal file
3
docs/README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Website
|
||||||
|
|
||||||
|
This is the documentation website for LiveCodes, hosted on https://livecodes.io/web/.
|
||||||
11
docs/docs/about.mdx
Normal file
11
docs/docs/about.mdx
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# About us
|
||||||
|
|
||||||
|
LiveCodes is built and maintained by [Hatem Hosny](https://github.com/hatemhosny), and wonderful [contributors](https://github.com/live-codes/livecodes/graphs/contributors).
|
||||||
|
|
||||||
|
Feature requests and bug reports are received on the [GitHub repo](https://github.com/live-codes/livecodes/issues).
|
||||||
|
|
||||||
|
Contributions are most welcome. Please open an issue on the GitHub repo to discuss your potential contribution before submitting a pull request.
|
||||||
|
|
||||||
|
Reach out to us using this [contact form](./contact.mdx).
|
||||||
|
|
||||||
|
Please consider [sponsoring LiveCodes](./sponsor.mdx) to support its maintenance and continued development.
|
||||||
1
docs/docs/advanced/custom-settings.mdx
Normal file
1
docs/docs/advanced/custom-settings.mdx
Normal file
@ -0,0 +1 @@
|
|||||||
|
# Custom Settings
|
||||||
12
docs/docs/advanced/index.mdx
Normal file
12
docs/docs/advanced/index.mdx
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
---
|
||||||
|
sidebar_class_name: exclude_from_sidebar
|
||||||
|
---
|
||||||
|
|
||||||
|
# Advanced Topics {#advanced-topics-custom-content-top}
|
||||||
|
|
||||||
|
```mdx-code-block
|
||||||
|
import DocCardList from '@theme/DocCardList';
|
||||||
|
import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
|
||||||
|
|
||||||
|
<DocCardList items={useCurrentSidebarCategory().items.filter(item => item.docId !== 'languages/index')}/>
|
||||||
|
```
|
||||||
30
docs/docs/advanced/services.mdx
Normal file
30
docs/docs/advanced/services.mdx
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# Services
|
||||||
|
|
||||||
|
LiveCodes (being a client-side app) uses multiple services (for example for authentication, sharing, module resolution, etc).
|
||||||
|
|
||||||
|
These services are [defined here](https://github.com/live-codes/livecodes/tree/develop/src/livecodes/services).
|
||||||
|
|
||||||
|
Some of the services are not supported on [self-hosted](../features/self-hosting.mdx) deploys and are either replaced by other compatible services or require you to provide an alternative service.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
- The [share](../features/share.mdx) service in [self-hosted](../features/self-hosting.mdx) apps uses [dpaste](https://dpaste.com/) for short URLs, which are [**deleted after 365 days**](https://dpaste.com/help).
|
||||||
|
- [Firebase configuration](https://github.com/live-codes/livecodes/tree/develop/src/livecodes/services/firebase.ts) for authentication.
|
||||||
|
|
||||||
|
:::info
|
||||||
|
|
||||||
|
LiveCodes [sponsors](../sponsor.mdx) (Bronze sponsors and above) get access to managed custom services.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
If you [self-host](../features/self-hosting.mdx) your app and need to change any of these services, start by following the [guide described there](../features/self-hosting.mdx).
|
||||||
|
|
||||||
|
Then, edit the services you want (in [`src/livecodes/services`](https://github.com/live-codes/livecodes/tree/develop/src/livecodes/services)). The used services need to have the same interface.
|
||||||
|
|
||||||
|
The app then needs to be re-built using the command:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
The built app is in `build` directory. This can be hosted on any static file server.
|
||||||
34
docs/docs/bookmarklet.mdx
Normal file
34
docs/docs/bookmarklet.mdx
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# Bookmarklet
|
||||||
|
|
||||||
|
LiveCodes allows [importing code](./features/import.mdx) from a [wide variety of sources](./features/import.mdx#sources).
|
||||||
|
|
||||||
|
Instead of manually copy/pasting URLs to import, adding **"Edit in LiveCodes"** bookmarklet to the browser bookmarks bar can be a more convenient way. It opens LiveCodes in a new window and imports the current webpage URL.
|
||||||
|
|
||||||
|
## Add Bookmarklet
|
||||||
|
|
||||||
|
Drag this link to the browser bookmarks bar:
|
||||||
|
|
||||||
|
<div
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: `<a href='javascript:(()=>{window.open("https://livecodes.io/?x="+encodeURIComponent(location.href),"_blank");})();'>Edit in LiveCodes</a>`,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
|
or manually create a new bookmark in your browser and add this code as its URL:
|
||||||
|
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
```js
|
||||||
|
javascript:(()=>{window.open("https://livecodes.io/?x="+encodeURIComponent(location.href),"_blank");})();
|
||||||
|
```
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
After adding the bookmarklet to your browser (see above), open this GitHub directory:
|
||||||
|
|
||||||
|
https://github.com/bradtraversy/50projects50days/tree/master/expanding-cards
|
||||||
|
|
||||||
|
Then click on the bookmarklet.
|
||||||
|
|
||||||
|
LiveCodes playground should open in a new window and [import](./features/import.mdx) the directory files (each file in the appropriate editor). It just works!
|
||||||
721
docs/docs/configuration/configuration-object.mdx
Normal file
721
docs/docs/configuration/configuration-object.mdx
Normal file
@ -0,0 +1,721 @@
|
|||||||
|
# Configuration Object
|
||||||
|
|
||||||
|
import LiveCodes from '../../src/components/LiveCodes.tsx';
|
||||||
|
|
||||||
|
LiveCodes is very flexible and provides a wide range of configuration options.
|
||||||
|
A JavaScript object is used for configuration and keeping state.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
The configuration object can be used while initializing a new playground using the [SDK](../sdk/index.mdx).
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { createPlayground } from 'livecodes';
|
||||||
|
|
||||||
|
(async () => {
|
||||||
|
const playground = await createPlayground('#container', {
|
||||||
|
config: {
|
||||||
|
// config options here
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// the object can be retrieved using the method `getConfig`
|
||||||
|
console.log(await playground.getConfig());
|
||||||
|
|
||||||
|
// and can be later changed using the method `setConfig`
|
||||||
|
await playground.setConfig({
|
||||||
|
// new config options
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively, the URL [query parameter](./query-params.mdx) `config` can provide a URL to a JSON representation of the configuration object to be used while initializing the app.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
https://livecodes.io/?config=https://my-custom-server.com/config.json
|
||||||
|
```
|
||||||
|
|
||||||
|
## TypeScript Types
|
||||||
|
|
||||||
|
TypeScript types are [documented here](../api/interfaces/Config.md) and can be imported from the library.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import type { Config } from 'livecodes';
|
||||||
|
```
|
||||||
|
|
||||||
|
## Default Config
|
||||||
|
|
||||||
|
Default config is [defined here](https://github.com/live-codes/livecodes/blob/develop/src/livecodes/config/default-config.ts).
|
||||||
|
|
||||||
|
## Project Content
|
||||||
|
|
||||||
|
These are properties that define the content of the current [project](../features/projects.mdx).
|
||||||
|
|
||||||
|
### `title`
|
||||||
|
|
||||||
|
Type: [`string`](../api/interfaces/Config.md#title)
|
||||||
|
|
||||||
|
Default: `"Untitled Project"`
|
||||||
|
|
||||||
|
Project title. This is used as [result page](../features/result.mdx) title and title meta tag. Also used in [project](../features/projects.mdx) search. This can be set in the UI from the title input (above result page) or from Project menu → Project Info.
|
||||||
|
|
||||||
|
### `description`
|
||||||
|
|
||||||
|
Type: [`string`](../api/interfaces/Config.md#description)
|
||||||
|
|
||||||
|
Default: `""`
|
||||||
|
|
||||||
|
Project description. Used in [project](../features/projects.mdx) search and result page description meta tag. This can be set in the UI from Project menu → Project Info.
|
||||||
|
|
||||||
|
### `head`
|
||||||
|
|
||||||
|
Type: [`string`](../api/interfaces/Config.md#head)
|
||||||
|
|
||||||
|
Default: `'<meta charset="UTF-8" />\n<meta name="viewport" content="width=device-width, initial-scale=1.0" />'`
|
||||||
|
|
||||||
|
Content added to the [result page](../features/result.mdx) `<head>` element. This can be set in the UI from Project menu → Project Info.
|
||||||
|
|
||||||
|
### `htmlAttrs`
|
||||||
|
|
||||||
|
Type: [`string | Record<string, string>`](../api/interfaces/Config.md#htmlattrs)
|
||||||
|
|
||||||
|
Default: `'lang="en" class=""'`
|
||||||
|
|
||||||
|
Attributes added to the [result page](../features/result.mdx) `<html>` element. It can be an object or a string.
|
||||||
|
|
||||||
|
Example: `{ lang: "en", class: "dark" }` or `'lang="en" class="dark"'`,
|
||||||
|
become `<html lang="en" class="dark">`.
|
||||||
|
|
||||||
|
This can be set in the UI from Project menu → Project Info.
|
||||||
|
|
||||||
|
### `tags`
|
||||||
|
|
||||||
|
Type: [`string[]`](../api/interfaces/Config.md#tags)
|
||||||
|
|
||||||
|
Default: `[]`
|
||||||
|
|
||||||
|
Project tags. Used in [project](../features/projects.mdx) filter and search. This can be set in the UI from Project menu → Project Info.
|
||||||
|
|
||||||
|
### `activeEditor`
|
||||||
|
|
||||||
|
Type: [`"markup" | "style" | "script" | undefined`](../api/interfaces/Config.md#activeeditor)
|
||||||
|
|
||||||
|
Default: Last used editor for user, otherwise "markup"
|
||||||
|
|
||||||
|
Selects the active editor to show.
|
||||||
|
|
||||||
|
### `languages`
|
||||||
|
|
||||||
|
Type: [`Language[] | undefined`](../api/interfaces/Config.md#languages)
|
||||||
|
|
||||||
|
Default: all supported languages in full app and only current editor languages in [embeds](../features/embeds.mdx).
|
||||||
|
|
||||||
|
List of enabled languages. Languages that are not already loaded in the editors ([markup](#markup), [style](#style) and [script](#script)) can be selected from a drop down menu at the editor title.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### `markup`
|
||||||
|
|
||||||
|
Type: [`Editor`](../api/interfaces/Config.md#markup)
|
||||||
|
|
||||||
|
Default: `{ language: "html", content: "" }`
|
||||||
|
|
||||||
|
An object that configures the language and content of the markup editor. This can include the following properties:
|
||||||
|
|
||||||
|
- `language`:
|
||||||
|
Type: [Language](../api/type-aliases/Language.md)
|
||||||
|
Default: `"html"` in markup editor, `"css"` in style editor and `"javascript"` in script editor.
|
||||||
|
This can be a language name, extension or alias (as defined in [language documentations](../languages/index.mdx)).
|
||||||
|
(e.g. `"markdown"`, `"md"`)
|
||||||
|
|
||||||
|
- `content`:
|
||||||
|
Type: [`string | undefined`](../api/interfaces/Config.md#content)
|
||||||
|
Default: `""`
|
||||||
|
The initial content of the code editor.
|
||||||
|
|
||||||
|
- `contentUrl`:
|
||||||
|
Type: [`string | undefined`](../api/interfaces/Config.md#contenturl)
|
||||||
|
Default: `undefined`
|
||||||
|
A URL to load `content` from. It has to be a valid URL that is CORS-enabled.
|
||||||
|
The URL is only fetched if `content` property had no value.
|
||||||
|
|
||||||
|
- `hiddenContent`:
|
||||||
|
Type: [`string | undefined`](../api/interfaces/Config.md#hiddencontent)
|
||||||
|
Default: `undefined`
|
||||||
|
Hidden content that gets evaluated without being visible in the code editor.
|
||||||
|
This can be useful in embedded playgrounds (e.g. for adding helper functions, utilities or tests)
|
||||||
|
|
||||||
|
- `hiddenContentUrl`:
|
||||||
|
Type: [`string | undefined`](../api/interfaces/Config.md#hiddencontenturl)
|
||||||
|
Default: `undefined`
|
||||||
|
A URL to load `hiddenContent` from. It has to be a valid URL that is CORS-enabled.
|
||||||
|
The URL is only fetched if `hiddenContent` property had no value.
|
||||||
|
|
||||||
|
- `foldedLines`:
|
||||||
|
Type: [`Array<{ from: number; to: number }> | undefined`](../api/interfaces/Config.md#foldedlines)
|
||||||
|
Default: `undefined`
|
||||||
|
Lines that get folded when the editor loads. The code can be unfolded by clicking on arrow beside the line.
|
||||||
|
This can be useful for less relevant code in embedded playgrounds.
|
||||||
|
|
||||||
|
- `title`:
|
||||||
|
Type: [`string | undefined`](../api/interfaces/Config.md#title)
|
||||||
|
Default: `""`
|
||||||
|
If set, this is used as the title of the editor in the UI, overriding the default title set to the language name (e.g. "Python" can be used instead of "Py (Wasm)").
|
||||||
|
|
||||||
|
- `hideTitle`:
|
||||||
|
Type: [`boolean | undefined`](../api/interfaces/Config.md#hidetitle)
|
||||||
|
Default: `""`
|
||||||
|
If `true`, the title of the code editor is hidden, however its code is still evaluated.
|
||||||
|
This can be useful in embedded playgrounds (e.g. for hiding unnecessary code).
|
||||||
|
|
||||||
|
- `order`:
|
||||||
|
Type: [`number | undefined`](../api/interfaces/Config.md#order)
|
||||||
|
Default: `0`
|
||||||
|
The order of the editor in the UI.
|
||||||
|
|
||||||
|
- `selector`:
|
||||||
|
Type: [`string | undefined`](../api/interfaces/Config.md#selector)
|
||||||
|
Default: `undefined`
|
||||||
|
A CSS selector to load `content` from [DOM import](../features/import.mdx#import-code-from-dom).
|
||||||
|
|
||||||
|
- `position`:
|
||||||
|
Type: [`{lineNumber: number, column?: number} | undefined`](../api/interfaces/Config.md#position)
|
||||||
|
Default: `undefined`
|
||||||
|
The initial position of the cursor in the code editor.
|
||||||
|
Example: `{lineNumber: 5, column: 10}`
|
||||||
|
|
||||||
|
### `style`
|
||||||
|
|
||||||
|
Type: [`Editor`](../api/interfaces/Config.md#style)
|
||||||
|
|
||||||
|
Default: `{ language: "css", content: "" }`
|
||||||
|
|
||||||
|
An object that configures the language and content of the style editor. See [markup](#markup) for more details.
|
||||||
|
|
||||||
|
### `script`
|
||||||
|
|
||||||
|
Type: [`Editor`](../api/interfaces/Config.md#script)
|
||||||
|
|
||||||
|
Default: `{ language: "javascript", content: "" }`
|
||||||
|
|
||||||
|
An object that configures the language and content of the script editor. See [markup](#markup) for more details.
|
||||||
|
|
||||||
|
### `stylesheets`
|
||||||
|
|
||||||
|
Type: [`string[]`](../api/interfaces/Config.md#stylesheets)
|
||||||
|
|
||||||
|
Default: `[]`
|
||||||
|
|
||||||
|
List of URLs for [external stylesheets](../features/external-resources.mdx) to add to the [result page](../features/result.mdx).
|
||||||
|
|
||||||
|
### `scripts`
|
||||||
|
|
||||||
|
Type: [`string[]`](../api/interfaces/Config.md#scripts)
|
||||||
|
|
||||||
|
Default: `[]`
|
||||||
|
|
||||||
|
List of URLs for [external scripts](../features/external-resources.mdx) to add to the [result page](../features/result.mdx).
|
||||||
|
|
||||||
|
### `cssPreset`
|
||||||
|
|
||||||
|
Type: [`"" | "normalize.css" | "reset-css"`](../api/interfaces/Config.md#csspreset)
|
||||||
|
|
||||||
|
Default: `""`
|
||||||
|
|
||||||
|
[CSS Preset](../features/external-resources.mdx#css-presets) to use.
|
||||||
|
|
||||||
|
### `processors`
|
||||||
|
|
||||||
|
Type: [`Processor[]`](../api/internal/type-aliases/Processor.md)
|
||||||
|
|
||||||
|
Default: `[]`
|
||||||
|
|
||||||
|
List of enabled [CSS processors](../features/css.mdx#css-processors).
|
||||||
|
|
||||||
|
### `customSettings`
|
||||||
|
|
||||||
|
Type: [`CustomSettings`](../api/interfaces/Config.md#customsettings)
|
||||||
|
|
||||||
|
Default: `{}`
|
||||||
|
|
||||||
|
Defines [custom settings](../advanced/custom-settings.mdx) for the current project.
|
||||||
|
|
||||||
|
### `imports`
|
||||||
|
|
||||||
|
Type: [`[key: string]: string`](../api/interfaces/Config.md#imports)
|
||||||
|
|
||||||
|
Default: `{}`
|
||||||
|
|
||||||
|
Allows specifying custom [import maps](https://github.com/WICG/import-maps) for [module imports](../features/module-resolution.mdx#custom-module-resolution).
|
||||||
|
|
||||||
|
For example, adding this JavaScript code:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import moment from 'moment';
|
||||||
|
import { partition } from 'lodash';
|
||||||
|
```
|
||||||
|
|
||||||
|
would add this import map in the result page:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script type="importmap">
|
||||||
|
{
|
||||||
|
"imports": {
|
||||||
|
"moment": "https://esm.sh/moment",
|
||||||
|
"lodash": "https://esm.sh/lodash"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
However, if `imports` is specified as follows:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"imports": {
|
||||||
|
"moment": "https://cdn.jsdelivr.net/npm/moment@2.29.4/dist/moment.js"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The import map becomes like this:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script type="importmap">
|
||||||
|
{
|
||||||
|
"imports": {
|
||||||
|
"moment": "https://cdn.jsdelivr.net/npm/moment@2.29.4/dist/moment.js",
|
||||||
|
"lodash": "https://esm.sh/lodash"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
:::info Note
|
||||||
|
|
||||||
|
Currently, multiple import maps are not yet supported. https://crbug.com/927119
|
||||||
|
|
||||||
|
When bare module imports are encountered, LiveCodes adds an import map to the result page. If you need to add custom import map or override the automatically generated one, you need to add them to `imports` config property or `imports` [customSettings](#customsettings) property.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
### `types`
|
||||||
|
|
||||||
|
Type: `[key: string]: string | { autoload?: boolean ; declareAsModule?: boolean ; url: string }`
|
||||||
|
|
||||||
|
Default: `{}`
|
||||||
|
|
||||||
|
Allows providing custom [TypeScript type declarations](https://www.typescriptlang.org/docs/handbook/2/type-declarations.html) for better [editor intellisense](../features/intellisense.mdx).
|
||||||
|
|
||||||
|
It is an object where each key represents module name and value represents the types.
|
||||||
|
This can be a URL to a type declaration file. For example, if this is the type declaration file:
|
||||||
|
|
||||||
|
```ts title="https://my-custom-domain/my-type-declarations.d.ts"
|
||||||
|
declare module 'my-demo-lib' {
|
||||||
|
export class Greeter {
|
||||||
|
morning(): string;
|
||||||
|
evening(): string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
It can be used like that:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"types": {
|
||||||
|
"my-demo-lib": "https://my-custom-domain/my-type-declarations.d.ts"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively, the value for module name can be an object with the following properties:
|
||||||
|
|
||||||
|
- `url`: `string` (required). The URL to type declaration file.
|
||||||
|
- `autoload`: `boolean` (optional). By default, the types are only loaded when the module is imported in code. If `autoload` property is set to `true`, the types are loaded regardless if the module was imported.
|
||||||
|
- `declareAsModule`: `boolean` (optional). Declares the types as module with the supplied module name.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"types": {
|
||||||
|
"my-demo-lib": {
|
||||||
|
"url": "https://my-custom-domain/types.d.ts",
|
||||||
|
"autoload": true,
|
||||||
|
"declareAsModule": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `tests`
|
||||||
|
|
||||||
|
Type: `undefined` | `Partial<Editor>`
|
||||||
|
|
||||||
|
Default: `{ language: 'typescript', content: '' }`
|
||||||
|
|
||||||
|
Configures the [language](../features/tests.mdx#supported-languages) and content of [tests](../features/tests.mdx).
|
||||||
|
|
||||||
|
### `version`
|
||||||
|
|
||||||
|
Type: `Readonly` [`string`](../api/interfaces/Config.md#description)
|
||||||
|
|
||||||
|
Default: Current LiveCodes Version.
|
||||||
|
|
||||||
|
This is a read-only property which specifies the current LiveCodes version. It can be shown using the SDK [`exec`](../sdk/js-ts.mdx#exec) method.
|
||||||
|
|
||||||
|
```js
|
||||||
|
// in browser console of full app (e.g. https://livecodes.io)
|
||||||
|
await livecodes.exec('showVersion');
|
||||||
|
```
|
||||||
|
|
||||||
|
Version specified in [exported](../features/export.mdx) projects allows automatically upgrading the project configuration when imported by an app with a newer version.
|
||||||
|
|
||||||
|
## App Settings
|
||||||
|
|
||||||
|
These are properties that define how the app behaves.
|
||||||
|
|
||||||
|
### `readonly`
|
||||||
|
|
||||||
|
Type: [`boolean`](../api/interfaces/Config.md#readonly)
|
||||||
|
|
||||||
|
Default: `false`
|
||||||
|
|
||||||
|
If `true`, editors are loaded in read-only mode, where the user is not allowed to change the code.
|
||||||
|
|
||||||
|
By default, when `readonly` is set to `true`, the light-weight code editor [CodeJar](../features/editor-settings.mdx#code-editor) is used. If you wish to use another editor, set the [editor](#editor) property.
|
||||||
|
|
||||||
|
### `allowLangChange`
|
||||||
|
|
||||||
|
Type: [`boolean`](../api/interfaces/Config.md#allowlangchange)
|
||||||
|
|
||||||
|
Default: `true`
|
||||||
|
|
||||||
|
If `false`, the UI will not show the menu that allows changing editor language.
|
||||||
|
|
||||||
|
### `view`
|
||||||
|
|
||||||
|
Type: [`"split" | "editor" | "result"`](../api/interfaces/Config.md#view)
|
||||||
|
|
||||||
|
Default: `"split"`
|
||||||
|
|
||||||
|
The [default view](../features/default-view.mdx) for the playground.
|
||||||
|
|
||||||
|
### `mode`
|
||||||
|
|
||||||
|
Type: [`"full" | "focus" | "simple" | "lite" | "result" | "editor" | "codeblock"`](../api/interfaces/Config.md#mode)
|
||||||
|
|
||||||
|
Default: `"full"`
|
||||||
|
|
||||||
|
Sets the [display mode](../features/display-modes.mdx).
|
||||||
|
|
||||||
|
### `tools`
|
||||||
|
|
||||||
|
Type: [`Partial<{ enabled: Array<'console' | 'compiled' | 'tests'> | 'all'; active: 'console' | 'compiled' | 'tests' | ''; status: 'closed' | 'open' | 'full' | 'none' | ''; }>`](../api/interfaces/Config.md#tools)
|
||||||
|
|
||||||
|
Default: `{ enabled: 'all', active: '', status: '' }`
|
||||||
|
|
||||||
|
Sets enabled and active tools and status of [tools pane](../features/tools-pane.mdx).
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"tools": {
|
||||||
|
"enabled": ["console", "compiled"],
|
||||||
|
"active": "console",
|
||||||
|
"status": "open"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
<LiveCodes
|
||||||
|
config={{
|
||||||
|
script: { language: 'javascript', content: "console.log('Hello World!');" },
|
||||||
|
activeEditor: 'script',
|
||||||
|
tools: { enabled: ['console', 'compiled'], active: 'console', status: 'open' },
|
||||||
|
}}
|
||||||
|
></LiveCodes>
|
||||||
|
|
||||||
|
### `zoom`
|
||||||
|
|
||||||
|
Type: [`1 | 0.5 | 0.25`](../api/interfaces/Config.md#zoom)
|
||||||
|
|
||||||
|
Default: `1`
|
||||||
|
|
||||||
|
Sets result page [zoom level](../features/result.mdx#result-page-zoom).
|
||||||
|
|
||||||
|
## User Settings
|
||||||
|
|
||||||
|
These are properties that define the [user settings](./../features/user-settings.mdx), including [editor settings](../features/editor-settings.mdx).
|
||||||
|
|
||||||
|
### `enableAI`
|
||||||
|
|
||||||
|
Type: [`boolean`](../api/interfaces/Config.md#enableai)
|
||||||
|
|
||||||
|
Default: `false`
|
||||||
|
|
||||||
|
If `true`, [AI code assistant](../features/ai.mdx) is enabled.
|
||||||
|
|
||||||
|
### `autoupdate`
|
||||||
|
|
||||||
|
Type: [`boolean`](../api/interfaces/Config.md#autoupdate)
|
||||||
|
|
||||||
|
Default: `true`
|
||||||
|
|
||||||
|
If `true`, the result page is automatically updated on code change, after time [delay](#delay).
|
||||||
|
|
||||||
|
### `autosave`
|
||||||
|
|
||||||
|
Type: [`boolean`](../api/interfaces/Config.md#autosave)
|
||||||
|
|
||||||
|
Default: `false`
|
||||||
|
|
||||||
|
If `true`, the project is automatically saved on code change, after time [delay](#delay).
|
||||||
|
|
||||||
|
### `autotest`
|
||||||
|
|
||||||
|
Type: [`boolean`](../api/interfaces/Config.md#autotest)
|
||||||
|
|
||||||
|
Default: `false`
|
||||||
|
|
||||||
|
If `true`, the project is watched for code changes which trigger tests to auto-run.
|
||||||
|
|
||||||
|
### `delay`
|
||||||
|
|
||||||
|
Type: [`number`](../api/interfaces/Config.md#delay)
|
||||||
|
|
||||||
|
Default: `1500`
|
||||||
|
|
||||||
|
Time delay (in milliseconds) following code change, after which the result page is updated (if [`autoupdate`](#autoupdate) is `true`) and/or the project is saved (if [`autosave`](#autosave) is `true`).
|
||||||
|
|
||||||
|
### `formatOnsave`
|
||||||
|
|
||||||
|
Type: [`boolean`](../api/interfaces/Config.md#formatonsave)
|
||||||
|
|
||||||
|
Default: `false`
|
||||||
|
|
||||||
|
If `true`, the code is automatically [formatted](../features/code-format.mdx) on saving the project.
|
||||||
|
|
||||||
|
### `layout`
|
||||||
|
|
||||||
|
Type: [`"horizontal"| "vertical" | "responsive" | undefined`](../api/interfaces/Config.md#layout)
|
||||||
|
|
||||||
|
Default: `"responsive"`
|
||||||
|
|
||||||
|
Sets the app layout to horizontal or vertical. If set to `"responsive"` (the default) or `undefined`, the layout is vertical in small screens when the playground height is larger than its width, otherwise horizontal.
|
||||||
|
|
||||||
|
### `theme`
|
||||||
|
|
||||||
|
Type: [`"light" | "dark"`](../api/interfaces/Config.md#theme)
|
||||||
|
|
||||||
|
Default: `"dark"`
|
||||||
|
|
||||||
|
Sets the app [theme](../features/themes.mdx) to light/dark mode.
|
||||||
|
|
||||||
|
### `themeColor`
|
||||||
|
|
||||||
|
Type: [`string | undefined`](../api/interfaces/Config.md#themecolor)
|
||||||
|
|
||||||
|
Default: `"hsl(214, 40%, 50%)"`
|
||||||
|
|
||||||
|
A string representing a [CSS color value](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value), used to set the app [theme color](../features/themes.mdx). It can be any valid CSS color value, such as `"#4DB39E"`, `"rgb(245, 225, 49)"`, `"hsl(324, 40%, 50%)"` and `"lightblue"`.
|
||||||
|
|
||||||
|
### `editorTheme`
|
||||||
|
|
||||||
|
Type: [`EditorTheme[] | string | undefined`](../api/interfaces/Config.md#editortheme)
|
||||||
|
|
||||||
|
Default: `undefined`
|
||||||
|
|
||||||
|
Sets the code editor themes.
|
||||||
|
|
||||||
|
:::info Note
|
||||||
|
You can preview and set editor themes in the [editor settings screen](pathname:///../?screen=editor-settings).
|
||||||
|
:::
|
||||||
|
|
||||||
|
Three [code editors](#editor) are supported in LiveCodes: **Monaco** (the default on desktop), **CodeMirror** (the default on mobile) and **CodeJar** (the default in [codeblocks](../features/display-modes.mdx#codeblock), in [lite mode](../features/lite.mdx) and in [readonly](#readonly) playgrounds). Each editor has its own set of themes, represented by the types: [`MonacoTheme`](../api/internal/type-aliases/MonacoTheme.md), [`CodemirrorTheme`](../api/internal/type-aliases/CodemirrorTheme.md) and [`CodejarTheme`](../api/internal/type-aliases/CodejarTheme.md).
|
||||||
|
|
||||||
|
The `editorTheme` property can be used to set the editor theme for each editor and on light/dark modes. It can be set to an array of [`EditorTheme`](../api/internal/type-aliases/EditorTheme.md) items or a string of comma-separated items.
|
||||||
|
|
||||||
|
Each item can be composed of:
|
||||||
|
|
||||||
|
` editor:` `theme-name` `@app-theme`
|
||||||
|
|
||||||
|
Where:
|
||||||
|
|
||||||
|
- `editor` is the name of the editor (`"monaco" | "codemirror" | "codejar"`). [Optional]
|
||||||
|
- `theme-name` is the name of the theme (e.g. `"monokai"`). [Required]
|
||||||
|
Valid theme names can be found here:
|
||||||
|
- Monaco: [`MonacoTheme`](../api/internal/type-aliases/MonacoTheme.md)
|
||||||
|
- CodeMirror: [`CodemirrorTheme`](../api/internal/type-aliases/CodemirrorTheme.md)
|
||||||
|
- CodeJar: [`CodejarTheme`](../api/internal/type-aliases/CodejarTheme.md).
|
||||||
|
- `app-theme` is the name of the app theme (`"dark" | "light"`). [Optional]
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
- `"vs"`
|
||||||
|
- `"monaco:twilight, codemirror:one-dark"`
|
||||||
|
- `["vs@light"]`
|
||||||
|
- `["vs@light", "vs-dark@dark"]`
|
||||||
|
- `["monaco:vs@light", "codemirror:github-light@light", "dracula@dark"]`
|
||||||
|
|
||||||
|
Each `EditorTheme` item requires a theme name. The theme name can optionally be preceded with the editor name separated by a colon to specify the editor (e.g. `"monaco:monokai"`). It can also optionally be followed by the app theme separated by "@" (e.g. `"monokai@dark"`).
|
||||||
|
|
||||||
|
Multiple `EditorTheme` items can be supplied (as array items or in the comma-separated string) to specify the theme for each editor and in dark and light modes. The order matters. The first valid item in the array or string for the current editor (`monaco`, `codemirror` or `codejar`) and app theme (`light` or `dark`) will be used. If no items match the current editor and app theme, the default theme for the editor and app theme will be used.
|
||||||
|
|
||||||
|
### `appLanguage`
|
||||||
|
|
||||||
|
Type: [`AppLanguage | undefined`](../api/interfaces/Config.md#applanguage)
|
||||||
|
|
||||||
|
Default: `undefined`
|
||||||
|
|
||||||
|
Spoken language code that sets the app UI language (e.g. `"ar"`, `"zh-CN"`). Used in translations for internationalization. If `undefined` (the default), the language is automatically detected based on the user's browser settings and falls back to English, if detection fails or the language is not supported.
|
||||||
|
|
||||||
|
### `recoverUnsaved`
|
||||||
|
|
||||||
|
Type: [`boolean`](../api/interfaces/Config.md#recoverunsaved)
|
||||||
|
|
||||||
|
Default: `true`
|
||||||
|
|
||||||
|
Enables [recovering last unsaved project](../features/recover.mdx) when the app is reopened.
|
||||||
|
|
||||||
|
### `welcome`
|
||||||
|
|
||||||
|
Type: [`boolean`](../api/interfaces/Config.md#welcome)
|
||||||
|
|
||||||
|
Default: `true`
|
||||||
|
|
||||||
|
If `true`, the [welcome screen](../features/welcome.mdx) is displayed when the app loads.
|
||||||
|
|
||||||
|
### `showSpacing`
|
||||||
|
|
||||||
|
Type: [`boolean`](../api/interfaces/Config.md#showspacing)
|
||||||
|
|
||||||
|
Default: `false`
|
||||||
|
|
||||||
|
Enables [showing element spacing](../features/result.mdx#show-spacings) in the result page.
|
||||||
|
|
||||||
|
### `editor`
|
||||||
|
|
||||||
|
Type: [`"monaco" | "codemirror" | "codejar" | "auto" | undefined`](../api/interfaces/Config.md#editor)
|
||||||
|
|
||||||
|
Default: `undefined`
|
||||||
|
|
||||||
|
Selects the [code editor](../features/editor-settings.mdx#code-editor) to use.
|
||||||
|
|
||||||
|
If `undefined` (the default):<br />
|
||||||
|
Monaco editor is used on desktop,<br />
|
||||||
|
CodeMirror is used on mobile and in `simple` mode,<br />
|
||||||
|
while CodeJar is used in [`codeblock` mode](../features/display-modes.mdx#codeblock), in [`lite` mode](../features/lite.mdx) and in [`readonly`](#readonly) playgrounds.
|
||||||
|
|
||||||
|
If set to `auto`, Monaco editor is used on desktop and CodeMirror is used on mobile regardless of other settings.
|
||||||
|
|
||||||
|
### `fontFamily`
|
||||||
|
|
||||||
|
Type: [`string | undefined`](../api/interfaces/Config.md#fontfamily)
|
||||||
|
|
||||||
|
Default: `undefined`
|
||||||
|
|
||||||
|
Sets the [code editor](../features/editor-settings.mdx) font family.
|
||||||
|
|
||||||
|
### `fontSize`
|
||||||
|
|
||||||
|
Type: [`number | undefined`](../api/interfaces/Config.md#fontfamily)
|
||||||
|
|
||||||
|
Default: `undefined`
|
||||||
|
|
||||||
|
Sets the [code editor](../features/editor-settings.mdx) font size.
|
||||||
|
|
||||||
|
If `undefined` (the default), the font size is set to 14 for the full app and 12 for [embeds](../features/embeds.mdx).
|
||||||
|
|
||||||
|
### `useTabs`
|
||||||
|
|
||||||
|
Type: [`boolean`](../api/interfaces/Config.md#usetabs)
|
||||||
|
|
||||||
|
Default: `false`
|
||||||
|
|
||||||
|
If `true`, lines are indented with tabs instead of spaces. Also used in [code formatting](../features/code-format.mdx).
|
||||||
|
|
||||||
|
### `tabSize`
|
||||||
|
|
||||||
|
Type: [`number`](../api/interfaces/Config.md#tabsize)
|
||||||
|
|
||||||
|
Default: `2`
|
||||||
|
|
||||||
|
The number of spaces per indentation-level. Also used in [code formatting](../features/code-format.mdx).
|
||||||
|
|
||||||
|
### `lineNumbers`
|
||||||
|
|
||||||
|
Type: [`boolean | "relative"`](../api/interfaces/Config.md#linenumbers)
|
||||||
|
|
||||||
|
Default: `true`
|
||||||
|
|
||||||
|
Show line numbers in [code editor](../features/editor-settings.mdx).
|
||||||
|
If set to `"relative"`, line numbers are shown relative to the current line. This can be useful with [vim mode](#editormode).
|
||||||
|
|
||||||
|
### `wordWrap`
|
||||||
|
|
||||||
|
Type: [`boolean`](../api/interfaces/Config.md#wordwrap)
|
||||||
|
|
||||||
|
Default: `false`
|
||||||
|
|
||||||
|
Enables word-wrap for long lines.
|
||||||
|
|
||||||
|
### `closeBrackets`
|
||||||
|
|
||||||
|
Type: [`boolean`](../api/interfaces/Config.md#closebrackets)
|
||||||
|
|
||||||
|
Default: `true`
|
||||||
|
|
||||||
|
Use auto-complete to close brackets and quotes.
|
||||||
|
|
||||||
|
### `foldRegions`
|
||||||
|
|
||||||
|
Type: [`boolean`](../api/interfaces/Config.md#foldregions)
|
||||||
|
|
||||||
|
Default: `false`
|
||||||
|
|
||||||
|
When set to `true`, regions marked by `#region` and `#endregion` comments are folded when the project is loaded.
|
||||||
|
|
||||||
|
### `emmet`
|
||||||
|
|
||||||
|
Type: [`boolean`](../api/interfaces/Config.md#emmet)
|
||||||
|
|
||||||
|
Default: `true`
|
||||||
|
|
||||||
|
Enables [Emmet](../features/editor-settings.mdx#emmet).
|
||||||
|
|
||||||
|
### `editorMode`
|
||||||
|
|
||||||
|
Type: [`"vim" | "emacs" | undefined`](../api/interfaces/Config.md#editormode)
|
||||||
|
|
||||||
|
Default: `undefined`
|
||||||
|
|
||||||
|
Sets [editor mode](../features/editor-settings.mdx#editor-modes).
|
||||||
|
|
||||||
|
### `semicolons`
|
||||||
|
|
||||||
|
Type: [`boolean`](../api/interfaces/Config.md#semicolons)
|
||||||
|
|
||||||
|
Default: `true`
|
||||||
|
|
||||||
|
Configures Prettier [code formatter](../features/code-format.mdx) to use [semi-colons](https://prettier.io/docs/en/options.html#semicolons).
|
||||||
|
|
||||||
|
### `singleQuote`
|
||||||
|
|
||||||
|
Type: [`boolean`](../api/interfaces/Config.md#singlequote)
|
||||||
|
|
||||||
|
Default: `false`
|
||||||
|
|
||||||
|
Configures Prettier [code formatter](../features/code-format.mdx) to use [single quotes instead of double quotes](https://prettier.io/docs/en/options.html#quotes).
|
||||||
|
|
||||||
|
### `trailingComma`
|
||||||
|
|
||||||
|
Type: [`boolean`](../api/interfaces/Config.md#trailingcomma)
|
||||||
|
|
||||||
|
Default: `true`
|
||||||
|
|
||||||
|
Configures Prettier [code formatter](../features/code-format.mdx) to use [trailing commas](https://prettier.io/docs/en/options.html#trailing-commas).
|
||||||
17
docs/docs/configuration/index.mdx
Normal file
17
docs/docs/configuration/index.mdx
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
sidebar_class_name: exclude_from_sidebar
|
||||||
|
---
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
|
||||||
|
LiveCodes is very flexible and provides a wide range of configuration options.
|
||||||
|
|
||||||
|
This can generally be achieved by:
|
||||||
|
|
||||||
|
### [Configuration Object](./configuration-object.mdx)
|
||||||
|
|
||||||
|
A JavaScript object used for configuration and keeping state.
|
||||||
|
|
||||||
|
### [Query Parameters](./query-params.mdx)
|
||||||
|
|
||||||
|
A flexible and convenient way to configure the app using URL query parameters
|
||||||
163
docs/docs/configuration/query-params.mdx
Normal file
163
docs/docs/configuration/query-params.mdx
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
# Query Parameters
|
||||||
|
|
||||||
|
import LiveCodes from '../../src/components/LiveCodes.tsx';
|
||||||
|
|
||||||
|
A flexible and convenient way to configure the app is to use URL query parameters.
|
||||||
|
It allows configuration of a wide range of options, including those of the [configuration object](./configuration-object.mdx) and [embed options](../sdk/js-ts.mdx#embed-options).
|
||||||
|
|
||||||
|
<div style={{ clear: 'both' }}></div>
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
https://livecodes.io?js=console.log('Hello World!')&console=open
|
||||||
|
```
|
||||||
|
|
||||||
|
<LiveCodes params={{ js: "console.log('Hello World!')", console: 'open' }}></LiveCodes>
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
- All properties of [configuration object](./configuration-object.mdx) and [embed options](../sdk/js-ts.mdx#embed-options) that have values of primitive types (e.g. string, number, boolean) can be assigned to a query parameter with the same name.
|
||||||
|
|
||||||
|
These include:
|
||||||
|
[config](../sdk/js-ts.mdx#config),
|
||||||
|
[import](../sdk/js-ts.mdx#import),
|
||||||
|
[lite](../configuration/configuration-object.mdx#mode),
|
||||||
|
[loading](../sdk/js-ts.mdx#loading),
|
||||||
|
[template](../sdk/js-ts.mdx#template),
|
||||||
|
[view](../configuration/configuration-object.mdx#view),
|
||||||
|
[title](./configuration-object.mdx#title),
|
||||||
|
[description](./configuration-object.mdx#description),
|
||||||
|
[activeEditor](./configuration-object.mdx#activeeditor),
|
||||||
|
[cssPreset](./configuration-object.mdx#csspreset),
|
||||||
|
[readonly](./configuration-object.mdx#readonly),
|
||||||
|
[allowLangChange](./configuration-object.mdx#allowlangchange),
|
||||||
|
[mode](./configuration-object.mdx#mode),
|
||||||
|
[autoupdate](./configuration-object.mdx#autoupdate),
|
||||||
|
[autosave](./configuration-object.mdx#autosave),
|
||||||
|
[delay](./configuration-object.mdx#delay),
|
||||||
|
[formatOnsave](./configuration-object.mdx#formatonsave),
|
||||||
|
[theme](./configuration-object.mdx#theme),
|
||||||
|
[themeColor](./configuration-object.mdx#themecolor),
|
||||||
|
[appLanguage](./configuration-object.mdx#applanguage),
|
||||||
|
[recoverUnsaved](./configuration-object.mdx#recoverunsaved),
|
||||||
|
[welcome](./configuration-object.mdx#welcome),
|
||||||
|
[showSpacing](./configuration-object.mdx#showspacing),
|
||||||
|
[layout](./configuration-object.mdx#layout),
|
||||||
|
[editor](./configuration-object.mdx#editor),
|
||||||
|
[editorTheme](./configuration-object.mdx#editortheme),
|
||||||
|
[fontFamily](./configuration-object.mdx#fontfamily),
|
||||||
|
[fontSize](./configuration-object.mdx#fontsize),
|
||||||
|
[useTabs](./configuration-object.mdx#usetabs),
|
||||||
|
[tabSize](./configuration-object.mdx#tabsize),
|
||||||
|
[lineNumbers](./configuration-object.mdx#linenumbers),
|
||||||
|
[wordWrap](./configuration-object.mdx#wordwrap),
|
||||||
|
[closeBrackets](./configuration-object.mdx#closebrackets),
|
||||||
|
[emmet](./configuration-object.mdx#emmet),
|
||||||
|
[editorMode](./configuration-object.mdx#editormode),
|
||||||
|
[semicolons](./configuration-object.mdx#semicolons),
|
||||||
|
[singleQuote](./configuration-object.mdx#singlequote),
|
||||||
|
[trailingComma](./configuration-object.mdx#trailingcomma).
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
?theme=light&delay=500&lineNumbers=false
|
||||||
|
```
|
||||||
|
|
||||||
|
- Any value given for booleans except `"false"` (including no value) will be considered `true`.
|
||||||
|
|
||||||
|
Example: all these are considered `true`
|
||||||
|
|
||||||
|
```
|
||||||
|
?lite=true
|
||||||
|
?lite=1
|
||||||
|
?lite=any
|
||||||
|
?lite
|
||||||
|
```
|
||||||
|
|
||||||
|
while this is considered `false`
|
||||||
|
|
||||||
|
```
|
||||||
|
?lite=false
|
||||||
|
```
|
||||||
|
|
||||||
|
- Parameters that expect array of values can be supplied with comma separated values. These include:
|
||||||
|
[tags](./configuration-object.mdx#tags),
|
||||||
|
[languages](./configuration-object.mdx#languages),
|
||||||
|
[processors](./configuration-object.mdx#processors),
|
||||||
|
[stylesheets](./configuration-object.mdx#stylesheets),
|
||||||
|
[scripts](./configuration-object.mdx#scripts).
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
?languages=html,md,css,ts
|
||||||
|
```
|
||||||
|
|
||||||
|
- Values set in the URL query parameters override those set in [configuration object](./configuration-object.mdx).
|
||||||
|
|
||||||
|
- Unlike [user settings](../features/user-settings.mdx) that are set in the UI which are saved and subsequently used, those that are set in query parameters are not automatically saved.
|
||||||
|
|
||||||
|
- Additional query parameters include:
|
||||||
|
|
||||||
|
- `no-defaults`: `boolean` (Default: `false`).
|
||||||
|
|
||||||
|
If `true`, the app will not load the [default template/language](../features/default-template-language.mdx).
|
||||||
|
|
||||||
|
- `x`: `string`.
|
||||||
|
|
||||||
|
Alias to [`import`](../sdk/js-ts.mdx#import) (a URL to [import](../features/import.mdx)).
|
||||||
|
|
||||||
|
- `files`: `string`.
|
||||||
|
|
||||||
|
A comma-separated [list of files to import](../features/import.mdx#file-selection).
|
||||||
|
|
||||||
|
- `raw`: [`Language`](../api/type-aliases/Language.md).
|
||||||
|
|
||||||
|
When used with `import` or `x`, imports the URL as code of the provided language.
|
||||||
|
|
||||||
|
- `language`: [`Language`](../api/type-aliases/Language.md).
|
||||||
|
|
||||||
|
The language to load by default in the editor.
|
||||||
|
|
||||||
|
- `lang`: [`Language`](../api/type-aliases/Language.md).
|
||||||
|
|
||||||
|
Alias to `language`.
|
||||||
|
|
||||||
|
- `active`: `"markup" | "style" | "script" | 0 | 1 | 2`.
|
||||||
|
|
||||||
|
Alias to [`activeEditor`](./configuration-object.mdx#activeeditor).
|
||||||
|
|
||||||
|
- `tools`: `"open" | "full" | "closed" | "console" | "compiled" | "tests" | "none"`
|
||||||
|
|
||||||
|
The [tools pane](../features/tools-pane.mdx) status.
|
||||||
|
|
||||||
|
- `console`: `"open" | "full" | "closed" | "none"`
|
||||||
|
|
||||||
|
The [console](../features/console.mdx) status.
|
||||||
|
|
||||||
|
- `compiled`: `"open" | "full" | "closed" | "none"`
|
||||||
|
|
||||||
|
The [compiled code viewer](../features/compiled-code.mdx) status.
|
||||||
|
|
||||||
|
- `tests`: `"open" | "full" | "closed" | "none"`
|
||||||
|
|
||||||
|
The [tests panel](../features/tests.mdx) status.
|
||||||
|
|
||||||
|
- `scrollPosition`: `boolean` (Default: `true`).
|
||||||
|
|
||||||
|
If `false`, the [result page](../features/result.mdx) [scroll position](../features/result.mdx#scroll-position) will not be maintained after reload.
|
||||||
|
|
||||||
|
- Any [`Language`](../api/type-aliases/Language.md) can used as a query parameter, and the value will be used as its code.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
https://livecodes.io?js=console.log('Hello World!')
|
||||||
|
```
|
||||||
|
|
||||||
|
:::info Examples
|
||||||
|
For usage examples, check [storybook](pathname:///../stories/?path=/story/embed-options-params--select-language) and [unit tests](https://github.com/live-codes/livecodes/blob/develop/src/livecodes/config/__tests__/build-config.spec.ts).
|
||||||
|
:::
|
||||||
|
|
||||||
|
<!-- TODO: add docs for languageSelector and ToolsStatus -->
|
||||||
18
docs/docs/contact.mdx
Normal file
18
docs/docs/contact.mdx
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Contact {#contact-custom-content-none}
|
||||||
|
|
||||||
|
We would love to hear from you!
|
||||||
|
|
||||||
|
import ContactForm from '../src/components/ContactForm.tsx'
|
||||||
|
import MailLink from '../src/components/MailLink.tsx'
|
||||||
|
|
||||||
|
<ContactForm></ContactForm>
|
||||||
|
|
||||||
|
Or you can send us an email to:
|
||||||
|
|
||||||
|
- Info: <MailLink email="info@livecodes.io" />
|
||||||
|
- Security: <MailLink email="security@livecodes.io" />
|
||||||
|
- Sponsor: <MailLink email="sponsor@livecodes.io" />
|
||||||
|
|
||||||
|
For non-security-related code issues, please report them in the [repo issues](https://github.com/live-codes/livecodes/issues).
|
||||||
|
|
||||||
|
Please follow the twitter account: [@livecodes_io](https://twitter.com/livecodes_io).
|
||||||
13
docs/docs/contribution.mdx
Normal file
13
docs/docs/contribution.mdx
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Contribution
|
||||||
|
|
||||||
|
Contributions are always welcome, no matter how large or small. Before contributing,
|
||||||
|
please read the [code of conduct](https://github.com/live-codes/livecodes/blob/HEAD/CODE_OF_CONDUCT.mdx).
|
||||||
|
|
||||||
|
For code contribution, please refer to the [contribution guide](https://github.com/live-codes/livecodes/blob/HEAD/CONTRIBUTING.mdx)
|
||||||
|
.
|
||||||
|
|
||||||
|
For financial and in-kind contributions, please refer to the [sponsor page](./sponsor.mdx).
|
||||||
|
|
||||||
|
You can always support the project by [giving feedback](https://github.com/live-codes/livecodes/discussions), [reporting issues, suggesting features](https://github.com/live-codes/livecodes/issues) and spreading the word.
|
||||||
|
|
||||||
|
Thank you :)
|
||||||
30
docs/docs/contribution/adding-languages.mdx
Normal file
30
docs/docs/contribution/adding-languages.mdx
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# Adding Languages
|
||||||
|
|
||||||
|
## Criteria for a new language
|
||||||
|
|
||||||
|
- Has a syntax that needs to be compiled/transpiled to work in browsers (e.g. not a JS library).
|
||||||
|
- A compiler/runtime that runs [client-side](../why.mdx#client-side) in the browser (not on a remote server).
|
||||||
|
- Its output can be represented in a web page.
|
||||||
|
- Relatively popular (e.g. at least hundreds of GitHub stars/thousands of weekly downloads).
|
||||||
|
- Not [esoteric](https://en.wikipedia.org/wiki/Esoteric_programming_language) (otherwise, [convince me](https://github.com/live-codes/livecodes/discussions) if you have a good use case).
|
||||||
|
- The compiler/runtime is still reasonably maintained.
|
||||||
|
- The compiler/runtime has a permissive license compatible with MIT license.
|
||||||
|
|
||||||
|
If you still have doubts if the language qualifies, [let's discuss it](https://github.com/live-codes/livecodes/discussions).
|
||||||
|
|
||||||
|
## Checklist when adding
|
||||||
|
|
||||||
|
- [ ] Add [language specs](https://github.com/live-codes/livecodes/tree/develop/src/livecodes/languages) and include that in the list of [languages](https://github.com/live-codes/livecodes/blob/develop/src/livecodes/languages/languages.ts) or [processors](https://github.com/live-codes/livecodes/blob/develop/src/livecodes/languages/processors.ts).
|
||||||
|
- [ ] The compiler +/- formatter should be lazy-loaded.
|
||||||
|
- [ ] If the compiler needs a separate build, add it to the [build script](https://github.com/live-codes/livecodes/blob/3a2617850f09487b9af92de862093f082942b8a9/scripts/build.js#L207).
|
||||||
|
- [ ] If the compiler/formatter require installing new packages or adding static files (e.g. wasm) add them to the [browser compilers repo](https://github.com/live-codes/browser-compilers/) and load them from [CDN](https://github.com/live-codes/livecodes/blob/3a2617850f09487b9af92de862093f082942b8a9/src/livecodes/vendors.ts#L1).
|
||||||
|
- [ ] Any links to CDN hosted assets should be referenced from [list of vendors](https://github.com/live-codes/livecodes/blob/develop/src/livecodes/vendors.ts).
|
||||||
|
- [ ] Add language name and aliases to [models](https://github.com/live-codes/livecodes/blob/3a2617850f09487b9af92de862093f082942b8a9/src/sdk/models.ts#L129).
|
||||||
|
- [ ] Add editor support (e.g. syntax highlighting) for [Monaco](https://github.com/live-codes/livecodes/tree/develop/src/livecodes/editor/monaco), [CodeMirror](https://github.com/live-codes/livecodes/tree/develop/src/livecodes/editor/codemirror) and [Prismjs](https://github.com/live-codes/livecodes/blob/develop/src/livecodes/editor/codejar/codejar.ts) (if not auto-loaded).
|
||||||
|
- [ ] Add [language info](https://github.com/live-codes/livecodes/blob/develop/src/livecodes/html/language-info.html).
|
||||||
|
- [ ] Consider adding a [starter template](https://github.com/live-codes/livecodes/tree/develop/src/livecodes/templates/starter). If you do, add it to the [list of starter templates](https://github.com/live-codes/livecodes/blob/develop/docs/src/components/TemplateList.tsx) in docs, [command menu](https://github.com/live-codes/livecodes/blob/develop/src/livecodes/UI/command-menu-actions.ts#L235) and [language info](https://github.com/live-codes/livecodes/blob/develop/src/livecodes/html/language-info.html).
|
||||||
|
- [ ] Add [end-to-ends tests](https://github.com/live-codes/livecodes/tree/develop/e2e/specs).
|
||||||
|
- [ ] Add language [documentation](https://github.com/live-codes/livecodes/tree/develop/docs/docs/languages).
|
||||||
|
- [ ] Add language to documentation website [slider](https://github.com/live-codes/livecodes/blob/develop/docs/src/components/LanguageSliders.tsx).
|
||||||
|
- [ ] Add compiler/formatter [license(s)](https://github.com/live-codes/livecodes/blob/develop/vendor-licenses.mdx).
|
||||||
|
- [ ] Update language count badge in [README](https://github.com/live-codes/livecodes/blob/develop/README.mdx).
|
||||||
264
docs/docs/contribution/i18n.mdx
Normal file
264
docs/docs/contribution/i18n.mdx
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
# i18n
|
||||||
|
|
||||||
|
This document provides a guide on how to contribute to the translation of the app.
|
||||||
|
|
||||||
|
## For Translators
|
||||||
|
|
||||||
|
Translators are responsible for translating the source texts on Lokalise.
|
||||||
|
|
||||||
|
### Contribute to Translation
|
||||||
|
|
||||||
|
Please visit the [Lokalise project page](https://app.lokalise.com/public/34958094667a72e9454592.95108106/) to contribute to the translation of LiveCodes. You might find the [Onboarding Guide for Translators](https://docs.lokalise.com/en/articles/2967175-onboarding-guide-for-translators) on Lokalise helpful.
|
||||||
|
|
||||||
|
### Add a New Language
|
||||||
|
|
||||||
|
If you find that the language you want to translate to is not available on Lokalise, please kindly [raise an issue](https://github.com/live-codes/livecodes/issues/new?template=i18n_request.yml) in the repository with further details about the language you want to add.
|
||||||
|
|
||||||
|
## Technical Overview
|
||||||
|
|
||||||
|
The i18n framework [`i18next`](https://www.i18next.com/) and the online translation collaboration platform [Lokalise](https://lokalise.com/) are used to manage the i18n of LiveCodes.
|
||||||
|
|
||||||
|
> It is recommended to read the related documentation of the above tools before continuing.
|
||||||
|
|
||||||
|
The i18n workflow is designed to be **source-based**, which means that the source texts are extracted from the codebase and uploaded to Lokalise for translation. After the translation is complete, the translated texts are integrated back into the codebase. For more details, please refer to the [Workflow](#workflow) section.
|
||||||
|
|
||||||
|
Two types of strings mentioned in the [Strings](#strings) section are considered as the **source texts**, and English is the **source language**.
|
||||||
|
|
||||||
|
Extracted source texts are stored in two forms under `src/livecodes/i18n/locales/en`:
|
||||||
|
|
||||||
|
- `.ts` files: used by the app to load the source texts and provide type-safety for TypeScript
|
||||||
|
- `.lokalise.json` files: used to upload the source texts to Lokalise
|
||||||
|
|
||||||
|
> These files are generated and kept in sync with each other by the `i18n-export` npm script. See the [Scripts](#scripts) section for more details.
|
||||||
|
|
||||||
|
Other directories under `src/livecodes/i18n/locales` are used to store the translated texts in other target languages, which only contain `.ts` files.
|
||||||
|
|
||||||
|
## For Developers
|
||||||
|
|
||||||
|
Developers are responsible for implementing new features or making changes to the existing codebase. When adding new strings or modifying existing strings, developers should ensure that the newly-edited strings are properly extracted and saved.
|
||||||
|
|
||||||
|
### Strings
|
||||||
|
|
||||||
|
Strings that need to be translated are located in both `src/livecodes/html/*.html` and other `.ts` files in `src/livecodes` (mostly in `src/livecodes/UI/`). These two different types of files, which also represent two types of translation methods, are handled differently in the i18n workflow:
|
||||||
|
|
||||||
|
#### Element-level Translation (HTML Files)
|
||||||
|
|
||||||
|
In these files, strings are wrapped inside HTML elements with `data-i18n` attribute and two optional attributes (`data-i18n-prop`, `data-i18n-interpolation`). For example:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<div class="modal-title" data-i18n="assets.heading">Assets</div>
|
||||||
|
|
||||||
|
<input
|
||||||
|
id="search-assets"
|
||||||
|
type="text"
|
||||||
|
placeholder="Search"
|
||||||
|
data-i18n="assets.search"
|
||||||
|
data-i18n-prop="placeholder"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div class="description" data-i18n="backup.backup.desc" data-i18n-prop="innerHTML">
|
||||||
|
Backup LiveCodes data, so that it can be later restored on this or other devices. <br />
|
||||||
|
Please visit the
|
||||||
|
<a href="{{DOCS_BASE_URL}}features/backup-restore" target="_blank" rel="noopener"
|
||||||
|
>documentations</a
|
||||||
|
>
|
||||||
|
for details.
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
##### Keys
|
||||||
|
|
||||||
|
The `data-i18n` attribute is used to specify the **key** of the string and is a **period-separated** string with each part being a **lowerCamelCase** word.
|
||||||
|
|
||||||
|
##### Value
|
||||||
|
|
||||||
|
The value of the corresponding attribute of the element is used as the **default / fallback value** of the string.
|
||||||
|
|
||||||
|
##### Props
|
||||||
|
|
||||||
|
The `data-i18n-prop` attribute is a **space-separated list** of properties that should be translated. If it is not present, the string will be translated as the `textContent` of the element. When two or more properties are specified, a "full key" (`<key>.<property>`, or `<key>#<property>` on Lokalise) will be used to identify the string. For example, for the following element:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<div title="This is a title" data-i18n="key.to.title" data-i18n-prop="title textContent">
|
||||||
|
This is a content
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
The string will be identified as `key.to.title#title` and `key.to.title#textContent` on Lokalise.
|
||||||
|
|
||||||
|
###### Abstract HTML Tags
|
||||||
|
|
||||||
|
When the `data-i18n-prop` attribute is `innerHTML`, HTML tags inside the value will be abstracted during exporting, making the final source texts more readable. For example, the following value:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<div class="description" data-i18n="backup.backup.desc" data-i18n-prop="innerHTML">
|
||||||
|
Backup LiveCodes data, so that it can be later restored on this or other devices. <br />
|
||||||
|
Please visit the
|
||||||
|
<a href="{{DOCS_BASE_URL}}features/backup-restore" target="_blank" rel="noopener"
|
||||||
|
>documentations</a
|
||||||
|
>
|
||||||
|
for details.
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
will be abstracted to:
|
||||||
|
|
||||||
|
```html
|
||||||
|
Backup LiveCodes data, so that it can be later restored on this or other devices. <1></1> Please visit the <2>documentations</2> for details.
|
||||||
|
```
|
||||||
|
|
||||||
|
Although overriding specified attributes or adding new ones to the corresponding element is supported (`<2 href="https://example.org">documentations</2>`), it is not recommended to do so unless necessary (e.g., docs link for different languages).
|
||||||
|
|
||||||
|
##### Interpolation
|
||||||
|
|
||||||
|
Interpolation is used to insert dynamic content into the string. The `data-i18n-interpolation` attribute is a **JSON object string** that contains the key-value pairs of the dynamic content. For example:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<div class="share-encoded-url-expiry">
|
||||||
|
<span class="{{warnClass}}" data-i18n="share.characters">{{urlLength}} characters</span
|
||||||
|
><a href="#" data-i18n="share.shortURL">Get short URL</a>
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
In related TypeScript files, the `data-i18n-interpolation` attribute should be set as follows:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
charactersSpan.dataset.i18nInterpolation = JSON.stringify({ urlLength });
|
||||||
|
```
|
||||||
|
|
||||||
|
#### String-level Translation (TypeScript Files)
|
||||||
|
|
||||||
|
In these files, strings are wrapped inside `window.deps.translateString(key, value, interpolation)` function calls. For example:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
window.deps.translateString(
|
||||||
|
'namespace:file.key1.subkey1',
|
||||||
|
'default <strong>value</strong>, {{interpol}}',
|
||||||
|
{
|
||||||
|
isHTML: true,
|
||||||
|
interpol: 'abc',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
window.deps.translateString('core.login.successWithName', 'Logged in as: {{name}}', {
|
||||||
|
name: displayName,
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
The function is completely type-safe:
|
||||||
|
|
||||||
|
- The first argument is `key`, which is validated with valid keys in `i18n/locales/en/`.
|
||||||
|
- The second argument is `value`. With the `key` provided, the type of `value` will be narrowed down to the value in the translation file to ensure all occurrences of the key have the same value. If this is an HTML string (with the `isHTML` attribute set to `true`), the value will automatically be abstracted when exporting the translation.
|
||||||
|
- The third argument is `interpolation`, which could be omitted when the value doesn't contain any interpolation. Otherwise, it should be an object whose attributes are inferred from the `value`. Moreover, an additional `isHTML` boolean attribute is added to indicate whether the `value` contains HTML tags and should be abstracted when exporting the translation.
|
||||||
|
|
||||||
|
To provide better readability and maintainability, only string-level translation will be used in .ts files when it comes to dynamic content. For static content, element-level translation is still the best choice.
|
||||||
|
|
||||||
|
### Scripts
|
||||||
|
|
||||||
|
Several npm scripts are available to facilitate the i18n workflow:
|
||||||
|
|
||||||
|
- [`vscode-intellisense`](../../../scripts/vscode-intellisense.js): Generates the `html.html-data.json` file in the `.vscode` folder to enhance intellisense for the `data-i18n` attribute in HTML files in VSCode.
|
||||||
|
- [`i18n-export`](../../../scripts/i18n-export.js): Extracts source texts from the codebase and generates `.ts` and `.lokalise.json` files under `src/livecodes/i18n/locales/en`.
|
||||||
|
- The `--save-tmp` flag can be used to save the extracted source texts to `i18n/locales/tmp` instead of `en` for debugging purposes.
|
||||||
|
- [`i18n-update-push` / `i18n-upload.mjs`](../../../scripts/i18n-upload.mjs): **(Only used in CI and should not be run locally)** Pushes the source texts in `.lokasile.json` files to Lokalise.
|
||||||
|
- The `<branch>` argument is required to specify the branch to push to.
|
||||||
|
- The `--force` flag can be used to skip the check for environment variable `CI` and allow running the script locally.
|
||||||
|
- [`i18n-update-pull` / `i18n-import.mjs`](../../../scripts/i18n-import.mjs): **(Only used in CI and should not be run locally)** Pulls the translated texts from Lokalise and updates the `.ts` files under `src/livecodes/i18n/locales`. _Outdated translation will be deprecated during import._
|
||||||
|
- The `<branch>` argument is required to specify the branch to pull from.
|
||||||
|
- The `--force` flag can be used to skip the check for environment variable `CI` and allow running the script locally.
|
||||||
|
- The `--local` flag can be used to let the script use local resources in the directory defined by the `LOKALISE_TEMP` environment variable instead of fetching from Lokalise.
|
||||||
|
- [`i18n-exclude`](../../../scripts/i18n-exclude.js): **(Only used in other scripts and should not be run locally)** Excludes all other i18n locales except for English from type checking, as they might stay outdated and cause errors.
|
||||||
|
- The `<phase>` argument is required to specify whether the script is to exclude files or revert the exclusion. Valid values are `pre` and `post`.
|
||||||
|
- This script only works when environment variable `BUILD_INCLUDE_LOCALES` is **NOT** set to `true`.
|
||||||
|
- [`i18n-lokalise-json`](../../../scripts/i18n-lokalise-json.mjs): Generates `.lokalise.json` files from codebase for manually authoring translations on Lokalise.
|
||||||
|
- Arguments to the script are required to specify the languages that the `.lokalise.json` files are generated from.
|
||||||
|
- You can also use `all` to generate `.lokalise.json` files for all languages.
|
||||||
|
- This script **should not** be used for the source language English. Use `i18n-export` instead.
|
||||||
|
|
||||||
|
Please run `i18n-export` before pushing changes to the codebase to ensure that the source texts are up-to-date.
|
||||||
|
|
||||||
|
## For Maintainers
|
||||||
|
|
||||||
|
Maintainers are responsible for managing the i18n workflow and ensuring the quality of translations.
|
||||||
|
|
||||||
|
### Workflow
|
||||||
|
|
||||||
|
We consider the i18n process to consist of two parts:
|
||||||
|
|
||||||
|
#### No-Source Update
|
||||||
|
|
||||||
|
This means there are no changes to the source code/texts, only translations are updated. Adding new languages or updating existing translations are examples of this part.
|
||||||
|
|
||||||
|
In such cases, there is a scheduled workflow [`i18n-update-scheduled`](../../../.github/workflows/i18n-update-scheduled.yml) to handle this. The workflow will sync from the `master` branch on Lokalise to the `i18n/develop` branch on the codebase, then automatically create a PR if there are any changes.
|
||||||
|
|
||||||
|
Basically, maintainers only need to focus on the following for this part:
|
||||||
|
|
||||||
|
- Reviewing PRs created by the `i18n-update-scheduled` workflow
|
||||||
|
- Do merging on Lokalise after they consider the translation for a specific feature is ready, before commenting `.i18n-update-pull` to trigger the `i18n-update-pull` workflow
|
||||||
|
|
||||||
|
#### Source Update
|
||||||
|
|
||||||
|
This means new changes are made to the source code/texts. In this case, maintainers should follow the steps below:
|
||||||
|
|
||||||
|
1. Developers work on the source code, developing new features or modifying existing ones. They use `data-i18n` and `window.deps.translateString` to mark the strings that need to be translated.
|
||||||
|
2. Once a new feature or version is ready, developers run `npm run i18n-export` to extract and update all marked strings, then export them to `.lokalise.json` and `.ts` files.
|
||||||
|
3. Developers commit and push the changes to the repository. A feature PR is created and reviewed, and related tests, checks, and manual review could be carried out.
|
||||||
|
4. After the PR is merged, an auto-generated comment will notify maintainers to comment `.i18n-update-push` to trigger the `i18n-update-push` workflow when they think it is ready.
|
||||||
|
5. Maintainers comment `.i18n-update-push` to trigger the `i18n-update-push` workflow. The workflow will create a new branch named `i18n/<owner>/<head-branch>`, run `npm run i18n-export` again to ensure the source texts are up-to-date, and push the changes. Then, it will push the changes to the `i18n/<owner>/<head-branch>` branch on Lokalise.
|
||||||
|
6. Translators can start translating the texts on Lokalise.
|
||||||
|
7. Once the translation is complete, maintainers can comment `.i18n-update-pull` to trigger the `i18n-update-pull` workflow. The workflow will pull the translated texts from Lokalise, update the `.ts` files under `src/livecodes/i18n/locales`, and commit the changes to the `i18n/<owner>/<head-branch>` branch. Then, it will create a PR to merge the changes back to the default branch `develop`.
|
||||||
|
8. Maintainers should perform a final review on the i18n PR and merge it if everything is fine. Meanwhile, a merging from the `i18n/<owner>/<head-branch>` to `master` should also be done to keep the `master` branch on Lokalise up-to-date.
|
||||||
|
|
||||||
|
#### Minor Fixes / Updates
|
||||||
|
|
||||||
|
Sometimes there is already an ongoing main prerelease branch with many features being developed and translated on Lokalise, and a minor fix or update to the prerelease branch is needed. In this case, maintainers should follow the steps below:
|
||||||
|
|
||||||
|
1. Switch to `develop` branch.
|
||||||
|
2. Do `i18n-export` and upload corresponding `.lokalise.json` to the prerelease branch of the Lokalise project through web UI.
|
||||||
|
3. Affected entries will be updated and [marked as `unverified`](https://docs.lokalise.com/en/articles/3684557-translation-statuses-translated-verified-reviewed-and-completed#verified-and-unverified).
|
||||||
|
4. Provide correct translations in other languages on Lokalise.
|
||||||
|
|
||||||
|
Here we do not want an extra i18n branch for simplicity, nor need to pull from Lokalise as we always consider English source strings from codebase as the latest version and do not recommend modifying them on Lokalise directly.
|
||||||
|
|
||||||
|
### Github Actions (CI)
|
||||||
|
|
||||||
|
Four i18n-related workflows are set up in the repository:
|
||||||
|
|
||||||
|
- [`i18n-update-notify`](../../../.github\workflows\i18n-update-notify.yml): Creates a comment on merged PRs to notify maintainers to trigger the `i18n-update-push` workflow.
|
||||||
|
- [`i18n-update-push`](../../../.github\workflows\i18n-update-push.yml): Creates a new branch named `i18n/<owner>/<head-branch>`, runs `npm run i18n-export` again to ensure the source texts are up-to-date, pushes the changes on git, then pushes the changes to the `i18n/<owner>/<head-branch>` branch on Lokalise.
|
||||||
|
- [`i18n-update-pull`](../../../.github\workflows\i18n-update-pull.yml): Pulls the translated texts from Lokalise, updates the `.ts` files under `src/livecodes/i18n/locales`, commits the changes to the `i18n/<owner>/<head-branch>` branch, then creates a PR to merge the changes back to the default branch `develop`.
|
||||||
|
- [`i18n-update-scheduled`](../../../.github\workflows\i18n-update-scheduled.yml): Syncs between the `master` branch on Lokalise and the `i18n/develop` branch on the codebase, then automatically creates a PR if there are any changes.
|
||||||
|
|
||||||
|
### Hashing and Cache
|
||||||
|
|
||||||
|
After production build, [file hashes are added](../../../scripts/hash.js) to all files in `build/livecodes/` directory. The hash is the checksum of the file content. So if the file content does not change, it will get the same hash across builds.
|
||||||
|
|
||||||
|
This assumes that all files to be hashed are in that directory (without nesting), and that they are referenced in code using placeholders like `{{hash:file-name.js}}`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const mod = await import(baseUrl + '{{hash:file-name.js}}');
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, these files are [aggressively cached](https://github.com/live-codes/livecodes/tree/develop/src/_headers) (for 1 year).
|
||||||
|
|
||||||
|
So, any file that has not changed will continue to be served from cache even for later releases.
|
||||||
|
|
||||||
|
File hashing is also applied to translation files during build, by auto-generating a path loader file that contains hard-coded hash placeholders for each translation file.
|
||||||
|
|
||||||
|
## For Those Who Forked the Repo
|
||||||
|
|
||||||
|
This repository is utilizing [LiveCodes CI](https://github.com/apps/livecodes-ci) Github App to ensure the i18n workflow functions properly.
|
||||||
|
|
||||||
|
For forked repositories, maintainers should set up their own Lokalise project and Github App (see [here](https://github.com/peter-evans/create-pull-request/blob/main/docs/concepts-guidelines.mdx#authenticating-with-github-app-generated-tokens)) to handle the i18n workflow. Changes to related workflow files are necessary.
|
||||||
|
|
||||||
|
### Secrets and Variables Checklist
|
||||||
|
|
||||||
|
#### Repository Secrets
|
||||||
|
|
||||||
|
- `LOKALISE_API_TOKEN`
|
||||||
|
- `CI_APP_ID`
|
||||||
|
- `CI_APP_PRIVATE_KEY`
|
||||||
|
|
||||||
|
#### Repository Variables
|
||||||
|
|
||||||
|
- `LOKALISE_PROJECT_ID`
|
||||||
33
docs/docs/contribution/release.mdx
Normal file
33
docs/docs/contribution/release.mdx
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# Release
|
||||||
|
|
||||||
|
To start a new release:
|
||||||
|
|
||||||
|
- Checkout the branch `develop`.
|
||||||
|
- Make sure there are no uncommitted changes.
|
||||||
|
- Run `npm run start-release` and answer the prompts. This will:
|
||||||
|
- Increment the version number:
|
||||||
|
App -> "./package.json" (`appVersion`)
|
||||||
|
SDK -> "./src/sdk/package.sdk.json" (`version`)
|
||||||
|
- Generate changelog.
|
||||||
|
- Create a release branch (`releases/v{version}` | `releases/sdk-v{version}`) and commit changes.
|
||||||
|
- Push the branch to GitHub (which triggers a preview deploy).
|
||||||
|
- Create a pull request to `develop`.
|
||||||
|
- Once the pull request is merged a GitHub action workflow runs, which will:
|
||||||
|
- Build the app.
|
||||||
|
- Create and push a release tag:
|
||||||
|
App -> v\{version\}
|
||||||
|
SDK -> sdk-v\{version\}
|
||||||
|
- Compress the build directory to zip and tar files.
|
||||||
|
- Create a release:
|
||||||
|
- Use changelog as release notes.
|
||||||
|
- Upload compressed files as release artifacts.
|
||||||
|
- Create a pull request to `main`.
|
||||||
|
- If App release -> create a permanent URL (v\{version\}.livecodes.io) which is a proxy to preview deploy.
|
||||||
|
- If SDK release -> publish to npm.
|
||||||
|
|
||||||
|
:::info
|
||||||
|
|
||||||
|
App versions are numeric e.g. `v20`
|
||||||
|
SDK versions are semver e.g. `v1.2.3`
|
||||||
|
|
||||||
|
:::
|
||||||
174
docs/docs/credits.mdx
Normal file
174
docs/docs/credits.mdx
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
# Credits
|
||||||
|
|
||||||
|
## Services
|
||||||
|
|
||||||
|
LiveCodes uses services that are generously provided by:
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
float: 'left',
|
||||||
|
display: 'flex',
|
||||||
|
flexWrap: 'wrap',
|
||||||
|
justifyContent: 'space-evenly',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<p>
|
||||||
|
<a href="https://pages.cloudflare.com/" target="_blank" title="Cloudflare Pages">
|
||||||
|
<img
|
||||||
|
alt="Cloudflare Pages"
|
||||||
|
width="200"
|
||||||
|
style={{ margin: '0.5em' }}
|
||||||
|
src="/docs/img/credits/cloudflare-pages.svg"
|
||||||
|
></img>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://www.jsdelivr.com/" target="_blank" title="jsDelivr">
|
||||||
|
<img
|
||||||
|
alt="jsDelivr"
|
||||||
|
width="200"
|
||||||
|
style={{ margin: '0.5em' }}
|
||||||
|
src="/docs/img/credits/jsdelivr.svg"
|
||||||
|
></img>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://esm.sh/" target="_blank" title="esm.sh">
|
||||||
|
<img
|
||||||
|
alt="esm.sh"
|
||||||
|
width="200"
|
||||||
|
style={{ margin: '0.5em' }}
|
||||||
|
src="/docs/img/credits/esm.sh.png"
|
||||||
|
></img>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://unpkg.com/" target="_blank" title="unpkg">
|
||||||
|
<img
|
||||||
|
alt="unpkg"
|
||||||
|
width="200"
|
||||||
|
style={{ margin: '0.5em' }}
|
||||||
|
src="/docs/img/credits/unpkg.png"
|
||||||
|
></img>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://codeium.com/" target="_blank" title="Codeium">
|
||||||
|
<img
|
||||||
|
alt="Codeium"
|
||||||
|
width="200"
|
||||||
|
style={{ margin: '0.5em' }}
|
||||||
|
src="/docs/img/credits/codeium.svg"
|
||||||
|
></img>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://bundlejs.com/" target="_blank" title="bundlejs">
|
||||||
|
<img
|
||||||
|
alt="bundlejs"
|
||||||
|
width="200"
|
||||||
|
style={{ margin: '0.5em' }}
|
||||||
|
src="/docs/img/credits/bundlejs.jpg"
|
||||||
|
></img>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://dpaste.com/" target="_blank" title="dpaste">
|
||||||
|
<img
|
||||||
|
alt="dpaste"
|
||||||
|
width="200"
|
||||||
|
style={{ margin: '0.5em' }}
|
||||||
|
src="/docs/img/credits/dpaste.png"
|
||||||
|
></img>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://github.com/" target="_blank" title="GitHub">
|
||||||
|
<img
|
||||||
|
alt="GitHub"
|
||||||
|
width="200"
|
||||||
|
style={{ margin: '0.5em' }}
|
||||||
|
src="/docs/img/credits/github.png"
|
||||||
|
></img>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://netlify.com/" target="_blank" title="Netlify">
|
||||||
|
<img
|
||||||
|
alt="Netlify"
|
||||||
|
width="200"
|
||||||
|
style={{ margin: '0.5em' }}
|
||||||
|
src="/docs/img/credits/netlify.svg"
|
||||||
|
></img>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://www.sonarsource.com/products/sonarcloud/" target="_blank" title="SonarCloud">
|
||||||
|
<img
|
||||||
|
alt="SonarCloud"
|
||||||
|
width="200"
|
||||||
|
style={{ margin: '0.5em' }}
|
||||||
|
src="/docs/img/credits/sonarcloud.svg"
|
||||||
|
></img>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://www.codacy.com/" target="_blank" title="Codacy">
|
||||||
|
<img
|
||||||
|
alt="Codacy"
|
||||||
|
width="200"
|
||||||
|
style={{ margin: '0.5em' }}
|
||||||
|
src="/docs/img/credits/codacy.svg"
|
||||||
|
></img>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://bundlewatch.io/" target="_blank" title="BundleWatch">
|
||||||
|
<img
|
||||||
|
alt="BundleWatch"
|
||||||
|
width="200"
|
||||||
|
style={{ margin: '0.5em' }}
|
||||||
|
src="/docs/img/credits/bundlewatch.svg"
|
||||||
|
></img>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://www.browserstack.com/" target="_blank" title="BrowserStack">
|
||||||
|
<img
|
||||||
|
alt="BrowserStack"
|
||||||
|
width="200"
|
||||||
|
style={{ margin: '0.5em' }}
|
||||||
|
src="/docs/img/credits/browserstack.svg"
|
||||||
|
></img>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="https://lokalise.com/" target="_blank" title="Lokalise">
|
||||||
|
<img
|
||||||
|
alt="Lokalise"
|
||||||
|
width="200"
|
||||||
|
style={{ margin: '0.5em' }}
|
||||||
|
src="/docs/img/credits/lokalise.png"
|
||||||
|
></img>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div style={{ clear: 'both' }}></div>
|
||||||
|
## Third Party Packages
|
||||||
|
|
||||||
|
Packages used by LiveCodes and their licenses are [listed here](https://github.com/live-codes/livecodes/blob/develop/vendor-licenses.mdx).
|
||||||
|
|
||||||
|
## Prior Art
|
||||||
|
|
||||||
|
Many of LiveCodes features/ideas were inspired by:
|
||||||
|
|
||||||
|
- [CodePen](https://codepen.io/)
|
||||||
|
- [JSFiddle](https://jsfiddle.net/)
|
||||||
|
- [JS Bin](https://jsbin.com/)
|
||||||
|
- [CodeSandbox](https://codesandbox.io/)
|
||||||
|
- [Replit](https://replit.com/)
|
||||||
|
- [VS Code](https://code.visualstudio.com/)
|
||||||
|
- [Monacode](https://github.com/lukejacksonn/monacode/)
|
||||||
|
|
||||||
|
Thank you ❤️
|
||||||
9
docs/docs/examples/display-modes/codeblock.mdx
Normal file
9
docs/docs/examples/display-modes/codeblock.mdx
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
title: codeblock
|
||||||
|
---
|
||||||
|
|
||||||
|
# Display Mode: codeblock
|
||||||
|
|
||||||
|
import LiveCodes from '../../../src/components/LiveCodes.tsx';
|
||||||
|
|
||||||
|
<LiveCodes config={{mode:'codeblock'}} template="react"></LiveCodes>
|
||||||
9
docs/docs/examples/display-modes/editor.mdx
Normal file
9
docs/docs/examples/display-modes/editor.mdx
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
title: editor
|
||||||
|
---
|
||||||
|
|
||||||
|
# Display Mode: editor
|
||||||
|
|
||||||
|
import LiveCodes from '../../../src/components/LiveCodes.tsx';
|
||||||
|
|
||||||
|
<LiveCodes config={{mode:'editor'}} template="react"></LiveCodes>
|
||||||
9
docs/docs/examples/display-modes/full.mdx
Normal file
9
docs/docs/examples/display-modes/full.mdx
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
title: full
|
||||||
|
---
|
||||||
|
|
||||||
|
# Display Mode: full
|
||||||
|
|
||||||
|
import LiveCodes from '../../../src/components/LiveCodes.tsx';
|
||||||
|
|
||||||
|
<LiveCodes template="react"></LiveCodes>
|
||||||
6
docs/docs/examples/display-modes/index.mdx
Normal file
6
docs/docs/examples/display-modes/index.mdx
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# Display Modes
|
||||||
|
|
||||||
|
import DocCardList from '@theme/DocCardList';
|
||||||
|
import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
|
||||||
|
|
||||||
|
<DocCardList items={useCurrentSidebarCategory().items}/>
|
||||||
9
docs/docs/examples/display-modes/result.mdx
Normal file
9
docs/docs/examples/display-modes/result.mdx
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
title: result
|
||||||
|
---
|
||||||
|
|
||||||
|
# Display Mode: result
|
||||||
|
|
||||||
|
import LiveCodes from '../../../src/components/LiveCodes.tsx';
|
||||||
|
|
||||||
|
<LiveCodes config={{mode:'result'}} template="react"></LiveCodes>
|
||||||
79
docs/docs/features/ai.mdx
Normal file
79
docs/docs/features/ai.mdx
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
# AI Code Assistant 🪄
|
||||||
|
|
||||||
|
LiveCodes supports AI-powered code completion, totally for **free** with **no account or API token required**, using [Codeium](https://codeium.com/), the ultrafast Copilot alternative. This can be easily enabled from the UI (as easy as [flipping a switch](#ui)!)
|
||||||
|
|
||||||
|
The large generative machine learning model is capable of understanding the context of your code and comments (across the [3 code editors](./projects#markup-editor)) in order to generate suggestions on what you might want to type next.
|
||||||
|
|
||||||
|
It has a wide range of language support, and it works everywhere (in the [standalone app](../getting-started.mdx#standalone-app), [embedded playgrounds](./embeds.mdx) and [self-hosted](./self-hosting.mdx) apps).
|
||||||
|
|
||||||
|
Powered by:
|
||||||
|
|
||||||
|
<a href="https://codeium.com/">
|
||||||
|
<img width="300px" src="/docs/img/credits/codeium.svg" alt="Codeium logo" />
|
||||||
|
</a>
|
||||||
|
.
|
||||||
|
|
||||||
|
## Examples:
|
||||||
|
|
||||||
|
JavaScript:
|
||||||
|
|
||||||
|
<video controls style={{width: '100%'}}>
|
||||||
|
|
||||||
|
<source src="/docs/vid/LiveCodes-AI.mp4" type="video/mp4" />
|
||||||
|
</video>
|
||||||
|
|
||||||
|
Python:
|
||||||
|
|
||||||
|
<video controls style={{width: '100%'}}>
|
||||||
|
|
||||||
|
<source src="/docs/vid/LiveCodes-AI-py.mp4" type="video/mp4" />
|
||||||
|
</video>
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
The AI code assistant can be enabled from:
|
||||||
|
|
||||||
|
### UI
|
||||||
|
|
||||||
|
The [editor settings](./editor-settings.mdx) screen (Settings menu → Editor Settings → Enable AI Code Assistant).
|
||||||
|
|
||||||
|
import RunInLiveCodes from '../../src/components/RunInLiveCodes.tsx';
|
||||||
|
|
||||||
|
<RunInLiveCodes params={{ screen: 'editor-settings' }} linkText="direct link" />
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**Note**
|
||||||
|
|
||||||
|
When set from the UI, this configuration is saved locally to [user settings](./user-settings.mdx) and is remembered across sessions.
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
Alternatively, this can be enabled (_only for the current session_) using the [`enableAI`](../configuration/configuration-object.mdx#enableai) property in the [configuration object](../configuration/configuration-object.mdx). This can be used to enable the AI code assistant in [embedded playgrounds](./embeds.mdx).
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { createPlayground } from 'livecodes';
|
||||||
|
|
||||||
|
createPlayground('#container', {
|
||||||
|
config: {
|
||||||
|
// highlight-next-line
|
||||||
|
enableAI: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
Also this can be enabled using [query params](../configuration/query-params.mdx) (e.g. https://livecodes.io/?enableAI).
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
On typing, the code completion suggestions will be shown in dimmed color. Press <kbd>Tab</kbd> to accept, or <kbd>Esc</kbd> to cancel.
|
||||||
|
|
||||||
|
On mobile, tap on the suggestion to accept it, or continue typing to reject.
|
||||||
|
|
||||||
|
:::caution Note
|
||||||
|
|
||||||
|
Please note that when using Codeium AI assistant, your code is sent to Codeium servers for code completion. However, your code is not used for training their model. Check Codeium [FAQ](https://codeium.com/faq#Will-Codeium-regurgitate-private-code%3F) and [privacy policy](https://codeium.com/privacy-policy) for more details.
|
||||||
|
|
||||||
|
:::
|
||||||
26
docs/docs/features/assets.mdx
Normal file
26
docs/docs/features/assets.mdx
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# Assets
|
||||||
|
|
||||||
|
Adding local assets (e.g. images, fonts, stylesheets, scripts) that are not hosted online is such a common need that a UI was developed to allow easily adding them.
|
||||||
|
|
||||||
|
The assets are saved locally on the user's device and are available across projects (i.e the same image can be used in different projects without having to add it multiple times).
|
||||||
|
|
||||||
|
In addition, assets are supported in [sync](./sync.mdx), [backup](./backup-restore.mdx#backup) and [restore](./backup-restore.mdx#restore).
|
||||||
|
|
||||||
|
The `Assets` screen can be accessed from Settings menu → Assets
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
import RunInLiveCodes from '../../src/components/RunInLiveCodes.tsx';
|
||||||
|
|
||||||
|
<RunInLiveCodes params={{ screen: 'assets' }} linkText="direct link" />
|
||||||
|
|
||||||
|
Assets are either:
|
||||||
|
|
||||||
|
- Encoded as [data URLs](./data-urls.mdx).
|
||||||
|
- Uploaded to a [GitHub Pages](https://pages.github.com/). This requires login with a [GitHub account](./github-integration.mdx) (allowing access to repos). A **public** repo called `livecodes-assets` is created if not present. The assets are pushed to `gh-pages` branch. They can then be accessed by URLs like:
|
||||||
|
|
||||||
|
https://\{user\}.github.io/livecodes-assets/assets/...
|
||||||
|
|
||||||
|
When an asset item is clicked, the URL is copied to clipboard. The URL can then be used in projects.
|
||||||
|
|
||||||
|

|
||||||
38
docs/docs/features/backup-restore.mdx
Normal file
38
docs/docs/features/backup-restore.mdx
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
# Backup / Restore
|
||||||
|
|
||||||
|
LiveCodes data can be backed-up, so that it can be later restored on the same or different device.
|
||||||
|
|
||||||
|
The Backup/Restore screen can be accessed from the Settings menu → Backup / Restore.
|
||||||
|
|
||||||
|
import RunInLiveCodes from '../../src/components/RunInLiveCodes.tsx';
|
||||||
|
|
||||||
|
<RunInLiveCodes params={{ screen: 'backup' }} linkText="direct link" />
|
||||||
|
|
||||||
|
## Backup
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
The backup can include one or more of the following:
|
||||||
|
|
||||||
|
- [Projects](./projects.mdx)
|
||||||
|
- [User Templates](./templates.mdx)
|
||||||
|
- [Code Snippets](./snippets.mdx)
|
||||||
|
- [Assets](./assets.mdx)
|
||||||
|
- [User Settings](./user-settings.mdx)
|
||||||
|
|
||||||
|
A zip file containing the (base64-encoded binary) backup data is downloaded. This file can be restored later on the same or different device.
|
||||||
|
|
||||||
|
## Restore
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
When restoring a backup, there are 2 options for managing the current data:
|
||||||
|
|
||||||
|
1. The current data can be deleted and replaced by the backup data. It cannot then be retrieved, so you may want to back it up first.
|
||||||
|
|
||||||
|
2. The backup data can be merged with the current data with best effort to preserve both.
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [Sync](./sync.mdx)
|
||||||
|
- [Export](./export.mdx)
|
||||||
94
docs/docs/features/broadcast.mdx
Normal file
94
docs/docs/features/broadcast.mdx
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
# Broadcast
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
LiveCodes Broadcast allows sending the [result page](./result.mdx) (and optionally source & compiled code and project configuration) to custom API. This can be used to live-view result page updates on different browsers/devices in real-time or broadcast live-coding sessions.
|
||||||
|
|
||||||
|
:::note
|
||||||
|
|
||||||
|
Broadcast can only be performed from the full app, and not from embedded playgrounds.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
The `Broadcast` screen can be accessed from the Broadcast icon in the [tools pane](./tools-pane.mdx) (below the result page), or from the Project menu → Broadcast.
|
||||||
|
|
||||||
|
import RunInLiveCodes from '../../src/components/RunInLiveCodes.tsx';
|
||||||
|
|
||||||
|
<RunInLiveCodes params={{ screen: 'broadcast' }} linkText="direct link" />
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
On connecting to the server, the channel URL returned by the server is displayed. The channel URL can be shared to different clients (browsers on same or different devices) to view result page or code updates in real-time.
|
||||||
|
|
||||||
|
If the option `Include source code` is enabled, the source and compiled code together with the current project configuration are also posted to the server with each update.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
The Broadcast icon (in tools pane), shows the broadcast status. Clicking the icon, opens the broadcast UI, where the channel URL is displayed and the broadcast can be stopped.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
:::info Server
|
||||||
|
|
||||||
|
An open-source example implementation of an API server is available on: [live-codes/broadcast](https://github.com/live-codes/broadcast).
|
||||||
|
|
||||||
|
It is a [simple implementation](https://github.com/live-codes/broadcast/blob/main/index.js), which you can use or extend. It makes use of LiveCodes [Embeds](./embeds.mdx) and [SDK](../sdk/index.mdx) for code broadcasting.
|
||||||
|
|
||||||
|
A demo, free-to-test, instance is hosted on:
|
||||||
|
https://livecodes-broadcast.onrender.com/ (low resources - sleeps after 15 minutes of inactivity)
|
||||||
|
|
||||||
|
You can use one of these links to self-host it:
|
||||||
|
|
||||||
|
<a href="https://render.com/deploy?repo=https://github.com/live-codes/broadcast">
|
||||||
|
<img
|
||||||
|
src="https://render.com/images/deploy-to-render-button.svg"
|
||||||
|
alt="Deploy to Render"
|
||||||
|
width="150"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="https://heroku.com/deploy?template=https://github.com/live-codes/broadcast/tree/main">
|
||||||
|
<img src="https://www.herokucdn.com/deploy/button.svg" alt="Deploy to Heroku" width="150" />
|
||||||
|
</a>
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::tip Hosted API
|
||||||
|
|
||||||
|
[LiveCodes sponsors](../sponsor.mdx) (bronze sponsors and above) get access to a hosted (always-on) API, which they can use without having to manage their own server.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
These are screenshots for the live-updated result page and code:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Technical Details
|
||||||
|
|
||||||
|
When starting a broadcast, the app sends a `POST` request to the specified server with a body that has the following properties:
|
||||||
|
|
||||||
|
- `result`: a string with the result page html.
|
||||||
|
- `data` (Only if `Include source code` option is enabled): an object containing source and compiled code together with the current project configuration.
|
||||||
|
- `userToken` (Optional): Can be used by the server to authorize users who can broadcast (see below how to set it).
|
||||||
|
|
||||||
|
When the server successfully creates a channel, it should respond by sending a JSON object with the following properties:
|
||||||
|
|
||||||
|
- `channel`: a string representing the channel Id.
|
||||||
|
- `channelUrl`: a string with the URL of the channel that can be shared to the clients who want to connect to it.
|
||||||
|
- `channelToken`: a string representing a secret token for this channel, to prevent others from sending to the same channel. This is only sent once (in response to the request that created the channel).
|
||||||
|
|
||||||
|
The `channel` and `channelToken` are remembered by the app, and are sent in subsequent requests for the same channel (with every result page update). They are deleted when stopping broadcast or when the app reloads.
|
||||||
|
|
||||||
|
:::note
|
||||||
|
|
||||||
|
To set a `userToken` for authorization with a broadcast server, run the following in the browser console:
|
||||||
|
|
||||||
|
```js
|
||||||
|
await livecodes.exec('setBroadcastToken', 'my-token');
|
||||||
|
```
|
||||||
|
|
||||||
|
The supplied value (in this case `my-token`) will be posted to the server with every update as the value for the property `userToken`.
|
||||||
|
|
||||||
|
This value is saved for the current user across app reloads.
|
||||||
52
docs/docs/features/code-format.mdx
Normal file
52
docs/docs/features/code-format.mdx
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
# Code Format
|
||||||
|
|
||||||
|
Code formatting is supported for most [languages](../languages/index.mdx).
|
||||||
|
|
||||||
|
## Code Formatters
|
||||||
|
|
||||||
|
The code formatter used for each language is specified in the [language documentation](../languages/index.mdx) page.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
- [Prettier](https://prettier.io/) is used for many languages including HTML, CSS, JavaScript, TypeScript, JSX, TSX.
|
||||||
|
- [gofmt](https://pkg.go.dev/cmd/gofmt) (via [GopherJS](https://github.com/gopherjs/gopherjs)) is used for Go.
|
||||||
|
- [Parinfer](https://shaunlebron.github.io/parinfer/) is used for Scheme, Common Lisp and ClojureScript.
|
||||||
|
|
||||||
|
## Format Button
|
||||||
|
|
||||||
|
Code formatting for the code in the active editor can be triggered by the `Format` button below the editor.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Keyboard Shortcut
|
||||||
|
|
||||||
|
Code formatting can also be trigger by the keyboard shortcut <kbd>Alt</kbd> + <kbd>Shift</kbd> + <kbd>F</kbd>.
|
||||||
|
|
||||||
|
## Format on-save
|
||||||
|
|
||||||
|
Format on-save can be enabled from the Settings menu → Format on-save.
|
||||||
|
|
||||||
|
## Format Options
|
||||||
|
|
||||||
|
Some format options can be configured from [Editor Settings](./editor-settings.mdx) screen. These include [Prettier](https://prettier.io/) [configuration options](https://prettier.io/docs/en/options.html) for:
|
||||||
|
|
||||||
|
- Indentation (Spaces/Tabs)
|
||||||
|
- Tab size
|
||||||
|
- Use Semicolons
|
||||||
|
- Use Single Quotes
|
||||||
|
- Use Trailing Commas
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Code format can be configured using the [configuration object](../configuration/configuration-object.mdx) properties:
|
||||||
|
|
||||||
|
- [`formatOnsave`](../configuration/configuration-object.mdx#formatonsave)
|
||||||
|
- [`useTabs`](../configuration/configuration-object.mdx#usetabs)
|
||||||
|
- [`tabSize`](../configuration/configuration-object.mdx#tabsize)
|
||||||
|
- [`semicolons`](../configuration/configuration-object.mdx#semicolons)
|
||||||
|
- [`singleQuote`](../configuration/configuration-object.mdx#singlequote)
|
||||||
|
- [`trailingComma`](../configuration/configuration-object.mdx#trailingcomma)
|
||||||
|
|
||||||
|
## SDK Method: `format`
|
||||||
|
|
||||||
|
The code format can be programmatically triggered by the [SDK](../sdk/index.mdx) method [`format`](../sdk/js-ts.mdx#format).
|
||||||
71
docs/docs/features/code-prefill.mdx
Normal file
71
docs/docs/features/code-prefill.mdx
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
# Code Prefill
|
||||||
|
|
||||||
|
import LiveCodes from '../../src/components/LiveCodes.tsx';
|
||||||
|
|
||||||
|
There are many ways to pre-fill code into playgrounds. This is generally achieved either by the [SDK](../sdk/index.mdx) or using [query params](../configuration/query-params.mdx).
|
||||||
|
|
||||||
|
## Prefill using SDK
|
||||||
|
|
||||||
|
When creating an embedded playground, the following [embed options](../sdk/js-ts.mdx#embed-options) allow prefill with code:
|
||||||
|
|
||||||
|
### config
|
||||||
|
|
||||||
|
[EmbedOptions.config](../sdk/js-ts.mdx#config)
|
||||||
|
|
||||||
|
loads a [configuration object](../configuration/configuration-object.mdx) (or a URL to JSON file representing the configuration object)
|
||||||
|
|
||||||
|
<LiveCodes
|
||||||
|
config={{
|
||||||
|
markup: { language: 'html', content: '<h1>Hello World!</h1>' },
|
||||||
|
style: { language: 'css', content: 'h1 { color: blue; }' },
|
||||||
|
}}
|
||||||
|
></LiveCodes>
|
||||||
|
|
||||||
|
### import
|
||||||
|
|
||||||
|
[EmbedOptions.import](../sdk/js-ts.mdx#import)
|
||||||
|
|
||||||
|
allows [importing](./import.mdx) from many sources.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
Import GitHub directory:
|
||||||
|
|
||||||
|
<LiveCodes import="https://github.com/bradtraversy/50projects50days/tree/master/progress-steps"></LiveCodes>
|
||||||
|
|
||||||
|
Import shared project:
|
||||||
|
|
||||||
|
<LiveCodes import="id/6ys2b8txf33"></LiveCodes>
|
||||||
|
|
||||||
|
### template
|
||||||
|
|
||||||
|
[EmbedOptions.template](../sdk/js-ts.mdx#template)
|
||||||
|
|
||||||
|
loads one of the [starter templates](./templates.mdx).
|
||||||
|
|
||||||
|
<LiveCodes template="react"></LiveCodes>
|
||||||
|
|
||||||
|
## Prefill using query params
|
||||||
|
|
||||||
|
[Query parameters](../configuration/query-params.mdx) can provide easy and powerful ways for configuring the playground.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
<a href="https://livecodes.io/?md=**Hello World!**" target="_blank">
|
||||||
|
{'https://livecodes.io/?md=**Hello World!**'}
|
||||||
|
</a>
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<LiveCodes params={{ md: '**Hello World!**' }}></LiveCodes>
|
||||||
|
|
||||||
|
## Auto-Prefill from page DOM
|
||||||
|
|
||||||
|
TODO...
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [Import](./import.mdx)
|
||||||
|
- [Templates](./templates.mdx)
|
||||||
|
- [Configuration](../configuration/index.mdx)
|
||||||
|
- [SDK](../sdk/index.mdx)
|
||||||
23
docs/docs/features/code-to-image.mdx
Normal file
23
docs/docs/features/code-to-image.mdx
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
# Code to Image
|
||||||
|
|
||||||
|
LiveCodes has a feature called "Code to Image" that allows converting the code in the code editor into nice-looking images (or code screenshots), that can be downloaded or shared.
|
||||||
|
|
||||||
|
This can be accessed from the camera icon in the toolbar below the editor. Clicking the icon will open the "Code to Image" screen and load the code in the editor.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Code can be modified in the "Code to Image" screen and then downloaded as image or shared.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
There are many options to configure the image to be generated, including background color, border radius, image size, padding, shadow, window style, share URL, editor theme, opacity, code font, image format, etc.
|
||||||
|
|
||||||
|
There are multiple presets that can be used or the options can be manually configured.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
34
docs/docs/features/command-menu.mdx
Normal file
34
docs/docs/features/command-menu.mdx
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# Command Menu
|
||||||
|
|
||||||
|
The command menu allows running a large set of commands from the UI. It is keyboard-friendly and allows for searching and selecting commands. Most of the functionality of LiveCodes can be achieved using the command menu, which can really improve productivity and DX.
|
||||||
|
|
||||||
|
It can be triggered from the keyboard by pressing <kbd>Ctrl</kbd> + <kbd>K</kbd> (or <kbd>⌘</kbd> + <kbd>K</kbd> on Mac), or from the Help Menu.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
The available commands cover a wide range of functionality, like showing and hiding UI elements (e.g. different editors, the [result page](./result.mdx), [console](./console.mdx), [compiled code viewer](./compiled-code.mdx), and [tests](./tests.mdx)), changing [languages](../languages), loading [starter templates](./templates.mdx), opening different screens (e.g. new project, opening saved projects, [import](./import.mdx), [embeds](./embeds.mdx), [deploy](./deploy.mdx), [share](./share.mdx) and more).
|
||||||
|
In addition many commands can be executed from the command menu, such as running code, formatting code, changing settings (e.g. autorun, autosave, [AI code assistant](./ai.mdx), changing [themes](./themes.mdx), [editor settings](./editor-settings.mdx), and more).
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Using the Command Menu
|
||||||
|
|
||||||
|
Commands can be navigated and selected by:
|
||||||
|
|
||||||
|
- The mouse: scrolling and clicking
|
||||||
|
- The keyboard: using the up and down arrow keys to navigate, pressing <kbd>Enter</kbd> to select, <kbd>Backspace</kbd> to move to parent category and <kbd>Esc</kbd> to close the command menu.
|
||||||
|
- Searching: typing in the search box for fuzzy search.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Keyboard Shortcuts
|
||||||
|
|
||||||
|
If a command has a keyboard shortcut, it will be shown in the command menu. In addition, the whole list of keyboard shortcuts can be opened from the command menu (by searching for "Keyboard Shortcuts") or from the UI from the Help Menu.
|
||||||
|
|
||||||
|

|
||||||
19
docs/docs/features/compiled-code.mdx
Normal file
19
docs/docs/features/compiled-code.mdx
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Compiled Code
|
||||||
|
|
||||||
|
import LiveCodes from '../../src/components/LiveCodes.tsx';
|
||||||
|
|
||||||
|
The resulting compiled/transpiled code can be seen in the compiled code viewer (in the [tools pane](./tools-pane.mdx)) in real-time, as you type. This works for all compiled code (e.g. Markdown, Pug, SCSS, Less, Stylus, Typescript, CoffeeScript, ...etc.).
|
||||||
|
|
||||||
|
This can be a great tool for learning. As you write code, you see the compiled code and the resulting page at the same time. The compiled code viewer shows the code compiled from the currently active editor (markup/style/script). This includes the CSS produced by CSS processors (e.g. Autoprefixer), if enabled.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
e.g. https://livecodes.io/?ts&compiled=full <br />
|
||||||
|
sets TypeScript as the active editor and shows compiled code viewer maximized.
|
||||||
|
|
||||||
|
This demo shows TypeScript code along with the compiled Javascript code, similar to the [official TypeScript Playground](https://www.typescriptlang.org/play):
|
||||||
|
|
||||||
|
<LiveCodes
|
||||||
|
import="https://gist.github.com/hatemhosny/4bed283ef9757a6a541aee685c710dc7"
|
||||||
|
params={{ 'ts-selector': 'playground.ts', activeEditor: 'script', compiled: 'full' }}
|
||||||
|
></LiveCodes>
|
||||||
36
docs/docs/features/console.mdx
Normal file
36
docs/docs/features/console.mdx
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# Console
|
||||||
|
|
||||||
|
import LiveCodes from '../../src/components/LiveCodes.tsx';
|
||||||
|
|
||||||
|
Console messages are shown in the integrated console (in the [tools pane](./tools-pane.mdx), below the result page), without having to open the native browser console.
|
||||||
|
|
||||||
|
Messages can be sent to the console using the standard `console` methods in the code editor (e.g. `console.log`, `console.warn`, `console.error`, `console.table`, ...etc). The console can also be used as REPL (read–eval–print loop) using the integrated console input.
|
||||||
|
|
||||||
|
The code is evaluated in the context of the result page (i.e. variables defined in the script editor are accessible for evaluation in the console input). Also code completion works in the console input.
|
||||||
|
|
||||||
|
e.g. https://livecodes.io/?ts&console=full <br />
|
||||||
|
sets TypeScript as the active editor and shows the console maximized.
|
||||||
|
|
||||||
|
Demo: (console=full)
|
||||||
|
|
||||||
|
<LiveCodes
|
||||||
|
params={{
|
||||||
|
console: 'full',
|
||||||
|
js: `const x = 5;\nconsole.log('x:', x);\nconsole.log({x, y: 6});\nconsole.table({x, y: 6});\nconsole.warn('take care!');\nconst z = x * y;`,
|
||||||
|
}}
|
||||||
|
></LiveCodes>
|
||||||
|
|
||||||
|
<p> </p>
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
|
||||||
|
Setting the querystring `languages` only shows these languages.
|
||||||
|
Selecting one language and setting console to `full` gives an environment similar to a REPL.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
Demo: (Python - print to console)
|
||||||
|
|
||||||
|
<LiveCodes
|
||||||
|
params={{ languages: 'py', console: 'full', py: "print('hello from python')" }}
|
||||||
|
></LiveCodes>
|
||||||
143
docs/docs/features/css.mdx
Normal file
143
docs/docs/features/css.mdx
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
# CSS
|
||||||
|
|
||||||
|
import LiveCodes from '../../src/components/LiveCodes.tsx';
|
||||||
|
|
||||||
|
The [result page](./result.mdx) can be styled with CSS using various methods, including:
|
||||||
|
|
||||||
|
## Style Editor
|
||||||
|
|
||||||
|
Code added to [style editor](./projects.mdx#style-editor) is [compiled](#languages) and [processed](#css-processors), then added as CSS to the [result page](./result.mdx) `head` element.
|
||||||
|
|
||||||
|
 <!-- http://127.0.0.1:8080/?x=id/8gvn866qvh5 -->
|
||||||
|
|
||||||
|
### Languages
|
||||||
|
|
||||||
|
LiveCodes supports multiple languages that compile to CSS, including [SCSS](../languages/scss.mdx), [Sass](../languages/sass.mdx), [Less](../languages/less.mdx) and [Stylus](../languages/stylus.mdx). Code authored in any of these languages is compiled to CSS before being added to the [result page](./result.mdx).
|
||||||
|
|
||||||
|
The style language can be selected from the style editor menu. In embedded playgrounds, the language can be configured via the configuration object property [`style.language`](../configuration/configuration-object.mdx#style)
|
||||||
|
|
||||||
|
### CSS Processors
|
||||||
|
|
||||||
|
The (compiled) CSS code can be processed by one or more of the supported CSS processors. Examples of these include: [Autoprefixer](../languages/autoprefixer.mdx), [postcss-preset-env](../languages/postcssPresetEnv.mdx), [Lightning CSS](../languages/lightningcss.mdx), [CSS Modules](../languages/cssmodules.mdx), [cssnano](../languages/cssnano.mdx), ...etc.
|
||||||
|
|
||||||
|
Multiple CSS processors can be enabled at the same time. The code is processed in the order of processors placed in the style editor menu of the app.
|
||||||
|
|
||||||
|
Processors are enabled in the [standalone app](../getting-started.mdx#standalone-app) from the style editor menu, by switching on the toggles of the required processors.
|
||||||
|
|
||||||
|
In embedded playgrounds, processors are enabled via the [`processors`](../configuration/configuration-object.mdx#processors) property of the [configuration object](../configuration/configuration-object.mdx).
|
||||||
|
|
||||||
|
### Style Imports
|
||||||
|
|
||||||
|
[Bare modules](./module-resolution.mdx#bare-module-imports) used with `@import` rules are supposed to be npm modules. These are converted to [full URLs from CDN](./module-resolution.mdx#cdn-providers).
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
This code:
|
||||||
|
|
||||||
|
```css
|
||||||
|
@import 'github-markdown-css/github-markdown.css';
|
||||||
|
```
|
||||||
|
|
||||||
|
becomes:
|
||||||
|
|
||||||
|
```css
|
||||||
|
@import 'https://unpkg.com/github-markdown-css/github-markdown.css';
|
||||||
|
```
|
||||||
|
|
||||||
|
Packages that specify a stylesheet as the main module can be imported like that:
|
||||||
|
|
||||||
|
```css
|
||||||
|
@import 'github-markdown-css';
|
||||||
|
```
|
||||||
|
|
||||||
|
demo:
|
||||||
|
|
||||||
|
<LiveCodes template="markdown" params={{ activeEditor: 'style', compiled: 'open' }}></LiveCodes>
|
||||||
|
|
||||||
|
The content can be inlined in the compiled CSS by enabling the processor [postcss-import-url](../languages/postcssImportUrl.mdx).
|
||||||
|
|
||||||
|
### Compiled CSS
|
||||||
|
|
||||||
|
Compiled CSS (following compilation of style language, and all enabled processors) is added to the [result page](./result.mdx) `head` element.
|
||||||
|
|
||||||
|
The compiled code can be inspected in the [compiled code viewer](./compiled-code.mdx) in the [tools pane](./tools-pane.mdx).
|
||||||
|
|
||||||
|
### Auto-update
|
||||||
|
|
||||||
|
When [`autoupdate`](../configuration/configuration-object.mdx#autoupdate) is enabled (default), in contrast to [markup editor](./projects.mdx#markup-editor) and [script editor](./projects.mdx#script-editor), changes in style editor code does NOT trigger a full reload of the [result page](./result.mdx). The updated CSS code is sent to the page and applied without a reload.
|
||||||
|
|
||||||
|
The page can be force-reloaded by clicking the run button or using the keyboard shortcut: <kbd>Shift</kbd> + <kbd>Enter</kbd>.
|
||||||
|
|
||||||
|
## External Resources
|
||||||
|
|
||||||
|
External stylesheets can be added in [external resources](./external-resources.mdx) screen. These are added to the [result page](./result.mdx) before the compiled style editor code. This allows code in style editor to override CSS properties in external stylesheets.
|
||||||
|
|
||||||
|
External stylesheets can be added to embedded playgrounds using the [configuration object](../configuration/configuration-object.mdx) property [`stylesheets`](../configuration/configuration-object.mdx#stylesheets).
|
||||||
|
|
||||||
|
## CSS Presets
|
||||||
|
|
||||||
|
CSS presets like [Normalize.css](https://necolas.github.io/normalize.css/) and [Reset CSS](https://meyerweb.com/eric/tools/css/reset/) can be selected in [external resources](./external-resources.mdx#css-presets) screen.
|
||||||
|
|
||||||
|
## Stylesheets Imported in Script Editor
|
||||||
|
|
||||||
|
### External Stylesheets
|
||||||
|
|
||||||
|
CSS stylesheets imported in the script editor are added to the [result page](./result.mdx) `head` element. _The URL has to end with **`.css` extension**_.
|
||||||
|
|
||||||
|
For example, adding this in the script editor (JavaScript):
|
||||||
|
|
||||||
|
```js
|
||||||
|
import 'https://unpkg.com/github-markdown-css/github-markdown.css';
|
||||||
|
```
|
||||||
|
|
||||||
|
adds this to the page `head`:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<link rel="stylesheet" href="https://unpkg.com/github-markdown-css/github-markdown.css" />
|
||||||
|
```
|
||||||
|
|
||||||
|
Currently, compiling imported stylesheets (e.g. SCSS) is not supported.
|
||||||
|
|
||||||
|
Similar to [imports in style editor](#style-imports), bare imports are converted to full URLs from CDN.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import 'github-markdown-css/github-markdown.css';
|
||||||
|
```
|
||||||
|
|
||||||
|
becomes:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<link rel="stylesheet" href="https://unpkg.com/github-markdown-css/github-markdown.css" />
|
||||||
|
```
|
||||||
|
|
||||||
|
### `./style.css`
|
||||||
|
|
||||||
|
Importing the URLs (`./style.css` or `./styles.css`) gets the style editor compiled/processed CSS **string** as the module's default export.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import styles from './style.css';
|
||||||
|
|
||||||
|
console.log(styles); // => compiled CSS as string
|
||||||
|
```
|
||||||
|
|
||||||
|
## CSS Modules
|
||||||
|
|
||||||
|
CSS modules are supported and are [documented separately](../languages/cssmodules.mdx).
|
||||||
|
|
||||||
|
## CSS Frameworks
|
||||||
|
|
||||||
|
Multiple CSS frameworks are supported including [Tailwind CSS](../languages/tailwindcss.mdx), [UnoCSS](../languages/unocss.mdx) and [WindiCSS](../languages/windicss.mdx).
|
||||||
|
|
||||||
|
## Styles in Markup & Script
|
||||||
|
|
||||||
|
Of course, styles and stylesheets can still be added as usual in markup and script editors (via HTML elements and/or DOM).
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [Projects](./projects.mdx)
|
||||||
|
- [External resources](./external-resources.mdx)
|
||||||
|
- [Module resolution](./module-resolution.mdx)
|
||||||
70
docs/docs/features/data-urls.mdx
Normal file
70
docs/docs/features/data-urls.mdx
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
# Data URLs
|
||||||
|
|
||||||
|
> **Data URLs**, URLs prefixed with the `data:` scheme, allow content creators to embed small files inline in documents.
|
||||||
|
>
|
||||||
|
> — [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URLs)
|
||||||
|
|
||||||
|
Sometimes, you need to use an external file (e.g. script, stylesheet) that is not hosted online. In this case, you can use data URLs to embed the file in your code. These can then be used similar to regular URLs (e.g. for `<script src>`, `<link href>`, import URL, etc.).
|
||||||
|
|
||||||
|
LiveCodes UI allows creating and consuming these data URLs.
|
||||||
|
|
||||||
|
## Creating data URLs
|
||||||
|
|
||||||
|
Data URLs can be created from:
|
||||||
|
|
||||||
|
### Assets
|
||||||
|
|
||||||
|
For local files on user's device.
|
||||||
|
|
||||||
|
[Assets screen](./assets.mdx) can be accessed from Settings menu → Assets. This works for any file type, including text files (e.g. stylesheets or scripts) and binary files like images. Generated data URLs are saved locally in the user's browser storage and are available across projects.
|
||||||
|
|
||||||
|
### "Copy code as data URL" button
|
||||||
|
|
||||||
|
For code in code editor.
|
||||||
|
|
||||||
|
The button can be found in the editor toolbar, below the code editor. This copies the code of the active editor as data URL to the clipboard.
|
||||||
|
|
||||||
|
The content is base64-encoded. Unicode content is appropriately encoded (see [The "Unicode Problem"](https://developer.mozilla.org/en-US/docs/Glossary/Base64#the_unicode_problem)).
|
||||||
|
|
||||||
|
## Consuming data URLs
|
||||||
|
|
||||||
|
Data URLs can be used anywhere you use a regular URL (e.g. for `<script src>`, `<link href>`, import URL, etc.).
|
||||||
|
|
||||||
|
In addition, LiveCodes supports [importing](./import.mdx) data URLs, like other URLs. If the language is detected, it is loaded in the appropriate editor (e.g. `data:text/typescript;charset=UTF-8;base64,....` is detected as TypeScript).
|
||||||
|
|
||||||
|
:::caution
|
||||||
|
|
||||||
|
Depending on the browser, there may be [length limitations](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URLs#common_problems) on URLs. So, it is generally recommended to use data URLs for small files.
|
||||||
|
|
||||||
|
For large files, it is better to host these online. LiveCodes allows hosting assets on [GitHub Pages](https://pages.github.com/) (see [assets](./assets.mdx)).
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
If we add this this in script editor:
|
||||||
|
|
||||||
|
```js
|
||||||
|
export const sayHello = (name) => 'Hello ' + name;
|
||||||
|
```
|
||||||
|
|
||||||
|
then copy it as data URL, we will get:
|
||||||
|
|
||||||
|
`data:text/javascript;charset=UTF-8;base64,ZXhwb3J0IGNvbnN0IHNheUhlbGxvID0gKG5hbWUpID0+ICdIZWxsbyAnICsgbmFtZTs=`.
|
||||||
|
|
||||||
|
This can be used (e.g. in another project) like this:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { sayHello } from 'data:text/javascript;charset=UTF-8;base64,ZXhwb3J0IGNvbnN0IHNheUhlbGxvID0gKG5hbWUpID0+ICdIZWxsbyAnICsgbmFtZTs=';
|
||||||
|
|
||||||
|
console.log(sayHello('Ali'));
|
||||||
|
```
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [Data URLs (MDN)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URLs)
|
||||||
|
- [Assets](./assets.mdx)
|
||||||
|
- [Import](./import.mdx)
|
||||||
|
- [External Resources](./external-resources.mdx)
|
||||||
|
- [Module resolution](./module-resolution.mdx)
|
||||||
|
- [CSS](./css.mdx)
|
||||||
22
docs/docs/features/default-template-language.mdx
Normal file
22
docs/docs/features/default-template-language.mdx
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# Default Template/Language
|
||||||
|
|
||||||
|
When the app is loaded, by default, the last used [language](../languages/index.mdx) is selected.
|
||||||
|
|
||||||
|
The app can also be configured to load a default [user template](./templates.mdx#user-templates).
|
||||||
|
|
||||||
|
If you do not already have any user templates, save any loaded project as template:
|
||||||
|
|
||||||
|
Project menu → Save as → Template.
|
||||||
|
|
||||||
|
Then, in the user templates screen (Project menu → New ... → My Templates), find your template and click "Set as default".
|
||||||
|
|
||||||
|
If you wish to clear that selection, find the default template in user templates and click "unset".
|
||||||
|
|
||||||
|
If you want to temporarily not load the default template/language add the [query param](../configuration/query-params.mdx) `no-defaults`.
|
||||||
|
|
||||||
|
Example: https://livecodes.io?no-defaults
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [Templates](./templates.mdx)
|
||||||
|
- [Query params](../configuration/query-params.mdx)
|
||||||
47
docs/docs/features/default-view.mdx
Normal file
47
docs/docs/features/default-view.mdx
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
# Default View
|
||||||
|
|
||||||
|
import LiveCodes from '../../src/components/LiveCodes.tsx';
|
||||||
|
|
||||||
|
The playground can be loaded in one of the following views:
|
||||||
|
|
||||||
|
## `split`
|
||||||
|
|
||||||
|
Both the code editor and the result page are visible. This is the default.
|
||||||
|
|
||||||
|
Example: https://livecodes.io/?view=split
|
||||||
|
|
||||||
|
Demo:
|
||||||
|
|
||||||
|
<LiveCodes config={{ view: 'split' }}></LiveCodes>
|
||||||
|
|
||||||
|
## `editor`
|
||||||
|
|
||||||
|
The code editor is visible, while the result page is collapsed. The result page can be shown by dragging the split gutter, or clicking the "Toggle Result" button.
|
||||||
|
|
||||||
|
Example: https://livecodes.io/?view=editor
|
||||||
|
|
||||||
|
Demo:
|
||||||
|
|
||||||
|
<LiveCodes config={{ view: 'editor' }}></LiveCodes>
|
||||||
|
|
||||||
|
## `result`
|
||||||
|
|
||||||
|
The result page is visible, while the code editor is collapsed. The code editor can be shown by dragging the split gutter, or clicking one of the editor tabs.
|
||||||
|
|
||||||
|
Example: https://livecodes.io/?view=result
|
||||||
|
|
||||||
|
Demo:
|
||||||
|
|
||||||
|
<LiveCodes config={{ view: 'result' }}></LiveCodes>
|
||||||
|
|
||||||
|
## Display Mode vs Default View
|
||||||
|
|
||||||
|
:::info
|
||||||
|
|
||||||
|
"[Display Mode](./display-modes.mdx)" is different from "Default View".
|
||||||
|
|
||||||
|
In `editor` display mode, only the editor is loaded and the result page is not available. While `editor` default view shows the editor by default, and the result page can be shown by dragging the split gutter.
|
||||||
|
|
||||||
|
The same applies for `result` display mode and default view.
|
||||||
|
|
||||||
|
:::
|
||||||
28
docs/docs/features/deploy.mdx
Normal file
28
docs/docs/features/deploy.mdx
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# Deploy
|
||||||
|
|
||||||
|
The result page (of any number of projects) can be deployed and hosted at [GitHub Pages](https://pages.github.com/) (a free service from GitHub for hosting static websites). This requires login with a [GitHub account](./github-integration.mdx).
|
||||||
|
|
||||||
|
The `Deploy` screen can be accessed from the Project menu → Deploy.
|
||||||
|
|
||||||
|
import RunInLiveCodes from '../../src/components/RunInLiveCodes.tsx';
|
||||||
|
|
||||||
|
<RunInLiveCodes params={{ screen: 'deploy' }} linkText="direct link" />
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
The result page (and optionally the source code) is pushed to `gh-pages` branch of a **public** GitHub repo (new or existing). The page, shortly, becomes available on `https://{user}.github.io/{repo}/`.
|
||||||
|
|
||||||
|
If an existing repo is selected, the content of the `gh-pages` branch (if existing) is replaced by the deployed content.
|
||||||
|
|
||||||
|
If the option `Commit source code` is enabled, the source code will be deployed to the directory `/src`.
|
||||||
|
|
||||||
|
The code for the result page (and source code) is deployed as separate files for markup (`/index.html`), styles (`style.css`) and script (`script.js`). This allows re-use of these resources in other projects. Of course, multiple projects can be deloyed and linked to each other to act like a multi-page website.
|
||||||
|
|
||||||
|
The LiveCodes app will remember the repo used to deploy each project, so that later updates to the project can be deployed to the same repo.
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [Export](./export.mdx)
|
||||||
|
- [Share](./share.mdx)
|
||||||
|
- [Broadcast](./broadcast.mdx)
|
||||||
|
- [GitHub integration](./github-integration.mdx)
|
||||||
134
docs/docs/features/display-modes.mdx
Normal file
134
docs/docs/features/display-modes.mdx
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
# Display Modes
|
||||||
|
|
||||||
|
import LiveCodes from '../../src/components/LiveCodes.tsx';
|
||||||
|
|
||||||
|
The [configuration](../configuration/configuration-object.mdx) option [`mode`](../configuration/configuration-object.mdx#mode), also available as [query param](../configuration/query-params.mdx), can be used to select different display modes.
|
||||||
|
The following display modes are supported:
|
||||||
|
|
||||||
|
## `full`
|
||||||
|
|
||||||
|
This is the default mode with toolbars, editor and result panes.
|
||||||
|
|
||||||
|
Example: https://livecodes.io/?template=react
|
||||||
|
|
||||||
|
Screenshot: (App in full mode)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Demo: (Embedded playground in full mode)
|
||||||
|
|
||||||
|
<LiveCodes template="react"></LiveCodes>
|
||||||
|
|
||||||
|
## `focus`
|
||||||
|
|
||||||
|
This hides most of UI buttons and menus and keeps only the essential elements: editors, editor titles, result page, console, and run and share buttons. It can be toggled during runtime from the full mode through the UI from a button in the lower left corner. Also the query param `?mode=focus`.
|
||||||
|
|
||||||
|
Example: https://livecodes.io/?template=react&mode=focus
|
||||||
|
|
||||||
|
Screenshot: (focus mode)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## `simple`
|
||||||
|
|
||||||
|
This mode is mainly useful for embedded playgrounds.
|
||||||
|
It shows only 1 editor with the output (result page +/- console). The content of other editors can be set using [SDK](../sdk/index.mdx) [config](../configuration/configuration-object.mdx) even though the editors are not shown.
|
||||||
|
By default, `codemirror` editor is used, however, this can be changed by the [`editor`](../configuration/configuration-object.mdx#editor) option.
|
||||||
|
By default, the layout is `responsive` but can also be overridden by the [`layout`](../configuration/configuration-object.mdx#layout) option to `vertical` or `horizontal`.
|
||||||
|
|
||||||
|
Demo: JS with console
|
||||||
|
|
||||||
|
<LiveCodes
|
||||||
|
params={{ mode: 'simple', js: 'console.log("hello world")', layout: 'vertical', console: 'full' }}
|
||||||
|
></LiveCodes>
|
||||||
|
|
||||||
|
Demo: JSX & Result page (Monaco editor, add CSS)
|
||||||
|
|
||||||
|
export const simpleConfig = {
|
||||||
|
mode: 'simple',
|
||||||
|
layout: 'vertical',
|
||||||
|
activeEditor: 'script',
|
||||||
|
editor: 'monaco',
|
||||||
|
tools: { status: 'none' },
|
||||||
|
script: {
|
||||||
|
language: 'jsx',
|
||||||
|
content: `import { atom, useAtom } from 'jotai';\n\nconst countAtom = atom(0);\n\nconst Counter = () => {\n const [count, setCount] = useAtom(countAtom);\n const inc = () => setCount((c) => c + 1);\n return (\n <>\n {count} <button onClick={inc}>+1</button>\n </>\n );\n};\n\nconst App = () => (\n <div className="App">\n <h1>Hello Jotai</h1>\n <h2>Enjoy coding!</h2>\n <Counter />\n </div>\n);\n\nexport default App;\n`,
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
language: 'css',
|
||||||
|
content: '.App {\n font-family: sans-serif;\n text-align: center;\n}\n'.trimStart(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
<LiveCodes config={simpleConfig} height="400px"></LiveCodes>
|
||||||
|
|
||||||
|
## `lite`
|
||||||
|
|
||||||
|
Loads a light-weight, minimal code editor, with limited playground features.
|
||||||
|
See the section about [lite mode](./lite.mdx) for details
|
||||||
|
|
||||||
|
Example: https://livecodes.io/?mode=lite&template=react
|
||||||
|
|
||||||
|
Demo:
|
||||||
|
|
||||||
|
<LiveCodes config={{ mode: 'lite' }} template="react"></LiveCodes>
|
||||||
|
|
||||||
|
## `editor`
|
||||||
|
|
||||||
|
Hides the results pane and works as editor only.
|
||||||
|
|
||||||
|
Example: https://livecodes.io/?mode=editor&template=react
|
||||||
|
|
||||||
|
Demo:
|
||||||
|
|
||||||
|
<LiveCodes config={{ mode: 'editor' }} template="react"></LiveCodes>
|
||||||
|
|
||||||
|
## `codeblock`
|
||||||
|
|
||||||
|
A read-only mode showing only the code block without editor interface. On mouse-over a copy button appears that allows to copy the code. This is specially useful when embedded.
|
||||||
|
|
||||||
|
Example: https://livecodes.io/?mode=codeblock&template=react
|
||||||
|
|
||||||
|
Demo:
|
||||||
|
|
||||||
|
<LiveCodes config={{ mode: 'codeblock' }} template="react"></LiveCodes>
|
||||||
|
|
||||||
|
By default, in `codeblock` mode, the light-weight `CodeJar` editor is used (in read-only mode). You can override this by setting the `editor` option. Refer to [Editor Settings](./editor-settings.mdx#code-editor) for details.
|
||||||
|
|
||||||
|
Example: https://livecodes.io/?mode=codeblock&editor=monaco&template=react
|
||||||
|
|
||||||
|
Demo:
|
||||||
|
|
||||||
|
<LiveCodes config={{ mode: 'codeblock', editor: 'monaco' }} template="react"></LiveCodes>
|
||||||
|
|
||||||
|
## `result`
|
||||||
|
|
||||||
|
Shows the result page only, with a drawer at the bottom (which can be closed) that allows opening the project in the full playground.
|
||||||
|
|
||||||
|
Example: https://livecodes.io/?mode=result&template=react
|
||||||
|
|
||||||
|
Demo:
|
||||||
|
|
||||||
|
<LiveCodes params={{ mode: 'result', template: 'react' }}></LiveCodes>
|
||||||
|
|
||||||
|
The tools pane (e.g. console/compiled code viewer) is hidden by default in `result` mode. It can be shown if set to `open` or `full`. Refer to [Tools pane](./tools-pane.mdx) documentation for details.
|
||||||
|
|
||||||
|
Example: https://livecodes.io/?mode=result&tools=console|full&&js=console.log("Hello%20World!")
|
||||||
|
|
||||||
|
Demo:
|
||||||
|
|
||||||
|
<LiveCodes
|
||||||
|
params={{ mode: 'result', tools: 'console|full', js: 'console.log("Hello World!")' }}
|
||||||
|
></LiveCodes>
|
||||||
|
|
||||||
|
## Display Mode vs Default View
|
||||||
|
|
||||||
|
:::info
|
||||||
|
|
||||||
|
"Display Mode" is different from "[Default View](./default-view.mdx)".
|
||||||
|
|
||||||
|
In `editor` display mode, only the editor is loaded and the result page is not available. While `editor` default view shows the editor by default, and the result page can be shown by dragging the split gutter.
|
||||||
|
|
||||||
|
The same applies for `result` display mode and default view.
|
||||||
|
|
||||||
|
:::
|
||||||
71
docs/docs/features/editor-settings.mdx
Normal file
71
docs/docs/features/editor-settings.mdx
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
# Editor Settings
|
||||||
|
|
||||||
|
LiveCodes allows a lot of flexibility for configuring which code editor to use and its settings.
|
||||||
|
|
||||||
|
`Editor Settings` screen can be accessed from Settings menu → Editor Settings.
|
||||||
|
|
||||||
|
import RunInLiveCodes from '../../src/components/RunInLiveCodes.tsx';
|
||||||
|
|
||||||
|
<RunInLiveCodes params={{ screen: 'editor-settings' }} linkText="direct link" />
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
A preview code editor is displayed to preview the settings in real time.
|
||||||
|
|
||||||
|
The settings selected in the `Editor Settings` screen are saved locally to [user settings](./user-settings.mdx) and are used subsequently. These include:
|
||||||
|
|
||||||
|
### Enable AI Code Assistant
|
||||||
|
|
||||||
|
Enables the [AI code assistant](./ai.mdx). (Free and no account required)
|
||||||
|
|
||||||
|
### Code Editor
|
||||||
|
|
||||||
|
The following code editors are supported:
|
||||||
|
|
||||||
|
- [**Monaco Editor**](https://microsoft.github.io/monaco-editor/): This is the code editor that powers [**VS Code**](https://code.visualstudio.com/). It is [feature-rich](https://code.visualstudio.com/docs/editor/codebasics) and supports autocomplete with [**IntelliSense**](https://code.visualstudio.com/docs/editor/intellisense) (including [types for custom libraries](./intellisense.mdx)). However, it requires a relatively large download and is not supported in mobile browsers.
|
||||||
|
- [**CodeMirror**](https://codemirror.net/): Has [many editing features](https://codemirror.net/docs/extensions/), including autocomplete, with good **mobile support**.
|
||||||
|
- [**CodeJar**](https://medv.io/codejar/): A **lightweight** code editor with very basic editing features. [PrismJs](https://prismjs.com/) is used for syntax highlighting. Please note that some editor settings are not supported in CodeJar (see below).
|
||||||
|
|
||||||
|
This can be configured using the [`editor`](../configuration/configuration-object.mdx#editor) configuration option.
|
||||||
|
|
||||||
|
By default, Monaco editor is used on desktop, CodeMirror is used on mobile and CodeJar is used in [codeblocks](./display-modes.mdx#codeblock), in [lite mode](./lite.mdx) and in [readonly](../configuration/configuration-object.mdx#readonly) playgrounds.
|
||||||
|
|
||||||
|
### Editor Options
|
||||||
|
|
||||||
|
These include:
|
||||||
|
|
||||||
|
- [Editor theme](../configuration/configuration-object.mdx#editortheme)
|
||||||
|
- [Font family](../configuration/configuration-object.mdx#fontfamily)
|
||||||
|
- [Font size](../configuration/configuration-object.mdx#fontsize)
|
||||||
|
- [Indentation](../configuration/configuration-object.mdx#usetabs) (Spaces/Tabs)
|
||||||
|
- [Tab size](../configuration/configuration-object.mdx#tabsize)
|
||||||
|
- [Line numbers](../configuration/configuration-object.mdx#linenumbers)
|
||||||
|
- [Word-wrap](../configuration/configuration-object.mdx#wordwrap)
|
||||||
|
- [Auto-close brackets and quotes](../configuration/configuration-object.mdx#closebrackets)
|
||||||
|
- [Fold (collapse) regions](../configuration/configuration-object.mdx#foldregions)
|
||||||
|
|
||||||
|
### Emmet
|
||||||
|
|
||||||
|
Allows using [**Emmet**](https://emmet.io/) [abbreviations and actions](https://docs.emmet.io/). See [`emmet`](../configuration/configuration-object.mdx#emmet) configuration option.
|
||||||
|
|
||||||
|
(Not supported in CodeJar)
|
||||||
|
|
||||||
|
### Editor Modes
|
||||||
|
|
||||||
|
Allows using [**Vim**](https://vimhelp.org/) and [**Emacs**](https://www.gnu.org/software/emacs/manual/html_node/emacs/Basic.html) keyboard bindings. See [`editorMode`](../configuration/configuration-object.mdx#editormode) configuration option.
|
||||||
|
|
||||||
|
(Not supported in CodeJar)
|
||||||
|
|
||||||
|
### Format Options
|
||||||
|
|
||||||
|
These are [**Prettier**](https://prettier.io/) [configuration options](https://prettier.io/docs/en/options.html) used for code formatting.
|
||||||
|
|
||||||
|
In addition to those specified in [Editor Options](#editor-options), the following options are available:
|
||||||
|
|
||||||
|
- [Use Semicolons](../configuration/configuration-object.mdx#semicolons)
|
||||||
|
- [Use Single Quotes](../configuration/configuration-object.mdx#singlequote)
|
||||||
|
- [Use Trailing Commas](../configuration/configuration-object.mdx#trailingcomma)
|
||||||
101
docs/docs/features/embeds.mdx
Normal file
101
docs/docs/features/embeds.mdx
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
# Embedded Playgrounds
|
||||||
|
|
||||||
|
import LiveCodes from '../../src/components/LiveCodes.tsx';
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
LiveCodes playgrounds can be embedded in any web page. The playground can be [prefilled with code](./code-prefill.mdx) in any supported language. This can be very useful in documentation websites, technical blogs, educational websites and others.
|
||||||
|
|
||||||
|
Demo:
|
||||||
|
|
||||||
|
<LiveCodes template="javascript"></LiveCodes>
|
||||||
|
|
||||||
|
The embedding web page can communicate with the playground using a powerful [SDK](../sdk/index.mdx) (e.g. edit/format code, watch for code changes, get the compiled code or result page HTML, run tests, change layout, ...etc).
|
||||||
|
|
||||||
|
## Create Embedded Playground
|
||||||
|
|
||||||
|
### App Embed Screen
|
||||||
|
|
||||||
|
In the [standalone app](../getting-started.mdx#standalone-app), the Embed Screen can be accessed from Project menu → Embed.
|
||||||
|
|
||||||
|
import RunInLiveCodes from '../../src/components/RunInLiveCodes.tsx';
|
||||||
|
|
||||||
|
<RunInLiveCodes params={{ screen: 'embed' }} linkText="direct link" />
|
||||||
|
|
||||||
|
It shows a preview of the embedded playground, allows customizations of [embed options](../sdk/js-ts.mdx#embed-options) and provides generated code that can be added to the web page that will embed the playground.
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
:::info Note
|
||||||
|
|
||||||
|
Please note that the Embed Screen sends the project code to [LiveCodes share service](./share.mdx) to generate a short URL for usage in the embed code.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
The setting "Embed Type" allows selection from different variations of the generated code:
|
||||||
|
|
||||||
|
- Using the SDK from CDN.
|
||||||
|
- Using the SDK with a bundler (e.g. vite, parcel, webpack, etc).
|
||||||
|
- Using the React SDK.
|
||||||
|
- Using the Vue SDK.
|
||||||
|
- Using iframe and [query params](../configuration/query-params.mdx).
|
||||||
|
- Using HTML code that the SDK can use to [auto-prefill](./code-prefill.mdx#auto-prefill-from-page-dom) the playground.
|
||||||
|
|
||||||
|
### SDK
|
||||||
|
|
||||||
|
The LiveCodes [SDK](../sdk/index.mdx) can be used to embed playgrounds, specify [embed](../sdk/js-ts.mdx#embed-options) and [configuration](../configuration/index.mdx) options and allows communication with the embedded playground with many [SDK methods](../sdk/js-ts.mdx#sdk-methods).
|
||||||
|
|
||||||
|
This method provides more control and allows advanced scenarios.
|
||||||
|
|
||||||
|
## Avoid Breaking Changes
|
||||||
|
|
||||||
|
To avoid breaking changes that would cause the embedded playgrounds to stop working as expected with later updates, follow these recommendations:
|
||||||
|
|
||||||
|
- Use a [permanent URL](./permanent-url.mdx) to a pinned version of the LiveCodes app for [`EmbedOptions.appUrl`](../sdk/js-ts.mdx#appurl). The code generated in the Embed screen uses that by default.
|
||||||
|
- Specify the version of the SDK used. The code generated in the Embed screen also does that.
|
||||||
|
- For project code, [specify the versions](./module-resolution.mdx#package-version) of the imported packages and [external resources](./external-resources.mdx). [Custom import maps](./module-resolution.mdx#custom-module-resolution) can be set to control the module import behavior.
|
||||||
|
|
||||||
|
Check the [Permanent URL](./permanent-url.mdx) section for more details.
|
||||||
|
|
||||||
|
## Differences from Full App
|
||||||
|
|
||||||
|
Some of the features of the full standalone app are not available or shown by default in embedded playgrounds, either because of security reasons, being not useful when embedded or because of space limitations.
|
||||||
|
|
||||||
|
### Features Not Available
|
||||||
|
|
||||||
|
- All features that require saving/loading from browser storage:
|
||||||
|
e.g. [projects](./projects.mdx), [assets](./assets.mdx), [code snippets](./snippets.mdx), [user settings](./user-settings.mdx), [default template/language](./default-template-language.mdx), [recover unsaved](./recover.mdx), [backup/restore](./backup-restore.mdx).
|
||||||
|
- All features that require authentication:
|
||||||
|
e.g. [login/logout](./github-integration.mdx), [sync](./sync.mdx), [deploy](./deploy.mdx), [importing](./import.mdx) from private github repos.
|
||||||
|
- [Broadcast](./broadcast.mdx).
|
||||||
|
- App menus.
|
||||||
|
- Some tools in [tools pane](./tools-pane.mdx):
|
||||||
|
e.g. open result page in new window, broadcast status.
|
||||||
|
- [Welcome screen](./welcome.mdx).
|
||||||
|
|
||||||
|
### Features Not Shown by Default
|
||||||
|
|
||||||
|
- [External resources](./external-resources.mdx) button (below the editor) and external resources screen are only shown if the loaded project has external resources (e.g. via [`EmbedOptions.config.stylesheets`](../configuration/configuration-object.mdx#stylesheets) and [`EmbedOptions.config.scripts`](../configuration/configuration-object.mdx#scripts)).
|
||||||
|
- [Tests](./tests.mdx) are not shown in [tools pane](./tools-pane.mdx) unless the loaded project has tests (e.g. via [`EmbedOptions.config.tests`](../configuration/configuration-object.mdx#tests)). Test editor is not available.
|
||||||
|
- Loading [starter templates](./templates.mdx) can be achieved by the [SDK](../sdk/index.mdx) ([`EmbedOptions.template`](../sdk/js-ts.mdx#template)), not from the UI.
|
||||||
|
- [Importing](./import.mdx) from external sources can be achieved by the [SDK](../sdk/index.mdx) ([`EmbedOptions.import`](../sdk/js-ts.mdx#import)), not from the UI.
|
||||||
|
- Getting a [share](./share.mdx) URL can be achieved by the [SDK](../sdk/index.mdx) ([`getShareUrl`](../sdk/js-ts.mdx#getshareurl) method), not from the UI.
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
- All user code, [result page](./result.mdx) and compilers run in [sandboxed iframes](https://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/) with a unique origin.
|
||||||
|
|
||||||
|
- Embedded playgrounds do not have access to the parent page, or to sensitive data like user cookies and localstorage of the embedding page origin. Communications with the SDK occur by means of [`postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage) calls.
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [SDK](../sdk/index.mdx)
|
||||||
|
- [Code prefill](./code-prefill.mdx)
|
||||||
|
- [Configuration](../configuration/index.mdx)
|
||||||
|
- [Embed options](../sdk/js-ts.mdx#embed-options)
|
||||||
|
- [SDK methods](../sdk/js-ts.mdx#sdk-methods)
|
||||||
|
- [Permanent URL](./permanent-url.mdx)
|
||||||
|
- [Lite mode](./lite.mdx)
|
||||||
|
- [Read-only](./read-only.mdx)
|
||||||
1
docs/docs/features/emmet.mdx
Normal file
1
docs/docs/features/emmet.mdx
Normal file
@ -0,0 +1 @@
|
|||||||
|
# Emmet Support
|
||||||
45
docs/docs/features/export.mdx
Normal file
45
docs/docs/features/export.mdx
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
# Export
|
||||||
|
|
||||||
|
## Exporting A Single Project
|
||||||
|
|
||||||
|
Project export can be accessed from the Project menu → Export.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Any project can be exported to:
|
||||||
|
|
||||||
|
- **Project (JSON):** a JSON file containing project [configuration object](../configuration/configuration-object.mdx). This can be used to later [import](./import.mdx#import-exported-livecodes-projects) that project on the same or a different device or to share a copy of the project with others.
|
||||||
|
- **Source (ZIP):** a zip file containing the project configuration file as JSON, in addition to the source code in separate files. This can be useful for opening the code in an external IDE.
|
||||||
|
- **Result (HTML):** [result page](./result.mdx) as a single html file. Can be used for the purpose of demo or deploy.
|
||||||
|
- **GitHub gist** (_requires login with [GitHub account](./github-integration.mdx)_): creates a **public** GitHub gist on the user's GitHub account containing the source code as separate files.
|
||||||
|
- **CodePen:** creates a [CodePen](https://codepen.io/) prefilled with the project code. If the used [languages/frameworks](./../languages/index.mdx) are not supported in CodePen (e.g. Astro, Svelte, Python, ...etc), the compiled code is exported so that it continues to work there. [Bare module imports](./module-resolution.mdx) are converted to esm imports, for example:
|
||||||
|
|
||||||
|
```js
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
becomes:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import React from 'https://cdn.skypack.dev/react';
|
||||||
|
```
|
||||||
|
|
||||||
|
- **JSFiddle:** creates a [JSFiddle](https://jsfiddle.net/) prefilled with the project code. Exported code may be modified like with CodePen (see above).
|
||||||
|
|
||||||
|
## Exporting Multiple Projects
|
||||||
|
|
||||||
|
Multiple projects can be exported in bulk from the [Saved Projects](./projects.mdx) screen (Project menu → Open) using the button `Export All`.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
This produces a JSON file containing an array of project configuration objects. They can be later imported in the same or a different device using the `Bulk Import` functionality in the [Import screen](./import.mdx#import-exported-livecodes-projects).
|
||||||
|
|
||||||
|
All the currently visible projects will be exported. If projects are filtered (e.g. by language, tag or search query), only the shown projects are exported.
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [Projects](./projects.mdx)
|
||||||
|
- [Import](./import.mdx)
|
||||||
|
- [Backup/Restore](./backup-restore.mdx)
|
||||||
|
- [Sync](./sync.mdx)
|
||||||
|
- [Share](./share.mdx)
|
||||||
51
docs/docs/features/external-resources.mdx
Normal file
51
docs/docs/features/external-resources.mdx
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
# External Resources
|
||||||
|
|
||||||
|
## Stylesheets and Scripts
|
||||||
|
|
||||||
|
URLs to external CSS stylesheets and JS scripts can be added to the page from the UI using the Project menu → External Resources. In addition, there is a button to the External Resources in the toolbar below the editors.
|
||||||
|
|
||||||
|
import RunInLiveCodes from '../../src/components/RunInLiveCodes.tsx';
|
||||||
|
|
||||||
|
<RunInLiveCodes params={{ screen: 'resources' }} linkText="direct link" />
|
||||||
|
|
||||||
|
URLs to stylesheets/scripts should be added each in a separate line.
|
||||||
|
|
||||||
|
Stylesheets and scripts are loaded in the [result page](./result.mdx) before editor codes. Thus, CSS properties defined in external stylesheets can be overridden in the style editor. Global javascript variables defined in external scripts are available to code in the script editor.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Importing and Exporting code to other services (e.g. Codepen and Github gists) takes into consiedration the external resources.
|
||||||
|
|
||||||
|
## Search for NPM Packages
|
||||||
|
|
||||||
|
Package search allows finding NPM Packages and adding URLs to default scripts/stylesheets (hosted by [jsDelivr](https://www.jsdelivr.com/)). Specific package version can be specified.
|
||||||
|
|
||||||
|
Examples for search terms:
|
||||||
|
|
||||||
|
```
|
||||||
|
jque
|
||||||
|
|
||||||
|
jquery
|
||||||
|
|
||||||
|
jquery@3
|
||||||
|
|
||||||
|
jquery@3.6
|
||||||
|
|
||||||
|
jquery@3.6.3
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Fonts
|
||||||
|
|
||||||
|
Fonts can be added from [Google fonts](https://fonts.google.com/).
|
||||||
|
|
||||||
|
## CSS Presets
|
||||||
|
|
||||||
|
CSS presets currently include [Normalize.css](https://necolas.github.io/normalize.css/) and [Reset CSS](https://meyerweb.com/eric/tools/css/reset/).
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [Module resolution](./module-resolution.mdx)
|
||||||
|
- [Assets](./assets.mdx)
|
||||||
43
docs/docs/features/github-integration.mdx
Normal file
43
docs/docs/features/github-integration.mdx
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# GitHub Integration
|
||||||
|
|
||||||
|
Generally, LiveCodes can be used anonymously without any accounts. This includes [importing](./import.mdx) code from GitHub gists or public repos.
|
||||||
|
|
||||||
|
However, some features do require [login](./user-management.mdx) with a GitHub account and giving [specific permissions](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/scopes-for-oauth-apps#available-scopes) to make use of GitHub services (e.g. [import](./import.mdx) from private repos, [export](./export.mdx) to gist, [deploy](./deploy.mdx), [assets](./assets.mdx) and [sync](./sync.mdx)).
|
||||||
|
|
||||||
|
:::caution cookies
|
||||||
|
|
||||||
|
User authentication is handled using [Firebase Authentication](https://firebase.google.com/products/auth) which **may use cookies**. By logging in, you agree that cookies may be stored on your device.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Features that require GitHub Account
|
||||||
|
|
||||||
|
### Public Repos
|
||||||
|
|
||||||
|
Access to public repos is required for:
|
||||||
|
|
||||||
|
- [Deploy](./deploy.mdx): A new public repo is created (if required) and code is pushed to the branch `gh-pages` of the repo. The is deployed on [GitHub pages](https://pages.github.com/).
|
||||||
|
- [Assets](./assets.mdx): can be stored on a public repo published on [GitHub pages](https://pages.github.com/).
|
||||||
|
|
||||||
|
### Private Repos
|
||||||
|
|
||||||
|
Access to private repos is required to:
|
||||||
|
|
||||||
|
- [Import](./import.mdx) code from private repos.
|
||||||
|
- [Sync](./sync.mdx) LiveCodes data to a private repo.
|
||||||
|
|
||||||
|
### Gists
|
||||||
|
|
||||||
|
Access to gists is required to:
|
||||||
|
|
||||||
|
- [Export](./export.mdx) projects to GitHub gist.
|
||||||
|
|
||||||
|
## Setting Permissions
|
||||||
|
|
||||||
|
GitHub user permissions for LiveCodes app are set the first time the user logs in. Any subsequent login will use the first permissions, even if they are set differently.
|
||||||
|
|
||||||
|
To change previously set permissions:
|
||||||
|
|
||||||
|
- [Logout](./user-management.mdx) from the LiveCodes app.
|
||||||
|
- [Revoke permissions](https://docs.github.com/en/apps/oauth-apps/using-oauth-apps/reviewing-your-authorized-oauth-applications) of LiveCodes app in your GitHub account.
|
||||||
|
- [Login](./user-management.mdx) again in LiveCodes and set the new permissions.
|
||||||
40
docs/docs/features/i18n.mdx
Normal file
40
docs/docs/features/i18n.mdx
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
# Internationalization (i18n)
|
||||||
|
|
||||||
|
import LiveCodes from '../../src/components/LiveCodes.tsx';
|
||||||
|
|
||||||
|
LiveCodes currently supports UI internationalization. By default, the UI language will be automatically detected based on your browser settings.
|
||||||
|
|
||||||
|
You can easily switch between supported UI languages using the i18n menu, allowing you to explore and use LiveCodes in your preferred language!
|
||||||
|
|
||||||
|
If you are interested in contributing to the translation of LiveCodes, please refer to the [i18n Contribution Guide](https://github.com/live-codes/livecodes/blob/develop/docs/docs/contribution/i18n.mdx).
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Demo: ([Embedded playground](./embeds.mdx) with `appLanguage: 'zh-CN'`)
|
||||||
|
|
||||||
|
<LiveCodes template="javascript" config={{ appLanguage: 'zh-CN' }}></LiveCodes>
|
||||||
|
|
||||||
|
## Using SDK
|
||||||
|
|
||||||
|
Set the [configuration object](../configuration/configuration-object.mdx) property [`appLanguage`](../configuration/configuration-object.mdx#applanguage) to a supported language code.
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { createPlayground } from 'livecodes';
|
||||||
|
|
||||||
|
createPlayground('#container', { template: 'javascript', config: { appLanguage: 'auto' } });
|
||||||
|
```
|
||||||
|
|
||||||
|
## Using query params
|
||||||
|
|
||||||
|
Add the [query parameter](../configuration/query-params.mdx) `appLanguage` with your preferred language code.
|
||||||
|
|
||||||
|
https://livecodes.io?template=javascript&appLanguage=fr
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [User Settings](./user-settings.mdx)
|
||||||
|
- [Editor Settings](./editor-settings.mdx)
|
||||||
|
- [Query params](../configuration/query-params.mdx)
|
||||||
|
- [i18n Contribution Guide](https://github.com/live-codes/livecodes/blob/develop/docs/docs/contribution/i18n.mdx)
|
||||||
199
docs/docs/features/import.mdx
Normal file
199
docs/docs/features/import.mdx
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
# Import
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
LiveCodes supports importing code from a wide variety of [sources](#sources). This can be achieved using one of the following methods:
|
||||||
|
|
||||||
|
### UI
|
||||||
|
|
||||||
|
The Import screen can be accessed from the Project menu → Import.
|
||||||
|
|
||||||
|
import RunInLiveCodes from '../../src/components/RunInLiveCodes.tsx';
|
||||||
|
|
||||||
|
<RunInLiveCodes params={{ screen: 'import' }} linkText="direct link" />
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Query Param
|
||||||
|
|
||||||
|
A URL of any of the [sources](#sources) can be imported by adding it as a value to [query param](../configuration/query-params.mdx) key: `x`.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
https://livecodes.io/?x=https://gist.github.com/f01deb828a42f363502fbae7964d48e9
|
||||||
|
|
||||||
|
### Bookmarklet
|
||||||
|
|
||||||
|
Instead of manually copy/pasting URLs to import, adding [**"Edit in LiveCodes"** bookmarklet](../bookmarklet.mdx) to the browser bookmarks bar can be a more convenient way. It opens LiveCodes in a new window and imports the current webpage URL.
|
||||||
|
|
||||||
|
### SDK
|
||||||
|
|
||||||
|
For [embedded playgrounds](./embeds.mdx), use the [SDK](../sdk/index.mdx) property [`EmbedOptions.import`](../sdk/js-ts.mdx#import).
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
- GitHub File:
|
||||||
|
|
||||||
|
URL: https://github.com/lodash/lodash/blob/master/isObject.js
|
||||||
|
|
||||||
|
[Open in LiveCodes](https://livecodes.io/?x=https://github.com/lodash/lodash/blob/master/isObject.js)
|
||||||
|
|
||||||
|
- GitHub Directory:
|
||||||
|
|
||||||
|
URL: https://github.com/bradtraversy/50projects50days/tree/master/expanding-cards
|
||||||
|
|
||||||
|
[Open in LiveCodes](https://livecodes.io/?x=https://github.com/bradtraversy/50projects50days/tree/master/expanding-cards)
|
||||||
|
|
||||||
|
- GitHub Gist:
|
||||||
|
|
||||||
|
URL: https://gist.github.com/f01deb828a42f363502fbae7964d48e9
|
||||||
|
|
||||||
|
[Open in LiveCodes](https://livecodes.io/?x=https://gist.github.com/f01deb828a42f363502fbae7964d48e9)
|
||||||
|
|
||||||
|
- JS Bin:
|
||||||
|
|
||||||
|
URL: https://jsbin.com/iwovaj/73/embed?html,js,output
|
||||||
|
|
||||||
|
[Open in LiveCodes](https://livecodes.io/?x=https://jsbin.com/iwovaj/73/embed?html,js,output)
|
||||||
|
|
||||||
|
- Vue Playground:
|
||||||
|
|
||||||
|
URL: [https://play.vuejs.org/#eNp9kUFKAzEUhq/yyKYKtUW6K9OCli4UUVFxlU2Z...](https://play.vuejs.org/#eNp9kUFKAzEUhq/yyKYKtUW6K9OCli4UUVFxlU2Zvk5TM0lIXsbCMGdw7QG8g+fxAl7Bl5RWF9Jd3v//7+cLrxUXzg2aiGIsilB65QgCUnRTaVTtrCdoweMKOlh5W0OPoz1ppCmtCQR1qGCS/JPejWpwZpcY4Ov94/vzDZ45eSpNMdzVciEPhLXTC0KeAIr1+bRtc0nXFUOesqqMiwTNWc1teiIF+1KwVQwP26IvKDDCSlWDTbCG6du0K0Vpa6c0+jtHihGlGEN2krfQ2r5eZ418xP5eL9dYvvyjb8I2aVLcewzoG5Ti4NHCV0g7e/54i1t+H0wmj5rTR8wHDFbHxLiLXUazZOw/uUx7lW+gTPUU5ltCE/afSqAp2eW8FHyX2ZGv/+KOBqO8J00nuh/8Wasi)
|
||||||
|
|
||||||
|
[Open in LiveCodes](https://livecodes.io/?x=https%3A%2F%2Fplay.vuejs.org%2F%23eNp9kUFKAzEUhq%2FyyKYKtUW6K9OCli4UUVFxlU2Zvk5TM0lIXsbCMGdw7QG8g%2BfxAl7Bl5RWF9Jd3v%2F%2F7%2BcLrxUXzg2aiGIsilB65QgCUnRTaVTtrCdoweMKOlh5W0OPoz1ppCmtCQR1qGCS%2FJPejWpwZpcY4Ov94%2FvzDZ45eSpNMdzVciEPhLXTC0KeAIr1%2BbRtc0nXFUOesqqMiwTNWc1teiIF%2B1KwVQwP26IvKDDCSlWDTbCG6du0K0Vpa6c0%2BjtHihGlGEN2krfQ2r5eZ418xP5eL9dYvvyjb8I2aVLcewzoG5Ti4NHCV0g7e%2F54i1t%2BH0wmj5rTR8wHDFbHxLiLXUazZOw%2FuUx7lW%2BgTPUU5ltCE%2FafSqAp2eW8FHyX2ZGv%2F%2BKOBqO8J00nuh%2F8Wasi)
|
||||||
|
|
||||||
|
## Sources
|
||||||
|
|
||||||
|
Import is supported from any of the following:
|
||||||
|
|
||||||
|
- GitHub gist
|
||||||
|
- GitHub file
|
||||||
|
- Directory in a GitHub repo
|
||||||
|
- Gitlab snippet
|
||||||
|
- Gitlab file
|
||||||
|
- Directory in a Gitlab repo
|
||||||
|
- JS Bin
|
||||||
|
- [Shared projects](./share.mdx)
|
||||||
|
- Raw code
|
||||||
|
- Code in web page DOM
|
||||||
|
- Local file(s)
|
||||||
|
- Code in zip file (Local or URL)
|
||||||
|
- Code in image - OCR (Local or URL)
|
||||||
|
- Projects shared in official playgrounds of [TypeScript](https://www.typescriptlang.org/play) and [Vue](https://play.vuejs.org/)
|
||||||
|
- [Exported project JSON](./export.mdx) (single project and bulk import)
|
||||||
|
|
||||||
|
Import sources are identified by URL patterns (e.g. origin, pathname and extension).
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
Local files can be imported from the "Import Screen" or by dragging and dropping the file(s) in the editor.
|
||||||
|
:::
|
||||||
|
|
||||||
|
## File Selection
|
||||||
|
|
||||||
|
For sources that provide multiple files (e.g. GitHub/GitLab directories, GitHub gists, GitLab snippets and local files), a best guess is tried to load files in respective editors. Best results are when there are 3 files and each file is in a language (identified by file extension) that can be loaded to a different editor, for example:
|
||||||
|
|
||||||
|
- index.html, style.css, script.js
|
||||||
|
- default.pug, app.scss, main.ts
|
||||||
|
|
||||||
|
The following file names are given higher priority:
|
||||||
|
|
||||||
|
- Markup files starting with `index.` or `default.`
|
||||||
|
- Style files starting with `style.` or `styles.`
|
||||||
|
- Script files starting with `script.`, `app.`, `main.` or `index.`
|
||||||
|
|
||||||
|
While README, markdown files and files with no extension are given lower priority.
|
||||||
|
|
||||||
|
Alternatively, files can be specified using the `files` [query param](../configuration/query-params.mdx). It takes a **comma-separated list** of filenames. The first 3 found files are loaded. If 1 or 2 files are specified, only these will be loaded. The first matching file is shown by default in the active editor.
|
||||||
|
|
||||||
|
The query params should have the following format:
|
||||||
|
`?x={url}&files={file1},{file2},{file3}`
|
||||||
|
|
||||||
|
Example:
|
||||||
|
`?x={url}&files=Counter.tsx,counter.scss,counter.html`
|
||||||
|
|
||||||
|
The active editor can be specified using the [`activeEditor`](../configuration/configuration-object.mdx#activeeditor) (or its alias `active`) [query param](../configuration/query-params.mdx). It takes the name of the editor (`markup`, `style` or `script`) or its ID (`0`, `1` or `2`) to be shown by default.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
`?x={url}&activeEditor=style` or `?x={url}&active=1`
|
||||||
|
|
||||||
|
## Import Shared Projects
|
||||||
|
|
||||||
|
[Shared Projects](./share.mdx) can be imported using the value of the query param `x` generated by the Share screen. This starts with either:
|
||||||
|
|
||||||
|
- `code/`: for compressed base64-encoded project config
|
||||||
|
- `id/`: for short URLs recognized by shared project id.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
https://livecodes.io/?x=id/bi9qszw86w3
|
||||||
|
|
||||||
|
## Import Code from DOM
|
||||||
|
|
||||||
|
If the source URL does not match one of the supported origins (GitHub, GitLab and JS Bin), the URL is fetched, its response text is parsed as [DOM](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model) and code is extracted from elements that match specific CSS selectors.
|
||||||
|
(By default: `.livecodes [data-lang="{language}"]`)
|
||||||
|
|
||||||
|
:::info Example
|
||||||
|
|
||||||
|
```html
|
||||||
|
<code class="livecodes">
|
||||||
|
<pre data-lang="html">This is identified as <strong>HTML</strong> code</pre>
|
||||||
|
</code>
|
||||||
|
```
|
||||||
|
|
||||||
|
The HTML editor is prefilled with: `This is identified as <strong>HTML</strong> code`
|
||||||
|
|
||||||
|
Please note that the code should be html-encoded to avoid interference with the HTML of the page.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
https://livecodes.io/?x=https://live-codes.github.io/livecodes-examples/prefill-from-code-blocks.html
|
||||||
|
|
||||||
|
Alternatively, custom CSS selectors can be specified using [query params](../configuration/query-params.mdx):
|
||||||
|
`?x={url}&{language}-selector={selector}`
|
||||||
|
|
||||||
|
The following example loads the content of the first element that matches the CSS selector `h3` as `html`:
|
||||||
|
|
||||||
|
https://livecodes.io/?html-selector=h3&x=https://live-codes.github.io/livecodes-examples/prefill-from-code-blocks.html
|
||||||
|
|
||||||
|
Of course, [embedded playgrounds](./embeds.mdx) can be prefilled with code from the same embedding page. This works well for documentation and educational websites.
|
||||||
|
|
||||||
|
[This is a demo](https://live-codes.github.io/livecodes-examples/prefill-from-code-blocks.html) for automatic extraction of code blocks to prefill editors by creating "Edit in LiveCodes" links. Also embedded editors are prefilled from the code blocks. ([View source](https://github.com/live-codes/livecodes-examples/blob/master/prefill-from-code-blocks.html))
|
||||||
|
|
||||||
|
## Import Raw Code
|
||||||
|
|
||||||
|
If the response text could not be parsed as DOM or no elements matched the CSS selectors, it is assumed to be raw code and the response text is loaded to editor. If the URL ends with an extension it is used to identify the language, otherwise it is assumed to be `html`.
|
||||||
|
|
||||||
|
Alternatively, the language of raw code can be specified using [query params](../configuration/query-params.mdx):
|
||||||
|
`?x={url}&raw={language}`
|
||||||
|
|
||||||
|
## Import from CodePen
|
||||||
|
|
||||||
|
Currently, CodePen API does not allow directly importing code from Pens. However, you can export any saved Pen as a [zip file](https://blog.codepen.io/documentation/exporting-pens/#export-zip-1) or [Github gist](https://blog.codepen.io/documentation/exporting-pens/#save-as-github-gist-2) and then import it to LiveCodes. The format that Codepen exports is well understood by LiveCodes. Most Pens can be imported with no or minimal changes.
|
||||||
|
|
||||||
|
**Note:** External resources (styles/scripts) are not exported with source code in zip file export of CodePen. However, export to GitHub gist does export these. So if a Pen with external resources exported as zip file is not imported properly, try exporting to GitHub gist or manually add the [external resources](./external-resources.mdx).
|
||||||
|
|
||||||
|
## Import Code from Image (OCR)
|
||||||
|
|
||||||
|
Code can be extracted from images (local or via URL) using [Tesseract.js](https://github.com/naptha/tesseract.js), a library for Optical Character Recognition (OCR).
|
||||||
|
To ensure accurate identification, the text in the image should be clear, have high contrast against the background, and be free from unrelated text.
|
||||||
|
Language detection is performed using [highlight.js](https://highlightjs.readthedocs.io/en/latest/api.html#highlightauto), which makes its best guess based on the content.
|
||||||
|
|
||||||
|
Best results are obtained when the image is generated using LiveCodes "[Code to Image](./code-to-image.mdx)" feature.
|
||||||
|
|
||||||
|
## Import Exported LiveCodes Projects
|
||||||
|
|
||||||
|
A [single project exported as JSON](./export.mdx#exporting-a-single-project) can be imported in the same or a different device from the import screen under the tab "Import Project JSON". The JSON file can be supplied as a local file upload or from a URL.
|
||||||
|
|
||||||
|
Similarly, [multiple projects exported in bulk](./export.mdx#exporting-multiple-projects) can be imported from the tab "Bulk Import".
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [Code prefill](./code-prefill.mdx)
|
||||||
|
- [Export](./export.mdx)
|
||||||
|
- [External resources](./external-resources.mdx)
|
||||||
|
- [Module resolution](./module-resolution.mdx)
|
||||||
|
- [Projects](./projects.mdx)
|
||||||
103
docs/docs/features/index.mdx
Normal file
103
docs/docs/features/index.mdx
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
---
|
||||||
|
sidebar_class_name: exclude_from_sidebar
|
||||||
|
---
|
||||||
|
|
||||||
|
# Features
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
_LiveCodes_ is an open-source, client-side, code playground that runs in the browser. It enables quick prototyping and experimenting with a wide variety of [technologies](../languages/index.mdx) (including 90+ languages, frameworks and processors) without having to manually setup a development environment for each. The [result](./result.mdx) is displayed as a regular web page. The rapid feedback of previewing the result page without waiting for build steps significantly boosts productivity.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
In this page, a quick overview of the important features are presented. A more detailed description of each feature is described in the following sections.
|
||||||
|
|
||||||
|
## Powerful Editor
|
||||||
|
|
||||||
|
The default code editor is the powerful editor that powers [VS Code](https://code.visualstudio.com/), featuring code-completion, go-to-definition, multi-cursor support and other powerful features you got used to. The editor is very [customizable](./editor-settings.mdx). It supports [keyboard shortcuts](./keyboard-shortcuts.mdx), [code formatting](./code-format.mdx), [Emmet abbreviations](./editor-settings.mdx#emmet) and even [Vim and Emacs bindings](./editor-settings.mdx#editor-modes).
|
||||||
|
|
||||||
|
## AI Code Assistant
|
||||||
|
|
||||||
|
LiveCodes supports AI-powered code completion, totally for **free**, using [Codeium](https://codeium.com/), the ultrafast Copilot alternative. Install the [Codeium chrome extension](https://codeium.com/chrome_tutorial) and enjoy the magic!
|
||||||
|
|
||||||
|
## Mobile-friendly
|
||||||
|
|
||||||
|
The responsive layout allows working on devices with different screen sizes. On mobile, a lighter-weight touch-friendly code editor (CodeMirror 6) is used, so that you can experiment your ideas on the go.
|
||||||
|
|
||||||
|
## External Code/Libraries
|
||||||
|
|
||||||
|
[External scripts/stylesheets](./external-resources.mdx) can be added to the web page. There is a UI screen that helps you search for and add NPM libraries and google fonts. Moreover, [NPM modules can be imported](./module-resolution.mdx) without the need for any `npm install`s.
|
||||||
|
|
||||||
|
## Import and Code Pre-fill
|
||||||
|
|
||||||
|
Code can be [imported](./import.mdx) from a variety of sources including GitHub gist, GitHub file, directory in a GitHub repo, Gitlab snippet, Gitlab file, directory in a Gitlab repo, JS Bin, raw code, code in web page DOM and code in zip file. You can also [pre-fill code](./code-prefill.mdx) using various ways.
|
||||||
|
|
||||||
|
## Share/Export
|
||||||
|
|
||||||
|
Projects can be easily [shared](./share.mdx) as URLs or QR codes. In addition, you may [export](./export.mdx) any project as HTML, JSON or zip file containing source code files. You may also export to other services like GitHub gists, CodePen or JSFiddle.
|
||||||
|
|
||||||
|
## Embed
|
||||||
|
|
||||||
|
Projects can be [embedded](./embeds.mdx) in any web page. The embed screen allows you to customize the embed options and preview the resulting playground. An easy-to-use, yet powerful, [SDK](../sdk/index.mdx), that allows [communication](../sdk/js-ts.mdx#sdk-methods) between the embedding page and the playground.
|
||||||
|
|
||||||
|
## Deploy
|
||||||
|
|
||||||
|
Projects can be [deployed](./deploy.mdx) to public URLs that can be shared with others. This is hosted for free on GitHub Pages.
|
||||||
|
|
||||||
|
## Starter Templates
|
||||||
|
|
||||||
|
A large number of [starter templates](./templates.mdx) are available. They can be used to get you started with most of the supported technologies.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Assets
|
||||||
|
|
||||||
|
Your own local assets (e.g. images, icons, fonts, local scripts and stylesheets) can be added to the app and then used in any project. The assets are made available even when the projects are shared, exported or deployed.
|
||||||
|
|
||||||
|
## Dev Tools
|
||||||
|
|
||||||
|
[Tools](./tools-pane.mdx) like [console](./console.mdx), [compiled code viewer](./compiled-code.mdx) and [test runner](./tests.mdx) can significantly improve your development experience.
|
||||||
|
|
||||||
|
## Broadcast
|
||||||
|
|
||||||
|
You can [broadcast](./broadcast.mdx) source code or result in real-time to others. This can be of great value as an educational tool and for demo purposes.
|
||||||
|
|
||||||
|
## Sync/Backup/Restore
|
||||||
|
|
||||||
|
Do you work on multiple devices? No Problem! You may [sync](./sync.mdx), [backup and restore](./backup-restore.mdx) your data any time on any device.
|
||||||
|
|
||||||
|
## Themes
|
||||||
|
|
||||||
|
LiveCodes comes with dark and light themes. In addition, a theme color can be set to change the app color.
|
||||||
|
|
||||||
|
## i18n
|
||||||
|
|
||||||
|
LiveCodes supports [internationalization](./i18n.mdx) for multiple languages.
|
||||||
|
|
||||||
|
## Client-side!
|
||||||
|
|
||||||
|
LiveCodes runs in the browser, where all the processing/transpilation occurs, with no server rounds required. So, after the initial load, it becomes pretty fast. It can be hosted on any static file server or CDN. No `npm install`s. Just the browser!
|
||||||
|
|
||||||
|
## Developer-friendly
|
||||||
|
|
||||||
|
LiveCodes makes it easy to [get started](../getting-started.mdx). It is highly [configurable](../configuration/index.mdx). Lots of features can be configured by URL [query params](../configuration/query-params.mdx). The [SDK](../sdk/index.mdx) facilitates [embedding](./embeds.mdx) playgrounds and allows easy [communication](../sdk/js-ts.mdx#sdk-methods) with them. The SDK is available for use in [JS/TS](../sdk/js-ts.mdx), [React](../sdk/react.mdx) [Vue](../sdk/vue.mdx) and [Svelte](../sdk/svelte.mdx).
|
||||||
|
|
||||||
|
## Comprehensive Documentations
|
||||||
|
|
||||||
|
Rich documentations with screenshots, code samples and live demos are available. They cover the app [features](../features/index.mdx), [configuration](../configuration/index.mdx), [supported languages](../languages/index.mdx) and [SDK](../sdk/index.mdx) (including [TypeScript Types](../api/globals.md)). A gallery of usage examples is provided as a [storybook](pathname:///../stories).
|
||||||
|
|
||||||
|
## Focused on Privacy
|
||||||
|
|
||||||
|
Projects are private by default. The code you write in LiveCodes never leaves your computer, unless you choose to [share](./share.mdx), [export](./export.mdx), [broadcast](./broadcast.mdx) or [sync](./sync.mdx) it. User data is stored in the browser.
|
||||||
|
|
||||||
|
## Free and Open-Source
|
||||||
|
|
||||||
|
LiveCodes is free, with no limits for use and no ads.
|
||||||
|
No account is even required (unless [GitHub integration](./github-integration.mdx) is needed).
|
||||||
|
Do you want to [self-host](./self-hosting.mdx) it for commercial use? No problem! It is [MIT-licensed](../license.mdx) 🎉. Please consider [sponsoring LiveCodes](../sponsor.mdx) ❤.
|
||||||
|
|
||||||
|
This was a quick overview of the important features of LiveCodes. A more detailed description of each feature is described in the following sections.
|
||||||
1
docs/docs/features/integrations.mdx
Normal file
1
docs/docs/features/integrations.mdx
Normal file
@ -0,0 +1 @@
|
|||||||
|
# Integrations
|
||||||
165
docs/docs/features/intellisense.mdx
Normal file
165
docs/docs/features/intellisense.mdx
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
# IntelliSense
|
||||||
|
|
||||||
|
import LiveCodes from '../../src/components/LiveCodes.tsx';
|
||||||
|
|
||||||
|
The [code editor](./editor-settings.mdx#code-editor) provides a rich experience with [intellisense](https://code.visualstudio.com/docs/editor/intellisense) and autocompletion. Many of the features required for this are based on TypeScript types that are either inferred by the editor or supplied as data definition files.
|
||||||
|
|
||||||
|
This not only works when the editor language is TypeScript, but also works with others like JavaScript and JSX.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Types for imported npm packages
|
||||||
|
|
||||||
|
LiveCodes will try to automatically find type definitions for npm modules imported in the editor.
|
||||||
|
|
||||||
|
These are examples for automatically loading React types with autocomplete and hover info:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## TypeScript TwoSlash
|
||||||
|
|
||||||
|
The code editor supports [TypeScript TwoSlash](https://github.com/microsoft/TypeScript-Website/tree/v2/packages/ts-twoslasher). This can be very useful for debugging, sharing and teaching TypeScript.
|
||||||
|
|
||||||
|
This is supported in [JavaScript](../languages/javascript.mdx), [TypeScript](../languages/typescript.mdx), [JSX](../languages/jsx.mdx) and [TSX](../languages/tsx.mdx). This also includes [Babel](../languages/babel.mdx), [Sucrase](../languages/sucrase.mdx), [Solid](../languages/solid.mdx), [React Native](../languages/react-native.mdx), etc.
|
||||||
|
|
||||||
|
 <!-- http://127.0.0.1:8080/?x=id/npgxgngikwj -->
|
||||||
|
|
||||||
|
 <!-- http://127.0.0.1:8080/?x=id/c9ttudp5b4x -->
|
||||||
|
|
||||||
|
## Custom Types
|
||||||
|
|
||||||
|
If no type definitions are found, or if you want to provide your own (e.g. for a module that is not hosted on npm), custom type definition files can be used.
|
||||||
|
|
||||||
|
In the standalone app, these can be provided in [custom settings](../advanced/custom-settings.mdx) using the `types` property. This takes an object with the key representing the module name and the value representing the URL of the file.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```json title="Custom Settings"
|
||||||
|
{
|
||||||
|
"types": {
|
||||||
|
"my-module": "https://cdn.jsdelivr.net/npm/my-module@1.0.0/types/my-module.d.ts",
|
||||||
|
"my-other-module": "https://my-website.com/my-other-module/my-other-module.d.ts"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
For embedded playgrounds, these can be provided in the [configuration object](../configuration/configuration-object.mdx) using the [`types`](../configuration/configuration-object.mdx#types) property.
|
||||||
|
|
||||||
|
This can be combined with the [`imports`](../configuration/configuration-object.mdx#imports) property to provide [importmap](./module-resolution.mdx#custom-module-resolution) for runtime implementation of your custom modules.
|
||||||
|
|
||||||
|
This is an example of how to create a playground that provides the implementation of the custom module: `my-module` and its type definition to provide editor intellisense:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { createPlayground } from 'livecodes';
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
activeEditor: 'script',
|
||||||
|
script: {
|
||||||
|
language: 'javascript',
|
||||||
|
content: `import { foo } from 'my-module';\n\nconsole.log(foo());`
|
||||||
|
};
|
||||||
|
imports: {
|
||||||
|
'my-module': 'https://my-website.com/my-module/index.js',
|
||||||
|
},
|
||||||
|
types: {
|
||||||
|
'my-module': 'https://my-website.com/my-module/my-module.d.ts',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
createPlayground('#container', {config});
|
||||||
|
```
|
||||||
|
|
||||||
|
Please note that the URLs used for `types` and `imports` properties may be full URLs or [data URLs](./data-urls.mdx).
|
||||||
|
|
||||||
|
This can be of great use for library authors who want to provide playgrounds for documenting their libraries that are not (yet) published to npm.
|
||||||
|
|
||||||
|
## Demo
|
||||||
|
|
||||||
|
Let's assume we have this TypeScript module:
|
||||||
|
|
||||||
|
```ts title="Greeter.ts"
|
||||||
|
export class Greeter {
|
||||||
|
private morningGreetings = ['Good morning', 'Have a good day', 'How are you today?'];
|
||||||
|
private eveningGreetings = ['Good evening', 'Good night', 'Sleep well'];
|
||||||
|
|
||||||
|
private randomSelector(array: string[]) {
|
||||||
|
return array[Math.floor(Math.random() * array.length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
public morning() {
|
||||||
|
return this.randomSelector(this.morningGreetings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public evening() {
|
||||||
|
return this.randomSelector(this.eveningGreetings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
which compiles to this JavaScript:
|
||||||
|
|
||||||
|
```js title="Greeter.js"
|
||||||
|
export class Greeter {
|
||||||
|
constructor() {
|
||||||
|
this.morningGreetings = ['Good morning', 'Have a good day', 'How are you today?'];
|
||||||
|
this.eveningGreetings = ['Good evening', 'Good night', 'Sleep well'];
|
||||||
|
}
|
||||||
|
randomSelector(array) {
|
||||||
|
return array[Math.floor(Math.random() * array.length)];
|
||||||
|
}
|
||||||
|
morning() {
|
||||||
|
return this.randomSelector(this.morningGreetings);
|
||||||
|
}
|
||||||
|
evening() {
|
||||||
|
return this.randomSelector(this.eveningGreetings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
and this type definition:
|
||||||
|
|
||||||
|
```ts title="Greeter.d.ts"
|
||||||
|
export declare class Greeter {
|
||||||
|
private morningGreetings;
|
||||||
|
private eveningGreetings;
|
||||||
|
private randomSelector;
|
||||||
|
morning(): string;
|
||||||
|
evening(): string;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The JavaScript output (Greeter.js) and the data definition file (Greeter.d.ts) should be hosted online or converted to data URLs (see [assets](./assets.mdx) and [data URLs](./data-urls.mdx)).
|
||||||
|
|
||||||
|
Then, they can be used like that:
|
||||||
|
|
||||||
|
export const customModules = {
|
||||||
|
editor: 'monaco',
|
||||||
|
activeEditor: 'script',
|
||||||
|
script: {
|
||||||
|
language: 'typescript',
|
||||||
|
content:
|
||||||
|
"import { Greeter } from 'my-greeter';\n\nconst greeter = new Greeter();\n// now `greeter` has autocomplete\n\ndocument.body.innerText = greeter.morning();\n\n// this should show error in the editor\n// Property 'morningGreetings' is private and only accessible within class 'Greeter'\nconsole.log(greeter.morningGreetings);",
|
||||||
|
},
|
||||||
|
imports: {
|
||||||
|
'my-greeter':
|
||||||
|
'data:text/javascript;charset=UTF-8;base64,ZXhwb3J0IGNsYXNzIEdyZWV0ZXIgew0KICAgIGNvbnN0cnVjdG9yKCkgew0KICAgICAgICB0aGlzLm1vcm5pbmdHcmVldGluZ3MgPSBbJ0dvb2QgbW9ybmluZycsICdIYXZlIGEgZ29vZCBkYXknLCAnSG93IGFyZSB5b3UgdG9kYXk/J107DQogICAgICAgIHRoaXMuZXZlbmluZ0dyZWV0aW5ncyA9IFsnR29vZCBldmVuaW5nJywgJ0dvb2QgbmlnaHQnLCAnU2xlZXAgd2VsbCddOw0KICAgIH0NCiAgICByYW5kb21TZWxlY3RvcihhcnJheSkgew0KICAgICAgICByZXR1cm4gYXJyYXlbTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogYXJyYXkubGVuZ3RoKV07DQogICAgfQ0KICAgIG1vcm5pbmcoKSB7DQogICAgICAgIHJldHVybiB0aGlzLnJhbmRvbVNlbGVjdG9yKHRoaXMubW9ybmluZ0dyZWV0aW5ncyk7DQogICAgfQ0KICAgIGV2ZW5pbmcoKSB7DQogICAgICAgIHJldHVybiB0aGlzLnJhbmRvbVNlbGVjdG9yKHRoaXMuZXZlbmluZ0dyZWV0aW5ncyk7DQogICAgfQ0KfQ0K',
|
||||||
|
},
|
||||||
|
types: {
|
||||||
|
'my-greeter':
|
||||||
|
'data:text/typescript;charset=UTF-8;base64,ZXhwb3J0IGRlY2xhcmUgY2xhc3MgR3JlZXRlciB7DQogIHByaXZhdGUgbW9ybmluZ0dyZWV0aW5nczsNCiAgcHJpdmF0ZSBldmVuaW5nR3JlZXRpbmdzOw0KICBwcml2YXRlIHJhbmRvbVNlbGVjdG9yOw0KICBtb3JuaW5nKCk6IHN0cmluZzsNCiAgZXZlbmluZygpOiBzdHJpbmc7DQp9DQo=',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
<LiveCodes config={customModules} height="80vh" />
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [Module Resolution](./module-resolution.mdx)
|
||||||
|
- [Data Urls](./data-urls.mdx)
|
||||||
|
- [Assets](./assets.mdx)
|
||||||
|
- [Custom Settings](../advanced/custom-settings.mdx)
|
||||||
|
- [Configuration Object](../configuration/configuration-object.mdx)
|
||||||
7
docs/docs/features/keyboard-shortcuts.mdx
Normal file
7
docs/docs/features/keyboard-shortcuts.mdx
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# Keyboard Shortcuts
|
||||||
|
|
||||||
|
Many commands can be executed from the keyboard using keyboard shortcuts. The full list can be found in the [Keyboard Shortcuts screen](https://livecodes.io/?screen=keyboard-shortcuts), which can be accessed from the Help Menu or from the [command menu](./command-menu.mdx) by pressing <kbd>Ctrl</kbd> + <kbd>K</kbd> (or <kbd>⌘</kbd> + <kbd>K</kbd> on Mac) and searching for "Keyboard Shortcuts".
|
||||||
|
|
||||||
|
The code editor shortcuts are the same as VS Code, which can be found [here](https://code.visualstudio.com/docs/getstarted/keybindings#_basic-editing).
|
||||||
|
|
||||||
|

|
||||||
31
docs/docs/features/lite.mdx
Normal file
31
docs/docs/features/lite.mdx
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
# Lite Mode
|
||||||
|
|
||||||
|
import LiveCodes from '../../src/components/LiveCodes.tsx';
|
||||||
|
|
||||||
|
In case you need to embed a playground in your web page to show case some code and expect users to mainly read through the code and to have just minor edits, it would be an overkill to load full-blown code editors with auto-complete and code formatting, specially if you want to embed more than one playground in the same page. That's why the LiveCodes playground has a lite mode.
|
||||||
|
|
||||||
|
In lite mode, a light-weight, minimal code editor is used ([CodeJar](./editor-settings.mdx#code-editor)). [Emmet abbreviations](./emmet.mdx) and [tools pane](./tools-pane.mdx) are not available. However, any language supported by LiveCodes can be used, with syntax highlighting. Code edits are compiled and shown in the [result page](./result.mdx) as usual.
|
||||||
|
|
||||||
|
Demo:
|
||||||
|
|
||||||
|
<LiveCodes template="react" config={{ mode: 'lite' }}></LiveCodes>
|
||||||
|
|
||||||
|
## Using SDK
|
||||||
|
|
||||||
|
Set [`EmbedOptions.config.mode`](../configuration/configuration-object.mdx#mode) to `"lite"`.
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { createPlayground } from 'livecodes';
|
||||||
|
|
||||||
|
createPlayground('#container', { config: { mode: 'lite' } });
|
||||||
|
```
|
||||||
|
|
||||||
|
## Using query params
|
||||||
|
|
||||||
|
Add the [query parameter](../configuration/query-params.mdx) `?mode=lite`.
|
||||||
|
|
||||||
|
https://livecodes.io?mode=lite
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [Read-only](./read-only.mdx).
|
||||||
9
docs/docs/features/mobile.mdx
Normal file
9
docs/docs/features/mobile.mdx
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# Mobile Support
|
||||||
|
|
||||||
|
LiveCodes provides a responsive layout that adapts to different screen sizes. Don't wait to be on your desk. Try your ideas on the go!
|
||||||
|
|
||||||
|
Projects that you create on mobile can be easily [shared](./share.mdx) or [synchronized](./sync.mdx) across devices. You can even share using QR code.
|
||||||
|
|
||||||
|
 <!-- https://yujinyeoh.com/website-mockup-generator -->
|
||||||
|
|
||||||
|
By default, LiveCodes uses the touch-friendly [CodeMirror 6](https://codemirror.net/) editor on mobile. This is configurable in the [editor settings](./editor-settings.mdx) and can be changed at any time.
|
||||||
265
docs/docs/features/module-resolution.mdx
Normal file
265
docs/docs/features/module-resolution.mdx
Normal file
@ -0,0 +1,265 @@
|
|||||||
|
# Module Resolution
|
||||||
|
|
||||||
|
import LiveCodes from '../../src/components/LiveCodes.tsx';
|
||||||
|
|
||||||
|
## NPM Modules
|
||||||
|
|
||||||
|
### Bare Module Imports
|
||||||
|
|
||||||
|
In LiveCodes you can use node-style bare module imports for npm modules like you do in your local development. However, there are no installation or build steps required.
|
||||||
|
|
||||||
|
e.g. consider the following code:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
|
document.body.innerHTML = v4();
|
||||||
|
```
|
||||||
|
|
||||||
|
If you run it directly in the browser, you get this error:
|
||||||
|
|
||||||
|
```
|
||||||
|
Uncaught TypeError: Failed to resolve module specifier "uuid". Relative references must start with either "/", "./", or "../".
|
||||||
|
```
|
||||||
|
|
||||||
|
However, in LiveCodes, bare module imports are transformed to full URLs that are imported from CDN (by default: [esm.sh](https://esm.sh/)) which provides ESM versions of NPM packages.
|
||||||
|
|
||||||
|
`import { v4 } from 'uuid';` <br /> becomes <br />
|
||||||
|
`import { v4 } from 'https://esm.sh/uuid';`
|
||||||
|
|
||||||
|
This is made possible by using [import maps](https://github.com/WICG/import-maps).
|
||||||
|
|
||||||
|
<p id="npm-modules-demo1">Demo:</p>
|
||||||
|
|
||||||
|
<LiveCodes
|
||||||
|
params={{ js: "import { v4 } from 'uuid';\n\ndocument.body.innerHTML = v4();" }}
|
||||||
|
></LiveCodes>
|
||||||
|
|
||||||
|
<p> </p>
|
||||||
|
|
||||||
|
You can import from React like that:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { useState } from 'react';
|
||||||
|
```
|
||||||
|
|
||||||
|
Demo:
|
||||||
|
|
||||||
|
<LiveCodes template="react"></LiveCodes>
|
||||||
|
|
||||||
|
It just works without a build step and without you having to worry about. And when you [export your project](./export.mdx) to another service (e.g. CodePen) or as HTML, the full URL imports are used, so your code continues to work.
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
It is recommended to use this method for dependencies over using [external scripts](./external-resources.mdx). The dependencies are explicitly stated in the code. And if you move to a local development environment, your bundler will take care of importing them and doing other optimizations like [tree-shaking](https://developer.mozilla.org/en-US/docs/Glossary/Tree_shaking).
|
||||||
|
:::
|
||||||
|
|
||||||
|
### CommonJS Modules
|
||||||
|
|
||||||
|
CommonJS module `require`s are also supported (they are converted to ESM imports).
|
||||||
|
|
||||||
|
So this also works (although not recommended - use ESM imports instead):
|
||||||
|
|
||||||
|
```js
|
||||||
|
const { v4 } = require('uuid');
|
||||||
|
|
||||||
|
document.body.innerHTML = v4();
|
||||||
|
```
|
||||||
|
|
||||||
|
Exercise:
|
||||||
|
|
||||||
|
Copy the previous code snippet and paste it in the playground below. Check the generated code in the compiled code viewer.
|
||||||
|
|
||||||
|
<LiveCodes params={{ activeEditor: 'script', compiled: 'open' }}></LiveCodes>
|
||||||
|
|
||||||
|
:::info
|
||||||
|
|
||||||
|
Script code that contains `import`, `export` or `require` gets served in a script tag with [`type="module"`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules).
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
### NPM Package Search
|
||||||
|
|
||||||
|
NPM packages can be searched and added as script tags from the [External Resources](./external-resources.mdx) screen.
|
||||||
|
|
||||||
|
## Deno Modules
|
||||||
|
|
||||||
|
Modules imported from [deno.land/x](https://deno.land/x) (or any other URL ending in `.ts`, `.jsx` or `.tsx`) are automatically transpiled (ts -> js) and bundled by [bundlejs](https://bundlejs.com/) (using [esbuild](https://esbuild.github.io/)), including their relative imports. The project on LiveCodes that imports these modules does not need to be using TypeScript.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { uuid } from 'https://deno.land/x/uuid/mod.ts';
|
||||||
|
|
||||||
|
document.body.innerHTML = uuid();
|
||||||
|
```
|
||||||
|
|
||||||
|
[Open in LiveCodes](<https://livecodes.io/?js=import%20%7B%20uuid%20%7D%20from%20'https%3A%2F%2Fdeno.land%2Fx%2Fuuid%2Fmod.ts'%3B%0A%0Adocument.body.innerHTML%20%3D%20uuid()%3B>)
|
||||||
|
|
||||||
|
## JSR Modules
|
||||||
|
|
||||||
|
Modules can be imported from [jsr.io](https://jsr.io/) using the prefix `jsr:`. The project on LiveCodes that imports these modules does not need to be using TypeScript.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { yassify } from 'jsr:@kwhinnery/yassify';
|
||||||
|
|
||||||
|
document.body.innerHTML = yassify('Hello, World!');
|
||||||
|
```
|
||||||
|
|
||||||
|
[Open in LiveCodes](<https://livecodes.io/?js=import%20%7B%20yassify%20%7D%20from%20'jsr%3A%40kwhinnery%2Fyassify'%3B%0A%0Adocument.body.innerHTML%20%3D%20yassify('Hello%2C%20World!')%3B>)
|
||||||
|
|
||||||
|
## GitHub/GitLab/Bitbucket
|
||||||
|
|
||||||
|
Modules can also be similarly imported from GitHub, Gitlab or Bitbucket. Also these imports are transpiled and bundled (see [Deno Modules](#deno-modules)).
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { flatten } from 'https://github.com/remeda/remeda/blob/master/src/flatten.ts';
|
||||||
|
|
||||||
|
console.log(flatten([[1, 2], [3], [4, 5]])); // -> [1, 2, 3, 4, 5]
|
||||||
|
```
|
||||||
|
|
||||||
|
[Open in LiveCodes](<https://livecodes.io/?console=open&js=import%20%7B%20flatten%20%7D%20from%20'https%3A%2F%2Fgithub.com%2Fremeda%2Fremeda%2Fblob%2Fmaster%2Fsrc%2Fflatten.ts'%3B%0A%0Aconsole.log(flatten(%5B%5B1%2C%202%5D%2C%20%5B3%5D%2C%20%5B4%2C%205%5D%5D))%3B>)
|
||||||
|
|
||||||
|
:::tip
|
||||||
|
|
||||||
|
If you do not want the import URL to be bundled (e.g. in Deno or GitHub imports), add `#nobundle` to the end of URL.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { flatten } from 'https://github.com/remeda/remeda/blob/master/src/flatten.ts#nobundle';
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want to bundle (and transpile) any import URL, prefix it with `bundle:` (see below).
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
## CDN Providers
|
||||||
|
|
||||||
|
By default, npm modules are imported from [esm.sh](https://esm.sh/). You may choose another provider by using a CDN prefix. These are examples of importing the library `uuid`:
|
||||||
|
|
||||||
|
`uuid` → https://esm.sh/uuid ([info](https://esm.sh))
|
||||||
|
|
||||||
|
`esm.sh:uuid` → https://esm.sh/uuid ([info](https://esm.sh/))
|
||||||
|
|
||||||
|
`skypack:uuid` → https://cdn.skypack.dev/uuid ([info](https://www.skypack.dev/))
|
||||||
|
|
||||||
|
`jsdelivr:uuid` → https://cdn.jsdelivr.net/npm/uuid ([info](https://www.jsdelivr.com/))
|
||||||
|
|
||||||
|
`esm.run:uuid` → https://esm.run/uuid ([info](https://esm.run/))
|
||||||
|
|
||||||
|
`unpkg:uuid` → https://unpkg.com/uuid?module ([info](https://unpkg.com/))
|
||||||
|
|
||||||
|
`esbuild:uuid` → https://esbuild.vercel.app/uuid ([info](https://esbuild.vercel.app/))
|
||||||
|
|
||||||
|
`bundlejs:uuid` → https://deno.bundlejs.com/?file&q=uuid ([info](https://bundlejs.com/))
|
||||||
|
|
||||||
|
`bundle:uuid` → https://deno.bundlejs.com/?file&q=uuid ([info](https://bundlejs.com/))
|
||||||
|
|
||||||
|
`deno:uuid` → https://deno.bundlejs.com/?file&q=https://deno.land/x/uuid/mod.ts ([info](https://bundlejs.com/))
|
||||||
|
|
||||||
|
`npm:uuid` → https://esm.sh/uuid ([info](https://esm.sh))
|
||||||
|
|
||||||
|
`node:uuid` → https://esm.sh/uuid ([info](https://esm.sh))
|
||||||
|
|
||||||
|
`jsr:@std/uuid` → https://esm.sh/jsr/@std/uuid ([info](https://esm.sh))
|
||||||
|
|
||||||
|
`jspm:uuid` → https://jspm.dev/uuid ([info](https://jspm.org) - [DEPRECATED](https://jspm.org/jspm-dev-deprecation))
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { useState } from 'esm.sh:react';
|
||||||
|
```
|
||||||
|
|
||||||
|
:::caution
|
||||||
|
|
||||||
|
Please note that importing the same module (even for dependencies) from different CDNs may cause conflicts.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```js
|
||||||
|
// this will NOT work!
|
||||||
|
import React, { useState } from 'esm.sh:react'; // React from esm.sh
|
||||||
|
import { createRoot } from 'skypack:react-dom/client'; // React from skypack.dev
|
||||||
|
```
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
### Change Default CDN
|
||||||
|
|
||||||
|
Default CDN can be changed on project-level using the [custom settings](../advanced/custom-settings.mdx) property `defaultCDN` which accepts a string representing one of the CDN aliases listed above.
|
||||||
|
|
||||||
|
Example: This assigns [Skypack](https://www.skypack.dev/) as the default CDN for all imports of the project
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"defaultCDN": "skypack"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Package Version
|
||||||
|
|
||||||
|
Most CDN providers allow specifying package version using the format: <br />
|
||||||
|
`{pkgName}@{version}/{path}`.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import latest from 'lodash';
|
||||||
|
import v3 from 'lodash@3';
|
||||||
|
|
||||||
|
console.log(latest.VERSION); // -> 4.17.21
|
||||||
|
console.log(v3.VERSION); // -> 3.10.1
|
||||||
|
```
|
||||||
|
|
||||||
|
## Custom Module Resolution
|
||||||
|
|
||||||
|
Module resolution described in this page mainly depends on [import maps](https://github.com/WICG/import-maps). The generated import map is added to the [result page](./result.mdx).
|
||||||
|
|
||||||
|
You may wish to override or customize module resolution behavior (e.g. change URL, CDN, specify version, import custom unpublished library, ...etc. ), however you cannot add another import map script because [currently multiple import maps are not yet supported](https://github.com/WICG/import-maps#multiple-import-map-support).
|
||||||
|
|
||||||
|
LiveCodes allows you to add your custom import map by one of the following methods:
|
||||||
|
|
||||||
|
#### Custom Settings
|
||||||
|
|
||||||
|
In the standalone app, via the [custom settings](../advanced/custom-settings.mdx) property `imports`.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```json title="Custom Settings"
|
||||||
|
{
|
||||||
|
"imports": {
|
||||||
|
"my-lib": "https://my-server.com/path/to/library.js"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### SDK
|
||||||
|
|
||||||
|
For embedded playgrounds, use the [SDK](../sdk/index.mdx) embed option [`config.imports`](../configuration/configuration-object.mdx#imports).
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```js title="index.js"
|
||||||
|
import { createPlayground } from 'livecodes';
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
imports: {
|
||||||
|
'my-lib': 'https://my-server.com/path/to/library.js',
|
||||||
|
},
|
||||||
|
// other configurations ...
|
||||||
|
};
|
||||||
|
|
||||||
|
createPlayground('#container', { config });
|
||||||
|
```
|
||||||
|
|
||||||
|
Please note that you may also provide [custom type definitions](./intellisense.mdx#custom-types) for your custom modules for editor intellisense and better development experience.
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [Import](./import.mdx)
|
||||||
|
- [External Resources](./external-resources.mdx)
|
||||||
|
- [Projects](./projects.mdx)
|
||||||
|
- [Intellisense](./intellisense.mdx)
|
||||||
131
docs/docs/features/permanent-url.mdx
Normal file
131
docs/docs/features/permanent-url.mdx
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
# Permanent URL
|
||||||
|
|
||||||
|
Any specific version of LiveCodes app can be accessed through the permanent unique URL:
|
||||||
|
|
||||||
|
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||||
|
import CodeBlock from '@theme/CodeBlock';
|
||||||
|
import { AppVersion } from '../../src/components/Versions.tsx';
|
||||||
|
|
||||||
|
export const AppVersionLink = () => {
|
||||||
|
const { siteConfig } = useDocusaurusContext();
|
||||||
|
return (
|
||||||
|
<a href={`https://v${siteConfig.customFields.appVersion}.livecodes.io`} target="\_blank">
|
||||||
|
https://v{siteConfig.customFields.appVersion}.livecodes.io
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
`{version}.livecodes.io`
|
||||||
|
(e.g. <AppVersionLink />)
|
||||||
|
|
||||||
|
This allows [embedded playgrounds](./embeds.mdx) to use a pinned version of the LiveCodes app and its dependencies and avoid any breaking changes that may occur in later versions.
|
||||||
|
|
||||||
|
Permanent URL is used by default in the code generated by the [embed screen UI](./embeds.mdx).
|
||||||
|
It is also available when [sharing](./share.mdx) projects from the share screen.
|
||||||
|
|
||||||
|
The [SDK](../sdk/index.mdx) embed option [`appUrl`](../sdk/js-ts.mdx#appurl) allows specifying the URL for the app to be used.
|
||||||
|
In addition, it is always a good practice to use a specific version of the SDK.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
export const Code = () => {
|
||||||
|
const { siteConfig } = useDocusaurusContext();
|
||||||
|
return (
|
||||||
|
<CodeBlock title="index.html" language="html">
|
||||||
|
{`<div id="container"></div>\n<script type="module">
|
||||||
|
${' '}// specific SDK version
|
||||||
|
// highlight-next-line
|
||||||
|
${' '}import { createPlayground } from 'https://cdn.jsdelivr.net/npm/livecodes@${siteConfig.customFields.sdkVersion}';\n
|
||||||
|
${' '}createPlayground('#container', {
|
||||||
|
${' '}// App permanent URL
|
||||||
|
// highlight-next-line
|
||||||
|
${' '}appUrl: 'https://v${siteConfig.customFields.appVersion}.livecodes.io',
|
||||||
|
${' '}template: 'react',
|
||||||
|
${' '}});
|
||||||
|
</script>`}
|
||||||
|
</CodeBlock>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
<Code />
|
||||||
|
|
||||||
|
## Get Permanent URL
|
||||||
|
|
||||||
|
You can get the permanent URL for the app from the [About screen](pathname:///../?screen=about) (Help menu → About). By default, the code generated in the [Embed screen](./embeds.mdx#app-embed-screen) uses permanent URL.
|
||||||
|
Alternatively, open the browser console of the standalone app (e.g. https://livecodes.io), and run this:
|
||||||
|
|
||||||
|
export const GetPermanentUrl = () => {
|
||||||
|
const { siteConfig } = useDocusaurusContext();
|
||||||
|
return (
|
||||||
|
<CodeBlock language="js">
|
||||||
|
{`await livecodes.exec('showVersion');\n
|
||||||
|
// output:
|
||||||
|
// App Version: ${siteConfig.customFields.appVersion} (https://github.com/live-codes/livecodes/releases/tag/v${siteConfig.customFields.appVersion})
|
||||||
|
// SDK Version: ${siteConfig.customFields.sdkVersion} (https://www.npmjs.com/package/livecodes/v/${siteConfig.customFields.sdkVersion})
|
||||||
|
// Git commit: 0698f9f (https://github.com/live-codes/livecodes/commit/0698f9f)
|
||||||
|
// App Permanent URL: https://v${siteConfig.customFields.appVersion}.livecodes.io/
|
||||||
|
// SDK Permanent URL: https://cdn.jsdelivr.net/npm/livecodes@${siteConfig.customFields.sdkVersion}/livecodes.js
|
||||||
|
`}
|
||||||
|
</CodeBlock>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
<GetPermanentUrl />
|
||||||
|
|
||||||
|
:::caution
|
||||||
|
|
||||||
|
Please note that this only applies to the LiveCodes app and its dependencies.
|
||||||
|
[NPM imports](./module-resolution.mdx) in [project code](./projects.mdx#script-editor) that do not specify versions use the latest version.
|
||||||
|
[Package versions](./module-resolution.mdx#package-version) can be specified in the import.
|
||||||
|
[Custom import maps](./module-resolution.mdx#custom-module-resolution) can be set to control the module import behavior.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import lodash from 'lodash@4.17.21';
|
||||||
|
|
||||||
|
console.log(lodash.VERSION); // -> 4.17.21
|
||||||
|
```
|
||||||
|
|
||||||
|
It is recommended to also specify versions of [external resources](./external-resources.mdx).
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
#### Full Example:
|
||||||
|
|
||||||
|
export const FullCode = () => {
|
||||||
|
const { siteConfig } = useDocusaurusContext();
|
||||||
|
return (
|
||||||
|
<CodeBlock title="index.html" language="html">
|
||||||
|
{`<div id="container"></div>\n<script type="module">
|
||||||
|
${' '}// specific SDK version
|
||||||
|
// highlight-next-line
|
||||||
|
${' '}import { createPlayground } from 'https://cdn.jsdelivr.net/npm/livecodes@${siteConfig.customFields.sdkVersion}';\n
|
||||||
|
${' '}createPlayground('#container', {
|
||||||
|
${' '}// App permanent URL
|
||||||
|
// highlight-next-line
|
||||||
|
${' '}appUrl: 'https://v${siteConfig.customFields.appVersion}.livecodes.io',
|
||||||
|
${' '}config: {
|
||||||
|
${' '}script: {
|
||||||
|
${' '}language: 'javascript',
|
||||||
|
${' '}// project code imports package with specific version
|
||||||
|
// highlight-next-line
|
||||||
|
${' '}content: 'import lodash from "lodash@4.17.21";\\nconsole.log(lodash.VERSION);',
|
||||||
|
${' '}},
|
||||||
|
${' '}activeEditor: 'script',
|
||||||
|
${' '}tools: { status: 'open', active: 'console' },
|
||||||
|
${' '}},
|
||||||
|
${' '}});
|
||||||
|
</script>`}
|
||||||
|
</CodeBlock>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
<FullCode />
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [Embedded playgrounds](./embeds.mdx)
|
||||||
|
- [Share](./share.mdx)
|
||||||
|
- [SDK](../sdk/index.mdx)
|
||||||
|
- [`exec` SDK method](../sdk/js-ts.mdx#exec)
|
||||||
63
docs/docs/features/projects.mdx
Normal file
63
docs/docs/features/projects.mdx
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
# Projects
|
||||||
|
|
||||||
|
A _LiveCodes_ project is a combination of markup, styles & scripts that result in a **single web page**. Check the section about the [Result Page](./result.mdx) to have more details about how this page is constructed.
|
||||||
|
|
||||||
|
There is no concept of file system or, for example, organizing multiple files in a directory structure of a single project.
|
||||||
|
|
||||||
|
:::info Simple Concept
|
||||||
|
code in [markup editor](#markup-editor) + code in [style editor](#style-editor) + code in [script editor](#script-editor) + [external resources](./external-resources.mdx) => [result page](./result.mdx)
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Markup Editor
|
||||||
|
|
||||||
|
Code added in this editor eventually represents the page markup (HTML).
|
||||||
|
|
||||||
|
Examples for languages supported include HTML, Markdown, Pug, Haml.
|
||||||
|
|
||||||
|
## Style Editor
|
||||||
|
|
||||||
|
Code added in this editor eventually represents the page styles (CSS).
|
||||||
|
|
||||||
|
Examples for languages supported include CSS, SCSS, SASS, Less, Stylus. In addition, many CSS processors are supported (e.g. Autoprefixer, postcss-preset-env, postcss-import-url, PurgeCSS, Tailwind CSS).
|
||||||
|
|
||||||
|
## Script Editor
|
||||||
|
|
||||||
|
Code added in this editor eventually represents the page scripts.
|
||||||
|
|
||||||
|
These are either:
|
||||||
|
|
||||||
|
- Languages compiled to JavaScript (e.g TypeScript, JSX, CoffeeScript)
|
||||||
|
- Languages that are interpreted by a JavaScript runtime (e.g. PHP - interpreted by [Uniter runtime](https://github.com/asmblah/uniter), Scheme - interpreted by [BiwaScheme](https://www.biwascheme.org))
|
||||||
|
- Languages running in WASM (e.g. Python - [Pyodide](https://pyodide.org/), AssemblyScript).
|
||||||
|
|
||||||
|
For the full list of supported languages, check the [Languages section](../languages/index.mdx).
|
||||||
|
|
||||||
|
## Organizing Projects
|
||||||
|
|
||||||
|
Projects can be saved to the local device browser storage from Project menu → Save / Project menu → Save as → Fork (New Project) or using the keyboard shortcut <kbd>Ctrl</kbd> + <kbd>S</kbd>.
|
||||||
|
|
||||||
|
The list of saved projects can be accessed from Project menu → Open.
|
||||||
|
|
||||||
|
.
|
||||||
|
|
||||||
|
Saved projects can be sorted by title or date (asc/desc). They can also be filtered by language and/or tags. You may, as well, search for a project by title or description.
|
||||||
|
|
||||||
|
Project title, description and tags can be edited from Project menu → Project Info.
|
||||||
|
|
||||||
|
Projects can be [imported](./import.mdx), [exported](./export.mdx), [synchronized](./sync.mdx), [backed up and restored](./backup-restore.mdx).
|
||||||
|
|
||||||
|
[Assets](./assets.mdx) and [code snippets](./snippets.mdx) are stored in the browser storage and can be used across projects.
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [Result Page](./result.mdx)
|
||||||
|
- [Templates](./templates.mdx)
|
||||||
|
- [Code Snippets](./snippets.mdx)
|
||||||
|
- [Assets](./assets.mdx)
|
||||||
|
- [External Resources](./external-resources.mdx)
|
||||||
|
- [Import](./import.mdx)
|
||||||
|
- [Export](./export.mdx)
|
||||||
|
- [Backup/Restore](./backup-restore.mdx)
|
||||||
|
- [Sync](./sync.mdx)
|
||||||
|
- [Share](./share.mdx)
|
||||||
|
- [Broadcast](./broadcast.mdx)
|
||||||
34
docs/docs/features/read-only.mdx
Normal file
34
docs/docs/features/read-only.mdx
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# Read-Only
|
||||||
|
|
||||||
|
import LiveCodes from '../../src/components/LiveCodes.tsx';
|
||||||
|
|
||||||
|
In case you need to embed a playground in your web page to show case some code and want users to read through the code and not allow edits, you may use the `readonly` setting.
|
||||||
|
|
||||||
|
Code editing, [formatting](./code-format.mdx), and [console input](./console.mdx) are not available. However, any language supported by LiveCodes can be used, with syntax highlighting. Code can be [prefilled](./code-prefill.mdx), and is compiled and shown in the [result page](./result.mdx) as usual.
|
||||||
|
|
||||||
|
By default, a light-weight, minimal [code editor](./editor-settings.mdx#code-editor) is used. This can be changed by explicitly setting the [configuration object](../configuration/configuration-object.mdx) property [`editor`](../configuration/configuration-object.mdx#editor) (e.g. to show hover intellisense).
|
||||||
|
|
||||||
|
Demo:
|
||||||
|
|
||||||
|
<LiveCodes template="javascript" config={{ readonly: true }}></LiveCodes>
|
||||||
|
|
||||||
|
## Using SDK
|
||||||
|
|
||||||
|
set the [configuration object](../configuration/configuration-object.mdx) property [`readonly`](../configuration/configuration-object.mdx#readonly) to `true`.
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { createPlayground } from 'livecodes';
|
||||||
|
|
||||||
|
createPlayground('#container', { template: 'javascript', config: { readonly: true } });
|
||||||
|
```
|
||||||
|
|
||||||
|
## Using query params
|
||||||
|
|
||||||
|
add the [query parameter](../configuration/query-params.mdx) `readonly` (no need to set a value).
|
||||||
|
|
||||||
|
https://livecodes.io?template=javascript&readonly
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [Code prefill](./code-prefill.mdx)
|
||||||
|
- [Lite mode](./lite.mdx)
|
||||||
1
docs/docs/features/recover.mdx
Normal file
1
docs/docs/features/recover.mdx
Normal file
@ -0,0 +1 @@
|
|||||||
|
# Recover Unsaved
|
||||||
107
docs/docs/features/result.mdx
Normal file
107
docs/docs/features/result.mdx
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
# Result Page
|
||||||
|
|
||||||
|
The output of a LiveCodes project is a single HTML page. This includes the (compiled) code from editors (markup + style + script) and [external resources](./external-resources.mdx) (CSS + JS), in addition to customizations specified in [custom settings](../advanced/custom-settings.mdx).
|
||||||
|
|
||||||
|
This page is loaded in a [sandboxed iframe](https://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/) with a unique origin to enforce [security](./security.mdx). The page code is sent to the iframe in the browser (no code is sent to the server).
|
||||||
|
|
||||||
|
## Result page structure
|
||||||
|
|
||||||
|
This is the pseudo-code for the structure of the result page (inspired by [CodePen docs](https://blog.codepen.io/documentation/preview-template/)).
|
||||||
|
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
```html
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html { Config.htmlAttrs }*>
|
||||||
|
<head>
|
||||||
|
<title>{ Config.title }*</title>
|
||||||
|
<meta name="title" content="{ Config.title }*" />
|
||||||
|
<meta name="description" content="{ Config.description }*" />
|
||||||
|
|
||||||
|
{ Config.head }*
|
||||||
|
|
||||||
|
{ CSS preset }**
|
||||||
|
|
||||||
|
{ External CSS }**
|
||||||
|
|
||||||
|
{ Editor CSS }
|
||||||
|
|
||||||
|
{ Language(s) run-time CSS }***
|
||||||
|
|
||||||
|
{ Language(s) run-time JS }***
|
||||||
|
|
||||||
|
{ Import map }****
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
{ Editor HTML }
|
||||||
|
|
||||||
|
{ External JS }**
|
||||||
|
|
||||||
|
{ Editor JS }
|
||||||
|
|
||||||
|
{ Spacing script (if enabled) }*****
|
||||||
|
|
||||||
|
{ Test scripts (if enabled) }******
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
```
|
||||||
|
|
||||||
|
\* See [Configuration Object](../configuration/configuration-object.mdx).
|
||||||
|
|
||||||
|
\*\* See [External Resources](./external-resources.mdx).
|
||||||
|
|
||||||
|
\*\*\* Although most languages are compiled and then the compiled code is used, some languages require run-time scripts or styles to run in the result page.
|
||||||
|
|
||||||
|
\*\*\*\* See [Module Resolution](./module-resolution.mdx).
|
||||||
|
|
||||||
|
\*\*\*\*\* See [Show Sapcings](#show-spacings).
|
||||||
|
|
||||||
|
\*\*\*\*\*\* See [Tests](./tests.mdx).
|
||||||
|
|
||||||
|
## Result page zoom
|
||||||
|
|
||||||
|
The zoom button in the [tools pane](./tools-pane.mdx) below result page, allows you to toggle result page zoom (1x/0.5x/0.25x).
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Open in new window
|
||||||
|
|
||||||
|
From the [tools pane](./tools-pane.mdx), the result page can be viewed in a separate window.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
:::caution
|
||||||
|
|
||||||
|
Please note that the URL of the result page shown in the new window is a [temporary URL](https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL#parameters), for local preview. Sharing this URL will not work.
|
||||||
|
|
||||||
|
If you need to share a project, use the [Share screen](./share.mdx). While, if you need to share the result page use the `result` [display mode](./display-modes.mdx) or the [broadcast](./broadcast.mdx) feature.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Show Spacings
|
||||||
|
|
||||||
|
The spacing between elements on the result page can be measured by adding [Spacing.js](https://spacingjs.com/) to the result page.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
1. Enable `Show Spacing` setting in the Settings menu.
|
||||||
|
2. Move your cursor to an element and press Alt on Windows, or Option on a Mac.
|
||||||
|
3. Move your cursor to another element, the measurement results will be there.
|
||||||
|
|
||||||
|
:::note
|
||||||
|
|
||||||
|
`Show Spacing` is only available when viewing the result page in the app. It is not added to the result page for example when [exported](./export.mdx) or [deployed](./deploy.mdx).
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Scroll Position
|
||||||
|
|
||||||
|
By default, the result page scroll position is maintained after reloads.
|
||||||
|
|
||||||
|
To disable this behavior, set the [query param](../configuration/query-params.mdx) `scrollPosition` to `false`.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
https://livecodes.io?scrollPosition=false
|
||||||
12
docs/docs/features/security.mdx
Normal file
12
docs/docs/features/security.mdx
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# Security
|
||||||
|
|
||||||
|
import MailLink from '../../src/components/MailLink.tsx';
|
||||||
|
|
||||||
|
User privacy and security are taken seriously.
|
||||||
|
|
||||||
|
- All user code, [result page](./result.mdx) and compilers run in [sandboxed iframes](https://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/) with a unique origin.
|
||||||
|
|
||||||
|
- [Embedded playgrounds](./embeds.mdx) do not have access to the parent page, or to sensitive data like user cookies and localstorage of the embedding page origin.
|
||||||
|
|
||||||
|
If you find any security vulnerability, please report it in the [contact page](../contact.mdx) or by email to <MailLink email="security@livecodes.io" text="security@livecodes.io" />
|
||||||
|
For other non-security-related bugs, please report them in the [repo issues](https://github.com/live-codes/livecodes/issues).
|
||||||
77
docs/docs/features/self-hosting.mdx
Normal file
77
docs/docs/features/self-hosting.mdx
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
# Self-Hosting
|
||||||
|
|
||||||
|
The LiveCodes app can be self-hosted on any static file server or CDN.
|
||||||
|
|
||||||
|
## Guide
|
||||||
|
|
||||||
|
The built app can be obtained by **one of the following** ways:
|
||||||
|
|
||||||
|
- Download the app from the [releases](https://github.com/live-codes/livecodes/releases), extract the folder and add it to your website.
|
||||||
|
- Fork the [GitHub repo](https://github.com/live-codes/livecodes) and clone it. You may wish to use the included setup to deploy to [GitHub Pages](https://pages.github.com/):
|
||||||
|
|
||||||
|
```shell
|
||||||
|
git clone https://github.com/{your-username}/livecodes
|
||||||
|
cd livecodes
|
||||||
|
npm install
|
||||||
|
npm build # build the app to "build" directory
|
||||||
|
npm run serve # locally serve to http://localhost:8080
|
||||||
|
|
||||||
|
# deploy
|
||||||
|
npm run deploy # build and deploy to github pages
|
||||||
|
|
||||||
|
# for development
|
||||||
|
npm start # start local development with code watch, rebuild and live-reload
|
||||||
|
```
|
||||||
|
|
||||||
|
- Fork the [GitHub repo](https://github.com/live-codes/livecodes) and use one of the hosting services that integrate with GitHub to allow automatic deploys on code push (e.g. [Cloudflare Pages](https://developers.cloudflare.com/pages/get-started), [Vercel](https://vercel.com/docs/concepts/git), [Netlify](https://docs.netlify.com/configure-builds/overview/), [Firebase](https://firebase.google.com/docs/hosting/github-integration)). When prompted, the build command is `npm run build` and the build output directory is `build`.
|
||||||
|
|
||||||
|
## Custom Build
|
||||||
|
|
||||||
|
By default, when building the app, it is expected to be hosted on the root of the domain/subdomain (e.g. `https://my-website.com` or `https://playground.my-website.com`). The documentation is also hosted in the `/docs/` directory (e.g. `https://my-website.com/docs`).
|
||||||
|
|
||||||
|
If you wish to host the app in a subdirectory (e.g. `https://my-username.github.io/playground/`), the base URL of the documentation directory needs to be supplied by the environment variable `DOCS_BASE_URL` during build.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
npx cross-env DOCS_BASE_URL="/playground/docs/" npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
If you do not want to build documentations and direct all links to documentations to https://livecodes.io/docs/, use the following command:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
npx cross-env DOCS_BASE_URL=null npm run build:app
|
||||||
|
```
|
||||||
|
|
||||||
|
## Services
|
||||||
|
|
||||||
|
Some of the [services](../advanced/services.mdx) used by the app are not supported on [self-hosted](../features/self-hosting.mdx) deploys and are either replaced by other compatible services (e.g. the [share](../features/share.mdx) service uses [dpaste](https://dpaste.com/) for short URLs, which are [**deleted after 365 days**](https://dpaste.com/help)) or require you to provide an alternative service (e.g. [Firebase configuration](https://github.com/live-codes/livecodes/tree/develop/src/livecodes/services/firebase.ts) for authentication).
|
||||||
|
|
||||||
|
You may wish to edit one or more of the used [services](../advanced/services.mdx) to use your own.
|
||||||
|
|
||||||
|
:::info
|
||||||
|
|
||||||
|
LiveCodes [sponsors](../sponsor.mdx) (Bronze sponsors and above) get access to managed custom services.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
This is an example of a self-hosted deployment, that was deployed to [GitHub Pages](https://pages.github.com/) using the [built-in setup](#guide):
|
||||||
|
|
||||||
|
https://live-codes.github.io/livecodes/
|
||||||
|
|
||||||
|
## SDK Usage
|
||||||
|
|
||||||
|
The [SDK](../sdk/index.mdx) can still be used with the self-hosted app by providing the [`appUrl`](../sdk/js-ts.mdx#appurl) [embed option](../sdk/js-ts.mdx#embed-options).
|
||||||
|
|
||||||
|
```js title="index.js"
|
||||||
|
import { createPlayground } from 'livecodes';
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
appUrl: 'https://playground.my-website.com',
|
||||||
|
template: 'react',
|
||||||
|
// other embed options
|
||||||
|
};
|
||||||
|
createPlayground('#container', options);
|
||||||
|
```
|
||||||
45
docs/docs/features/share.mdx
Normal file
45
docs/docs/features/share.mdx
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
# Share
|
||||||
|
|
||||||
|
It is easy to share LiveCodes projects!
|
||||||
|
|
||||||
|
A URL is generated to load the shared project. This URL can be copied or shared to different social media.
|
||||||
|
|
||||||
|
The share screen can be accessed from the share icon at the top right or from the Project menu → Share.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
By default, the generated URL encodes the project configuration in a base-64-encoded compressed query string. This step is generated locally in the browser without sending the code to any server. However, depending on the size of the project, the URL can be very long. The length of the URL is indicated in the share screen. [Try not to use very long URLs](https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers) to ensure cross-browser compatibility.
|
||||||
|
|
||||||
|
When requested by the user, short URLs can be generated. This requires sending the project configuration (**including source code**) to a server that saves the code and provides a short Id which can be used to retrieve the project.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
:::caution
|
||||||
|
|
||||||
|
Generating a short URL for sharing requires sending the project configuration (**including source code**) to LiveCodes share service. **It cannot then be deleted**.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
:::info Note
|
||||||
|
|
||||||
|
The app hosted on [`https://livecodes.io`](https://livecodes.io) uses an API endpoint specifically provided to generate short URLs for LiveCodes share service. We will make every effort to keep that online and available for free use, so long as it is not abused. Please help keep it available by not abusing it and by [sponsoring the project](../sponsor.mdx).
|
||||||
|
|
||||||
|
Short URLs generated by LiveCodes share service are **private** by default and are not listed or indexed.
|
||||||
|
|
||||||
|
However, [**self-hosted apps**](./self-hosting.mdx) use the free service [dpaste](https://dpaste.com/) for short URLs which are [**deleted after 365 days**](https://dpaste.com/help). You may want to use a [custom service](../advanced/services.mdx) instead. LiveCodes [sponsors](../sponsor.mdx) (Bronze sponsors and above) get access to managed custom services.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
QR code can be generated for the share URL. This can then be scanned by any QR code scanner (e.g. mobile/tablet camera) to load the project on other devices without having to send the link. Please note that generating QR code also requires generating a short URL (code is sent to the share service - see above).
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [Export](./export.mdx)
|
||||||
|
- [Import](./import.mdx)
|
||||||
|
- [Deploy](./deploy.mdx)
|
||||||
|
- [Broadcast](./broadcast.mdx)
|
||||||
|
- [Backup / Restore](./backup-restore.mdx)
|
||||||
|
- [Sync](./sync.mdx)
|
||||||
|
- [Permanent URL](./permanent-url.mdx)
|
||||||
28
docs/docs/features/snippets.mdx
Normal file
28
docs/docs/features/snippets.mdx
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# Code Snippets
|
||||||
|
|
||||||
|
LiveCodes supports saving and organizing code snippets in different languages.
|
||||||
|
|
||||||
|
Code snippets are saved locally on user's device. However, they are supported in [sync](./sync.mdx), [backup](./backup-restore.mdx#backup) and [restore](./backup-restore.mdx#restore).
|
||||||
|
|
||||||
|
Code snippets screen can be accessed from Settings menu → Code Snippets.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
import RunInLiveCodes from '../../src/components/RunInLiveCodes.tsx';
|
||||||
|
|
||||||
|
<RunInLiveCodes params={{ screen: 'snippets' }} linkText="direct link" />
|
||||||
|
|
||||||
|
Each snippet has a title, description, language and code.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
After adding snippets they can be sorted (by date modified or title), filtered (by language) or searched.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Code snippets can then be copied to clipboard and pasted in projects.
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [Projects](./projects.mdx)
|
||||||
|
- [Assets](./assets.mdx)
|
||||||
28
docs/docs/features/sync.mdx
Normal file
28
docs/docs/features/sync.mdx
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# Sync
|
||||||
|
|
||||||
|
LiveCodes local data can be synchronized to a GitHub repo. This can be used as a cloud backup, and to synchronize multiple devices.
|
||||||
|
|
||||||
|
A GitHub account is required. The user must give access to [(Private Repos) while logging in](./github-integration.mdx).
|
||||||
|
|
||||||
|
The Sync screen can be accessed from the Settings menu → Sync.
|
||||||
|
|
||||||
|
import RunInLiveCodes from '../../src/components/RunInLiveCodes.tsx';
|
||||||
|
|
||||||
|
<RunInLiveCodes params={{ screen: 'sync' }} linkText="direct link" />
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Data can be synchronized to a new (**private**) or existing repo.
|
||||||
|
|
||||||
|
The data is synchronized with the `main` branch in a directory named `livecodes-data`.
|
||||||
|
|
||||||
|
If `Auto sync` is selected, the sync will be attempted every 5 minutes. Remote files are downloaded only when changed (e.g. sync from another device).
|
||||||
|
|
||||||
|
`Auto sync` can be turned off and on by the switch on the Settings menu.
|
||||||
|
|
||||||
|
The sync can be manually triggered at any time from the Sync UI. Information regarding the last sync time and repo are displayed on the UI screen.
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [Backup / restore](./backup-restore.mdx)
|
||||||
|
- [Export](./export.mdx)
|
||||||
49
docs/docs/features/templates.mdx
Normal file
49
docs/docs/features/templates.mdx
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
# Templates
|
||||||
|
|
||||||
|
import TemplateList from '../../src/components/TemplateList';
|
||||||
|
|
||||||
|
A new project can be based on any of the provided [starter templates](#starter-templates) or [user templates](#user-templates).
|
||||||
|
|
||||||
|
A new project (from template) can be started from:
|
||||||
|
|
||||||
|
- Project menu → New
|
||||||
|
- [Welcome Screen](./welcome.mdx) → New
|
||||||
|
- Direct URL: https://livecodes.io?new
|
||||||
|
|
||||||
|
## Starter Templates
|
||||||
|
|
||||||
|
A Large number of starter templates are available. They act as starting points and example usage for the [languages](../languages/index.mdx) available in LiveCodes.
|
||||||
|
|
||||||
|
A direct link for a starter template has the following format:
|
||||||
|
|
||||||
|
`?template={template_name}` (e.g. https://livecodes.io/?template=react)
|
||||||
|
|
||||||
|
The list of template names are documented [here](../api/internal/type-aliases/TemplateName.md).
|
||||||
|
|
||||||
|
### Template List
|
||||||
|
|
||||||
|
The following list of starter templates are available:
|
||||||
|
|
||||||
|
<TemplateList />
|
||||||
|
|
||||||
|
## User Templates
|
||||||
|
|
||||||
|
Any project loaded in LiveCodes can be saved as a user template, to be used later as a starting point for new projects.
|
||||||
|
|
||||||
|
A project can be saved as a user template from Project menu → Save as → Template.
|
||||||
|
|
||||||
|
It can then be accessed from Project menu → New ... → My Templates.
|
||||||
|
|
||||||
|
A user template can be set as [default template](./default-template-language.mdx) to be automatically loaded when loading the app.
|
||||||
|
|
||||||
|
User templates are scoped to the currently [logged-in user](./user-management.mdx). They can be [backed up/restored](./backup-restore.mdx) and [synced](./sync.mdx) the same as other user data.
|
||||||
|
|
||||||
|
## Related
|
||||||
|
|
||||||
|
- [Default Template/Language](./default-template-language.mdx)
|
||||||
|
- [Project](./projects.mdx)
|
||||||
|
- [Code Snippets](./snippets.mdx)
|
||||||
|
- [User management](./user-management.mdx)
|
||||||
|
- [Backup/Restore](./backup-restore.mdx)
|
||||||
|
- [Sync](./sync.mdx)
|
||||||
|
- [Languages](../languages/index.mdx)
|
||||||
178
docs/docs/features/tests.mdx
Normal file
178
docs/docs/features/tests.mdx
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
# Tests
|
||||||
|
|
||||||
|
import LiveCodes from '../../src/components/LiveCodes.tsx';
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Automated tests can be added for projects. The tests are run in the context of the result web page.
|
||||||
|
|
||||||
|
The automated tests are run by the <a href="https://jestjs.io/" target="_blank">Jest testing framework</a>, which runs totally in the browser. In addition, other [testing libraries](#supported-testing-libraries) are also supported.
|
||||||
|
|
||||||
|
Screenshots:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Use Cases
|
||||||
|
|
||||||
|
- Automated tests increase the confidence in the code and can improve the quality of projects.
|
||||||
|
- Allows <a href="https://en.wikipedia.org/wiki/Test-driven_development" target="_blank">Test-driven development (TDD)</a>.
|
||||||
|
- Can be used for education and training by preparing projects with tests that are required to pass by the students' implementation (similar to <a href="https://www.freecodecamp.org/learn" target="_blank">freeCodeCamp</a>).
|
||||||
|
- Can be used by wesites that offer coding challenges (similar to <a href="https://www.codewars.com/" target="_blank">Codewars</a>).
|
||||||
|
|
||||||
|
## Demos
|
||||||
|
|
||||||
|
Demo: (template=jest)
|
||||||
|
|
||||||
|
<LiveCodes template="jest" params={{tests: 'open'}}></LiveCodes>
|
||||||
|
|
||||||
|
<p> </p>
|
||||||
|
|
||||||
|
Demo: (template=jest-react)
|
||||||
|
|
||||||
|
<LiveCodes template="jest-react" params={{tests: 'open'}}></LiveCodes>
|
||||||
|
|
||||||
|
## Tests Panel
|
||||||
|
|
||||||
|
The "Tests" panel is located in the "[Tools pane](./tools-pane.mdx)" below the result page.
|
||||||
|
|
||||||
|
In the tests panel, you can find:
|
||||||
|
|
||||||
|
- "Run" button: To run tests (keyboard shortcut: Ctrl/Cmd + Alt + t).
|
||||||
|
- "Watch" button toggle: To watch the project and re-run tests automatically when code changes.
|
||||||
|
- "Reset" button: Resets test results.
|
||||||
|
- "Edit" button: Opens a code editor to edit tests (not in embeds).
|
||||||
|
- Test results.
|
||||||
|
|
||||||
|
:::info Note
|
||||||
|
|
||||||
|
Please note that the tests panel are hidden by default in [embedded playgrounds](./embeds.mdx) unless the [project has tests](../configuration/configuration-object.mdx#tests). In such case, the panel is added to the [tools pane](./tools-pane.mdx). However, the test editor is not shown.
|
||||||
|
|
||||||
|
The [SDK](../sdk/index.mdx) can control the visibility of the different tools in the tools pane (see [`tools`](../configuration/configuration-object.mdx#tools) property of the [configuration object](../configuration/configuration-object.mdx)).
|
||||||
|
|
||||||
|
The tests panel and the test editor are always shown in the [full standalone app](../getting-started.mdx#standalone-app).
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
## Supported Languages
|
||||||
|
|
||||||
|
The testing code can be written using JavaScript, TypeScript, JSX or TSX.
|
||||||
|
However, since the tests run against the result web page, they can test projects that use any language/framework.
|
||||||
|
|
||||||
|
This is [a demo](https://livecodes.io/?x=id/xyi6usem2sf&tests) for running tests against a Ruby project.
|
||||||
|
|
||||||
|
<LiveCodes import="id/xyi6usem2sf" params={{tests: "open"}} height="80vh"></LiveCodes>
|
||||||
|
|
||||||
|
Languages may have test modules. This is [an example](https://livecodes.io/?x=id/665ar3bpqka&console=full) of running [Python doctest](https://docs.python.org/3/library/doctest.html) tests:
|
||||||
|
|
||||||
|
<LiveCodes import="id/665ar3bpqka" params={{console: "full"}} height="80vh"></LiveCodes>
|
||||||
|
|
||||||
|
|
||||||
|
## Importing Code
|
||||||
|
|
||||||
|
Functions, objects or values can be exported from the `script` code like a regular ES module.
|
||||||
|
These can then be imported in the test code for usage. This is only available for code in the `script` editor. The testing code also have access to global objects like `window`.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```js
|
||||||
|
// in the script editor
|
||||||
|
export default function greet() {
|
||||||
|
return 'Hello, World!';
|
||||||
|
}
|
||||||
|
|
||||||
|
export const add = (x, y) => x + y;
|
||||||
|
|
||||||
|
window.multiply = (x, y) => x * y;
|
||||||
|
```
|
||||||
|
|
||||||
|
```js
|
||||||
|
// in the test editor
|
||||||
|
import greet, { add } from './script'; // relative import without extension
|
||||||
|
|
||||||
|
describe('test imported', () => {
|
||||||
|
test('greet', () => {
|
||||||
|
expect(greet()).toBe('Hello, World!');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('add', () => {
|
||||||
|
expect(add(1, 2)).toBe(3);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('test global', () => {
|
||||||
|
test('multiply', () => {
|
||||||
|
expect(window.multiply(2, 3)).toBe(6);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Supported Jest features
|
||||||
|
|
||||||
|
- [Jest globals](https://jestjs.io/docs/api): `expect`, `test`, `xtest`, `it`, `fit`, `xit`, `describe`, `fdescribe`, `xdescribe`, `beforeAll`, `afterAll`, `beforeEach`, `afterEach`
|
||||||
|
- Jest function mocks: `jest.fn`, `jest.mocked`, `jest.replaceProperty`, `jest.spyOn`
|
||||||
|
|
||||||
|
These can be directly used in the test editor, without the need for any imports.
|
||||||
|
Autocomplete is available in Monaco editor for Jest API.
|
||||||
|
|
||||||
|
## Supported testing libraries
|
||||||
|
|
||||||
|
In addition to Jest, you may wish to use other supported testing libraries. These have to be explicitly imported to the testing code.
|
||||||
|
|
||||||
|
### Testing library
|
||||||
|
|
||||||
|
Simple and complete testing utilities that encourage good testing practices.
|
||||||
|
|
||||||
|
- <a href="https://testing-library.com/docs/dom-testing-library/intro" target="_blank">DOM Testing Library</a>
|
||||||
|
|
||||||
|
```js
|
||||||
|
import {
|
||||||
|
getByLabelText,
|
||||||
|
getByText,
|
||||||
|
getByTestId,
|
||||||
|
queryByTestId,
|
||||||
|
waitFor,
|
||||||
|
} from '@testing-library/dom';
|
||||||
|
```
|
||||||
|
|
||||||
|
- <a href="https://testing-library.com/docs/react-testing-library/intro" target="_blank">React Testing Library</a>
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { render, fireEvent, waitFor, screen } from '@testing-library/react';
|
||||||
|
```
|
||||||
|
|
||||||
|
- <a href="https://testing-library.com/docs/ecosystem-jest-dom" target="_blank">jest-dom</a>
|
||||||
|
|
||||||
|
```js
|
||||||
|
import '@testing-library/jest-dom';
|
||||||
|
```
|
||||||
|
|
||||||
|
- <a href="https://testing-library.com/docs/user-event/intro" target="_blank">user-event</a>
|
||||||
|
|
||||||
|
```js
|
||||||
|
import userEvent from '@testing-library/user-event';
|
||||||
|
```
|
||||||
|
|
||||||
|
### Chai
|
||||||
|
|
||||||
|
Jest assertions can be used in the tests. However, if you prefer Chai, it can be easily used.
|
||||||
|
Autocomplete is also available in Monaco editor for Chai API.
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { assert } from 'chai';
|
||||||
|
```
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
Usage examples are provided in the starter templates (<a href="pathname:///../?template=jest" target="_blank">Jest Starter</a> and <a href="pathname:///../?template=jest-react" target="_blank">Jest/React Starter</a>).
|
||||||
|
|
||||||
|
:::caution
|
||||||
|
|
||||||
|
The test code is added to the result page and runs in its context. Please note that script errors (e.g. import or syntax errors) may prevent the tests from loading.
|
||||||
|
|
||||||
|
:::
|
||||||
|
|
||||||
|
## SDK
|
||||||
|
|
||||||
|
The [SDK](../sdk/index.mdx) allows [running tests](../sdk/js-ts.mdx#runtests) and collecting results.
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user