จัดการไฮเปอร์ลิงก์การนำเสนอใน JavaScript

บทนำ

ไฮเปอร์ลิงก์เชื่อมต่อเนื้อหางานนำเสนอไปยังเว็บไซต์หรือตำแหน่งภายในงานนำเสนอเอง ใน PowerPoint ไฮเปอร์ลิงก์มักทำหน้าที่สองอย่าง:

  • เปิดเว็บไซต์จากข้อความ รูปร่าง หรือเฟรมสื่อ
  • ไปยังสไลด์อื่น ตัวอย่างเช่นจากสารบัญ

Aspose.Slides for Node.js via Java ให้คุณเพิ่มลิงก์เหล่านี้ ควบคุมลักษณะและเสียงของมัน ปรับปรุงคุณสมบัติ และลบออก ตัวอย่างด้านล่างแสดงวิธีทำงานกับไฮเปอร์ลิงก์บนองค์ประกอบแต่ละตัวและวิธีเข้าถึงไฮเปอร์ลิงก์ที่ระดับงานนำเสนอ สไลด์ หรือกรอบข้อความ

เพิ่มไฮเปอร์ลิงก์ URL

คุณสามารถกำหนด URL ของเว็บไซต์ให้กับข้อความ รูปร่าง หรือเฟรมสื่อได้ พื้นที่ที่คลิกได้จะขึ้นอยู่กับองค์ประกอบที่คุณกำหนดไฮเปอร์ลิงก์: ส่วนของข้อความจะเป็นลิงก์ที่เชื่อมต่อกับข้อความที่เลือก ขณะที่รูปร่างหรือเฟรมจะเป็นลิงก์ที่เชื่อมต่อกับอ็อบเจ็กต์สไลด์

เพิ่มไฮเปอร์ลิงก์ URL ให้กับข้อความ

เพื่อเชื่อมข้อความกับเว็บไซต์ ให้ส่ง Hyperlink ไปยังเมธอด setHyperlinkClick ของส่วนข้อความ ตามตัวอย่างด้านล่าง ส่วนของข้อความนั้นจะกลายเป็นคลิกได้เท่านั้น

const aspose = { slides: require("aspose.slides.via.java") };

const presentation = new aspose.slides.Presentation();
try {
    const textShape = presentation.getSlides().get_Item(0).getShapes().addAutoShape(aspose.slides.ShapeType.Rectangle, 100, 100, 600, 50, false);
    textShape.addTextFrame("Aspose: File Format APIs");
    const portionFormat = textShape.getTextFrame().getParagraphs().get_Item(0).getPortions().get_Item(0).getPortionFormat();
    portionFormat.setHyperlinkClick(new aspose.slides.Hyperlink("https://www.aspose.com/"));
    portionFormat.getHyperlinkClick().setTooltip("Explore Aspose file format APIs");
    portionFormat.setFontHeight(32);

    presentation.save("presentation-out.pptx", aspose.slides.SaveFormat.Pptx);
} finally {
    presentation.dispose();
}

เพิ่มไฮเปอร์ลิงก์ URL ให้กับรูปร่างและเฟรมสื่อ

เพื่อทำให้รูปร่างหรือเฟรมสามารถคลิกได้ ให้เรียกเมธอด setHyperlinkClick ของมัน ไฮเปอร์ลิงก์จะเป็นของอ็อบเจ็กต์เอง ไม่ใช่ของส่วนข้อความภายใน

วิธีเดียวกันใช้กับรูปภาพ เสียง และวิดีโอเฟรม: กำหนดไฮเปอร์ลิงก์ให้กับเฟรมและเรียก setTooltip หากต้องการ

ตัวอย่างต่อไปทำให้สี่เหลี่ยมสามารถคลิกได้:

const aspose = { slides: require("aspose.slides.via.java") };

const presentation = new aspose.slides.Presentation();
try {
    const shape = presentation.getSlides().get_Item(0).getShapes().addAutoShape(aspose.slides.ShapeType.Rectangle, 100, 100, 600, 50);

    shape.setHyperlinkClick(new aspose.slides.Hyperlink("https://www.aspose.com/"));
    shape.getHyperlinkClick().setTooltip("Explore Aspose file format APIs");

    presentation.save("presentation-out.pptx", aspose.slides.SaveFormat.Pptx);
} finally {
    presentation.dispose();
}

ใช้ไฮเปอร์ลิงก์สร้างสารบัญ

ไฮเปอร์ลิงก์ภายในทำให้ผู้อ่านกระโดดจากสารบัญไปยังสไลด์ที่ต้องการ ตัวอย่างต่อไปใช้ setInternalHyperlinkClick เพื่อเชื่อมข้อความ “Page 2” บนสไลด์แรกไปยังสไลด์ที่สอง

