diff --git a/cli/defaults/siteConfig.json b/cli/defaults/siteConfig.json index de2eca7b..15243fce 100644 --- a/cli/defaults/siteConfig.json +++ b/cli/defaults/siteConfig.json @@ -23,6 +23,7 @@ "publishing": { "primaryClaimAddress": null, "uploadDirectory": "/home/lbry/Uploads", + "lbrynetHome": "/home/lbry", "thumbnailChannel": null, "thumbnailChannelId": null, "additionalClaimAddresses": [], @@ -39,6 +40,18 @@ "maxSizeGif": 50000000, "maxSizeVideo": 50000000 }, + "serving": { + "markdownSettings": { + "skipHtml": true, + "privilegedDisallowedTypesDescriptions": ["Image"], + "privilegedDisallowedTypesMain": [], + "publicDisallowedTypesDescriptions": ["Image"], + "publicDisallowedTypesMain": [] + }, + "customFileExtensions": { + "application/example-type": "example" + } + }, "startup": { "performChecks": true, "performUpdates": true diff --git a/client/scss/_asset-display.scss b/client/scss/_asset-display.scss index cc338237..b6d8dae0 100644 --- a/client/scss/_asset-display.scss +++ b/client/scss/_asset-display.scss @@ -5,19 +5,10 @@ } .asset-document { - $asset-info-width: 1000px; - max-width: $asset-info-width; width: 100%; padding: $thin-padding; height: fit-content; - - @media (max-width: $break-point-tablet) { - margin: $primary-padding $secondary-padding; - } - - @media (max-width: $break-point-mobile) { - margin: $primary-padding 0; - } + box-sizing: border-box; } .asset-display { height: fit-content; diff --git a/client/scss/_label.scss b/client/scss/_label.scss index 2e92784a..41957add 100644 --- a/client/scss/_label.scss +++ b/client/scss/_label.scss @@ -2,13 +2,17 @@ padding-top: $thin-padding; padding-bottom: $thin-padding; display: inline-block; - font-size: 12px; + font-weight: bold; + font-size: $text-medium; + width: 100%; + box-sizing: border-box; } .label-radio { padding-left: $thin-padding; padding-right: $thin-padding; cursor: pointer; + font-weight: bold; } @media (max-width: $break-point-tablet ) { diff --git a/client/scss/_markdown.scss b/client/scss/_markdown.scss index 05b10c3c..ed972f03 100644 --- a/client/scss/_markdown.scss +++ b/client/scss/_markdown.scss @@ -8,14 +8,14 @@ h6 { font-size: inherit; font-weight: 600; - margin-bottom: var(--spacing-vertical-medium); - padding-top: var(--spacing-vertical-medium); + margin-bottom: $tertiary-padding; + padding-top: $tertiary-padding; } // Paragraphs p { font-size: 1.15rem; - margin-bottom: var(--spacing-vertical-medium); + margin-bottom: $tertiary-padding; white-space: pre-line; svg { @@ -28,15 +28,24 @@ } } + blockquote { + border-radius: 8px; + background: $blockquote-background; + padding: $tertiary-padding; + min-width: 60%; + } + // Strikethrough text del { } // Tables table { + width: 100%; margin-bottom: 1.2rem; - padding: var(--spacing-vertical-medium); background-color: $base-color; + border-spacing: 0; + border: .5px solid $chrome-color; tr { td, @@ -45,15 +54,32 @@ th:first-of-type, td:last-of-type, th:last-of-type { - padding: var(--spacing-vertical-medium); + padding: $thin-padding $tertiary-padding; + text-overflow: ellipsis; } + td:last-of-type { + text-align: right; + } + + th { + background: $chrome-color; + } + + } + tr:nth-child(even){ + background: $chrome-color; } } // Image img { - margin-bottom: var(--spacing-vertical-medium); - padding-top: var(--spacing-vertical-medium); + margin-bottom: $tertiary-padding; + margin-top: $tertiary-padding; + padding: $secondary-padding; + object-fit: scale-down; + max-width: 100%; + border: $subtle-border; + box-sizing: border-box; } // Horizontal Rule @@ -77,8 +103,8 @@ } code { - margin-bottom: var(--spacing-vertical-medium); - padding: var(--spacing-vertical-medium); + margin-bottom: $tertiary-padding; + padding: $tertiary-padding; background-color: $subtle-border-color; color: $text-color; @@ -94,7 +120,7 @@ // Lists ul, ol { - margin-bottom: var(--spacing-vertical-medium); + margin-bottom: $thin-padding; > li { list-style-position: outside; @@ -106,7 +132,7 @@ } li { - margin-left: var(--spacing-vertical-large); + margin-left: $primary-padding; p { display: inline-block; diff --git a/client/scss/_row.scss b/client/scss/_row.scss index 4fbdf10c..e9ae9ded 100644 --- a/client/scss/_row.scss +++ b/client/scss/_row.scss @@ -4,21 +4,21 @@ .row-labeled { display: flex; - flex-direction: row; + flex-direction: column; flex-wrap: nowrap; justify-content: flex-start; padding-bottom: $tertiary-padding; } .row-labeled-label { - width: 30%; + width: 100%; display: flex; align-items: center; flex: 1; } .row-labeled-content { align-self: center; - width: 70%; + width: 100%; } @media (max-width: $break-point-tablet ) { diff --git a/client/scss/_variables.scss b/client/scss/_variables.scss index 603e01b1..0722103d 100644 --- a/client/scss/_variables.scss +++ b/client/scss/_variables.scss @@ -2,6 +2,7 @@ $base-color: white; //default white $card-color: white; //default white $chrome-color: lightgray; //default white (navbar) +$blockquote-background: #EEEEFF; $background-color: $base-color; //text colors @@ -11,6 +12,7 @@ $text-color: #333; $success-color: green; $failure-color: red; $grey: #9095A5; +$blockquote-text: $text-color; //borders and highlights diff --git a/client/src/components/FileViewer/index.jsx b/client/src/components/FileViewer/index.jsx index 56f05453..0d3d4866 100644 --- a/client/src/components/FileViewer/index.jsx +++ b/client/src/components/FileViewer/index.jsx @@ -1,5 +1,6 @@ import React from 'react'; import ReactMarkdown from 'react-markdown'; +// TODO: get markdown settings from siteConfig class FileViewer extends React.Component { @@ -38,7 +39,7 @@ class FileViewer extends React.Component { <div className={'markdown'}> { this.state.fileLoaded && - <ReactMarkdown source={this.state.fileText}/> + <ReactMarkdown className={'markdown-preview'} source={this.state.fileText} skipHtml /> } { !this.state.fileLoaded && diff --git a/client/src/containers/AssetDisplay/view.jsx b/client/src/containers/AssetDisplay/view.jsx index 29c320ee..c12ad741 100644 --- a/client/src/containers/AssetDisplay/view.jsx +++ b/client/src/containers/AssetDisplay/view.jsx @@ -64,7 +64,7 @@ class AssetDisplay extends React.Component { if (typeof contentType === 'string') { fileExt = contentType.split('/')[1] || 'jpg'; } - const sourceUrl = `${createCanonicalLink({ asset: asset.claimData })}.${fileExt}?${outpoint}`; + const sourceUrl = `${createCanonicalLink({ asset: asset.claimData })}.${fileExt}?outpoint=${outpoint}`; return ( <div className={'asset-display'}> {(status === LOCAL_CHECK) && diff --git a/client/src/containers/AssetInfo/view.jsx b/client/src/containers/AssetInfo/view.jsx index 0f3a6187..c1e6154d 100644 --- a/client/src/containers/AssetInfo/view.jsx +++ b/client/src/containers/AssetInfo/view.jsx @@ -22,6 +22,7 @@ class AssetInfo extends React.Component { const canonicalUrl = createCanonicalLink({ asset: { ...claimData, shortId: asset.shortId }}); const assetCanonicalUrl = `${host}${canonicalUrl}`; // Todo Issue #882 centralize all this media type detection + // Todo get markdown settings from siteConfig const embedable = contentType.split('/')[0] === 'image' || contentType === 'video/mp4'; let channelCanonicalUrl; @@ -37,7 +38,7 @@ class AssetInfo extends React.Component { { description && ( <RowLabeled label={<Label value={'Description'} />} - content={<div className='asset-info__description'><ReactMarkdown source={description}/></div>} + content={<div className='asset-info__description'><ReactMarkdown className={'markdown-preview'} skipHtml disallowedTypes={['image']} source={description} /></div>} /> )} {editable && ( diff --git a/package-lock.json b/package-lock.json index 7fbffe40..bfd34b73 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5688,14 +5688,12 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, - "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -5710,20 +5708,17 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -5840,8 +5835,7 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "ini": { "version": "1.3.5", @@ -5853,7 +5847,6 @@ "version": "1.0.0", "bundled": true, "dev": true, - "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -5868,7 +5861,6 @@ "version": "3.0.4", "bundled": true, "dev": true, - "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -5876,14 +5868,12 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "minipass": { "version": "2.2.4", "bundled": true, "dev": true, - "optional": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -5902,7 +5892,6 @@ "version": "0.5.1", "bundled": true, "dev": true, - "optional": true, "requires": { "minimist": "0.0.8" } @@ -5983,8 +5972,7 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true, - "optional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -5996,7 +5984,6 @@ "version": "1.4.0", "bundled": true, "dev": true, - "optional": true, "requires": { "wrappy": "1" } @@ -6118,7 +6105,6 @@ "version": "1.0.2", "bundled": true, "dev": true, - "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -8519,16 +8505,16 @@ "integrity": "sha1-Eh+evEnjdm8xGnbh+hyAA8SwOqY=" }, "mime-db": { - "version": "1.36.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz", - "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==" + "version": "1.37.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.37.0.tgz", + "integrity": "sha512-R3C4db6bgQhlIhPU48fUtdVmKnflq+hRdad7IyKhtFj06VPNVdk2RhiYL3UjQIlso8L+YxAtFkobT0VK+S/ybg==" }, "mime-types": { - "version": "2.1.20", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz", - "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==", + "version": "2.1.21", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.21.tgz", + "integrity": "sha512-3iL6DbwpyLzjR3xHSFNFeb9Nz/M8WDkX33t1GFQnFOllWk8pOrh/LSrB5OXlnlW5P9LH73X6loW/eogc+F5lJg==", "requires": { - "mime-db": "~1.36.0" + "mime-db": "~1.37.0" } }, "mimic-fn": { diff --git a/package.json b/package.json index f0b37f13..8698d893 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "inquirer": "^5.2.0", "ip": "^1.1.5", "make-dir": "^1.3.0", + "mime-types": "^2.1.21", "module-alias": "^2.1.0", "mysql2": "^1.6.4", "npm": "^6.3.0", diff --git a/server/chainquery/models/ClaimModel.js b/server/chainquery/models/ClaimModel.js index 387e2e73..022656f9 100644 --- a/server/chainquery/models/ClaimModel.js +++ b/server/chainquery/models/ClaimModel.js @@ -1,40 +1,9 @@ const logger = require('winston'); - -const { - assetDefaults: { thumbnail: defaultThumbnail }, - details: { host }, -} = require('@config/siteConfig'); +const mime = require('mime-types'); const getterMethods = { generated_extension() { - switch (this.content_type) { - case 'image/jpeg': - case 'image/jpg': - return 'jpg'; - case 'image/png': - return 'png'; - case 'image/gif': - return 'gif'; - case 'image/svg+xml': - return 'svg'; - case 'video/mp4': - return 'mp4'; - case 'text/markdown': - return 'md'; - default: - logger.debug('setting unknown file type as file extension jpg'); - return 'jpg'; - } - }, - - // TODO: Factor this out. - generated_thumbnail() { - return this.thumbnail_url || defaultThumbnail; - }, - - generated_channel() { - console.log(this); - // + return mime.extension(this.content_type) ? mime.extension(this.content_type) : 'jpg'; }, }; diff --git a/server/utils/fetchClaimData.js b/server/utils/fetchClaimData.js index d192dfee..79bcf6a8 100644 --- a/server/utils/fetchClaimData.js +++ b/server/utils/fetchClaimData.js @@ -1,15 +1,15 @@ const chainquery = require('chainquery').default; const db = require('server/models'); -const fetchClaimData = async (params) => { +const fetchClaimData = async params => { let { claimId, claimName: name } = params; if (claimId === 'none') claimId = null; const [cq, local] = await Promise.all([ - chainquery.claim.queries.resolveClaim(name, claimId).then(res => res.dataValues).catch(() => {}), + chainquery.claim.queries.resolveClaim(name, claimId).catch(() => {}), db.Claim.resolveClaim(name, claimId).catch(() => {}), ]); - + // Todo: don't use localdb to get post publish content if (!cq && !local) { return null; } diff --git a/server/utils/getClaimData.js b/server/utils/getClaimData.js index 86385a96..f725f94e 100644 --- a/server/utils/getClaimData.js +++ b/server/utils/getClaimData.js @@ -1,52 +1,62 @@ -const { details: { host } } = require('@config/siteConfig'); +const { + details: { host }, + assetDefaults: { thumbnail }, +} = require('@config/siteConfig'); const chainquery = require('chainquery').default; -const { getClaim } = require('server/lbrynet'); +// const { getClaim } = require('server/lbrynet'); const { isBlocked } = require('./blockList'); module.exports = async (data, chName = null, chShortId = null) => { // TODO: Refactor getching the channel name out; requires invasive changes. - const certificateId = data.publisher_id || data.certificateId; - let lbrynetClaimResult = null; - let lbrynetFileExt = null; + const dataVals = data.dataValues ? data.dataValues : data; + const txid = dataVals.transaction_hash_id || dataVals.txid; + let nout; + + if (typeof dataVals.vout === 'number') { + nout = dataVals.vout; + } else { + nout = dataVals.nout; + } + + const outpoint = `${txid}:${nout}`; + const certificateId = dataVals.publisher_id || dataVals.certificateId; + const fileExt = data.generated_extension || dataVals.fileExt; + let channelShortId = chShortId; let channelName = chName; + // TODO: Factor blocked out let blocked; - const outPoint = `${data.transaction_hash_id}:${data.vout}`; - if (isBlocked(outPoint)) { + + if (isBlocked(outpoint)) { blocked = true; } if (!chName && certificateId && !channelName) { - channelName = await chainquery.claim.queries.getClaimChannelName(certificateId).catch(() => { - }); + channelName = await chainquery.claim.queries.getClaimChannelName(certificateId).catch(() => {}); } if (!chShortId && certificateId && channelName) { - channelShortId = await chainquery.claim.queries.getShortClaimIdFromLongClaimId(certificateId, channelName).catch(() => null); + channelShortId = await chainquery.claim.queries + .getShortClaimIdFromLongClaimId(certificateId, channelName) + .catch(() => null); } - if (!chName && !chShortId && !data.fileExt) { - const lbrynetUri = `${data.name}#${data.claim_id}`; - lbrynetClaimResult = await getClaim(lbrynetUri).catch(() => { - return 'invalid URI'; - }); - lbrynetFileExt = lbrynetClaimResult && lbrynetClaimResult.file_name && lbrynetClaimResult.file_name.includes('.') && lbrynetClaimResult.file_name.split('.').slice(-1).pop(); - } + // Find a solution for the legacy application/octet-stream file extensions - return ({ - name : data.name, - title : data.title, + return { + name: dataVals.name, + title: dataVals.title, certificateId, channelName, channelShortId, - contentType: data.content_type || data.contentType, - claimId : data.claim_id || data.claimId, - fileExt : data.generated_extension || data.fileExt || lbrynetFileExt, - description: data.description, - thumbnail : data.generated_thumbnail || data.thumbnail_url || data.thumbnail, - outpoint : outPoint || data.outpoint, + contentType: dataVals.content_type || data.contentType, + claimId: dataVals.claim_id || data.claimId, + fileExt: fileExt, + description: dataVals.description, + thumbnail: dataVals.thumbnail_url || data.thumbnail || thumbnail, + outpoint, host, - pending : Boolean(data.height === 0), - blocked : blocked, - }); + pending: Boolean(dataVals.height === 0), + blocked: blocked, + }; };