1
0
Fork 0

[mod] cleanup

This commit is contained in:
Andy Bunce 2024-05-08 21:11:24 +01:00
parent af2fac39b2
commit dd7b0c1d83
22 changed files with 72 additions and 875 deletions

View file

@ -1,4 +1,28 @@
# Pdfbox
BaseX (10+) interface to [Pdfbox](https://pdfbox.apache.org/) 3
BaseX (10+) interface to [Pdfbox](https://pdfbox.apache.org/) version 3
## Features
* read page count
* read outline
* read pagelabels
* read page text
* save pdf page range to new pdf
* save pdf page as image
Uses
* https://github.com/blikblum/slick-router#readme
* https://dev.to/blikblum/slick-router-a-powerful-router-for-web-components-3fck
## Sync
```
cd C:\Users\mrwhe\git\expkg-zone58\pdfbox\src\webapp\pdf
c:\DeltaCopy\rsync -rlptz --progress --exclude=.git --exclude=.vscode . andy@localhost::basexserv/
```
## Jars
* fontbox-3.0.2.jar
* pdfbox-3.0.2.jar
* pdfbox-io-3.0.2.jar
* commons-logging-1.3.1.jar
3.6 mb

View file

@ -1 +1 @@
{"cells":[{"kind":1,"language":"markdown","value":"# PDFBox3 \r\nA BaseX 10+ interface to Apache PDFBox® library version 3 \r\n## Apache PDFBox® - A Java PDF Library\r\n\r\nThe Apache PDFBox® library is an open source Java tool for working with PDF documents. This project allows creation of new PDF documents, manipulation of existing documents and the ability to extract content from documents. Apache PDFBox also includes several command-line utilities. Apache PDFBox is published under the Apache License v2.0.\r\nhttps://pdfbox.apache.org/"},{"kind":1,"language":"markdown","value":"It comes with the useful PDF debug tool `java -jar debugger-app-3.0.1.jar`"},{"kind":1,"language":"markdown","value":"## Set up XQuery context for following code..."},{"kind":2,"language":"xquery","value":"(:<:)(: XQuery Context :)\r\nimport module namespace pdfbox = \"urn:expkg-zone58:pdfbox3\" at \"../src/lib/pdfbox3.xqm\";\r\nimport module namespace bookpages = 'urn:bookpages' at \"../src/lib/bookpages.xqm\";\r\nimport module namespace pdfscrape = 'urn:pdfscrape' at \"../src/lib/pdfscrape.xqm\";\r\nimport module namespace config = 'urn:abc-clio:config' at 'C:\\Users\\mrwhe\\git\\bloomsbury\\content-architecture\\xquery\\ABC-CLIO/lib/abc-config.xqm';\r\n\r\ndeclare variable $samples:= map{\r\n \"climate\": \"drop-01d\\set\\2-6-1\\A5579C_1\\271989---Book_File-Web_PDF_9798400627484_486728.pdf\",\r\n \"women\": \"drop-01d\\set\\2-6-1\\A6229C_1\\257334---Book_File-Web_PDF_9798216172628_486742.pdf\",\r\n \"genocide\": \"drop1-pdf\\GR2967-TRD\\272791---Book_File-Web_PDF_9798400640216_486366.pdf\",\r\n \"world\": \"drop-01c\\gpg-book\\2-6\\A3506C-TRD\\256186---Book_File-Web_PDF_9798216038955_486148.pdf\"\r\n};\r\ndeclare variable $PDF:= (: $samples?women=>file:resolve-path($config:data) :)\r\n\"C:\\Users\\mrwhe\\git\\bloomsbury\\content-architecture\\xquery\\ABC-CLIO\\data\\drop-01e\\set\\2-6-1\\A5690C_1\\257107---Book_File-Web_PDF_9798400691218_486731.pdf\";"},{"kind":1,"language":"markdown","value":" ## Check pdfbox version"},{"kind":2,"language":"xquery","value":"pdfbox:version()"},{"kind":1,"language":"markdown","value":"PDF specification version used by document"},{"kind":2,"language":"xquery","value":"pdfbox:open($PDF)=>pdfbox:pdfVersion()"},{"kind":1,"language":"markdown","value":"# Page count for PDF"},{"kind":2,"language":"xquery","value":"pdfbox:open($PDF)=>pdfbox:page-count()"},{"kind":1,"language":"markdown","value":"# save range to new pdf"},{"kind":2,"language":"xquery","value":"pdfbox:open($PDF)=>pdfbox:extract(2,12,\"c:\\tmp\\a.pdf\")"},{"kind":1,"language":"markdown","value":"## Outline / bookmarks"},{"kind":1,"language":"markdown","value":"### sequence of maps"},{"kind":2,"language":"xquery","value":"\r\npdfbox:open($PDF)=>pdfbox:outline()"},{"kind":1,"language":"markdown","value":"XML"},{"kind":2,"language":"xquery","value":"pdfbox:open($PDF)=>pdfbox:outline()=>pdfbox:outline-xml()"},{"kind":1,"language":"markdown","value":"## Page labels"},{"kind":2,"language":"xquery","value":"\r\npdfbox:open($PDF)=>pdfbox:pageLabels()"},{"kind":1,"language":"markdown","value":"# getText from page index"},{"kind":2,"language":"xquery","value":"let $doc:=pdfbox:open($PDF)\r\nreturn pdfbox:getText($doc,56)"},{"kind":1,"language":"markdown","value":"# Page scraping"},{"kind":1,"language":"markdown","value":"## pdf scrape text analysis"},{"kind":2,"language":"xquery","value":"let $doc:=pdfbox:open($PDF)\r\nreturn pdfscrape:page-report($doc)\r\n"},{"kind":1,"language":"markdown","value":"## Inverted pageno map"},{"kind":2,"language":"xquery","value":"let $doc:=pdfbox:open($PDF)\r\nreturn pdfscrape:page-report($doc)=>pdfscrape:inverted-map()"},{"kind":1,"language":"markdown","value":"# Save images"},{"kind":2,"language":"xquery","value":"pdfbox:open($PDF)\r\n=> pdfbox:pageAsImage(0,0.25)\r\n=> pdfbox:imageSave(\"c:\\tmp\\page0.gif\",\"gif\")"},{"kind":1,"language":"markdown","value":"## report"},{"kind":2,"language":"xquery","value":"declare variable $a:=file:resolve-path(\"../data/1e/\",file:base-dir());\r\n\r\nfor $f in file:list($a,true(),\"*.pdf\") \r\nwhere not(contains($f,\"outputs\"))\r\nlet $doc:=pdfbox:open(file:resolve-path($f,$a))\r\n(: let $outline:=pdfbox:outline($doc) :)\r\nlet $count:=pdfbox:page-count($doc)\r\norder by $count \r\nreturn ``[`{$f}`: `{ $count }`]``"}]}
{"cells":[{"kind":1,"language":"markdown","value":"# PDFBox3 \r\nA BaseX 10+ interface to Apache PDFBox® library version 3 \r\n## Apache PDFBox® - A Java PDF Library\r\n\r\nThe Apache PDFBox® library is an open source Java tool for working with PDF documents. This project allows creation of new PDF documents, manipulation of existing documents and the ability to extract content from documents. Apache PDFBox also includes several command-line utilities. Apache PDFBox is published under the Apache License v2.0.\r\nhttps://pdfbox.apache.org/"},{"kind":1,"language":"markdown","value":"It comes with the useful PDF debug tool `java -jar debugger-app-3.0.2.jar`"},{"kind":1,"language":"markdown","value":"## Set up XQuery context for following code..."},{"kind":2,"language":"xquery","value":"(:<:)(: XQuery Context :)\r\nimport module namespace pdfbox = \"urn:expkg-zone58:pdfbox3\" at \"../src/lib/pdfbox3.xqm\";\r\nimport module namespace bookpages = 'urn:bookpages' at \"../src/lib/bookpages.xqm\";\r\nimport module namespace pdfscrape = 'urn:pdfscrape' at \"../src/lib/pdfscrape.xqm\";\r\nimport module namespace config = 'urn:abc-clio:config' at 'C:\\Users\\mrwhe\\git\\bloomsbury\\content-architecture\\xquery\\ABC-CLIO/lib/abc-config.xqm';\r\n\r\ndeclare variable $samples:= map{\r\n \"climate\": \"drop-01d\\set\\2-6-1\\A5579C_1\\271989---Book_File-Web_PDF_9798400627484_486728.pdf\",\r\n \"women\": \"drop-01d\\set\\2-6-1\\A6229C_1\\257334---Book_File-Web_PDF_9798216172628_486742.pdf\",\r\n \"genocide\": \"drop1-pdf\\GR2967-TRD\\272791---Book_File-Web_PDF_9798400640216_486366.pdf\",\r\n \"world\": \"drop-01c\\gpg-book\\2-6\\A3506C-TRD\\256186---Book_File-Web_PDF_9798216038955_486148.pdf\"\r\n};\r\ndeclare variable $PDF:= (: $samples?women=>file:resolve-path($config:data) :)\r\n\"C:\\Users\\mrwhe\\git\\bloomsbury\\content-architecture\\xquery\\ABC-CLIO\\data\\drop-01e\\set\\2-6-1\\A5690C_1\\257107---Book_File-Web_PDF_9798400691218_486731.pdf\";"},{"kind":1,"language":"markdown","value":" ## Check pdfbox version"},{"kind":2,"language":"xquery","value":"pdfbox:version()"},{"kind":1,"language":"markdown","value":"PDF specification version used by document"},{"kind":2,"language":"xquery","value":"pdfbox:open($PDF)=>pdfbox:pdfVersion()"},{"kind":1,"language":"markdown","value":"# Page count for PDF"},{"kind":2,"language":"xquery","value":"pdfbox:open($PDF)=>pdfbox:page-count()"},{"kind":1,"language":"markdown","value":"# save range to new pdf"},{"kind":2,"language":"xquery","value":"pdfbox:open($PDF)=>pdfbox:extract(2,12,\"c:\\tmp\\a.pdf\")"},{"kind":1,"language":"markdown","value":"## Outline / bookmarks"},{"kind":1,"language":"markdown","value":"### sequence of maps"},{"kind":2,"language":"xquery","value":"\r\npdfbox:open($PDF)=>pdfbox:outline()"},{"kind":1,"language":"markdown","value":"XML"},{"kind":2,"language":"xquery","value":"pdfbox:open($PDF)=>pdfbox:outline()=>pdfbox:outline-xml()"},{"kind":1,"language":"markdown","value":"## Page labels"},{"kind":2,"language":"xquery","value":"\r\npdfbox:open($PDF)=>pdfbox:pageLabels()"},{"kind":1,"language":"markdown","value":"# getText from page index"},{"kind":2,"language":"xquery","value":"let $doc:=pdfbox:open($PDF)\r\nreturn pdfbox:getText($doc,56)"},{"kind":1,"language":"markdown","value":"# Page scraping"},{"kind":1,"language":"markdown","value":"## pdf scrape text analysis"},{"kind":2,"language":"xquery","value":"let $doc:=pdfbox:open($PDF)\r\nreturn pdfscrape:page-report($doc)\r\n"},{"kind":1,"language":"markdown","value":"## Inverted pageno map"},{"kind":2,"language":"xquery","value":"let $doc:=pdfbox:open($PDF)\r\nreturn pdfscrape:page-report($doc)=>pdfscrape:inverted-map()"},{"kind":1,"language":"markdown","value":"# Save images"},{"kind":2,"language":"xquery","value":"pdfbox:open($PDF)\r\n=> pdfbox:pageBufferedImage(99,1)\r\n=>pdfbox:imageSave(\"c:\\tmp\\page3.png\",\"png\")\r\n"},{"kind":2,"language":"xquery","value":"pdfbox:open($PDF)\r\n=> pdfbox:pageBufferedImage(3,0.25)\r\n=>pdfbox:imageBinary(\"jpg\")"},{"kind":1,"language":"markdown","value":"## report"},{"kind":2,"language":"xquery","value":"declare variable $a:=file:resolve-path(\"../data/1e/\",file:base-dir());\r\n\r\nfor $f in file:list($a,true(),\"*.pdf\") \r\nwhere not(contains($f,\"outputs\"))\r\nlet $doc:=pdfbox:open(file:resolve-path($f,$a))\r\n(: let $outline:=pdfbox:outline($doc) :)\r\nlet $count:=pdfbox:page-count($doc)\r\norder by $count \r\nreturn ``[`{$f}`: `{ $count }`]``"},{"kind":2,"language":"xquery","value":"declare variable $a:=file:resolve-path(\"../data/1e/\",file:base-dir());\r\n\r\nfor $f at $pos in file:list($a,true(),\"*.pdf\") \r\nwhere not(contains($f,\"outputs\"))\r\nreturn pdfbox:open(file:resolve-path($f,$a))\r\n=> pdfbox:pageAsImage(0,0.25)\r\n=> pdfbox:imageSave(``[c:\\tmp\\titles\\p`{$pos}`.gif]``,\"gif\")"}]}

6
package-lock.json generated
View file

@ -1,6 +0,0 @@
{
"name": "pdfbox",
"lockfileVersion": 3,
"requires": true,
"packages": {}
}

20
package.json Normal file
View file

@ -0,0 +1,20 @@
{
"name": "pdfbox",
"version": "1.0.0",
"description": "A BaseX interface to Apache Pdfbox version 3",
"main": "index.js",
"directories": {
"doc": "docs"
},
"scripts": {
"test": "basex -t ."
},
"keywords": [
"pdf",
"xquery",
"basex",
"java"
],
"author": "Andy Bunce",
"license": "Apache-2.0"
}

View file

@ -1,5 +1,7 @@
# Example PDFs with pageLabels and outlines
## Sources
* [BaseX100.pdf](https://files.basex.org/releases/10.0/BaseX100.pdf)
* [icelandic-dictionary.pdf](http://css4.pub/2015/icelandic/dictionary.pdf)
* [page-numbers.pdf](https://www.w3.org/WAI/WCAG22/working-examples/pdf-page-numbers/page-numbers.pdf)
* [page-numbers.pdf](https://www.w3.org/WAI/WCAG22/working-examples/pdf-page-numbers/page-numbers).
* [Sentience-in-Cephalopod-Molluscs-and-Decapod-Crustaceans](https://www.lse.ac.uk/News/News-Assets/PDFs/2021/Sentience-in-Cephalopod-Molluscs-and-Decapod-Crustaceans-Final-Report-November-2021.pdfpdf)

1
src/lib/.xqdoca Normal file
View file

@ -0,0 +1 @@
<xqdoca xmlns="urn:quodatum:xqdoca" version="1.0"><source>.</source><target>xqdoca/</target></xqdoca>

View file

@ -244,12 +244,14 @@ as map(*){
)=>map:merge()
};
(:~ page (ZERO based) as image
@param $scale 1=72 dpi :)
declare function pdfbox:pageAsImage($doc as item(), $pageNo as xs:integer,$scale as xs:float)
(:~ java:bufferedImage for $pageNo using $scale times dpi= 72
@param $pageNo (ZERO based)
@param $scale 1=72 dpi
@return Java java.awt.image.BufferedImage object
:)
declare function pdfbox:pageBufferedImage($doc as item(), $pageNo as xs:integer,$scale as xs:float)
as item(){
PDFRenderer:new($doc)
=>PDFRenderer:renderImage($pageNo,$scale)
PDFRenderer:new($doc)=>PDFRenderer:renderImage($pageNo,$scale)
};
(:~ save bufferedimage to $dest
@ -258,3 +260,13 @@ declare function pdfbox:imageSave($bufferedImage as item(),$dest as xs:string,$t
as xs:boolean{
Q{java:javax.imageio.ImageIO}write($bufferedImage , $type, File:new($dest))
};
(:~ return image
@param $type = "gif","png" etc:)
declare function pdfbox:imageBinary($bufferedImage as item(),$type as xs:string)
as xs:base64Binary{
let $bytes:=Q{java:java.io.ByteArrayOutputStream}new()
let $_:=Q{java:javax.imageio.ImageIO}write($bufferedImage , $type, $bytes)
return Q{java:java.io.ByteArrayOutputStream}toByteArray($bytes)
=>convert:integers-to-base64()
};

View file

@ -5,26 +5,26 @@ pdfscrape:page-report($doc )=>pdfscrape:inverted-map()
module namespace pdfscrape = 'urn:pdfscrape';
import module namespace pdfbox="urn:expkg-zone58:pdfbox3" at "pdfbox3.xqm";
(: look for possible page number in first/last line of page text
(:~ page number regex
@todo last line and roman
1=Number system ( D=decimal, R=Roman)
2=Side L=left,R=right
:)
declare variable $pdfscrape:pats:=map{
declare %private variable $pdfscrape:pats:=map{
"DL": "^([1-9][0-9]*).*",
"DR": ".*[^0-9]([1-9][0-9]*)$",
"RL": "^([ivxlc]+).*",
"RR": ".*[^ivxlc]([ivxlc]+)$"
};
(: page-reports for all pages :)
(:~ page-reports for all pages :)
declare function pdfscrape:page-report($doc as item())
as element(page)*{
let $count:=pdfbox:page-count($doc)=>trace("Pages: ")
return (1 to $count )!pdfscrape:page-report($doc,.)
};
(: page-report for given page :)
(:~ page-report for given page :)
declare function pdfscrape:page-report($doc as item(), $page as xs:integer)
as element(page){
let $txt:=pdfbox:getText($doc,$page)
@ -35,7 +35,7 @@ as element(page){
return <page index="{ $page }">{ $found, $line1 }</page>
};
(: empty or attributes created by matching $style with $line1 :)
(:~ empty or attributes created by matching $style with $line1 :)
declare function pdfscrape:line-report($style as xs:string, $line1 as xs:string)
as attribute(*)*{
if(matches($line1,$pdfscrape:pats?($style)))

View file

@ -1,30 +0,0 @@
(:~
pdf
:)
module namespace api = 'pdf/api';
import module namespace functx = "http://www.functx.com";
(:~ list slugs :)
declare
%rest:path('/pdf/api/sources')
%output:method("json")
%output:json("format=xquery")
function api:apt() as map(*)
{
let $base:="C:/Users/mrwhe/git/expkg-zone58/pdfbox/data/"
let $d:="1e/"
let $f:=file:list($base || $d,true(),"*.pdf")[not(contains(.,"\outputs\"))]
return map{
"count": count($f),
"items": array{$f!api:path-info(.)}
}
};
declare function api:path-info($file as xs:string)
as map(*)
{
map{
"id": $file,
"slug":functx:substring-before-last($file,"\"),
"filename": file:name($file)
}
};

View file

@ -1,47 +0,0 @@
(:~
pdf
:)
module namespace pdf = 'pdf/common';
(:~
: Redirects to the start page.
: @return redirection
:)
declare
%rest:path('/pdf')
function pdf:home() as element() {
web:forward('/pdf/static/index.html')
};
declare
%rest:path('/pdf/{$file=.+}')
function pdf:spa($file)as element(){
pdf:home()
};
(:~
: Returns a file.
: @param $file file or unknown path
: @return rest binary data
:)
declare
%rest:path('/pdf/static/{$file=.+}')
%output:method('basex')
%perm:allow('public')
function pdf:file(
$file as xs:string
) as item()+ {
let $path := file:base-dir() || "static/" || $file
return if(file:exists($path))
then (
web:response-header(
map { 'media-type': web:content-type($path) },
map { 'Cache-Control': 'max-age=3600,public', 'Content-Length': file:size($path) }
),
file:read-binary($path)
)else
()
};

View file

@ -1,164 +0,0 @@
{
"name": "pdf",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"dependencies": {
"@shoelace-style/shoelace": "^2.15.0"
}
},
"node_modules/@ctrl/tinycolor": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-4.0.3.tgz",
"integrity": "sha512-e9nEVehVJwkymQpkGhdSNzLT2Lr9UTTby+JePq4Z2SxBbOQjY7pLgSouAaXvfaGQVSAaY0U4eJdwfSDmCbItcw==",
"engines": {
"node": ">=14"
}
},
"node_modules/@floating-ui/core": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.0.tgz",
"integrity": "sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==",
"dependencies": {
"@floating-ui/utils": "^0.2.1"
}
},
"node_modules/@floating-ui/dom": {
"version": "1.6.3",
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.3.tgz",
"integrity": "sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw==",
"dependencies": {
"@floating-ui/core": "^1.0.0",
"@floating-ui/utils": "^0.2.0"
}
},
"node_modules/@floating-ui/utils": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.1.tgz",
"integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q=="
},
"node_modules/@lit-labs/ssr-dom-shim": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.2.0.tgz",
"integrity": "sha512-yWJKmpGE6lUURKAaIltoPIE/wrbY3TEkqQt+X0m+7fQNnAv0keydnYvbiJFP1PnMhizmIWRWOG5KLhYyc/xl+g=="
},
"node_modules/@lit/react": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@lit/react/-/react-1.0.4.tgz",
"integrity": "sha512-6HBvk3AwF46z17fTkZp5F7/EdCJW9xqqQgYKr3sQGgoEJv0TKV1voWydG4UQQA2RWkoD4SHjy08snSpzyoyd0w==",
"peerDependencies": {
"@types/react": "17 || 18"
}
},
"node_modules/@lit/reactive-element": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.0.4.tgz",
"integrity": "sha512-GFn91inaUa2oHLak8awSIigYz0cU0Payr1rcFsrkf5OJ5eSPxElyZfKh0f2p9FsTiZWXQdWGJeXZICEfXXYSXQ==",
"dependencies": {
"@lit-labs/ssr-dom-shim": "^1.2.0"
}
},
"node_modules/@shoelace-style/animations": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@shoelace-style/animations/-/animations-1.1.0.tgz",
"integrity": "sha512-Be+cahtZyI2dPKRm8EZSx3YJQ+jLvEcn3xzRP7tM4tqBnvd/eW/64Xh0iOf0t2w5P8iJKfdBbpVNE9naCaOf2g==",
"funding": {
"type": "individual",
"url": "https://github.com/sponsors/claviska"
}
},
"node_modules/@shoelace-style/localize": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@shoelace-style/localize/-/localize-3.1.2.tgz",
"integrity": "sha512-Hf45HeO+vdQblabpyZOTxJ4ZeZsmIUYXXPmoYrrR4OJ5OKxL+bhMz5mK8JXgl7HsoEowfz7+e248UGi861de9Q=="
},
"node_modules/@shoelace-style/shoelace": {
"version": "2.15.0",
"resolved": "https://registry.npmjs.org/@shoelace-style/shoelace/-/shoelace-2.15.0.tgz",
"integrity": "sha512-Lcg938Y8U2VsHqIYewzlt+H1rbrXC4GRSUkTJgXyF8/0YAOlI+srd5OSfIw+/LYmwLP2Peyh398Kae/6tg4PDA==",
"dependencies": {
"@ctrl/tinycolor": "^4.0.2",
"@floating-ui/dom": "^1.5.3",
"@lit/react": "^1.0.0",
"@shoelace-style/animations": "^1.1.0",
"@shoelace-style/localize": "^3.1.2",
"composed-offset-position": "^0.0.4",
"lit": "^3.0.0",
"qr-creator": "^1.0.0"
},
"engines": {
"node": ">=14.17.0"
},
"funding": {
"type": "individual",
"url": "https://github.com/sponsors/claviska"
}
},
"node_modules/@types/prop-types": {
"version": "15.7.12",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz",
"integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==",
"peer": true
},
"node_modules/@types/react": {
"version": "18.2.74",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.74.tgz",
"integrity": "sha512-9AEqNZZyBx8OdZpxzQlaFEVCSFUM2YXJH46yPOiOpm078k6ZLOCcuAzGum/zK8YBwY+dbahVNbHrbgrAwIRlqw==",
"peer": true,
"dependencies": {
"@types/prop-types": "*",
"csstype": "^3.0.2"
}
},
"node_modules/@types/trusted-types": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
"integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="
},
"node_modules/composed-offset-position": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/composed-offset-position/-/composed-offset-position-0.0.4.tgz",
"integrity": "sha512-vMlvu1RuNegVE0YsCDSV/X4X10j56mq7PCIyOKK74FxkXzGLwhOUmdkJLSdOBOMwWycobGUMgft2lp+YgTe8hw=="
},
"node_modules/csstype": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
"peer": true
},
"node_modules/lit": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/lit/-/lit-3.1.2.tgz",
"integrity": "sha512-VZx5iAyMtX7CV4K8iTLdCkMaYZ7ipjJZ0JcSdJ0zIdGxxyurjIn7yuuSxNBD7QmjvcNJwr0JS4cAdAtsy7gZ6w==",
"dependencies": {
"@lit/reactive-element": "^2.0.4",
"lit-element": "^4.0.4",
"lit-html": "^3.1.2"
}
},
"node_modules/lit-element": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.0.4.tgz",
"integrity": "sha512-98CvgulX6eCPs6TyAIQoJZBCQPo80rgXR+dVBs61cstJXqtI+USQZAbA4gFHh6L/mxBx9MrgPLHLsUgDUHAcCQ==",
"dependencies": {
"@lit-labs/ssr-dom-shim": "^1.2.0",
"@lit/reactive-element": "^2.0.4",
"lit-html": "^3.1.2"
}
},
"node_modules/lit-html": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.1.2.tgz",
"integrity": "sha512-3OBZSUrPnAHoKJ9AMjRL/m01YJxQMf+TMHanNtTHG68ubjnZxK0RFl102DPzsw4mWnHibfZIBJm3LWCZ/LmMvg==",
"dependencies": {
"@types/trusted-types": "^2.0.2"
}
},
"node_modules/qr-creator": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/qr-creator/-/qr-creator-1.0.0.tgz",
"integrity": "sha512-C0cqfbS1P5hfqN4NhsYsUXePlk9BO+a45bAQ3xLYjBL3bOIFzoVEjs79Fado9u9BPBD3buHi3+vY+C8tHh4qMQ=="
}
}
}