const aspose = { slides: require("aspose.slides.via.java") };
const java = require("java");

const presentation = new aspose.slides.Presentation();
try {
    const firstSlide = presentation.getSlides().get_Item(0);
    const secondSlide = presentation.getSlides().addEmptySlide(firstSlide.getLayoutSlide());

    const tableOfContents = firstSlide.getShapes().addAutoShape(aspose.slides.ShapeType.Rectangle, 40, 40, 300, 100);
    tableOfContents.getFillFormat().setFillType(java.newByte(aspose.slides.FillType.NoFill));
    tableOfContents.getLineFormat().getFillFormat().setFillType(java.newByte(aspose.slides.FillType.NoFill));
    tableOfContents.getTextFrame().getParagraphs().clear();

    const paragraph = new aspose.slides.Paragraph();
    paragraph.getParagraphFormat().getDefaultPortionFormat().getFillFormat().setFillType(java.newByte(aspose.slides.FillType.Solid));
    paragraph.getParagraphFormat().getDefaultPortionFormat().getFillFormat().getSolidFillColor().setColor(java.getStaticFieldValue("java.awt.Color", "BLACK"));
    paragraph.setText("Title of slide 2 .......... ");

    const linkPortion = new aspose.slides.Portion();
    linkPortion.setText("Page 2");
    linkPortion.getPortionFormat().getHyperlinkManager().setInternalHyperlinkClick(secondSlide);

    paragraph.getPortions().add(linkPortion);
    tableOfContents.getTextFrame().getParagraphs().add(paragraph);

    presentation.save("link_to_slide.pptx", aspose.slides.SaveFormat.Pptx);
} finally {
    presentation.dispose();
}

กำหนดรูปแบบไฮเปอร์ลิงก์

สี

เมธอด setColorSource ของ Hyperlink กำหนดว่าไฮเปอร์ลิงก์จะใช้สีไฮเปอร์ลิงก์ของงานนำเสนอหรือการจัดรูปแบบของส่วนข้อความหรือไม่ หากต้องการใช้สีข้อความที่กำหนดเอง ให้เลือก HyperlinkColorSource.PortionFormat และตั้งค่าสีเติมของส่วนนั้น ฟีเจอร์นี้เริ่มต้นตั้งแต่ PowerPoint 2019; รุ่นก่อนหน้าจะไม่ใช้การตั้งค่านี้

ตัวอย่างต่อไปเพิ่มไฮเปอร์ลิงก์ข้อความสองตัวบนสไลด์เดียว ตัวแรกใช้สีเติมข้อความสีแดง ส่วนที่สองใช้สีไฮเปอร์ลิงก์เริ่มต้น

const aspose = { slides: require("aspose.slides.via.java") };
const java = require("java");

const presentation = new aspose.slides.Presentation();
try {
    const coloredShape = presentation.getSlides().get_Item(0).getShapes().addAutoShape(aspose.slides.ShapeType.Rectangle, 100, 100, 450, 50, false);
    coloredShape.addTextFrame("This hyperlink uses a custom color.");
    const coloredPortionFormat = coloredShape.getTextFrame().getParagraphs().get_Item(0).getPortions().get_Item(0).getPortionFormat();
    coloredPortionFormat.setHyperlinkClick(new aspose.slides.Hyperlink("https://www.aspose.com/"));
    coloredPortionFormat.getHyperlinkClick().setColorSource(aspose.slides.HyperlinkColorSource.PortionFormat);
    coloredPortionFormat.getFillFormat().setFillType(java.newByte(aspose.slides.FillType.Solid));
    coloredPortionFormat.getFillFormat().getSolidFillColor().setColor(java.getStaticFieldValue("java.awt.Color", "RED"));

    const defaultShape = presentation.getSlides().get_Item(0).getShapes().addAutoShape(aspose.slides.ShapeType.Rectangle, 100, 200, 450, 50, false);
    defaultShape.addTextFrame("This hyperlink uses the default color.");
    defaultShape.getTextFrame().getParagraphs().get_Item(0).getPortions().get_Item(0).getPortionFormat().setHyperlinkClick(new aspose.slides.Hyperlink("https://www.aspose.com/"));

    presentation.save("presentation-out-hyperlink.pptx", aspose.slides.SaveFormat.Pptx);
} finally {
    presentation.dispose();
}

เสียง

