Cleanup examples (#5817)

- Remove outdated examples
- Rename folders for consistency
- Remove lots of unused deps in angular example.
- Rename `name` inside `package.json`'s from `@uppy-example/*` to
`example-*`.

**Before**

```
├── angular-example
├── aws-companion
├── aws-nodejs
├── aws-php
├── bundled
├── cdn-example
├── custom-provider
├── digitalocean-spaces
├── multiple-instances
├── node-xhr
├── php-xhr
├── python-xhr
├── react
├── react-native-expo
├── redux
├── sveltekit
├── transloadit
├── transloadit-markdown-bin
├── uppy-with-companion
├── vue3
└── xhr-bundle
```

**After**

```
examples
├── angular
├── aws-companion
├── aws-nodejs
├── aws-php
├── cdn
├── companion
├── companion-custom-provider
├── companion-digitalocean-spaces
├── react
├── react-native-expo
├── redux
├── sveltekit
├── transloadit
├── vue
├── xhr-bundle
├── xhr-node
├── xhr-php
└── xhr-python
```
This commit is contained in:
Merlijn Vos 2025-07-10 17:23:58 +02:00 committed by GitHub
parent 271db86ad0
commit 7a50ab89ef
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
101 changed files with 335 additions and 1187 deletions

View file

@ -33,9 +33,7 @@ jobs:
node-version: lts/*
cache: yarn
- name: Install dependencies
# List all projects that use a custom ESLint config:
run:
corepack yarn workspaces focus @uppy/angular @uppy-example/angular
@uppy-example/react-native-expo @uppy/react-native @uppy-dev/build
corepack yarn workspaces focus @uppy-dev/build
- name: Run linter
run: corepack yarn run check:ci

View file

@ -1,9 +0,0 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/spec",
"types": ["jasmine"]
},
"include": ["src/**/*.spec.ts", "src/**/*.d.ts"]
}

View file

@ -1,13 +1,11 @@
{
"name": "@uppy-example/angular",
"name": "example-angular",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test",
"lint": "ng lint"
"watch": "ng build --watch --configuration development"
},
"private": true,
"dependencies": {
@ -32,20 +30,8 @@
},
"devDependencies": {
"@angular-devkit/build-angular": "^18.0.2",
"@angular-eslint/eslint-plugin": "18.0.1",
"@angular-eslint/eslint-plugin-template": "18.0.1",
"@angular/cli": "^18.0.2",
"@angular/compiler-cli": "^18.0.0",
"@types/jasmine": "~5.1.0",
"@typescript-eslint/eslint-plugin": "^7.2.0",
"@typescript-eslint/parser": "^7.2.0",
"eslint": "^8.57.0",
"jasmine-core": "~5.1.0",
"karma": "~6.4.0",
"karma-chrome-launcher": "~3.2.0",
"karma-coverage": "~2.2.0",
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.1.0",
"typescript": "~5.4"
}
}

View file

Before

Width:  |  Height:  |  Size: 948 B

After

Width:  |  Height:  |  Size: 948 B

Before After
Before After

View file