View file

@ -1,5 +0,0 @@
{
"dependencies": {
"@shoelace-style/shoelace": "^2.15.0"
}
}

View file

@ -1,24 +0,0 @@
Uses
* https://github.com/blikblum/slick-router#readme
* https://dev.to/blikblum/slick-router-a-powerful-router-for-web-components-3fck
## Sync
```
cd C:\Users\mrwhe\git\expkg-zone58\pdfbox\src\webapp\pdf
c:\DeltaCopy\rsync -rlptz --progress --exclude=.git --exclude=.vscode . andy@localhost::basexserv/
```
## random html in markdown
<style>table, th, td {
border: 1px solid black;
border-collapse: collapse;
}</style>
<table >
<caption>Sample table</caption>
<tr>
<td>Foo</td>
</tr>
<tr>
<td>3</td>
</tr>
</table>

View file

@ -1,53 +0,0 @@
/* extracted from https://vuejs.org/v2/guide/transitions.html */
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.5s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
opacity: 0;
}
/* Enter and leave animations can use different */
/* durations and timing functions. */
.slide-fade-enter-active {
transition: all 0.3s ease;
}
.slide-fade-leave-active {
transition: all 0.8s cubic-bezier(1, 0.5, 0.8, 1);
}
.slide-fade-enter, .slide-fade-leave-to {
transform: translateX(1000px);
opacity: 0;
}
.bounce-enter {
opacity: 0;
}
.bounce-enter-active {
animation: bounce-in 0.8s;
}
.bounce-leave-active {
animation: bounce-in 0.8s reverse;
}
@keyframes bounce-in {
0% {
transform: scale(0);
}
80% {
transform: scale(1.1);
}
100% {
transform: scale(1);
}
}
router-outlet > * {
display: block;
}