ไฮเปอร์ลิงก์สามารถเล่นเสียงเมื่อเปิดใช้งานหรือหยุดเสียงที่กำลังเล่นอยู่ได้ ใช้เมธอดต่อไปนี้เพื่อกำหนดพฤติกรรมเหล่านั้น:

  • Hyperlink.setSound ระบุไฟล์เสียงที่เชื่อมกับไฮเปอร์ลิงก์
  • Hyperlink.setStopSoundOnClick ควบคุมว่าการคลิกไฮเปอร์ลิงก์จะหยุดเสียงก่อนหน้าหรือไม่

เพิ่มเสียงให้กับไฮเปอร์ลิงก์

ตัวอย่างต่อไปโหลด sampleaudio.wav แล้วเชื่อมกับปุ่มบนสไลด์แรก การคลิกปุ่มจะเล่นเสียงและไปยังสไลด์ถัดไป รูปร่างที่สองบนสไลด์เดียวกันจะหยุดเสียงก่อนหน้าเมื่อคลิกโดยไม่ทำการนำทางใด ๆ

const aspose = { slides: require("aspose.slides.via.java") };
const java = require("java");

const presentation = new aspose.slides.Presentation();
try {
    const audioStream = java.newInstanceSync("java.io.FileInputStream", "sampleaudio.wav");
    let hyperlinkSound;
    try {
        hyperlinkSound = presentation.getAudios().addAudio(audioStream);
    } finally {
        audioStream.close();
    }

    const firstSlide = presentation.getSlides().get_Item(0);

    const playButton = firstSlide.getShapes().addAutoShape(aspose.slides.ShapeType.SoundButton, 100, 100, 100, 50);
    playButton.setHyperlinkClick(aspose.slides.Hyperlink.getNextSlide());

    if (!playButton.getHyperlinkClick().getStopSoundOnClick() && playButton.getHyperlinkClick().getSound() == null)
    {
        playButton.getHyperlinkClick().setSound(hyperlinkSound);
    }

    const secondSlide = presentation.getSlides().addEmptySlide(firstSlide.getLayoutSlide());

    const stopButton = secondSlide.getShapes().addAutoShape(aspose.slides.ShapeType.Rectangle, 100, 100, 100, 50);
    stopButton.setHyperlinkClick(aspose.slides.Hyperlink.getNoAction());

    stopButton.getHyperlinkClick().setStopSoundOnClick(true);

    presentation.save("hyperlink-sound.pptx", aspose.slides.SaveFormat.Pptx);
} finally {
    presentation.dispose();
}

ดึงเสียงจากไฮเปอร์ลิงก์

ตัวอย่างต่อไปเปิดงานนำเสนอที่สร้างไว้ข้างต้นและอ่านเสียงของไฮเปอร์ลิงก์ในรูปร่างแรกเข้าสู่หน่วยความจำโดยใช้ getSound และ getBinaryData

const aspose = { slides: require("aspose.slides.via.java") };

const presentation = new aspose.slides.Presentation("hyperlink-sound.pptx");
try {
    if (presentation.getSlides().size() > 0 && presentation.getSlides().get_Item(0).getShapes().size() > 0) {
        const hyperlink = presentation.getSlides().get_Item(0).getShapes().get_Item(0).getHyperlinkClick();
        const sound = hyperlink == null ? null : hyperlink.getSound();
        if (sound != null) {
            const audioData = sound.getBinaryData();
            console.log("Extracted " + audioData.length + " bytes of hyperlink audio.");
        } else {
            console.log("The first shape has no hyperlink sound.");
        }
    } else {
        console.log("The presentation has no first slide or shape to inspect.");
    }
} finally {
    presentation.dispose();
}

Tooltip และการตั้งค่าปฏิสัมพันธ์

หลังจากกำหนดไฮเปอร์ลิงก์ให้กับข้อความหรือรูปร่าง คุณสามารถเรียกเมธอด Hyperlink ดังต่อไปนี้:

  • setTooltip ตั้งข้อความที่ผู้ชมสามารถแสดงเป็นคำแนะนำสำหรับลิงก์
  • setTargetFrame ระบุเฟรมเป้าหมายภายในชุดเฟรม HTML ของพาเรนต์ (หากมี)
  • setHistory ควบคุมว่าการเปิดลิงก์จะเพิ่มตำแหน่งปลายทางไปยังรายการไฮเปอร์ลิงก์ที่เคยดูหรือไม่
  • setHighlightClick ควบคุมว่าฮไฮเปอร์ลิงก์จะถูกเน้นเมื่อคลิกหรือไม่

ลบไฮเปอร์ลิงก์ออกจากงานนำเสนอ