@ -1,5 +1,5 @@
{
"name": "@uppy-example/aws-companion",
"name": "example-aws-companion",
"version": "0.0.0",
"type": "module",
"dependencies": {

View file

@ -1,5 +1,5 @@
{
"name": "@uppy-example/aws-nodejs",
"name": "example-aws-nodejs",
"version": "1.0.0",
"description": "Uppy for AWS S3 with a custom Node.js backend for signing URLs",
"main": "index.js",

View file

@ -1,5 +1,5 @@
{
"name": "@uppy-example/aws-php",
"name": "example-aws-php",
"version": "0.0.0",
"dependencies": {
"@uppy/aws-s3": "workspace:*",

View file

@ -1,32 +0,0 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>uppy</title>
</head>
<body>
<style>
main {
padding-top: 50px;
text-align: center;
}
#upload-form {
max-width: 600px;
margin: auto;
text-align: left;
}
</style>
<main>
<h1>Uppy</h1>
<form id="upload-form" action="/">
<input type="file" />
<button type="submit">Upload</button>
</form>
</main>
<script src="index.js" type="module"></script>
</body>
</html>

View file

@ -1,72 +0,0 @@
import Uppy from '@uppy/core'
import Dashboard from '@uppy/dashboard'
import GoogleDrive from '@uppy/google-drive'
import Instagram from '@uppy/instagram'
import Tus from '@uppy/tus'
import Url from '@uppy/url'
import Webcam from '@uppy/webcam'
import '@uppy/core/dist/style.css'
import '@uppy/dashboard/dist/style.css'
import '@uppy/url/dist/style.css'
import '@uppy/webcam/dist/style.css'
const TUS_ENDPOINT = 'https://tusd.tusdemo.net/files/'
const uppy = new Uppy({
debug: true,
meta: {
username: 'John',
license: 'Creative Commons',
},
})
.use(Dashboard, {
trigger: '#pick-files',
target: '#upload-form',
inline: true,
metaFields: [
{ id: 'license', name: 'License', placeholder: 'specify license' },
{ id: 'caption', name: 'Caption', placeholder: 'add caption' },
],
showProgressDetails: true,
proudlyDisplayPoweredByUppy: true,
note: '2 files, images and video only',
restrictions: { requiredMetaFields: ['caption'] },
})
.use(GoogleDrive, {
target: Dashboard,
companionUrl: 'http://localhost:3020',
})
.use(Instagram, { target: Dashboard, companionUrl: 'http://localhost:3020' })
.use(Url, { target: Dashboard, companionUrl: 'http://localhost:3020' })
.use(Webcam, { target: Dashboard })
.use(Tus, { endpoint: TUS_ENDPOINT })
// You can optinally enable the Golden Retriever plugin — it will
// restore files after a browser crash / accidental closed window
// see more at https://uppy.io/docs/golden-retriever/
//
// .use(GoldenRetriever, { serviceWorker: true })
uppy.on('complete', (result) => {
if (result.failed.length === 0) {
console.log('Upload successful 😀')
} else {
console.warn('Upload failed 😞')
}
console.log('successful files:', result.successful)
console.log('failed files:', result.failed)
})
// uncomment if you enable Golden Retriever
//
// if ('serviceWorker' in navigator) {
// navigator.serviceWorker
// .register('/sw.js')
// .then((registration) => {
// console.log('ServiceWorker registration successful with scope: ', registration.scope)
// })
// .catch((error) => {
// console.log('Registration failed with ' + error)
// })
// }

View file

@ -1,22 +0,0 @@
{
"name": "@uppy-example/bundled",
"version": "0.0.0",
"dependencies": {
"@uppy/core": "workspace:*",
"@uppy/dashboard": "workspace:*",
"@uppy/google-drive": "workspace:*",
"@uppy/instagram": "workspace:*",
"@uppy/tus": "workspace:*",
"@uppy/url": "workspace:*",
"@uppy/webcam": "workspace:*"
},
"devDependencies": {
"parcel": "^2.0.0"
},
"private": true,
"type": "module",
"scripts": {
"build": "parcel build index.html",
"dev": "parcel index.html"
}
}

View file

@ -1,67 +0,0 @@
// This service worker is needed for Golden Retriever plugin,
// only include if youve enabled it
// https://uppy.io/docs/golden-retriever/
/* globals clients */
const fileCache = Object.create(null)
function getCache(name) {
if (!fileCache[name]) {
fileCache[name] = Object.create(null)
}
return fileCache[name]
}
self.addEventListener('install', (event) => {
console.log('Installing Uppy Service Worker...')
event.waitUntil(Promise.resolve().then(() => self.skipWaiting()))
})
self.addEventListener('activate', (event) => {
event.waitUntil(self.clients.claim())
})
function sendMessageToAllClients(msg) {
clients.matchAll().then((clients) => {
clients.forEach((client) => {
client.postMessage(msg)
})
})
}
function addFile(store, file) {
getCache(store)[file.id] = file.data
console.log('Added file blob to service worker cache:', file.data)
}
function removeFile(store, fileID) {
delete getCache(store)[fileID]
console.log('Removed file blob from service worker cache:', fileID)
}
function getFiles(store) {
sendMessageToAllClients({
type: 'uppy/ALL_FILES',
store,
files: getCache(store),
})
}
self.addEventListener('message', (event) => {
switch (event.data.type) {
case 'uppy/ADD_FILE':
addFile(event.data.store, event.data.file)
break
case 'uppy/REMOVE_FILE':
removeFile(event.data.store, event.data.fileID)
break
case 'uppy/GET_FILES':
getFiles(event.data.store)
break
default:
throw new Error('unreachable')
}
})

View file

@ -1,5 +1,5 @@
{
"name": "@uppy-example/cdn",
"name": "example-cdn",
"version": "0.0.0",
"private": true,
"scripts": {

View file

@ -1,5 +1,5 @@
{
"name": "@uppy-example/custom-provider",
"name": "example-companion-custom-provider",
"version": "0.0.0",
"type": "module",
"dependencies": {

View file

@ -1,5 +1,5 @@
{
"name": "@uppy-example/digitalocean-spaces",
"name": "example-companion-digitalocean-spaces",
"version": "0.0.0",
"type": "module",
"dependencies": {

View file

@ -1,5 +1,5 @@
{
"name": "@uppy-example/uppy-with-companion",
"name": "example-companion",
"version": "0.0.0",
"dependencies": {
"@uppy/companion": "workspace:*",

View file

@ -1,23 +0,0 @@
# Multiple Instances
This example uses Uppy with the `@uppy/golden-retriever` plugin. It has two
instances on the same page, side-by-side, but with different `id`s so their
stored files don't interfere with each other.
## Run it
To run this example, make sure you've correctly installed the **repository
root**:
```bash
corepack yarn install
corepack yarn build
```
That will also install the dependencies for this example.
Then, again in the **repository root**, start this example by doing:
```bash
corepack yarn workspace @uppy-example/multiple-instances start
```

View file

@ -1,33 +0,0 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Uppy example: Multiple instances</title>
<style>
main {
display: flex;
justify-content: space-around;
align-items: center;
}
h1 {
text-align: center;
}
</style>
</head>
<body>
<main>
<div>
<h1>Instance A</h1>
<div id="a"></div>
</div>
<div>
<h1>Instance B</h1>
<div id="b"></div>
</div>
</main>
<noscript>This app requires JavaScript to be enabled.</noscript>
<script src="./main.js" type="module"></script>
</body>
</html>

View file

@ -1,33 +0,0 @@
import Uppy from '@uppy/core'
import Dashboard from '@uppy/dashboard'
import GoldenRetriever from '@uppy/golden-retriever'
import '@uppy/core/dist/style.css'
import '@uppy/dashboard/dist/style.css'
// Initialise two Uppy instances with the GoldenRetriever plugin,
// but with different `id`s.
const a = new Uppy({
id: 'a',
debug: true,
})
.use(Dashboard, {
target: '#a',
inline: true,
width: 400,
})
.use(GoldenRetriever, { serviceWorker: false })
const b = new Uppy({
id: 'b',
debug: true,
})
.use(Dashboard, {
target: '#b',
inline: true,
width: 400,
})
.use(GoldenRetriever, { serviceWorker: false })
window.a = a
window.b = b

View file

@ -1,17 +0,0 @@
{
"name": "@uppy-example/multiple-instances",
"version": "0.0.0",
"type": "module",
"dependencies": {
"@uppy/core": "workspace:*",
"@uppy/dashboard": "workspace:*",
"@uppy/golden-retriever": "workspace:*"
},
"devDependencies": {
"vite": "^5.4.17"
},
"private": true,
"scripts": {
"start": "vite"
}
}

View file

@ -1,5 +1,5 @@
{
"name": "@uppy-example/react-native-expo",
"name": "example-react-native-expo",
"version": "1.0.0",
"main": "index.js",
"scripts": {

View file

@ -1,5 +1,5 @@
{
"name": "@uppy-example/react",
"name": "example-react",
"private": true,
"type": "module",
"scripts": {

View file

@ -1,5 +1,5 @@
{
"name": "@uppy-example/redux",
"name": "example-redux",
"version": "0.0.0",
"type": "module",
"dependencies": {

View file

@ -1,5 +1,5 @@
{
"name": "@uppy-example/sveltekit",
"name": "example-sveltekit",
"private": true,
"version": "0.0.1",
"type": "module",

View file

@ -1,21 +0,0 @@
# Uppy Markdown Editor
This example uses Uppy to handle images in a markdown editor.
## Run it
To run this example, make sure you've correctly installed the **repository
root**:
```sh
corepack yarn install
corepack yarn build
```
That will also install the dependencies for this example.
Then, again in the **repository root**, start this example by doing:
```sh
corepack yarn workspace @uppy-example/transloadit-markdown-bin start
```

View file

@ -1,173 +0,0 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<style>
body {
font-family: Roboto, 'Open Sans';
background: #f4f5f6;
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-family:
Oxygen,
Raleway,
Open Sans;
}
header {
width: 800px;
margin: auto;
}
header h1 {
text-align: center;
}
main {
background: white;
margin: auto;
width: 800px;
border: 2px solid #e8eaee;
padding: 36px;
border-radius: 5px;
}
main p:first-child {
margin-top: 0;
}
label {
display: flex;
padding-bottom: 16px;
border-bottom: 1px solid #e8eaee;
margin-bottom: 16px;
}
.label-text {
width: 25%;
text-transform: uppercase;
color: #888888;
line-height: 34px;
}
label input,
label textarea {
flex-grow: 1;
height: 34px;
}
label textarea {
box-sizing: border-box;
padding: 6px;
border-radius: 5px;
border: 1px solid #b7b7b4;
font-family:
Roboto,
Open Sans;
min-height: 160px;
width: 100%;
resize: vertical;
}
.form-createSnippet {
border: 1px solid #2e6da4;
border-bottom-width: 3px;
padding: 8px;
border-radius: 5px;
background-color: #337ab7;
color: white;
width: 100%;
}
.mdtxt {
width: 100%;
height: 100%;
}
.mdtxt-controls {
}
.mdtxt-upload {
box-sizing: border-box;
width: 100%;
border-radius: 0 0 5px 5px;
border: 1px solid #b7b7b4;
border-top-width: 0;
padding: 4px 8px;
cursor: pointer;
}
.mdtxt textarea {
margin-bottom: 0;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
.mdtxt-upload .error {
border-color: red;
color: red;
}
.mdtxt-upload .error .message {
margin-right: 8px;
}
.snippet {
margin-top: 25px;
}
</style>
</head>
<body>
<header>
<h1>Markdown Bin</h1>
</header>
<main>
<p>
Markdown Bin is a demo app that works a bit like Github Gists or
pastebin. You can add markdown snippets, and add file attachments to
each snippet by clicking "Upload an attachment" or by dragging files
onto the text area. Transloadit generates an inline preview image for
images, videos, and audio files.
<a
target="_blank"
href="https://github.com/transloadit/uppy/blob/main/examples/transloadit-textarea/template.json"
>&raquo;&nbsp;View the Assembly Template here.</a
>
</p>
<p>
⚠️ For this demo, snippets are stored locally in your browser.
Attachments are stored in Transloadit's temporary storage and expire
after about 24 hours. In a real app, you can easily export files to a
permanent storage solution like Amazon S3 or Google Cloud.
<a
target="_blank"
href="https://transloadit.com/docs/#17-saving-conversion-results"
>&raquo;&nbsp;Learn more</a
>
</p>
<form id="new">
<h2>Create a new snippet</h2>
<label>
<span class="label-text">Snippet Title</span>
<input type="text" name="title" placeholder="Snippet Title" />
</label>
<label>
<textarea name="snippet"></textarea>
</label>
<p>
<button class="form-createSnippet" type="submit">Create</button>
</p>
</form>
<h2>Previous snippets</h2>
<div id="snippets"></div>
</main>
<template id="snippet">
<div class="snippet">
<h3 class="snippet-title"></h3>
<div class="snippet-content"></div>
</div>
</template>
<noscript>This app requires JavaScript.</noscript>
<script src="./main.js" type="module"></script>
</body>
</html>

View file

@ -1,181 +0,0 @@
import Uppy from '@uppy/core'
import Dashboard from '@uppy/dashboard'
import DropTarget from '@uppy/drop-target'
import ImageEditor from '@uppy/image-editor'
import RemoteSources from '@uppy/remote-sources'
import Transloadit from '@uppy/transloadit'
import Webcam from '@uppy/webcam'
import { marked } from 'marked'
import '@uppy/core/dist/style.css'
import '@uppy/dashboard/dist/style.css'
import '@uppy/image-editor/dist/style.css'
const TRANSLOADIT_EXAMPLE_KEY = '35c1aed03f5011e982b6afe82599b6a0'
const TRANSLOADIT_EXAMPLE_TEMPLATE = '0b2ee2bc25dc43619700c2ce0a75164a'
function matchFilesAndThumbs(results) {
const filesById = {}
const thumbsById = {}
for (const [stepName, result] of Object.entries(results)) {
result.forEach((result) => {
if (stepName === 'thumbnails') {
thumbsById[result.original_id] = result
} else {
filesById[result.original_id] = result
}
})
}
return Object.keys(filesById).map((key) => ({
file: filesById[key],
thumb: thumbsById[key],
}))
}
/**
* A textarea for markdown text, with support for file attachments.
*/
class MarkdownTextarea {
constructor(element) {
this.element = element
this.controls = document.createElement('div')
this.controls.classList.add('mdtxt-controls')
this.uploadLine = document.createElement('button')
this.uploadLine.setAttribute('type', 'button')
this.uploadLine.classList.add('form-upload')
this.uploadLine.appendChild(
document.createTextNode('Tap here to upload an attachment'),
)
}
install() {
const { element } = this
const wrapper = document.createElement('div')
wrapper.classList.add('mdtxt')
element.parentNode.replaceChild(wrapper, element)
wrapper.appendChild(this.controls)
wrapper.appendChild(element)
wrapper.appendChild(this.uploadLine)
this.setupUppy()
}
setupUppy = () => {
this.uppy = new Uppy({ autoProceed: true })
.use(Transloadit, {
waitForEncoding: true,
params: {
auth: { key: TRANSLOADIT_EXAMPLE_KEY },
template_id: TRANSLOADIT_EXAMPLE_TEMPLATE,
},
})
.use(DropTarget, { target: this.element })
.use(Dashboard, { closeAfterFinish: true, trigger: '.form-upload' })
.use(ImageEditor, { target: Dashboard })
.use(Webcam, { target: Dashboard })
.use(RemoteSources, { companionUrl: Transloadit.COMPANION })
this.uppy.on('complete', (result) => {
const { successful, failed, transloadit } = result
if (successful.length !== 0) {
this.insertAttachments(matchFilesAndThumbs(transloadit[0].results))
} else {
failed.forEach((error) => {
console.error(error)
this.reportUploadError(error)
})
}
this.uppy.cancelAll()
})
}
reportUploadError(err) {
this.uploadLine.classList.add('error')
const message = document.createElement('span')
message.appendChild(document.createTextNode(err.message))
this.uploadLine.insertChild(message, this.uploadLine.firstChild)
}
unreportUploadError() {
this.uploadLine.classList.remove('error')
const message = this.uploadLine.querySelector('message')
if (message) {
this.uploadLine.removeChild(message)
}
}
insertAttachments(attachments) {
attachments.forEach((attachment) => {
const { file, thumb } = attachment
const link = `\n[LABEL](${file.ssl_url})\n`
const labelText = `View File ${file.basename}`
if (thumb) {
this.element.value += link.replace(
'LABEL',
`![${labelText}](${thumb.ssl_url})`,
)
} else {
this.element.value += link.replace('LABEL', labelText)
}
})
}
uploadFiles = (files) => {
const filesForUppy = files.map((file) => {
return {
data: file,
type: file.type,
name: file.name,
meta: file.meta || {},
}
})
this.uppy.addFiles(filesForUppy)
}
}
const textarea = new MarkdownTextarea(document.querySelector('#new textarea'))
textarea.install()
function renderSnippet(title, text) {
const template = document.querySelector('#snippet')
const newSnippet = document.importNode(template.content, true)
const titleEl = newSnippet.querySelector('.snippet-title')
const contentEl = newSnippet.querySelector('.snippet-content')
titleEl.appendChild(document.createTextNode(title))
contentEl.innerHTML = marked.parse(text)
const list = document.querySelector('#snippets')
list.insertBefore(newSnippet, list.firstChild)
}
function saveSnippet(title, text) {
const id = parseInt(localStorage.numSnippets || 0, 10)
localStorage[`snippet_${id}`] = JSON.stringify({ title, text })
localStorage.numSnippets = id + 1
}
function loadSnippets() {
for (let id = 0; localStorage[`snippet_${id}`] != null; id += 1) {
const { title, text } = JSON.parse(localStorage[`snippet_${id}`])
renderSnippet(title, text)
}
}
document.querySelector('#new').addEventListener('submit', (event) => {
event.preventDefault()
const title = event.target.elements.title.value || 'Unnamed Snippet'
const text = textarea.element.value
saveSnippet(title, text)
renderSnippet(title, text)
event.target.querySelector('input').value = ''
event.target.querySelector('textarea').value = ''
})
window.addEventListener('DOMContentLoaded', loadSnippets, { once: true })

View file

@ -1,22 +0,0 @@
{
"name": "@uppy-example/transloadit-markdown-bin",
"version": "0.0.0",
"type": "module",
"dependencies": {
"@uppy/core": "workspace:*",
"@uppy/dashboard": "workspace:*",
"@uppy/drop-target": "workspace:*",
"@uppy/image-editor": "workspace:*",
"@uppy/remote-sources": "workspace:*",
"@uppy/transloadit": "workspace:*",
"@uppy/webcam": "workspace:*",
"marked": "^12.0.0"
},
"devDependencies": {
"vite": "^5.4.17"
},
"private": true,
"scripts": {
"start": "vite"
}
}

View file

@ -1,5 +1,5 @@
{
"name": "@uppy-example/transloadit",
"name": "example-transloadit",
"version": "0.0.0",
"type": "module",
"devDependencies": {

View file

@ -1,5 +1,5 @@
{
"name": "@uppy-example/vue3",
"name": "example-vue",
"version": "0.0.0",
"private": true,
"type": "module",

View file

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

Before After
Before After

View file

@ -1,5 +1,5 @@
{
"name": "@uppy-example/xhr-bundle",
"name": "example-xhr-bundle",
"version": "0.0.0",
"dependencies": {
"@uppy/core": "workspace:*",

View file

@ -1,5 +1,5 @@
{
"name": "@uppy-example/node-xhr",
"name": "example-xhr-node",
"version": "0.0.0",
"type": "module",
"dependencies": {

View file

@ -1,5 +1,5 @@
{
"name": "@uppy-example/php-xhr",
"name": "example-xhr-php",
"version": "0.0.0",
"type": "module",
"dependencies": {

View file

@ -1,5 +1,5 @@
{
"name": "@uppy-example/python-xhr",
"name": "example-xhr-python",
"version": "0.0.0",
"type": "module",
"dependencies": {

Some files were not shown because too many files have changed in this diff Show more