Skip to content

Commit

Permalink
merged with master
Browse files Browse the repository at this point in the history
  • Loading branch information
WardCunningham committed Feb 14, 2023
2 parents 6c8b87a + 8abd91e commit b1e6b22
Show file tree
Hide file tree
Showing 21 changed files with 348 additions and 13,520 deletions.
4 changes: 2 additions & 2 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ module.exports = function (grunt) {
src: ['./client.coffee'],
dest: 'client/client.max.js',
options: {
transform: [['coffeeify', {transpile: {presets: ['@babel/preset-env']}}]],
transform: [['coffeeify', {transpile: {presets: ['@babel/preset-env'], plugins: ['@babel/plugin-transform-runtime']}}]],
browserifyOptions: {
extensions: ".coffee"
}
Expand All @@ -71,7 +71,7 @@ module.exports = function (grunt) {
src: ['./testclient.coffee'],
dest: 'client/test/testclient.js',
options: {
transform: [['coffeeify', {transpile: {presets: ['@babel/preset-env']}}]],
transform: [['coffeeify', {transpile: {presets: ['@babel/preset-env'], plugins: ['@babel/plugin-transform-runtime']}}]],
browserifyOptions: {
extensions: ".coffee"
}
Expand Down
80 changes: 70 additions & 10 deletions client/style/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@ footer {
.story {
padding-bottom: 5px; }

.story .item {
min-width: 40px;
}

.story code {
background: rgba(0,0,0,0.04);
padding: 0.2em 0.4em;
Expand All @@ -171,15 +175,59 @@ footer {
.image {
overflow: auto; /* clearfix hack */
float: right;
margin-left: 0.4em;
margin-left: 1.4px;
margin-bottom: 0.4em;
background: #eeeeee;
padding: 0.8em;
width: 42%;
}
padding: 11.2px;
width: 183px;
}

.image.wide {
width: 100%;
margin-left: 0em;
padding: 0em;
padding-bottom: 0.8em;
float: none;
}

.image.left {
float: left;
margin-left: 0em;
margin-right: 2.8px;
}

.image :is(.thumbnail, .wide) {
width: 100%;
}

/* image overlay */

div.image {
position: relative;
}

.image img.overlay {
width: 16px;
height: 16px;
position: relative;
bottom: 22px;
right: 2px; /* or -2px without float */
float: right;
opacity: 0;
transition: .7s ease;
}

.image:hover img.overlay {
opacity: 1;
}

/* image plugin editor */

.imageEditing #image-options {
margin-left: 4px;
}

.image .thumbnail {
width: 100%; }
/* end image plugin editor */

.backlinks {
width: 420px;
Expand Down Expand Up @@ -212,7 +260,6 @@ footer {
/* margin-top: 2px; */
clear: both;
background-color: #eeeeee;
overflow: auto;
padding: 1px;
}

Expand Down Expand Up @@ -406,10 +453,17 @@ div.pending-remove.page {
position: relative;
}

.factory,
textarea {
.factory {
font-size: inherit;
width: 100%;
min-height: 150px;
}

textarea {
font-size: inherit;
margin-left: 2px;
resize: vertical;
width: calc(100% - 12px);
min-height: 150px; }

.clickable:hover {
Expand All @@ -422,6 +476,11 @@ textarea {
padding: 0; }
}

* {
scrollbar-width: thin;
scrollbar-color: #ccc #eee;
}

::-webkit-scrollbar {
width: 10px;
height: 10px;
Expand Down Expand Up @@ -471,7 +530,7 @@ textarea {
.revision {
position: relative;
font-size: 24px;
color: rgba(128,32,16,0.7); #7b2106
color: rgba(128,32,16,0.7); /* #7b2106 */
font-weight: bold; }

.revision span {
Expand All @@ -482,6 +541,7 @@ textarea {
text-align: center;
top: -40px;
right: 10px;
transform: rotate(-15deg);
-webkit-transform: rotate(-15deg);
-moz-transform: rotate(-15deg);

Expand Down
2 changes: 2 additions & 0 deletions lib/actionSymbols.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ symbols =
fork: ''
move: ''
remove: ''
copyIn: ''
copyOut: ''

fork = symbols['fork']
add = symbols['add']
Expand Down
12 changes: 7 additions & 5 deletions lib/addToJournal.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,17 @@ actionSymbols = require './actionSymbols'

module.exports = ($journal, action) ->
$page = $journal.parents('.page:first')
title = ''
title += "#{action.site}\n" if action.site?
title += action.type || 'separator'
title += " #{util.formatElapsedTime(action.date)}" if action.date?
$action = $("""<a href="#" /> """).addClass("action").addClass(action.type || 'separator')
.text(action.symbol || actionSymbols.symbols[action.type])
.attr('title',title)
.attr('title',util.formatActionTitle(action))
.attr('data-id', action.id || "0")
.attr('data-date', action.date || "0")
.data('action', action)
if action.type is 'add' and action.attribution?
$action.text(actionSymbols.symbols['copyIn'])
$action.css("background-image", "url(#{wiki.site(action.attribution.site).flag()})") if action.attribution.site?
if action.type is 'remove' and action.removedTo?
$action.text(actionSymbols.symbols['copyOut'])
controls = $journal.children('.control-buttons')
if controls.length > 0
$action.insertBefore(controls)
Expand Down
11 changes: 10 additions & 1 deletion lib/drop.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,13 @@ isPage = (url) ->

isImage = (url) ->
parsedURL = nurl.parse(url, true, true)
if parsedURL.pathname.match(/\.(jpg|jpeg|png|svg)$/i)
if parsedURL.pathname.match(/\.(jpg|jpeg|png)$/i)
return url
null

isSvg = (url) ->
parsedURL = nurl.parse(url, true, true)
if parsedURL.pathname.match(/\.(svg)$/i)
return url
null

Expand Down Expand Up @@ -77,6 +83,9 @@ dispatch = (handlers) ->
if image = isImage url
if (handle = handlers.image)?
return stop handle image
if svg = isSvg url
if (handle = handlers.svg)?
return stop handle svg
punt = {url}
if file = isFile event
if (handle = handlers.file)?
Expand Down
146 changes: 51 additions & 95 deletions lib/factory.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -107,30 +107,60 @@ bind = ($item, item) ->
addRemoteImage = (url) ->
# give some feedback, in case this is going to take a while...
document.documentElement.style.cursor = 'wait'
fetchRemoteImage(url)
.then (dataURL) ->
resizeImage dataURL
.then (resizedImageURL) ->
document.documentElement.style.cursor = 'default'
item.type = 'image'
item.url = resizedImageURL
item.source = url
item.caption ||= "Remote image"
syncEditAction()

fetch(url)
.then (response) ->
if response.ok
return response.blob()
throw new Error('Unable to fetch image')
.then (imageBlob) ->
imageFileName = url.split('/').pop().split('#')[0].split('?')[0]
# not sure if converting to file gives anything!
# imageFile = new File([imageBlob], imageFileName, { type: imageBlob.type })
reader = new FileReader()
reader.readAsDataURL(imageBlob)
reader.onload = (loadEvent) ->
imageDataURL = loadEvent.target.result
window.plugins['image'].editor({ imageDataURL, filename: imageFileName, imageSourceURL: url, imageCaption: "Remote image [#{url} source]", $item, item })


addRemoteSvg = (url) ->
document.documentElement.style.cursor = 'wait'
fetch(url)
.then (response) ->
if response.ok
return response
throw new Error('Unable to fetch svg')
.then (response) ->
return response.text()
.then (svgText) ->
document.documentElement.style.cursor = 'default'
item.type = 'html'
item.source = url
item.text = svgText + "<p>[#{url} Source]</p>"
syncEditAction()



readFile = (file) ->
if file?
[majorType, minorType] = file.type.split("/")
reader = new FileReader()
if majorType == "image"
reader.onload = (loadEvent) ->
resizeImage loadEvent.target.result
.then (resizedImageURL) ->
item.type = 'image'
item.url = resizedImageURL
item.caption ||= "Uploaded image"
# svg -> html plugin
if minorType.startsWith('svg')
reader.onload = (loadEvent) ->
result = loadEvent.target.result
item.type = 'html'
item.text = result
syncEditAction()
reader.readAsDataURL(file)
reader.readAsText(file)
else
reader.onload = (loadEvent) ->
console.log('upload file', file)
imageDataURL = loadEvent.target.result
window.plugins['image'].editor({ imageDataURL, filename: file.name, imageCaption: "Uploaded image" , $item, item})
reader.readAsDataURL(file)
else if majorType == "text"
reader.onload = (loadEvent) ->
result = loadEvent.target.result
Expand All @@ -153,6 +183,9 @@ bind = ($item, item) ->
lastModified: file.lastModified

$item.dblclick (e) ->

return unless $('.editEnable').is(':visible')

if e.shiftKey
editor.textEditor $item, item, {field: 'prompt'}
else
Expand All @@ -167,6 +200,7 @@ bind = ($item, item) ->
file: readFile
video: addVideo
image: addRemoteImage
svg: addRemoteSvg
punt: punt

# from http://www.bennadel.com/blog/1504-Ask-Ben-Parsing-CSV-Strings-With-Javascript-Exec-Regular-Expression-Command.htm
Expand Down Expand Up @@ -197,82 +231,4 @@ arrayToJson = (array) ->
(rowToObject row for row in array)


fetchRemoteImage = (url) ->
arrayBufferToBase64 = (buffer) ->
binary = ''
bytes = [].slice.call(new Uint8Array(buffer))
bytes.forEach((b) -> binary += String.fromCharCode(b));
return window.btoa(binary);

fetch(url)
.then (response) ->
if response.ok
return response
throw new Error('Unable to fetch image')
.then (response) ->
response.arrayBuffer()
.then (buffer) ->
imgStr = 'data:image/jpeg;base64,'
imgStr += arrayBufferToBase64(buffer)
return imgStr

.catch (error) ->
console.log 'Unable to fetch remote image'



# from https://web.archive.org/web/20140327091827/http://www.benknowscode.com/2014/01/resizing-images-in-browser-using-canvas.html
# Patrick Oswald version from comment, coffeescript and further simplification for wiki

resizeImage = (dataURL) ->
src = new Image
cW = undefined
cH = undefined
# target size
tW = 500
tH = 300
# image quality
imageQuality = 0.5

smallEnough = (img) ->
img.width <= tW or img.height <= tH

new Promise (resolve) ->
src.src = dataURL
src.onload = ->
resolve()
.then () ->
cW = src.naturalWidth
cH = src.naturalHeight
.then () ->
# determine size for first squeeze
return if smallEnough src

oversize = Math.max 1, Math.min cW/tW, cH/tH
iterations = Math.floor Math.log2 oversize
prescale = oversize / 2**iterations

cW = Math.round(cW / prescale)
cH = Math.round(cH / prescale)

.then () ->
new Promise (resolve) ->
tmp = new Image
tmp.src = src.src
tmp.onload = ->
if smallEnough tmp
return resolve dataURL
canvas = document.createElement('canvas')
canvas.width = cW
canvas.height = cH
context = canvas.getContext('2d')
context.drawImage tmp, 0, 0, cW, cH
dataURL = canvas.toDataURL('image/jpeg', imageQuality)
cW /= 2
cH /= 2
tmp.src = dataURL
.then ->
return dataURL


module.exports = {emit, bind}
Loading

0 comments on commit b1e6b22

Please sign in to comment.