ใช้ getAnyHyperlinks เพื่อรวบรวมคอนเทนเนอร์ไฮเปอร์ลิงก์ รวมถึงลิงก์ส่วนข้อความ ก่อนทำการเปลี่ยนแปลง ตัวอย่างต่อไปลบทั้งสองประเภทการเปิดใช้งานจากสไลด์แรก หากต้องการลบเฉพาะประเภทใดประเภทหนึ่ง ให้เรียกเฉพาะ removeHyperlinkClick หรือ removeHyperlinkMouseOver การลบการคลิกจะไม่ลบการเมาส์โอเวอร์ที่สอดคล้องกัน

const aspose = { slides: require("aspose.slides.via.java") };

const presentation = new aspose.slides.Presentation("pres.pptx");
try {
    if (presentation.getSlides().size() > 0) {
        const found = presentation.getSlides().get_Item(0).getHyperlinkQueries().getAnyHyperlinks();
        const containers = [];
        for (let index = 0; index < found.size(); index++) {
            containers.push(found.get_Item(index));
        }
        for (const container of containers) {
            container.getHyperlinkManager().removeHyperlinkClick();
            container.getHyperlinkManager().removeHyperlinkMouseOver();
        }
        presentation.save("pres-removed-hyperlinks.pptx", aspose.slides.SaveFormat.Pptx);
    } else {
        console.log("The presentation has no slides to process.");
    }
} finally {
    presentation.dispose();
}

สำหรับการลบแบบไม่มีเงื่อนไข removeAllHyperlinks จะลบทั้งสองประเภทการเปิดใช้งานในสโคปที่เลือกในหนึ่งคำสั่ง สำหรับการทำความสะอาดแบบเลือกและครอบคลุมมาสเตอร์, เลย์เอาต์, และโน้ต ให้ดูที่ Report, Sanitize, and Verify Hyperlinks

สร้างรายการตรวจสอบไฮเปอร์ลิงก์ครบถ้วน

ก่อนเผยแพร่งานนำเสนอ ควรตรวจสอบการกระทำแบบโต้ตอบและลิงก์เว็บของมัน getAnyHyperlinks จะคืนค่าคอนเทนเนอร์ไฮเปอร์ลิงก์ ไม่ใช่รายการแบนของสตริง URL ตรวจสอบทั้ง getHyperlinkClick และ getHyperlinkMouseOver บนแต่ละคอนเทนเนอร์ พวกมันเป็นอิสระกัน: คอนเทนเนอร์เดียวกันอาจเปิดให้ทำทั้งสองการกระทำ ดังนั้นรายงานครบถ้วนอาจต้องมีแถวสูงสุดสองแถวต่อคอนเทนเนอร์

การสแกนเฉพาะไฮเปอร์ลิงก์ระดับรูปร่างอาจพลาดลิงก์ที่แนบกับส่วนข้อความ ให้สืบค้นในสโคปที่เหมาะแทน แล้วเก็บคอนเทนเนอร์ที่คืนค่าไว้เพื่อที่คุณจะได้อัปเดตหรือลบการกระทำของมันภายหลัง

สืบค้นสโคปของงานนำเสนอ สไลด์ และกรอบข้อความ

คลาส HyperlinkQueries สามารถเข้าถึงได้ผ่าน Presentation.getHyperlinkQueries, BaseSlide.getHyperlinkQueries, และ TextFrame.getHyperlinkQueries แต่ละสโคปสนับสนุนการสืบค้นเดียวกัน:

  • getHyperlinkClicks คืนค่าคอนเทนเนอร์ที่มีการคลิก
  • getHyperlinkMouseOvers คืนค่าคอนเทนเนอร์ที่มีการเมาส์โอเวอร์
  • getAnyHyperlinks คืนค่าคอนเทนเนอร์ที่มีการกระทำอย่างใดอย่างหนึ่งหรือทั้งสอง

ตัวอย่างต่อไปสร้างไฟล์ hyperlink-audit-input.pptx ที่มีลิงก์คลิกภายนอก, ลิงก์เมาส์โอเวอร์ไฟล์, การนำทางสไลด์ภายใน, ลิงก์เมาส์โอเวอร์ข้อความ, และการกระทำแมโคร โดยไม่ทำการเรียกใช้การกระทำใด ๆ การสืบค้นทั้งสามทำงานที่ทุกสโคป; จำนวนที่แสดงเป็นจำนวนคอนเทนเนอร์ ไม่ใช่จำนวนการกระทำเอง กรอบข้อความจะยกเว้นลิงก์ของรูปร่างที่ล้อมรอบ

const aspose = { slides: require("aspose.slides.via.java") };