View file

@ -1,290 +0,0 @@
import { withRouterLinks } from 'https://unpkg.com/slick-router@2.5.0/middlewares/router-links.js'
customElements.define('application-view',
class ApplicationView extends withRouterLinks(HTMLElement) {
constructor() {
super()
this.addEventListener('change', e => {
if (e.target.matches('#animation-type')) {
const animation = e.target.value
if (animation) {
this.outlet.setAttribute('animation', e.target.value)
} else {
this.outlet.removeAttribute('animation')
}
}
})
this.addEventListener('load', e => {
const data = e.detail;
notify(JSON.stringify(data.items[0]));
}
)
// Custom function to emit toast notifications
function notify(message, variant = 'primary', icon = 'info-circle', duration = 3000) {
const alert = Object.assign(document.createElement('sl-alert'), {
variant,
closable: true,
duration: duration,
innerHTML: `
<sl-icon name="${icon}" slot="icon"></sl-icon>
${message}
`
});
document.body.append(alert);
return alert.toast();
}
// Always escape HTML for text arguments!
function escapeHtml(html) {
const div = document.createElement('div');
div.textContent = html;
return div.innerHTML;
}
this.addEventListener('click', e => {
if (e.target.matches('#more-toast')) {
const alert = this.querySelector('#toaster')
notify(`This is custom toast `);
}
})
}
connectedCallback() {
super.connectedCallback()
this.innerHTML = `
<div class='App'>
<div class='App-header'>
<h1>Application</h1>
<ul class='Nav' routerlinks>
<li class='Nav-item'><a route="home" >Home</a></li>
<li class='Nav-item'><a route="tweets" >Tweets</a></li>
<li class='Nav-item'><a route="messages">Messages</a></li>
<li class='Nav-item'><a route="profile.index" param-user="scrobblemuch">Profile</a></li>
<li class='Nav-item'><a route="settings" >Settings</a></li>
</ul>
</div>
<router-outlet animation="fade"></router-outlet>
<div class="App-footer">
<div>
Animation
<select id="animation-type">
<option value="">None</option>
<option value="fade" selected>Fade</option>
<option value="slide-fade">Slide Fade</option>
<option value="bounce">Bounce</option>
</select>
<button id="more-toast">toast</button>
</div>
</div>
</div>
`
this.outlet = this.querySelector('router-outlet')
}
}
)
customElements.define('home-view',
class HomeView extends withRouterLinks(HTMLElement) {
connectedCallback() {
this.getModel();
}
getModel() {
return new Promise((res, rej) => {
fetch('/pdf/api/sources')
.then(data => data.json())
.then((json) => {
this.renderPosts(json);
res();
})
.catch((error) => rej(error));
})
}
renderPosts(data) {
const count = data.count
const shadowRoot = this.attachShadow({ mode: "open" });
const div = document.createElement("div", { class: "cards" });
shadowRoot.appendChild(div);
data.items.forEach(item => {
div.appendChild(Object.assign(
document.createElement('sl-card'), { class: "card", textContent: item.slug })
)
})
}
}
)
customElements.define('tweet-view',
class TweetView extends withRouterLinks(HTMLElement) {
connectedCallback() {
super.connectedCallback()
this.innerHTML = `
<div class='Home' routerlinks>
<h2>Tweets</h2>
<div class='Tweet'>
<div class='Tweet-author'>
<a route="profile.index" param-user="dan_abramov">Dan Abramov @dan_abramov</a>
</div>
<div class='Tweet-time'>12m12 minutes ago</div>
<div class='Tweet-content'>Another use case for \`this.context\` I think might be valid: forms. They're too painful right now.</div>
</div>
<div class='Tweet'>
<div class='Tweet-author'>
<a route="profile.index" param-user="afanasjevas">Eduardas Afanasjevas @afanasjevas</a>
</div>
<div class='Tweet-time'>12m12 minutes ago</div>
<div class='Tweet-content'>I just published What will Datasmoothie bring to the analytics startup landscape? https://medium.com/@afanasjevas/what-will-datasmoothie-bring-to-the-analytics-startup-landscape-f7dab70d75c3?source=tw-81c4e81fe6f8-1427630532296</div>
</div>
<div class='Tweet'>
<div class='Tweet-author'>
<a route="profile.index" param-user="LNUGorg">LNUG @LNUGorg</a>
</div>
<div class='Tweet-time'>52m52 minutes ago</div>
<div class='Tweet-content'> new talks uploaded on our YouTube page - check them out http://bit.ly/1yoXSAO</div>
</div>
</div>
`
}
}
)
customElements.define('messages-view',
class MessagesView extends HTMLElement {
connectedCallback() {
this.innerHTML = `
<div class='Messages'>
<h2>Messages</h2>
<p>You have no direct messages</p>
<sl-tree>
<sl-tree-item lazy>Available Trees</sl-tree-item>
</sl-tree>
<script type="module">
const lazyItem = document.querySelector('sl-tree-item[lazy]');
lazyItem.addEventListener('sl-lazy-load', () => {
alert("heelo");
});
</script>
</div>
`
}
}
)
customElements.define('settings-view',
class SettingsView extends HTMLElement {
connectedCallback() {
this.innerHTML = `
<div class='Messages'>
<a href="/pdf/api/sources" target="_blank">DATA</a>
<h2>Settings</h2>
<div>
Animation
<select id="animation-type2">
<option value="">None</option>
<option value="fade" selected>Fade</option>
<option value="slide-fade">Slide Fade</option>
<option value="bounce">Bounce</option>
</select>
</div>
<sl-alert variant="neutral" duration="3000" closable >
<sl-icon slot="icon" name="gear"></sl-icon>
<strong>Your settings have been updated</strong><br />
Settings will take effect on next login.
</sl-alert>
<fetch-json src='/pdf/api/sources'/>
</div>
`
}
}
)
customElements.define('profile-view',
class ProfileView extends HTMLElement {
static get outlet() {
return '.Container'
}
connectedCallback() {
this.innerHTML = `
<div class='Profile'>
<div class='Container'></div>
</div>
`
}
}
)
customElements.define('profile-index-view',
class ProfileIndexView extends HTMLElement {
connectedCallback() {
this.innerHTML = `
<div class='ProfileIndex'>
<h2>${this.$route.params.user} profile</h2>
</div>
`
}
}
)
customElements.define('cards-panel',
class CardPanel extends HTMLElement {
constructor(){
super();
const template = document.createElement('template');
template.id = 'pool-calculator-template';
template.innerHTML = `
<style>
</style>
<div class="input-section">
<!-- ... -->
</div>
`;
}
connectedCallback() {
this.innerHTML = `
<div class='ProfileIndex'>
<h2>${this.$route.params.user} profile</h2>
</div>
`
}
}
)
customElements.define('fetch-json',
class FetchJson extends HTMLElement {
static observedAttributes = ["src", "size"];
connectedCallback() {
this.getModel();
}
getModel() {
const src = this.getAttribute('src')
+ "?" + new URLSearchParams({ foo: 'value', bar: 2, });
return new Promise((res, rej) => {
fetch(src)
.then(data => data.json())
.then((json) => {
this.data=data;
this.renderPosts(json);
res();
})
.catch((error) => rej(error));
})
}
renderPosts(data) {
this.innerHTML = `<span>${this.getAttribute('src')} : ${data.count}</span>`;
this.dispatchEvent(new CustomEvent("load", {
detail: data,
composed: true,
bubbles: true
}));
}
}
)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -1,24 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<base href="/pdf/static/" />
<title>PDFS453 </title>
<link rel="icon" href="favicon.png">
<link rel="stylesheet" href="/static/shoelace@2.15.0/cdn/themes/light.css" />
<script type="module" src="/static/shoelace@2.15.0/cdn/shoelace-autoloader.js"></script>
<script type="module" src="/static/shoelace@2.15.0/cdn/components/alert/alert.js"></script>
<script type="module" src="index.js"></script>
<link rel="stylesheet" href="styles.css" />
<link rel="stylesheet" href="animations.css" />
</head>
<body>
</body>
</html>

