From b5bb56b64737cedca8f4c592a3dfbb2f7800cb03 Mon Sep 17 00:00:00 2001 From: Johannes Zillmann Date: Wed, 22 Mar 2017 07:19:21 +0100 Subject: [PATCH] [WIP] parse metadata & display title --- src/javascript/components/App.jsx | 3 +- src/javascript/components/LoadingView.jsx | 85 +++++++++++++++-------- src/javascript/components/TopBar.jsx | 10 ++- src/javascript/models/AppState.jsx | 8 ++- src/javascript/models/Metadata.jsx | 17 +++++ 5 files changed, 88 insertions(+), 35 deletions(-) create mode 100644 src/javascript/models/Metadata.jsx diff --git a/src/javascript/components/App.jsx b/src/javascript/components/App.jsx index 747b043..fa660d3 100644 --- a/src/javascript/components/App.jsx +++ b/src/javascript/components/App.jsx @@ -37,9 +37,10 @@ export default class App extends React.Component { throw `View ${this.props.appState.mainView} not supported!`; } + const title = appState.metadata ? appState.metadata.title : ''; return (
- +
{ mainView } diff --git a/src/javascript/components/LoadingView.jsx b/src/javascript/components/LoadingView.jsx index 411388b..6de289c 100644 --- a/src/javascript/components/LoadingView.jsx +++ b/src/javascript/components/LoadingView.jsx @@ -4,6 +4,7 @@ import FaCheck from 'react-icons/lib/fa/check' import pdfjs from 'pdfjs-dist'; // eslint-disable-line no-unused-vars import { Line } from 'rc-progress'; +import Metadata from '../models/Metadata.jsx'; import Page from '../models/Page.jsx'; import TextItem from '../models/TextItem.jsx'; @@ -17,21 +18,38 @@ export default class LoadingView extends React.Component { constructor(props) { super(props); + + const progress = new Progress({ + stages: [ + new ProgressStage('Parsing Metadata', 2), + new ProgressStage('Parsing Pages'), + new ProgressStage('Parsing Fonts') + ] + }); + Progress.prototype.metadataStage = () => { + return progress.stages[0] + }; + Progress.prototype.pageStage = () => { + return progress.stages[1] + }; + Progress.prototype.fontStage = () => { + return progress.stages[2] + }; this.state = { + document: null, + metadata: null, pages: [], fontIds: new Set(), fontMap: new Map(), - progress: new Progress({ - stages: [ - new ProgressStage('Parsing PDF Pages'), - new ProgressStage('Parsing Fonts') - ] - }), + progress: progress, }; } - announceInitialParse(document) { - const pageStage = this.state.progress.stages[0]; + documentParsed(document) { + const metadataStage = this.state.progress.metadataStage(); + const pageStage = this.state.progress.pageStage(); + metadataStage.stepsDone++; + const numPages = document.numPages; pageStage.steps = numPages; pageStage.stepsDone; @@ -49,15 +67,24 @@ export default class LoadingView extends React.Component { }); } - announcePageParsed(index, textItems) { - const pageStage = this.state.progress.stages[0]; - const fontStage = this.state.progress.stages[1]; + metadataParsed(metadata) { + const metadataStage = this.state.progress.metadataStage(); + metadataStage.stepsDone++; + // console.debug(new Metadata(metadata)); + this.setState({ + metadata: new Metadata(metadata), + }); + } + + pageParsed(index, textItems) { + const pageStage = this.state.progress.pageStage(); + const fontStage = this.state.progress.fontStage(); + const self = this; textItems.forEach(item => { const fontId = item.font; if (!this.state.fontIds.has(fontId)) { - const announceFontFunction = this.announceFontParsed.bind(this); this.state.document.transport.commonObjs.get(fontId, function(font) { - announceFontFunction(fontId, font); + self.fontParsed(fontId, font); }); this.state.fontIds.add(fontId); fontStage.steps = this.state.fontIds.size; @@ -71,11 +98,11 @@ export default class LoadingView extends React.Component { }); } - announceFontParsed(fontId, font) { - const fontStage = this.state.progress.stages[1]; + fontParsed(fontId, font) { + const fontStage = this.state.progress.fontStage(); this.state.fontMap.set(fontId, font); // eslint-disable-line react/no-direct-mutation-state - fontStage.stepsDone = fontStage.stepsDone + 1; - if (this.state.progress.currentStage == 1) { + fontStage.stepsDone++; + if (this.state.progress.activeStage() === fontStage) { this.setState({ //force rendering fontMap: this.state.fontMap, }); @@ -83,20 +110,20 @@ export default class LoadingView extends React.Component { } componentWillMount() { - const announceInitialParseFunction = this.announceInitialParse.bind(this); - const announcePageParsedFunction = this.announcePageParsed.bind(this); - + const self = this; PDFJS.getDocument(this.props.fileBuffer).then(function(pdfDocument) { // eslint-disable-line no-undef // console.debug(pdfDocument); - announceInitialParseFunction(pdfDocument); + pdfDocument.getMetadata().then(function(metadata) { + // console.debug(metadata); + self.metadataParsed(metadata); + }); + self.documentParsed(pdfDocument); for (var j = 1; j <= pdfDocument.numPages; j++) { pdfDocument.getPage(j).then(function(page) { + // console.debug(page); var scale = 1.0; var viewport = page.getViewport(scale); - // pdfDocument.getMetadata().then(function(data) { - // console.debug(data); - // }); page.getTextContent().then(function(textContent) { // console.debug(textContent); const textItems = textContent.items.map(function(item) { @@ -116,7 +143,7 @@ export default class LoadingView extends React.Component { font: item.fontName }); }); - announcePageParsedFunction(page.pageIndex, textItems); + self.pageParsed(page.pageIndex, textItems); }); page.getOperatorList().then(function() { // do nothing... this is only for triggering the font retrieval @@ -127,10 +154,10 @@ export default class LoadingView extends React.Component { } render() { - const {pages, progress} = this.state; + const {pages, fontMap, metadata, progress} = this.state; const percentDone = getPercentDone(progress); if (percentDone == 100) { - this.props.storePdfPagesFunction(pages, this.state.fontMap); + this.props.storePdfPagesFunction(metadata, fontMap, pages); } const stageItems = progress.stages.filter((elem, i) => i <= progress.currentStage).map((stage, i) => { const progressDetails = stage.steps ? stage.stepsDone + ' / ' + stage.steps : ''; @@ -193,10 +220,10 @@ class Progress { class ProgressStage { - constructor(name) { + constructor(name, steps) { this.name = name; + this.steps = steps ; this.stepsDone = 0; - this.steps; } isComplete() { diff --git a/src/javascript/components/TopBar.jsx b/src/javascript/components/TopBar.jsx index 1423002..dfe3c0b 100644 --- a/src/javascript/components/TopBar.jsx +++ b/src/javascript/components/TopBar.jsx @@ -16,10 +16,11 @@ export default class TopBar extends React.Component { static propTypes = { mainView: React.PropTypes.object.isRequired, switchMainViewFunction: React.PropTypes.func.isRequired, + title: React.PropTypes.string.isRequired, }; render() { - const {mainView, switchMainViewFunction} = this.props; + const {mainView, switchMainViewFunction, title} = this.props; const aboutPopover = (

@@ -61,8 +62,13 @@ export default class TopBar extends React.Component { } + + + { title } + + - ); + ); } } \ No newline at end of file diff --git a/src/javascript/models/AppState.jsx b/src/javascript/models/AppState.jsx index 1aa3473..759a82f 100644 --- a/src/javascript/models/AppState.jsx +++ b/src/javascript/models/AppState.jsx @@ -24,8 +24,9 @@ export default class AppState { this.renderFunction = options.renderFunction; this.mainView = View.UPLOAD; this.fileBuffer; - this.pages = []; + this.metadata; this.fontMap; + this.pages = []; this.transformations = [ new CalculateGlobalStats(), new CompactLines(), @@ -63,9 +64,10 @@ export default class AppState { this.render() } - storePdfPages(pages, fontMap) { - this.pages = pages; + storePdfPages(metadata, fontMap, pages) { + this.metadata = metadata; this.fontMap = fontMap; + this.pages = pages; this.fileBuffer = null; this.mainView = View.RESULT; this.render(); diff --git a/src/javascript/models/Metadata.jsx b/src/javascript/models/Metadata.jsx new file mode 100644 index 0000000..47c37e6 --- /dev/null +++ b/src/javascript/models/Metadata.jsx @@ -0,0 +1,17 @@ +// Metadata of the PDF document +export default class Metadata { + + constructor(originalMetadata) { + if (originalMetadata.metadata) { + this.title = originalMetadata.metadata.get('dc:title'); + this.creator = originalMetadata.metadata.get('xap:creatortool') + this.producer = originalMetadata.metadata.get('pdf:producer') + } else { + this.title = originalMetadata.info.Title; + this.author = originalMetadata.info.Author; + this.creator = originalMetadata.info.Creator; + this.producer = originalMetadata.info.Producer; + } + } + +}