function printQueryCounts(scope, queries) {
const clickCount = queries.getHyperlinkClicks().size();
const mouseOverCount = queries.getHyperlinkMouseOvers().size();
const anyCount = queries.getAnyHyperlinks().size();
console.log(scope + ": click=" + clickCount + ", mouse-over=" + mouseOverCount + ", any=" + anyCount);
}

const presentation = new aspose.slides.Presentation();
try {
    const slide = presentation.getSlides().get_Item(0);
    const destination = presentation.getSlides().addEmptySlide(slide.getLayoutSlide());
    const shape = slide.getShapes().addAutoShape(aspose.slides.ShapeType.Rectangle, 20, 20, 400, 60);
    shape.getTextFrame().setText("Click the text to go to slide 2");
    shape.getHyperlinkManager().setExternalHyperlinkClick("https://example.com/");
    shape.getHyperlinkClick().setTooltip("Public website");
    shape.getHyperlinkManager().setExternalHyperlinkMouseOver("file:///C:/private/report.xlsx");

    const portionFormat = shape.getTextFrame().getParagraphs().get_Item(0).getPortions().get_Item(0).getPortionFormat();
    portionFormat.getHyperlinkManager().setInternalHyperlinkClick(destination);
    portionFormat.getHyperlinkManager().setExternalHyperlinkMouseOver("https://example.com/help");
    const macroButton = slide.getShapes().addAutoShape(aspose.slides.ShapeType.Rectangle, 20, 120, 200, 60);
    macroButton.getHyperlinkManager().setMacroHyperlinkClick("ReviewPresentation");

    printQueryCounts("Presentation", presentation.getHyperlinkQueries());
    printQueryCounts("Slide 1", slide.getHyperlinkQueries());
    printQueryCounts("Text frame", shape.getTextFrame().getHyperlinkQueries());
    presentation.save("hyperlink-audit-input.pptx", aspose.slides.SaveFormat.Pptx);
} finally {
    presentation.dispose();
}

สำหรับตัวอย่างนี้ การสืบค้นระดับงานนำเสนอและสไลด์แต่ละอันรายงานคอนเทนเนอร์คลิกสามรายการ, คอนเทนเนอร์เมาส์โอเวอร์สองรายการ, และคอนเทนเนอร์ที่มีการกระทำใดอย่างหนึ่งสามรายการ ส่วนการสืบค้นระดับกรอบข้อความรายงานหนึ่งคอนเทนเนอร์ในแต่ละประเภท

จำแนกการกระทำและปลายทาง

ใช้ Hyperlink.getActionType เพื่อแปลประเภทการกระทำก่อนแปลปลายทางค่า HyperlinkActionType ครอบคลุมมากกว่าการนำทางเว็บ:

ค่า ความหมายสำหรับการตรวจสอบ
Hyperlink ไฮเปอร์ลิงก์ภายนอก; ตรวจสอบ URL และสเค็มของมัน
JumpSpecificSlide การนำทางภายในไปยังสไลด์เฉพาะ
JumpFirstSlide, JumpPreviousSlide, JumpNextSlide, JumpLastSlide, JumpLastViewedSlide การนำทางสไลด์ที่มาพร้อมโปรแกรม, แก้ไขตามบริบทการแสดงสไลด์
JumpEndShow, StartCustomSlideShow สิ้นสุดการแสดงปัจจุบันหรือเริ่มการแสดงแบบกำหนดเอง
StartMacro เริ่มทำแมโคร
StartProgram เรียกโปรแกรม
OpenFile, OpenPresentation เปิดไฟล์หรือการนำเสนออื่น; ตรวจสอบแยกจาก URL เว็บ
StartStopMedia เริ่มหรือหยุดการเล่นสื่อ
NoAction, Unknown ไม่มีการนำทาง หรือการกระทำที่ไม่รู้จักต้องตรวจสอบ

อ่านปลายทางภายนอกจาก getExternalUrl และปลายทางภายในเฉพาะจาก getTargetSlide การกระทำภายในและคำสั่งในตัวอาจไม่มี URL ภายนอก; URL ว่างไม่หมายความว่าคอนเทนเนอร์ไม่มีการกระทำ อย่าลืมเก็บค่าที่คืนจาก getExternalUrlOriginal เมื่อแตกต่างจาก URL ที่ทำให้เป็นมาตรฐาน, และรวม tooltip จาก getTooltip หากมี

รายงาน ทำความสะอาด และตรวจสอบไฮเปอร์ลิงก์

