Skip to content

Commit b8527b6

Browse files
authored
Merge pull request #266 from OneNoteDev/feature/enable-selection-clips-to-grab-videos
Add the ability to save videos in the selection clip
2 parents 23d081f + 01cdff8 commit b8527b6

File tree

7 files changed

+49
-22
lines changed

7 files changed

+49
-22
lines changed

src/scripts/contentCapture/augmentationHelper.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ export class AugmentationHelper {
6060
let previewElement = AugmentationHelper.getArticlePreviewElement(doc);
6161

6262
DomUtils.removeElementsNotSupportedInOnml(doc);
63+
DomUtils.removeDisallowedIframes(doc);
6364
DomUtils.removeBlankImages(doc).then(() => {
6465
DomUtils.addPreviewContainerStyling(previewElement);
6566
AugmentationHelper.addSupportedVideosToElement(previewElement, pageContent, url);

src/scripts/domParsers/domUtils.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -921,14 +921,34 @@ export module DomUtils {
921921
*/
922922
export function toOnml(doc: Document): Promise<void> {
923923
removeElementsNotSupportedInOnml(doc);
924-
domReplacer(doc, [Tags.iframe].join());
924+
removeDisallowedIframes(doc);
925925
removeUnwantedItems(doc);
926926
convertRelativeUrlsToAbsolute(doc);
927927
removeAllStylesAndClasses(doc);
928928
removeEventListenerAttributes(doc);
929929
return removeBlankImages(doc);
930930
}
931931

932+
export function removeDisallowedIframes(doc: Document) {
933+
// We also detect if the iframe is a video, and we ensure that we have
934+
// the correct attribute set so that ONApi recognizes it
935+
domReplacer(doc, Tags.iframe, (node) => {
936+
let src = (node as HTMLIFrameElement).src;
937+
let supportedDomain = VideoUtils.videoDomainIfSupported(src);
938+
if (!supportedDomain) {
939+
return undefined;
940+
}
941+
942+
let domain = VideoUtils.SupportedVideoDomains[supportedDomain];
943+
let extractor = VideoExtractorFactory.createVideoExtractor(domain);
944+
let embeddedVideos = extractor.createEmbeddedVideos(src, doc.body.innerHTML);
945+
if (embeddedVideos && embeddedVideos.length > 0) {
946+
return embeddedVideos[0];
947+
}
948+
return undefined;
949+
});
950+
}
951+
932952
function removeAllStylesAndClasses(doc: Document): void {
933953
domReplacer(doc, "*", (oldNode, index) => {
934954
(<HTMLElement>oldNode).removeAttribute("style");

src/scripts/domParsers/khanAcademyVideoExtractor.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ export class KhanAcademyVideoExtractor implements VideoExtractor {
1414
public getVideoIds(pageUrl: string, pageContent: string): string[] {
1515
// Matches strings of the form id="video_\S+" OR id='video_\S+'
1616
// with any amount of whitespace padding in between strings of interest
17-
let regex = /id\s*=\s*("\s*video_(\S+)\s*"|'\s*video_(\S+)\s*')/gi;
17+
let regex1 = /id\s*=\s*("\s*video_(\S+)\s*"|'\s*video_(\S+)\s*')/gi;
1818

1919
// Matches strings of the form data-youtubeid="\S+" OR data-youtubeid='\S+'
2020
// with any amount of whitespace padding in between strings of interest
21-
let regexTwo = /data-youtubeid\s*=\s*("\s*(\S+)\s*"|'\s*(\S+)\s*')/gi;
22-
let regexes = [regex, regexTwo];
23-
return VideoUtils.matchRegexFromPageContent(pageContent, regexes);
21+
let regex2 = /data-youtubeid\s*=\s*("\s*(\S+)\s*"|'\s*(\S+)\s*')/gi;
22+
23+
return VideoUtils.matchRegexFromPageContent(pageContent, [regex1, regex2]);
2424
}
2525

2626
public getVideoSrcValues(pageUrl: string, pageContent: string): string[] {

src/scripts/domParsers/videoUtils.ts

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -46,19 +46,16 @@ export module VideoUtils {
4646
return;
4747
}
4848

49-
// looking for all matches in pageContent of the general format: id="clip_###"
50-
// - where ### could be any number of digits
51-
// - ignore casing
52-
// - ignore possible whitespacing variations between characters
53-
// - accept the use of either double- or single-quotes around clip_###
54-
let m;
49+
let match: RegExpExecArray;
5550
let matches = [];
5651
regexes.forEach((regex) => {
57-
while (m = regex.exec(pageContent)) {
58-
if (m[2]) {
59-
matches.push(m[2]);
60-
} else {
61-
matches.push(m[3]);
52+
// Calling exec multiple times with the same parameter will continue finding matches until
53+
// there are no more
54+
while (match = regex.exec(pageContent)) {
55+
if (match[2]) {
56+
matches.push(match[2]);
57+
} else if (match[3]) {
58+
matches.push(match[3]);
6259
}
6360
}
6461
});

src/scripts/domParsers/vimeoVideoExtractor.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,12 @@ export class VimeoVideoExtractor implements VideoExtractor {
2020
// - ignore casing
2121
// - ignore possible whitespacing variations between characters
2222
// - accept the use of either double- or single-quotes around clip_###
23-
let regex = /id\s*=\s*("\s*clip_(\d+)\s*"|'\s*clip_(\d+)\s*')/gi;
24-
return VideoUtils.matchRegexFromPageContent(pageContent, [regex]);
23+
let regex1 = /id\s*=\s*("\s*clip_(\d+)\s*"|'\s*clip_(\d+)\s*')/gi;
24+
25+
// also account for embedded Vimeo videos
26+
let regex2 = /player\.vimeo\.com\/video\/((\d+))\d{0}/gi;
27+
28+
return VideoUtils.matchRegexFromPageContent(pageContent, [regex1, regex2]);
2529
}
2630

2731
/**

src/scripts/domParsers/youtubeVideoExtractor.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ export class YoutubeVideoExtractor implements VideoExtractor {
3737
return;
3838
}
3939

40-
return [youTubeId];
40+
// Ensure we remove query parameters
41+
return [youTubeId.split("?")[0]];
4142
}
4243

4344
/**

src/tests/domParsers/domUtils_tests.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -265,9 +265,13 @@ export class DomUtilsTests extends TestModule {
265265
DomUtils.addEmbeddedVideosWhereSupported(previewElement, vimeoPageContentWithMultipleClipIds, "https://vimeo.com/album/3637653/").then((videoSrcUrls: DomUtils.EmbeddedVideoIFrameSrcs[]) => {
266266
let expectedVideoIds = ["45196609", "45196610", "45196611"];
267267
for (let i = 0; i < expectedVideoIds.length; i++) {
268-
let expectedUrl = "https://player.vimeo.com/video/" + expectedVideoIds[i];
269-
strictEqual(videoSrcUrls[i].dataOriginalSrcAttribute, expectedUrl, "expected dataOriginalSrcAttribute: " + expectedUrl);
270-
strictEqual(videoSrcUrls[i].srcAttribute, expectedUrl, "expected srcAttribute: " + expectedUrl);
268+
if (!videoSrcUrls[i]) {
269+
ok(false, "The video id " + expectedVideoIds[i] + " is missing in the return videoSrcUrls");
270+
} else {
271+
let expectedUrl = "https://player.vimeo.com/video/" + expectedVideoIds[i];
272+
strictEqual(videoSrcUrls[i].dataOriginalSrcAttribute, expectedUrl, "expected dataOriginalSrcAttribute: " + expectedUrl);
273+
strictEqual(videoSrcUrls[i].srcAttribute, expectedUrl, "expected srcAttribute: " + expectedUrl);
274+
}
271275
}
272276
}, (error: OneNoteApi.GenericError) => {
273277
ok(false, "reject should not be called");

0 commit comments

Comments
 (0)