View file

@ -1,43 +0,0 @@
import { Router } from 'https://unpkg.com/slick-router@2.5.0/slick-router.js?module'
import { wc } from 'https://unpkg.com/slick-router@2.5.0/middlewares/wc.js'
import { events } from 'https://unpkg.com/slick-router@2.5.0/middlewares/events.js'
import { routerLinks } from 'https://unpkg.com/slick-router@2.5.0/middlewares/router-links.js'
import { AnimatedOutlet } from 'https://unpkg.com/slick-router@2.5.0/components/animated-outlet.js'
import './components.js'
customElements.define('router-outlet', AnimatedOutlet)
// create the router
const router = new Router({
pushState: true,
log: true
})
// provide your route map
// in this particular case we configure components by its tag name
router.map(route => {
route('application', { path: '/pdf/',
component: 'application-view' }, () => {
route('home', { path: '', component: 'home-view' })
route('tweets', { component: 'tweet-view' })
route('messages', { component: 'messages-view' })
route('status', { path: ':user/status/:id' })
route('profile', { path: 'profile/:user', component: 'profile-view' }, () => {
route('profile.index', { path: '', component: 'profile-index-view' })
route('profile.lists')
route('profile.edit')
})
route('settings',{path: 'settings',component:'settings-view'})
})
})
// install middleware that will handle transitions
router.use(wc)
router.use(routerLinks)
router.use(events)
// start listening to browser's location bar changes
router.listen()