ตัวอย่าง JavaScript ต่อไปอ่านงานนำเสนอที่มีอยู่ (ใช้ไฟล์ที่สร้างด้านบน), เขียน hyperlink-audit.json, ใช้นโยบาย, บันทึก hyperlink-sanitized.pptx, แล้วเปิดใหม่เพื่อตรวจสอบทั้งสองประเภทการเปิดใช้งานอีกครั้ง ตัวอย่างจะรวบรวมคอนเทนเนอร์ก่อนทำการเปลี่ยนแปลงและใช้การเทียบค่าอ้างอิงเพื่อหลีกเลี่ยงการประมวลผลคอนเทนเนอร์ซ้ำ การสืบค้นงานนำเสนอครอบคลุมสไลด์ปกติ; สำหรับการตรวจสอบทั่วแพ็กเกจ จะสืบค้นมาสเตอร์, เลย์เอาต์, โน้ต, และมาสเตอร์ของโน้ตและแจกจ่ายเมื่อมี

รายงานบันทึกดัชนีสไลด์แบบหนึ่งฐานและ getSlideId หากมี getSlide จะให้สไลด์เจ้าของสำหรับคอนเทนเนอร์ที่รองรับ มาสเตอร์, เลย์เอาต์, และโน้ตไม่มีดัชนีสไลด์ปกติและจะระบุด้วยสโคปของมัน คอนเทนเนอร์รูปร่างและคอนเทนเนอร์การจัดรูปแบบส่วนข้อความจะถูกระบุแยกกัน; ประเภทคอนเทนเนอร์อื่นจะคงชื่อประเภทรันไทม์ของมันเอง แต่ละคอนเทนเนอร์จะได้รับ ID รายงานระดับท้องถิ่นเพื่อให้การกระทำสองอย่างสามารถเชื่อมโยงกันได้ รายงานจะเก็บประเภทการกระทำเป็นค่าคงที่จำนวนเต็มจากการนับของ HyperlinkActionType

นโยบายการใช้งานที่เข้มงวดนี้อนุญาตเฉพาะ URL HTTPS แบบเต็มและปลายทางสไลด์ภายในที่ถูกต้อง มันจะปฏิเสธแมโคร, โปรแกรม, การกระทำไฟล์, การกระทำสไลด์อื่น ๆ, การกระทำที่ไม่รู้จัก, และสเค็ม URL อื่น ๆ การปฏิเสธเหล่านี้เป็นการตัดสินใจของนโยบาย ไม่ใช่คำตัดสินด้านความปลอดภัยของ Aspose.Slides HTTPS เพียงอย่างเดียวไม่ทำให้เชื่อถือได้: ควรเพิ่มรายการอนุญาตโฮสต์และการตรวจสอบอื่น ๆ สำหรับแอปพลิเคชันของคุณ URL ภายนอกต้นฉบับและที่ทำให้เป็นมาตรฐานทั้งสองจะถูกตรวจสอบ ตัวอย่างตรวจสอบเมตาดาต้าโดยไม่เปิดลิงก์หรือรันการกระทำ

สำหรับการแก้ไข คอนเทนเนอร์ของ getHyperlinkManager รองรับ setExternalHyperlinkClick, removeHyperlinkClick และ removeHyperlinkMouseOver ที่นี่ลิงก์คลิกภายนอกที่ไม่ได้รับอนุญาตจะถูกแทนที่ด้วยหน้า Landing HTTPS คงที่; การคลิกที่ไม่ได้รับอนุญาตอื่น ๆ และการเมาส์โอเวอร์ที่ไม่ได้รับอนุญาตจะถูกลบแยกกัน ตั้งค่า replaceExternalClicks เป็น false เพื่อทำการลบทุกการละเมิดนโยบายแทน เลือกหน้าแทนที่ที่เป็นของแอปพลิเคชันก่อนการเผยแพร่

ธงการส่งออกของรายงานใช้การทบทวน PDF อย่างระมัดระวัง: ทำเครื่องหมายการกระทำเมาส์โอเวอร์และทุกอย่างที่ไม่ใช่ลิงก์ภายนอกหรือการกระโดดสไลด์เฉพาะว่าอาจไม่รองรับ มันเป็นเคล็ดลับการทบทวน ไม่ใช่การทดสอบความสามารถหรือการการันตีว่าลิงก์ที่ไม่มีเครื่องหมายจะคงอยู่ในการส่งออก การส่งออก PDF และ HTML ที่สนับสนุน (PDF และ HTML) อาจเก็บไฮเปอร์ลิงก์ไว้ขึ้นกับการกระทำ, ตัวเลือกการส่งออก, และโปรแกรมชมไฟล์ ภาพ raster (images) และวิดีโอ (video) ไม่สามารถเก็บไฮเปอร์ลิงก์แบบโต้ตอบได้; ควรทำเครื่องหมายทุกการกระทำเมื่อทำการตรวจสอบสำหรับผลลัพธ์เหล่านั้น

