Merge pull request #10771 from timvandermeij/annotation-dates
[api-minor] Implement creation/modification date for annotations
This commit is contained in:
commit
83f6de3cf8
@ -226,6 +226,10 @@ invalid_file_error=Invalid or corrupted PDF file.
|
||||
missing_file_error=Missing PDF file.
|
||||
unexpected_response_error=Unexpected server response.
|
||||
|
||||
# LOCALIZATION NOTE (annotation_date_string): "{{date}}" and "{{time}}" will be
|
||||
# replaced by the modification date, and time, of the annotation.
|
||||
annotation_date_string={{date}}, {{time}}
|
||||
|
||||
# LOCALIZATION NOTE (text_annotation_type.alt): This is used as a tooltip.
|
||||
# "{{type}}" will be replaced with an annotation type from a list defined in
|
||||
# the PDF spec (32000-1:2008 Table 169 – Annotation types).
|
||||
|
@ -226,6 +226,10 @@ invalid_file_error=Ongeldig of beschadigd PDF-bestand.
|
||||
missing_file_error=PDF-bestand ontbreekt.
|
||||
unexpected_response_error=Onverwacht serverantwoord.
|
||||
|
||||
# LOCALIZATION NOTE (annotation_date_string): "{{date}}" and "{{time}}" will be
|
||||
# replaced by the modification date, and time, of the annotation.
|
||||
annotation_date_string={{date}}, {{time}}
|
||||
|
||||
# LOCALIZATION NOTE (text_annotation_type.alt): This is used as a tooltip.
|
||||
# "{{type}}" will be replaced with an annotation type from a list defined in
|
||||
# the PDF spec (32000-1:2008 Table 169 – Annotation types).
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
import {
|
||||
AnnotationBorderStyleType, AnnotationFieldFlag, AnnotationFlag,
|
||||
AnnotationType, OPS, stringToBytes, stringToPDFString, Util, warn
|
||||
AnnotationType, isString, OPS, stringToBytes, stringToPDFString, Util, warn
|
||||
} from '../shared/util';
|
||||
import { Catalog, FileSpec, ObjectLoader } from './obj';
|
||||
import { Dict, isDict, isName, isRef, isStream } from './primitives';
|
||||
@ -176,6 +176,8 @@ class Annotation {
|
||||
constructor(params) {
|
||||
let dict = params.dict;
|
||||
|
||||
this.setCreationDate(dict.get('CreationDate'));
|
||||
this.setModificationDate(dict.get('M'));
|
||||
this.setFlags(dict.get('F'));
|
||||
this.setRectangle(dict.getArray('Rect'));
|
||||
this.setColor(dict.getArray('C'));
|
||||
@ -187,8 +189,10 @@ class Annotation {
|
||||
annotationFlags: this.flags,
|
||||
borderStyle: this.borderStyle,
|
||||
color: this.color,
|
||||
creationDate: this.creationDate,
|
||||
hasAppearance: !!this.appearance,
|
||||
id: params.id,
|
||||
modificationDate: this.modificationDate,
|
||||
rect: this.rectangle,
|
||||
subtype: params.subtype,
|
||||
};
|
||||
@ -239,6 +243,31 @@ class Annotation {
|
||||
return this._isPrintable(this.flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the creation date.
|
||||
*
|
||||
* @public
|
||||
* @memberof Annotation
|
||||
* @param {string} creationDate - PDF date string that indicates when the
|
||||
* annotation was originally created
|
||||
*/
|
||||
setCreationDate(creationDate) {
|
||||
this.creationDate = isString(creationDate) ? creationDate : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the modification date.
|
||||
*
|
||||
* @public
|
||||
* @memberof Annotation
|
||||
* @param {string} modificationDate - PDF date string that indicates when the
|
||||
* annotation was last modified
|
||||
*/
|
||||
setModificationDate(modificationDate) {
|
||||
this.modificationDate = isString(modificationDate) ?
|
||||
modificationDate : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the flags.
|
||||
*
|
||||
@ -947,6 +976,20 @@ class PopupAnnotation extends Annotation {
|
||||
this.data.title = stringToPDFString(parentItem.get('T') || '');
|
||||
this.data.contents = stringToPDFString(parentItem.get('Contents') || '');
|
||||
|
||||
if (!parentItem.has('CreationDate')) {
|
||||
this.data.creationDate = null;
|
||||
} else {
|
||||
this.setCreationDate(parentItem.get('CreationDate'));
|
||||
this.data.creationDate = this.creationDate;
|
||||
}
|
||||
|
||||
if (!parentItem.has('M')) {
|
||||
this.data.modificationDate = null;
|
||||
} else {
|
||||
this.setModificationDate(parentItem.get('M'));
|
||||
this.data.modificationDate = this.modificationDate;
|
||||
}
|
||||
|
||||
if (!parentItem.has('C')) {
|
||||
// Fall back to the default background color.
|
||||
this.data.color = null;
|
||||
|
@ -14,7 +14,8 @@
|
||||
*/
|
||||
|
||||
import {
|
||||
addLinkAttributes, DOMSVGFactory, getFilenameFromUrl, LinkTarget
|
||||
addLinkAttributes, DOMSVGFactory, getFilenameFromUrl, LinkTarget,
|
||||
PDFDateString
|
||||
} from './display_utils';
|
||||
import {
|
||||
AnnotationBorderStyleType, AnnotationType, stringToPDFString, unreachable,
|
||||
@ -251,6 +252,7 @@ class AnnotationElement {
|
||||
trigger,
|
||||
color: data.color,
|
||||
title: data.title,
|
||||
modificationDate: data.modificationDate,
|
||||
contents: data.contents,
|
||||
hideWrapper: true,
|
||||
});
|
||||
@ -664,6 +666,7 @@ class PopupAnnotationElement extends AnnotationElement {
|
||||
trigger: parentElement,
|
||||
color: this.data.color,
|
||||
title: this.data.title,
|
||||
modificationDate: this.data.modificationDate,
|
||||
contents: this.data.contents,
|
||||
});
|
||||
|
||||
@ -686,6 +689,7 @@ class PopupElement {
|
||||
this.trigger = parameters.trigger;
|
||||
this.color = parameters.color;
|
||||
this.title = parameters.title;
|
||||
this.modificationDate = parameters.modificationDate;
|
||||
this.contents = parameters.contents;
|
||||
this.hideWrapper = parameters.hideWrapper || false;
|
||||
|
||||
@ -724,9 +728,27 @@ class PopupElement {
|
||||
popup.style.backgroundColor = Util.makeCssRgb(r | 0, g | 0, b | 0);
|
||||
}
|
||||
|
||||
let contents = this._formatContents(this.contents);
|
||||
let title = document.createElement('h1');
|
||||
title.textContent = this.title;
|
||||
popup.appendChild(title);
|
||||
|
||||
// The modification date is shown in the popup instead of the creation
|
||||
// date if it is available and can be parsed correctly, which is
|
||||
// consistent with other viewers such as Adobe Acrobat.
|
||||
const dateObject = PDFDateString.toDateObject(this.modificationDate);
|
||||
if (dateObject) {
|
||||
const modificationDate = document.createElement('span');
|
||||
modificationDate.textContent = '{{date}}, {{time}}';
|
||||
modificationDate.dataset.l10nId = 'annotation_date_string';
|
||||
modificationDate.dataset.l10nArgs = JSON.stringify({
|
||||
date: dateObject.toLocaleDateString(),
|
||||
time: dateObject.toLocaleTimeString(),
|
||||
});
|
||||
popup.appendChild(modificationDate);
|
||||
}
|
||||
|
||||
let contents = this._formatContents(this.contents);
|
||||
popup.appendChild(contents);
|
||||
|
||||
// Attach the event listeners to the trigger element.
|
||||
this.trigger.addEventListener('click', this._toggle.bind(this));
|
||||
@ -734,8 +756,6 @@ class PopupElement {
|
||||
this.trigger.addEventListener('mouseout', this._hide.bind(this, false));
|
||||
popup.addEventListener('click', this._hide.bind(this, true));
|
||||
|
||||
popup.appendChild(title);
|
||||
popup.appendChild(contents);
|
||||
wrapper.appendChild(popup);
|
||||
return wrapper;
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
/* eslint no-var: error */
|
||||
|
||||
import {
|
||||
assert, CMapCompressionType, removeNullCharacters, stringToBytes,
|
||||
assert, CMapCompressionType, isString, removeNullCharacters, stringToBytes,
|
||||
unreachable, URL, Util, warn
|
||||
} from '../shared/util';
|
||||
|
||||
@ -491,6 +491,91 @@ function releaseImageResources(img) {
|
||||
img.removeAttribute('src');
|
||||
}
|
||||
|
||||
let pdfDateStringRegex;
|
||||
|
||||
class PDFDateString {
|
||||
/**
|
||||
* Convert a PDF date string to a JavaScript `Date` object.
|
||||
*
|
||||
* The PDF date string format is described in section 7.9.4 of the official
|
||||
* PDF 32000-1:2008 specification. However, in the PDF 1.7 reference (sixth
|
||||
* edition) Adobe describes the same format including a trailing apostrophe.
|
||||
* This syntax in incorrect, but Adobe Acrobat creates PDF files that contain
|
||||
* them. We ignore all apostrophes as they are not necessary for date parsing.
|
||||
*
|
||||
* Moreover, Adobe Acrobat doesn't handle changing the date to universal time
|
||||
* and doesn't use the user's time zone (effectively ignoring the HH' and mm'
|
||||
* parts of the date string).
|
||||
*
|
||||
* @param {string} input
|
||||
* @return {Date|null}
|
||||
*/
|
||||
static toDateObject(input) {
|
||||
if (!input || !isString(input)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Lazily initialize the regular expression.
|
||||
if (!pdfDateStringRegex) {
|
||||
pdfDateStringRegex = new RegExp(
|
||||
'^D:' + // Prefix (required)
|
||||
'(\\d{4})' + // Year (required)
|
||||
'(\\d{2})?' + // Month (optional)
|
||||
'(\\d{2})?' + // Day (optional)
|
||||
'(\\d{2})?' + // Hour (optional)
|
||||
'(\\d{2})?' + // Minute (optional)
|
||||
'(\\d{2})?' + // Second (optional)
|
||||
'([Z|+|-])?' + // Universal time relation (optional)
|
||||
'(\\d{2})?' + // Offset hour (optional)
|
||||
'\'?' + // Splitting apostrophe (optional)
|
||||
'(\\d{2})?' + // Offset minute (optional)
|
||||
'\'?' // Trailing apostrophe (optional)
|
||||
);
|
||||
}
|
||||
|
||||
// Optional fields that don't satisfy the requirements from the regular
|
||||
// expression (such as incorrect digit counts or numbers that are out of
|
||||
// range) will fall back the defaults from the specification.
|
||||
const matches = pdfDateStringRegex.exec(input);
|
||||
if (!matches) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// JavaScript's `Date` object expects the month to be between 0 and 11
|
||||
// instead of 1 and 12, so we have to correct for that.
|
||||
const year = parseInt(matches[1], 10);
|
||||
let month = parseInt(matches[2], 10);
|
||||
month = (month >= 1 && month <= 12) ? month - 1 : 0;
|
||||
let day = parseInt(matches[3], 10);
|
||||
day = (day >= 1 && day <= 31) ? day : 1;
|
||||
let hour = parseInt(matches[4], 10);
|
||||
hour = (hour >= 0 && hour <= 23) ? hour : 0;
|
||||
let minute = parseInt(matches[5], 10);
|
||||
minute = (minute >= 0 && minute <= 59) ? minute : 0;
|
||||
let second = parseInt(matches[6], 10);
|
||||
second = (second >= 0 && second <= 59) ? second : 0;
|
||||
const universalTimeRelation = matches[7] || 'Z';
|
||||
let offsetHour = parseInt(matches[8], 10);
|
||||
offsetHour = (offsetHour >= 0 && offsetHour <= 23) ? offsetHour : 0;
|
||||
let offsetMinute = parseInt(matches[9], 10) || 0;
|
||||
offsetMinute = (offsetMinute >= 0 && offsetMinute <= 59) ? offsetMinute : 0;
|
||||
|
||||
// Universal time relation 'Z' means that the local time is equal to the
|
||||
// universal time, whereas the relations '+'/'-' indicate that the local
|
||||
// time is later respectively earlier than the universal time. Every date
|
||||
// is normalized to universal time.
|
||||
if (universalTimeRelation === '-') {
|
||||
hour += offsetHour;
|
||||
minute += offsetMinute;
|
||||
} else if (universalTimeRelation === '+') {
|
||||
hour -= offsetHour;
|
||||
minute -= offsetMinute;
|
||||
}
|
||||
|
||||
return new Date(Date.UTC(year, month, day, hour, minute, second));
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
PageViewport,
|
||||
RenderingCancelledException,
|
||||
@ -508,4 +593,5 @@ export {
|
||||
loadScript,
|
||||
deprecated,
|
||||
releaseImageResources,
|
||||
PDFDateString,
|
||||
};
|
||||
|
@ -114,6 +114,7 @@ exports.getFilenameFromUrl = pdfjsDisplayDisplayUtils.getFilenameFromUrl;
|
||||
exports.LinkTarget = pdfjsDisplayDisplayUtils.LinkTarget;
|
||||
exports.addLinkAttributes = pdfjsDisplayDisplayUtils.addLinkAttributes;
|
||||
exports.loadScript = pdfjsDisplayDisplayUtils.loadScript;
|
||||
exports.PDFDateString = pdfjsDisplayDisplayUtils.PDFDateString;
|
||||
exports.GlobalWorkerOptions = pdfjsDisplayWorkerOptions.GlobalWorkerOptions;
|
||||
exports.apiCompatibilityParams =
|
||||
pdfjsDisplayAPICompatibility.apiCompatibilityParams;
|
||||
|
@ -35,3 +35,9 @@
|
||||
.annotationLayer .popupWrapper {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.annotationLayer .popup h1,
|
||||
.annotationLayer .popup p {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
@ -131,6 +131,34 @@ describe('annotation', function() {
|
||||
dict = ref = null;
|
||||
});
|
||||
|
||||
it('should set and get a valid creation date', function() {
|
||||
const annotation = new Annotation({ dict, ref, });
|
||||
annotation.setCreationDate('D:20190422');
|
||||
|
||||
expect(annotation.creationDate).toEqual('D:20190422');
|
||||
});
|
||||
|
||||
it('should set and get an invalid creation date', function() {
|
||||
const annotation = new Annotation({ dict, ref, });
|
||||
annotation.setCreationDate(undefined);
|
||||
|
||||
expect(annotation.creationDate).toEqual(null);
|
||||
});
|
||||
|
||||
it('should set and get a valid modification date', function() {
|
||||
const annotation = new Annotation({ dict, ref, });
|
||||
annotation.setModificationDate('D:20190422');
|
||||
|
||||
expect(annotation.modificationDate).toEqual('D:20190422');
|
||||
});
|
||||
|
||||
it('should set and get an invalid modification date', function() {
|
||||
const annotation = new Annotation({ dict, ref, });
|
||||
annotation.setModificationDate(undefined);
|
||||
|
||||
expect(annotation.modificationDate).toEqual(null);
|
||||
});
|
||||
|
||||
it('should set and get flags', function() {
|
||||
const annotation = new Annotation({ dict, ref, });
|
||||
annotation.setFlags(13);
|
||||
@ -1400,6 +1428,59 @@ describe('annotation', function() {
|
||||
});
|
||||
|
||||
describe('PopupAnnotation', function() {
|
||||
it('should inherit properties from its parent', function(done) {
|
||||
const parentDict = new Dict();
|
||||
parentDict.set('Type', Name.get('Annot'));
|
||||
parentDict.set('Subtype', Name.get('Text'));
|
||||
parentDict.set('CreationDate', 'D:20190422');
|
||||
parentDict.set('M', 'D:20190423');
|
||||
parentDict.set('C', [0, 0, 1]);
|
||||
|
||||
const popupDict = new Dict();
|
||||
popupDict.set('Type', Name.get('Annot'));
|
||||
popupDict.set('Subtype', Name.get('Popup'));
|
||||
popupDict.set('Parent', parentDict);
|
||||
|
||||
const popupRef = new Ref(13, 0);
|
||||
const xref = new XRefMock([
|
||||
{ ref: popupRef, data: popupDict, }
|
||||
]);
|
||||
|
||||
AnnotationFactory.create(xref, popupRef, pdfManagerMock,
|
||||
idFactoryMock).then(({ data, viewable, }) => {
|
||||
expect(data.annotationType).toEqual(AnnotationType.POPUP);
|
||||
expect(data.creationDate).toEqual('D:20190422');
|
||||
expect(data.modificationDate).toEqual('D:20190423');
|
||||
expect(data.color).toEqual(new Uint8ClampedArray([0, 0, 255]));
|
||||
done();
|
||||
}, done.fail);
|
||||
});
|
||||
|
||||
it('should handle missing parent properties', function(done) {
|
||||
const parentDict = new Dict();
|
||||
parentDict.set('Type', Name.get('Annot'));
|
||||
parentDict.set('Subtype', Name.get('Text'));
|
||||
|
||||
const popupDict = new Dict();
|
||||
popupDict.set('Type', Name.get('Annot'));
|
||||
popupDict.set('Subtype', Name.get('Popup'));
|
||||
popupDict.set('Parent', parentDict);
|
||||
|
||||
const popupRef = new Ref(13, 0);
|
||||
const xref = new XRefMock([
|
||||
{ ref: popupRef, data: popupDict, }
|
||||
]);
|
||||
|
||||
AnnotationFactory.create(xref, popupRef, pdfManagerMock,
|
||||
idFactoryMock).then(({ data, viewable, }) => {
|
||||
expect(data.annotationType).toEqual(AnnotationType.POPUP);
|
||||
expect(data.creationDate).toEqual(null);
|
||||
expect(data.modificationDate).toEqual(null);
|
||||
expect(data.color).toEqual(null);
|
||||
done();
|
||||
}, done.fail);
|
||||
});
|
||||
|
||||
it('should inherit the parent flags when the Popup is not viewable, ' +
|
||||
'but the parent is (PR 7352)', function(done) {
|
||||
const parentDict = new Dict();
|
||||
|
@ -15,7 +15,8 @@
|
||||
/* eslint no-var: error */
|
||||
|
||||
import {
|
||||
DOMCanvasFactory, DOMSVGFactory, getFilenameFromUrl, isValidFetchUrl
|
||||
DOMCanvasFactory, DOMSVGFactory, getFilenameFromUrl, isValidFetchUrl,
|
||||
PDFDateString
|
||||
} from '../../src/display/display_utils';
|
||||
import isNodeJS from '../../src/shared/is_node';
|
||||
|
||||
@ -220,4 +221,70 @@ describe('display_utils', function() {
|
||||
expect(isValidFetchUrl('https://www.example.com')).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('PDFDateString', function() {
|
||||
describe('toDateObject', function() {
|
||||
it('converts PDF date strings to JavaScript `Date` objects', function() {
|
||||
const expectations = {
|
||||
undefined: null,
|
||||
null: null,
|
||||
42: null,
|
||||
'2019': null,
|
||||
'D2019': null,
|
||||
'D:': null,
|
||||
'D:201': null,
|
||||
'D:2019': new Date(Date.UTC(2019, 0, 1, 0, 0, 0)),
|
||||
'D:20190': new Date(Date.UTC(2019, 0, 1, 0, 0, 0)),
|
||||
'D:201900': new Date(Date.UTC(2019, 0, 1, 0, 0, 0)),
|
||||
'D:201913': new Date(Date.UTC(2019, 0, 1, 0, 0, 0)),
|
||||
'D:201902': new Date(Date.UTC(2019, 1, 1, 0, 0, 0)),
|
||||
'D:2019020': new Date(Date.UTC(2019, 1, 1, 0, 0, 0)),
|
||||
'D:20190200': new Date(Date.UTC(2019, 1, 1, 0, 0, 0)),
|
||||
'D:20190232': new Date(Date.UTC(2019, 1, 1, 0, 0, 0)),
|
||||
'D:20190203': new Date(Date.UTC(2019, 1, 3, 0, 0, 0)),
|
||||
// Invalid dates like the 31th of April are handled by JavaScript:
|
||||
'D:20190431': new Date(Date.UTC(2019, 4, 1, 0, 0, 0)),
|
||||
'D:201902030': new Date(Date.UTC(2019, 1, 3, 0, 0, 0)),
|
||||
'D:2019020300': new Date(Date.UTC(2019, 1, 3, 0, 0, 0)),
|
||||
'D:2019020324': new Date(Date.UTC(2019, 1, 3, 0, 0, 0)),
|
||||
'D:2019020304': new Date(Date.UTC(2019, 1, 3, 4, 0, 0)),
|
||||
'D:20190203040': new Date(Date.UTC(2019, 1, 3, 4, 0, 0)),
|
||||
'D:201902030400': new Date(Date.UTC(2019, 1, 3, 4, 0, 0)),
|
||||
'D:201902030460': new Date(Date.UTC(2019, 1, 3, 4, 0, 0)),
|
||||
'D:201902030405': new Date(Date.UTC(2019, 1, 3, 4, 5, 0)),
|
||||
'D:2019020304050': new Date(Date.UTC(2019, 1, 3, 4, 5, 0)),
|
||||
'D:20190203040500': new Date(Date.UTC(2019, 1, 3, 4, 5, 0)),
|
||||
'D:20190203040560': new Date(Date.UTC(2019, 1, 3, 4, 5, 0)),
|
||||
'D:20190203040506': new Date(Date.UTC(2019, 1, 3, 4, 5, 6)),
|
||||
'D:20190203040506F': new Date(Date.UTC(2019, 1, 3, 4, 5, 6)),
|
||||
'D:20190203040506Z': new Date(Date.UTC(2019, 1, 3, 4, 5, 6)),
|
||||
'D:20190203040506-': new Date(Date.UTC(2019, 1, 3, 4, 5, 6)),
|
||||
'D:20190203040506+': new Date(Date.UTC(2019, 1, 3, 4, 5, 6)),
|
||||
'D:20190203040506+\'': new Date(Date.UTC(2019, 1, 3, 4, 5, 6)),
|
||||
'D:20190203040506+0': new Date(Date.UTC(2019, 1, 3, 4, 5, 6)),
|
||||
'D:20190203040506+01': new Date(Date.UTC(2019, 1, 3, 3, 5, 6)),
|
||||
'D:20190203040506+00\'': new Date(Date.UTC(2019, 1, 3, 4, 5, 6)),
|
||||
'D:20190203040506+24\'': new Date(Date.UTC(2019, 1, 3, 4, 5, 6)),
|
||||
'D:20190203040506+01\'': new Date(Date.UTC(2019, 1, 3, 3, 5, 6)),
|
||||
'D:20190203040506+01\'0': new Date(Date.UTC(2019, 1, 3, 3, 5, 6)),
|
||||
'D:20190203040506+01\'00': new Date(Date.UTC(2019, 1, 3, 3, 5, 6)),
|
||||
'D:20190203040506+01\'60': new Date(Date.UTC(2019, 1, 3, 3, 5, 6)),
|
||||
'D:20190203040506+0102': new Date(Date.UTC(2019, 1, 3, 3, 3, 6)),
|
||||
'D:20190203040506+01\'02': new Date(Date.UTC(2019, 1, 3, 3, 3, 6)),
|
||||
'D:20190203040506+01\'02\'': new Date(Date.UTC(2019, 1, 3, 3, 3, 6)),
|
||||
// Offset hour and minute that result in a day change:
|
||||
'D:20190203040506+05\'07': new Date(Date.UTC(2019, 1, 2, 22, 58, 6)),
|
||||
};
|
||||
|
||||
for (const [input, expectation] of Object.entries(expectations)) {
|
||||
const result = PDFDateString.toDateObject(input);
|
||||
if (result) {
|
||||
expect(result.getTime()).toEqual(expectation.getTime());
|
||||
} else {
|
||||
expect(result).toEqual(expectation);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -158,25 +158,33 @@
|
||||
z-index: 200;
|
||||
max-width: 20em;
|
||||
background-color: #FFFF99;
|
||||
box-shadow: 0px 2px 5px #333;
|
||||
box-shadow: 0px 2px 5px #888;
|
||||
border-radius: 2px;
|
||||
padding: 0.6em;
|
||||
padding: 6px;
|
||||
margin-left: 5px;
|
||||
cursor: pointer;
|
||||
font: message-box;
|
||||
font-size: 9px;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.annotationLayer .popup > * {
|
||||
font-size: 9px;
|
||||
}
|
||||
|
||||
.annotationLayer .popup h1 {
|
||||
font-size: 1em;
|
||||
border-bottom: 1px solid #000000;
|
||||
margin: 0;
|
||||
padding-bottom: 0.2em;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.annotationLayer .popup span {
|
||||
display: inline-block;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.annotationLayer .popup p {
|
||||
margin: 0;
|
||||
padding-top: 0.2em;
|
||||
border-top: 1px solid #333;
|
||||
margin-top: 2px;
|
||||
padding-top: 2px;
|
||||
}
|
||||
|
||||
.annotationLayer .highlightAnnotation,
|
||||
|
@ -13,10 +13,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { createPromiseCapability, PDFDateString } from 'pdfjs-lib';
|
||||
import {
|
||||
getPageSizeInches, getPDFFileNameFromURL, isPortraitOrientation, NullL10n
|
||||
} from './ui_utils';
|
||||
import { createPromiseCapability } from 'pdfjs-lib';
|
||||
|
||||
const DEFAULT_FIELD_CONTENT = '-';
|
||||
|
||||
@ -363,51 +363,15 @@ class PDFDocumentProperties {
|
||||
* @private
|
||||
*/
|
||||
_parseDate(inputDate) {
|
||||
if (!inputDate) {
|
||||
return;
|
||||
}
|
||||
// This is implemented according to the PDF specification, but note that
|
||||
// Adobe Reader doesn't handle changing the date to universal time
|
||||
// and doesn't use the user's time zone (they're effectively ignoring
|
||||
// the HH' and mm' parts of the date string).
|
||||
let dateToParse = inputDate;
|
||||
|
||||
// Remove the D: prefix if it is available.
|
||||
if (dateToParse.substring(0, 2) === 'D:') {
|
||||
dateToParse = dateToParse.substring(2);
|
||||
}
|
||||
|
||||
// Get all elements from the PDF date string.
|
||||
// JavaScript's `Date` object expects the month to be between
|
||||
// 0 and 11 instead of 1 and 12, so we're correcting for this.
|
||||
let year = parseInt(dateToParse.substring(0, 4), 10);
|
||||
let month = parseInt(dateToParse.substring(4, 6), 10) - 1;
|
||||
let day = parseInt(dateToParse.substring(6, 8), 10);
|
||||
let hours = parseInt(dateToParse.substring(8, 10), 10);
|
||||
let minutes = parseInt(dateToParse.substring(10, 12), 10);
|
||||
let seconds = parseInt(dateToParse.substring(12, 14), 10);
|
||||
let utRel = dateToParse.substring(14, 15);
|
||||
let offsetHours = parseInt(dateToParse.substring(15, 17), 10);
|
||||
let offsetMinutes = parseInt(dateToParse.substring(18, 20), 10);
|
||||
|
||||
// As per spec, utRel = 'Z' means equal to universal time.
|
||||
// The other cases ('-' and '+') have to be handled here.
|
||||
if (utRel === '-') {
|
||||
hours += offsetHours;
|
||||
minutes += offsetMinutes;
|
||||
} else if (utRel === '+') {
|
||||
hours -= offsetHours;
|
||||
minutes -= offsetMinutes;
|
||||
}
|
||||
|
||||
// Return the new date format from the user's locale.
|
||||
let date = new Date(Date.UTC(year, month, day, hours, minutes, seconds));
|
||||
let dateString = date.toLocaleDateString();
|
||||
let timeString = date.toLocaleTimeString();
|
||||
const dateObject = PDFDateString.toDateObject(inputDate);
|
||||
if (dateObject) {
|
||||
const dateString = dateObject.toLocaleDateString();
|
||||
const timeString = dateObject.toLocaleTimeString();
|
||||
return this.l10n.get('document_properties_date_string',
|
||||
{ date: dateString, time: timeString, },
|
||||
'{{date}}, {{time}}');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
|
Loading…
Reference in New Issue
Block a user