View file

@ -1,97 +0,0 @@
@import url('https://fonts.googleapis.com/css?family=Open+Sans:400,700');
body,
html {
margin: 0;
padding: 0;
font-family: 'Open Sans', sans-serif;
}
sl-card {
display: flex;
width: 100px;
}
.App {
width: 800px;
margin: 0 auto 20px auto;
}
.App-header {
border-bottom: 1px solid #eee;
}
.App-header .active {
font-weight: bolder;
}
.App-footer {
position: fixed;
left: 0;
bottom: 0;
width: 100%;
padding-bottom: 20px;
text-align: center;
background-color: bisque;
}
.App h1 {
display: inline-block;
}
.Nav {
display: inline-block;
}
.Nav-item {
list-style: none;
display: inline-block;
}
.Nav-item a {
padding: 10px;
}
.Tweet {
border: 1px solid #eee;
border-radius: 3px;
padding: 10px;
border-bottom: none;
}
.Tweet:last-child {
border-bottom: 1px solid #eee;
}
.Tweet-author {
font-weight: bold;
display: inline-block;
}
.Tweet-time {
color: #888;
display: inline-block;
margin-left: 20px;
font-size: 12px;
}
router-outlet > * {
display: block;
}
.card-header {
max-width: 300px;
}
.card-header [slot='header'] {
display: flex;
align-items: center;
justify-content: space-between;
}
.card-header h3 {
margin: 0;
}
.card-header sl-icon-button {
font-size: var(--sl-font-size-medium);
}