const aspose = { slides: require("aspose.slides.via.java") };
const java = require("java");
const fs = require("fs");

function slideIndex(presentation, slide) {
    if (slide == null) return null;
    for (let index = 0; index < presentation.getSlides().size(); index++) {
        if (presentation.getSlides().get_Item(index).equals(slide)) return index + 1;
    }
    return null;
}

function isHttps(value) {
    if (value == null || value.length === 0) return false;
    try {
        const uri = java.newInstanceSync("java.net.URI", value);
        const scheme = uri.getScheme();
        return uri.isAbsolute() && scheme != null && scheme.toLowerCase() === "https" && uri.getHost() != null;
    } catch (exception) {
        return false;
    }
}

function policyViolation(link) {
    if (link == null) return null;
    if (link.getActionType() === aspose.slides.HyperlinkActionType.JumpSpecificSlide) {
        return link.getTargetSlide() == null ? "Missing target slide" : null;
    }
    if (link.getActionType() !== aspose.slides.HyperlinkActionType.Hyperlink) return "Action is not allowed";
    if (!isHttps(link.getExternalUrl())) return "Normalized URL is not absolute HTTPS";
    const original = link.getExternalUrlOriginal();
    if (original != null && original.length > 0 && !isHttps(original)) return "Original URL is not absolute HTTPS";
    return null;
}

function collectContainers(presentation) {
    const found = [];
    function addQueries(queries) {
        const containers = queries.getAnyHyperlinks();
        for (let index = 0; index < containers.size(); index++) {
            found.push(containers.get_Item(index));
        }
    }
    function addScope(slide) {
        if (slide != null) addQueries(slide.getHyperlinkQueries());
    }
    addQueries(presentation.getHyperlinkQueries());
    for (let index = 0; index < presentation.getMasters().size(); index++) {
        addScope(presentation.getMasters().get_Item(index));
    }
    for (let index = 0; index < presentation.getLayoutSlides().size(); index++) {
        addScope(presentation.getLayoutSlides().get_Item(index));
    }
    for (let index = 0; index < presentation.getSlides().size(); index++) {
        addScope(presentation.getSlides().get_Item(index).getNotesSlideManager().getNotesSlide());
    }
    addScope(presentation.getMasterNotesSlideManager().getMasterNotesSlide());
    addScope(presentation.getMasterHandoutSlideManager().getMasterHandoutSlide());
    const seen = java.newInstanceSync("java.util.IdentityHashMap");
    const unique = [];
    for (const container of found) {
        if (!seen.containsKey(container)) {
            seen.put(container, true);
            unique.push(container);
        }
    }
    return unique;
}

function addRow(rows, presentation, link, activation, container, containerId) {
    if (link == null) return;
    const ownerSlide = java.instanceOf(container, "com.aspose.slides.ISlideComponent") ? container.getSlide() : null;
    const targetSlide = link.getTargetSlide();
    const violation = policyViolation(link);
    const ownerType = java.instanceOf(container, "com.aspose.slides.IShape") ? "Shape" : java.instanceOf(container, "com.aspose.slides.IPortionFormat") ? "Text portion" : container.getClass().getSimpleName();
    const ordinaryAction = link.getActionType() === aspose.slides.HyperlinkActionType.Hyperlink || link.getActionType() === aspose.slides.HyperlinkActionType.JumpSpecificSlide;
    rows.push({
        ContainerId: containerId,
        SlideIndex: slideIndex(presentation, ownerSlide),
        SlideId: ownerSlide == null ? null : ownerSlide.getSlideId(),
        Scope: ownerSlide == null ? null : ownerSlide.getClass().getSimpleName(),
        OwnerType: ownerType,
        Activation: activation,
        ActionType: link.getActionType(),
        ExternalUrl: link.getExternalUrl(),
        TargetSlideIndex: slideIndex(presentation, targetSlide),
        TargetSlideId: targetSlide == null ? null : targetSlide.getSlideId(),
        Tooltip: link.getTooltip(),
        OriginalExternalUrl: link.getExternalUrlOriginal() === link.getExternalUrl() ? null : link.getExternalUrlOriginal(),
        PotentiallyUnsafe: violation != null,
        PolicyViolation: violation,
        TargetExport: "PDF",
        PotentiallyUnsupportedByExport: activation === "mouse-over" || !ordinaryAction
    });
}

