This commit is contained in:
commit
2fd4e104b8
1
.dockerignore
Symbolic link
1
.dockerignore
Symbolic link
@ -0,0 +1 @@
|
||||
.gitignore
|
20
.drone.yml
Normal file
20
.drone.yml
Normal file
@ -0,0 +1,20 @@
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: default
|
||||
|
||||
steps:
|
||||
- name: deploy
|
||||
image: caprover/cli-caprover:2.2.3
|
||||
commands:
|
||||
- caprover deploy
|
||||
environment:
|
||||
CAPROVER_URL:
|
||||
from_secret: caprover_url
|
||||
CAPROVER_APP:
|
||||
from_secret: caprover_app
|
||||
CAPROVER_APP_TOKEN:
|
||||
from_secret: app_token
|
||||
CAPROVER_BRANCH: main
|
||||
when:
|
||||
branch:
|
||||
- main
|
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
/node_modules/
|
||||
/public/build/
|
||||
|
||||
.DS_Store
|
11
Dockerfile
Normal file
11
Dockerfile
Normal file
@ -0,0 +1,11 @@
|
||||
FROM node AS build
|
||||
|
||||
ARG CAPROVER_GIT_COMMIT_SHA=""
|
||||
WORKDIR /app
|
||||
COPY . /app
|
||||
RUN npm install && \
|
||||
npm run build
|
||||
|
||||
FROM nginx
|
||||
COPY --from=build /app/public /usr/share/nginx/html
|
||||
|
4
captain-definition
Normal file
4
captain-definition
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"schemaVersion": 2,
|
||||
"dockerfilePath": "./Dockerfile"
|
||||
}
|
1088
package-lock.json
generated
Normal file
1088
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
32
package.json
Normal file
32
package.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "pf2e-cards",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "rollup -c",
|
||||
"dev": "rollup -c -w",
|
||||
"start": "sirv public --no-clear",
|
||||
"check": "svelte-check --tsconfig ./tsconfig.json"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rollup/plugin-commonjs": "^17.0.0",
|
||||
"@rollup/plugin-node-resolve": "^11.0.0",
|
||||
"rollup": "^2.3.4",
|
||||
"rollup-plugin-css-only": "^3.1.0",
|
||||
"rollup-plugin-livereload": "^2.0.0",
|
||||
"rollup-plugin-svelte": "^7.0.0",
|
||||
"rollup-plugin-terser": "^7.0.0",
|
||||
"svelte": "^3.0.0",
|
||||
"svelte-check": "^2.0.0",
|
||||
"svelte-preprocess": "^4.0.0",
|
||||
"@rollup/plugin-typescript": "^8.0.0",
|
||||
"typescript": "^4.0.0",
|
||||
"tslib": "^2.0.0",
|
||||
"@tsconfig/svelte": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"dompurify": "^2.3.6",
|
||||
"lz-string": "^1.4.4",
|
||||
"sirv-cli": "^2.0.0"
|
||||
}
|
||||
}
|
BIN
public/bg.webp
Normal file
BIN
public/bg.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 105 KiB |
BIN
public/favicon.png
Normal file
BIN
public/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
63
public/global.css
Normal file
63
public/global.css
Normal file
@ -0,0 +1,63 @@
|
||||
html, body {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
color: #333;
|
||||
margin: 0;
|
||||
padding: 8px;
|
||||
box-sizing: border-box;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
||||
}
|
||||
|
||||
a {
|
||||
color: rgb(0,100,200);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: rgb(0,80,160);
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
}
|
||||
|
||||
input, button, select, textarea {
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
-webkit-padding: 0.4em 0;
|
||||
padding: 0.4em;
|
||||
margin: 0 0 0.5em 0;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
input:disabled {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
button {
|
||||
color: #333;
|
||||
background-color: #f4f4f4;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
button:disabled {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
button:not(:disabled):active {
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
||||
button:focus {
|
||||
border-color: #666;
|
||||
}
|
17
public/index.html
Normal file
17
public/index.html
Normal file
@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
<meta name='viewport' content='width=device-width,initial-scale=1'>
|
||||
|
||||
<title>Svelte app</title>
|
||||
|
||||
<link rel='icon' type='image/png' href='/favicon.png'>
|
||||
<link rel='stylesheet' href='/build/bundle.css'>
|
||||
|
||||
<script defer src='/build/bundle.js'></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
83
rollup.config.js
Normal file
83
rollup.config.js
Normal file
@ -0,0 +1,83 @@
|
||||
import svelte from 'rollup-plugin-svelte';
|
||||
import commonjs from '@rollup/plugin-commonjs';
|
||||
import resolve from '@rollup/plugin-node-resolve';
|
||||
import livereload from 'rollup-plugin-livereload';
|
||||
import { terser } from 'rollup-plugin-terser';
|
||||
import sveltePreprocess from 'svelte-preprocess';
|
||||
import typescript from '@rollup/plugin-typescript';
|
||||
import css from 'rollup-plugin-css-only';
|
||||
|
||||
const production = !process.env.ROLLUP_WATCH;
|
||||
|
||||
function serve() {
|
||||
let server;
|
||||
|
||||
function toExit() {
|
||||
if (server) server.kill(0);
|
||||
}
|
||||
|
||||
return {
|
||||
writeBundle() {
|
||||
if (server) return;
|
||||
server = require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
|
||||
stdio: ['ignore', 'inherit', 'inherit'],
|
||||
shell: true
|
||||
});
|
||||
|
||||
process.on('SIGTERM', toExit);
|
||||
process.on('exit', toExit);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default {
|
||||
input: 'src/main.ts',
|
||||
output: {
|
||||
sourcemap: true,
|
||||
format: 'iife',
|
||||
name: 'app',
|
||||
file: 'public/build/bundle.js'
|
||||
},
|
||||
plugins: [
|
||||
svelte({
|
||||
preprocess: sveltePreprocess({ sourceMap: !production }),
|
||||
compilerOptions: {
|
||||
// enable run-time checks when not in production
|
||||
dev: !production
|
||||
}
|
||||
}),
|
||||
// we'll extract any component CSS out into
|
||||
// a separate file - better for performance
|
||||
css({ output: 'bundle.css' }),
|
||||
|
||||
// If you have external dependencies installed from
|
||||
// npm, you'll most likely need these plugins. In
|
||||
// some cases you'll need additional configuration -
|
||||
// consult the documentation for details:
|
||||
// https://github.com/rollup/plugins/tree/master/packages/commonjs
|
||||
resolve({
|
||||
browser: true,
|
||||
dedupe: ['svelte']
|
||||
}),
|
||||
commonjs(),
|
||||
typescript({
|
||||
sourceMap: !production,
|
||||
inlineSources: !production
|
||||
}),
|
||||
|
||||
// In dev mode, call `npm run start` once
|
||||
// the bundle has been generated
|
||||
!production && serve(),
|
||||
|
||||
// Watch the `public` directory and refresh the
|
||||
// browser on changes when not in production
|
||||
!production && livereload('public'),
|
||||
|
||||
// If we're building for production (npm run build
|
||||
// instead of npm run dev), minify
|
||||
production && terser()
|
||||
],
|
||||
watch: {
|
||||
clearScreen: false
|
||||
}
|
||||
};
|
106
src/App.svelte
Normal file
106
src/App.svelte
Normal file
@ -0,0 +1,106 @@
|
||||
<script lang="ts">
|
||||
import Card from './Card.svelte';
|
||||
import CardInput from './CardInput.svelte';
|
||||
|
||||
import LZString from 'lz-string';
|
||||
|
||||
const MAX_CARDS = 9;
|
||||
let cards = [];
|
||||
let mhp = {
|
||||
name: "Minor healing potion",
|
||||
type: "Item 1",
|
||||
tags: ["Consumable", "Healing", "Magical", "Necromancy", "Positive", "Potion"],
|
||||
attributes: `<p><b>Usage</b> Held in 1 hand; <b>Bulk</b> L</p>
|
||||
<p><b>Activate (A)</b> Interact</p>`,
|
||||
description: `<p>A healing potion is a vial of a ruby-red liquid that imparts a tingling sensation as the drinker’s wounds heal rapidly. When you drink a healing potion, you regain 2d8+5 Hit Points.</p>`
|
||||
};
|
||||
|
||||
if (window.location.hash !== "") {
|
||||
debugger;
|
||||
cards = JSON.parse(LZString.decompressFromEncodedURIComponent(window.location.hash.substring(1)));
|
||||
} else {
|
||||
cards = [{id: 0, ...mhp}];
|
||||
}
|
||||
|
||||
function get_idx_by_id(id) {
|
||||
for(let idx = 0; idx < cards.length; idx++) {
|
||||
if(id === cards[idx].id) {
|
||||
return idx
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//let card_selected = 0;
|
||||
//$: selected_card = cards[card_selected];
|
||||
|
||||
let selector = cards[0].id;
|
||||
//$: selector = cards[card_selected].id;
|
||||
$: selected_card = cards.filter(x => x.id === selector)[0];
|
||||
$: selected_idx = get_idx_by_id(selector);
|
||||
|
||||
$: window.location.hash = LZString.compressToEncodedURIComponent(JSON.stringify(cards));
|
||||
|
||||
function change_tags(e) {
|
||||
selected_card.tags = e.detail.tags.split(',').map(x => x.replace(/\s+/g, '')).filter(x => x != '');
|
||||
cards[selected_idx] = selected_card;
|
||||
}
|
||||
|
||||
function add_card() {
|
||||
if (cards.length < MAX_CARDS) {
|
||||
cards = [...cards, {id: cards[cards.length-1].id+1, ...mhp}];
|
||||
selector = cards[cards.length-1].id;
|
||||
}
|
||||
}
|
||||
|
||||
function remove_card() {
|
||||
console.log(cards);
|
||||
console.log(selected_idx);
|
||||
if (cards.length > 1) { // remove only if there is more than 1 card
|
||||
cards = cards.filter(x => x.id != selector);
|
||||
if (selected_idx >= cards.length) {
|
||||
selector = cards[cards.length-1].id;
|
||||
} else {
|
||||
selector = cards[selected_idx].id;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<section class="controls">
|
||||
<h1>PF2e card generator</h1>
|
||||
<CardInput bind:name={selected_card.name} bind:type={selected_card.type} tags={selected_card.tags} bind:attributes={selected_card.attributes} bind:description={selected_card.description} on:change_tags={change_tags} on:add_card={add_card} on:remove_card={remove_card}/>
|
||||
</section>
|
||||
<section class="cards">
|
||||
{#each cards as card, idx (card.id)}
|
||||
<div class="card">
|
||||
<Card {...card}/>
|
||||
<input class="card-selector" type="radio" bind:group={selector} value={card.id}/>
|
||||
</div>
|
||||
{/each}
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<style>
|
||||
@media print {
|
||||
@page {
|
||||
margin: 0;
|
||||
}
|
||||
.controls {
|
||||
display: none;
|
||||
}
|
||||
.card-selector {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.cards {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
h1 {
|
||||
text-transform: uppercase;
|
||||
font-size: 4em;
|
||||
font-weight: 100;
|
||||
}
|
||||
|
||||
</style>
|
75
src/Card.svelte
Normal file
75
src/Card.svelte
Normal file
@ -0,0 +1,75 @@
|
||||
<script lang="ts">
|
||||
import DOMPurify from 'dompurify';
|
||||
export let name:string, type, tags = [], attributes:string, description:string;
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.card {
|
||||
width: 2.5in;
|
||||
height: 3.5in;
|
||||
font-size: 8pt;
|
||||
border: 2mm solid black;
|
||||
/*background-image: url("/bg.webp");*/
|
||||
background-clip: border-box;
|
||||
page-break-after: auto;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
.header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
border-bottom: 2px solid black;
|
||||
}
|
||||
.name, .type {
|
||||
font-family: serif;
|
||||
font-size: 10pt;
|
||||
font-weight: bold;
|
||||
}
|
||||
.tags {
|
||||
margin: 1pt 1pt 0pt 1pt;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.tag {
|
||||
font-family: sans-serif;
|
||||
font-size: 6pt;
|
||||
font-variant: all-small-caps;
|
||||
color: white;
|
||||
background-color: #5e0000;
|
||||
padding: 0.5pt 1pt;
|
||||
border: 1pt solid #d9c484;
|
||||
}
|
||||
.content {
|
||||
margin: 1pt;
|
||||
}
|
||||
:global(section.content p) {
|
||||
padding-bottom: 2pt;
|
||||
margin: 0;
|
||||
}
|
||||
.description {
|
||||
border-top: 1pt solid black;
|
||||
text-align: justify;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
<div class="card">
|
||||
<section class="header">
|
||||
<div class="name">{name}</div>
|
||||
<div class="type">{type}</div>
|
||||
</section>
|
||||
<section class="tags">
|
||||
{#each tags as tag}
|
||||
<div class="tag">{tag}</div>
|
||||
{/each}
|
||||
</section>
|
||||
<section class="content">
|
||||
<p class="attributes">
|
||||
{@html DOMPurify.sanitize(attributes)}
|
||||
</p>
|
||||
<p class="description">
|
||||
{@html DOMPurify.sanitize(description)}
|
||||
</p>
|
||||
</section>
|
||||
</div>
|
||||
|
35
src/CardInput.svelte
Normal file
35
src/CardInput.svelte
Normal file
@ -0,0 +1,35 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
export let name, type, tags, attributes, description;
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
function change_tags(e) {
|
||||
dispatch("change_tags", {tags: e.target.value});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
div.cardInput {
|
||||
width: 5in;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="cardInput">
|
||||
<div class="row">Name: <input name="name" bind:value={name}/></div>
|
||||
<div class="row">Type: <input name="type" bind:value={type}/></div>
|
||||
<div class="row">Tags: <input name="tags" on:change={change_tags} value={tags}/></div>
|
||||
<div class="row">Attributes:
|
||||
<textarea bind:value={attributes}></textarea>
|
||||
</div>
|
||||
<div class="row">Description:
|
||||
<textarea bind:value={description}></textarea>
|
||||
</div>
|
||||
<div class="row">
|
||||
<button on:click={e => dispatch('add_card')}>+</button>
|
||||
<button on:click={e => dispatch('remove_card')}>-</button>
|
||||
</div>
|
||||
</div>
|
1
src/global.d.ts
vendored
Normal file
1
src/global.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
/// <reference types="svelte" />
|
7
src/main.ts
Normal file
7
src/main.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import App from './App.svelte';
|
||||
|
||||
const app = new App({
|
||||
target: document.body,
|
||||
});
|
||||
|
||||
export default app;
|
6
tsconfig.json
Normal file
6
tsconfig.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"extends": "@tsconfig/svelte/tsconfig.json",
|
||||
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules/*", "__sapper__/*", "public/*"]
|
||||
}
|
Loading…
Reference in New Issue
Block a user