View file

@ -1,47 +0,0 @@
customElements.define('summary-display',
class extends HTMLElement {
constructor() {
super();
const template = document.getElementById('summary-display-template');
const templateContent = template.content;
const shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.appendChild(templateContent.cloneNode(true));
const items = Array.from(this.querySelectorAll('li'));
const descriptions = Array.from(this.querySelectorAll('p'));
items.forEach(item => {
handleClick(item);
});
function handleClick(item) {
item.addEventListener('click', function() {
items.forEach(item => {
item.style.backgroundColor = 'white';
});
descriptions.forEach(description => {
updateDisplay(description, item);
});
});
}
function updateDisplay(description, item) {
description.removeAttribute('slot');
if(description.getAttribute('data-name') === item.textContent) {
description.setAttribute('slot', 'choice');
item.style.backgroundColor = '#bad0e4';
}
}
const slots = this.shadowRoot.querySelectorAll('slot');
slots[1].addEventListener('slotchange', function(e) {
const nodes = slots[1].assignedNodes();
console.log(`Element in Slot "${slots[1].name}" changed to "${nodes[0].outerHTML}".`);
});
}
}
);

View file

@ -1,32 +0,0 @@
<!doctype html>
<script type="module">
import { define, store, html } from 'https://esm.sh/hybrids@^8';
const User = {
id: true,
res: null,
firstName: "",
lastName: "",
[store.connect]: {
get: id => fetch(`http://localhost:8080/pdf/api/sources`)
.then(data => data.json())
.then(res=> { "43"})
},
};
define({
tag: "user-details",
user: store(User),
render: ({ user }) => html`
<div>
${store.pending(user) && `Loading...`}
${store.error(user) && `Something went wrong...`}
${store.ready(user) && html`
<p>${user.id} ${user.lastName}</p>
`}
</div>
`,
});
</script>
<user-details user="2"></user-details>