const replaceExternalClicks = true;
const replacementUrl = "https://example.com/blocked-link";
const presentation = new aspose.slides.Presentation("hyperlink-audit-input.pptx");
try {
    const containers = collectContainers(presentation);
    const rows = [];
    for (let index = 0; index < containers.length; index++) {
        const container = containers[index];
        addRow(rows, presentation, container.getHyperlinkClick(), "click", container, index + 1);
        addRow(rows, presentation, container.getHyperlinkMouseOver(), "mouse-over", container, index + 1);
    }
    const json = JSON.stringify(rows, null, 2);
    fs.writeFileSync("hyperlink-audit.json", json, "utf8");

    for (const container of containers) {
        const click = container.getHyperlinkClick();
        if (policyViolation(click) != null) {
            if (replaceExternalClicks && click.getActionType() === aspose.slides.HyperlinkActionType.Hyperlink) {
                container.getHyperlinkManager().setExternalHyperlinkClick(replacementUrl);
            } else {
                container.getHyperlinkManager().removeHyperlinkClick();
            }
        }
        if (policyViolation(container.getHyperlinkMouseOver()) != null) {
            container.getHyperlinkManager().removeHyperlinkMouseOver();
        }
    }
    presentation.save("hyperlink-sanitized.pptx", aspose.slides.SaveFormat.Pptx);

    const reopened = new aspose.slides.Presentation("hyperlink-sanitized.pptx");
    try {
        const remainingContainers = collectContainers(reopened);
        let violations = 0;
        for (const container of remainingContainers) {
            if (policyViolation(container.getHyperlinkClick()) != null) violations++;
            if (policyViolation(container.getHyperlinkMouseOver()) != null) violations++;
        }
        console.log("Audit rows: " + rows.length + "; prohibited actions after reopening: " + violations);
        if (violations !== 0) {
            console.log("Verification failed: do not distribute the saved presentation.");
        }
    } finally {
        reopened.dispose();
    }
} finally {
    presentation.dispose();
}

ด้วยอินพุตที่สร้างข้างต้น รายงานมีห้าแถวการกระทำ ลิงก์เมาส์โอเวอร์ไฟล์และแมโครคลิกจะถูกลบ ส่วนลิงก์ HTTPS และการนำทางสไลด์ภายในยังคงอยู่ การตรวจสอบพิมพ์ศูนย์การกระทำที่ไม่ได้รับอนุญาต อินพุตที่มี URL คลิกภายนอกที่ไม่ได้รับอนุญาตจะทำให้สาขาการแทนที่ทำงาน คอนเทนเนอร์ที่มีคลิกที่ได้รับอนุญาตและเมาส์โอเวอร์ที่ไม่ได้รับอนุญาตจะเก็บคลิกไว้

การทำความสะอาดแบบเลือกนี้แตกต่างจาก removeAllHyperlinks ที่ลบทั้งสองประเภทการเปิดใช้งานในสโคปที่เลือกโดยไม่คำนึงถึงนโยบาย การตรวจสอบที่นี่ตรวจสอบการกระทำของไฮเปอร์ลิงก์เท่านั้น; ไม่ได้ลบโครงการ VBA ฝัง, วัตถุ OLE, หรือเนื้อหาแอคทีฟอื่น ๆ และไม่ได้ตรวจสอบไฟล์ PDF หรือ HTML ที่ส่งออก

FAQ

ฉันจะเชื่อมไปยังส่วนหรือสไลด์แรกของส่วนได้อย่างไร?

ส่วนใน PowerPoint จะจัดกลุ่มสไลด์ แต่ไฮเปอร์ลิงก์ภายในจะชี้ไปยังสไลด์เดียว หากต้องการสร้างการนำทางไปยังส่วน ให้เชื่อมไปยังสไลด์แรกของส่วนนั้น

ฉันสามารถแนบไฮเปอร์ลิงก์กับองค์ประกอบมาสเตอร์สไลด์เพื่อให้ทำงานบนทุกสไลด์ได้หรือไม่?

ได้ มาสเตอร์สไลด์และองค์ประกอบเลย์เอาต์รองรับไฮเปอร์ลิงก์ ลิงก์บนองค์ประกอบเหล่านี้จะพร้อมใช้งานในโหมดสไลด์โชว์บนสไลด์ที่ใช้มาสเตอร์หรือเลย์เอาต์ที่สอดคล้องกัน

ไฮเปอร์ลิงก์จะคงอยู่เมื่อส่งออกเป็น PDF, HTML, ภาพ หรือวิดีโอหรือไม่?

การส่งออก PDF และ HTML ที่สนับสนุนอาจคงไฮเปอร์ลิงก์ไว้; ภาพ raster และวิดีโอไม่สามารถคงไฮเปอร์ลิงก์แบบโต้ตอบได้ ดูข้อควรพิจารณาการส่งออกใน Report, Sanitize, and Verify Hyperlinks